diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..c816275 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,271 @@ +# Copyright 2022-2024, axodotdev +# SPDX-License-Identifier: MIT or Apache-2.0 +# +# CI that: +# +# * checks for a Git Tag that looks like a release +# * builds artifacts with cargo-dist (archives, installers, hashes) +# * uploads those artifacts to temporary workflow zip +# * on success, uploads the artifacts to a GitHub Release +# +# Note that the GitHub Release will be created with a generated +# title/body based on your changelogs. + +name: Release + +permissions: + contents: write + +# This task will run whenever you push a git tag that looks like a version +# like "1.0.0", "v0.1.0-prerelease.1", "my-app/0.1.0", "releases/v1.0.0", etc. +# Various formats will be parsed into a VERSION and an optional PACKAGE_NAME, where +# PACKAGE_NAME must be the name of a Cargo package in your workspace, and VERSION +# must be a Cargo-style SemVer Version (must have at least major.minor.patch). +# +# If PACKAGE_NAME is specified, then the announcement will be for that +# package (erroring out if it doesn't have the given version or isn't cargo-dist-able). +# +# If PACKAGE_NAME isn't specified, then the announcement will be for all +# (cargo-dist-able) packages in the workspace with that version (this mode is +# intended for workspaces with only one dist-able package, or with all dist-able +# packages versioned/released in lockstep). +# +# If you push multiple tags at once, separate instances of this workflow will +# spin up, creating an independent announcement for each one. However, GitHub +# will hard limit this to 3 tags per commit, as it will assume more tags is a +# mistake. +# +# If there's a prerelease-style suffix to the version, then the release(s) +# will be marked as a prerelease. +on: + pull_request: + push: + tags: + - '**[0-9]+.[0-9]+.[0-9]+*' + +jobs: + # Run 'cargo dist plan' (or host) to determine what tasks we need to do + plan: + runs-on: "ubuntu-20.04" + outputs: + val: ${{ steps.plan.outputs.manifest }} + tag: ${{ !github.event.pull_request && github.ref_name || '' }} + tag-flag: ${{ !github.event.pull_request && format('--tag={0}', github.ref_name) || '' }} + publishing: ${{ !github.event.pull_request }} + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + steps: + - uses: actions/checkout@v4 + with: + submodules: recursive + - name: Install cargo-dist + # we specify bash to get pipefail; it guards against the `curl` command + # failing. otherwise `sh` won't catch that `curl` returned non-0 + shell: bash + run: "curl --proto '=https' --tlsv1.2 -LsSf https://github.com/axodotdev/cargo-dist/releases/download/v0.15.1/cargo-dist-installer.sh | sh" + # sure would be cool if github gave us proper conditionals... + # so here's a doubly-nested ternary-via-truthiness to try to provide the best possible + # functionality based on whether this is a pull_request, and whether it's from a fork. + # (PRs run on the *source* but secrets are usually on the *target* -- that's *good* + # but also really annoying to build CI around when it needs secrets to work right.) + - id: plan + run: | + cargo dist ${{ (!github.event.pull_request && format('host --steps=create --tag={0}', github.ref_name)) || 'plan' }} --output-format=json > plan-dist-manifest.json + echo "cargo dist ran successfully" + cat plan-dist-manifest.json + echo "manifest=$(jq -c "." plan-dist-manifest.json)" >> "$GITHUB_OUTPUT" + - name: "Upload dist-manifest.json" + uses: actions/upload-artifact@v4 + with: + name: artifacts-plan-dist-manifest + path: plan-dist-manifest.json + + # Build and packages all the platform-specific things + build-local-artifacts: + name: build-local-artifacts (${{ join(matrix.targets, ', ') }}) + # Let the initial task tell us to not run (currently very blunt) + needs: + - plan + if: ${{ fromJson(needs.plan.outputs.val).ci.github.artifacts_matrix.include != null && (needs.plan.outputs.publishing == 'true' || fromJson(needs.plan.outputs.val).ci.github.pr_run_mode == 'upload') }} + strategy: + fail-fast: false + # Target platforms/runners are computed by cargo-dist in create-release. + # Each member of the matrix has the following arguments: + # + # - runner: the github runner + # - dist-args: cli flags to pass to cargo dist + # - install-dist: expression to run to install cargo-dist on the runner + # + # Typically there will be: + # - 1 "global" task that builds universal installers + # - N "local" tasks that build each platform's binaries and platform-specific installers + matrix: ${{ fromJson(needs.plan.outputs.val).ci.github.artifacts_matrix }} + runs-on: ${{ matrix.runner }} + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + BUILD_MANIFEST_NAME: target/distrib/${{ join(matrix.targets, '-') }}-dist-manifest.json + steps: + - name: enable windows longpaths + run: | + git config --global core.longpaths true + - uses: actions/checkout@v4 + with: + submodules: recursive + - uses: swatinem/rust-cache@v2 + with: + key: ${{ join(matrix.targets, '-') }} + - name: Install cargo-dist + run: ${{ matrix.install_dist }} + # Get the dist-manifest + - name: Fetch local artifacts + uses: actions/download-artifact@v4 + with: + pattern: artifacts-* + path: target/distrib/ + merge-multiple: true + - name: Install dependencies + run: | + ${{ matrix.packages_install }} + - name: Build artifacts + run: | + # Actually do builds and make zips and whatnot + cargo dist build ${{ needs.plan.outputs.tag-flag }} --print=linkage --output-format=json ${{ matrix.dist_args }} > dist-manifest.json + echo "cargo dist ran successfully" + - id: cargo-dist + name: Post-build + # We force bash here just because github makes it really hard to get values up + # to "real" actions without writing to env-vars, and writing to env-vars has + # inconsistent syntax between shell and powershell. + shell: bash + run: | + # Parse out what we just built and upload it to scratch storage + echo "paths<> "$GITHUB_OUTPUT" + jq --raw-output ".upload_files[]" dist-manifest.json >> "$GITHUB_OUTPUT" + echo "EOF" >> "$GITHUB_OUTPUT" + + cp dist-manifest.json "$BUILD_MANIFEST_NAME" + - name: "Upload artifacts" + uses: actions/upload-artifact@v4 + with: + name: artifacts-build-local-${{ join(matrix.targets, '_') }} + path: | + ${{ steps.cargo-dist.outputs.paths }} + ${{ env.BUILD_MANIFEST_NAME }} + + # Build and package all the platform-agnostic(ish) things + build-global-artifacts: + needs: + - plan + - build-local-artifacts + runs-on: "ubuntu-20.04" + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + BUILD_MANIFEST_NAME: target/distrib/global-dist-manifest.json + steps: + - uses: actions/checkout@v4 + with: + submodules: recursive + - name: Install cargo-dist + shell: bash + run: "curl --proto '=https' --tlsv1.2 -LsSf https://github.com/axodotdev/cargo-dist/releases/download/v0.15.1/cargo-dist-installer.sh | sh" + # Get all the local artifacts for the global tasks to use (for e.g. checksums) + - name: Fetch local artifacts + uses: actions/download-artifact@v4 + with: + pattern: artifacts-* + path: target/distrib/ + merge-multiple: true + - id: cargo-dist + shell: bash + run: | + cargo dist build ${{ needs.plan.outputs.tag-flag }} --output-format=json "--artifacts=global" > dist-manifest.json + echo "cargo dist ran successfully" + + # Parse out what we just built and upload it to scratch storage + echo "paths<> "$GITHUB_OUTPUT" + jq --raw-output ".upload_files[]" dist-manifest.json >> "$GITHUB_OUTPUT" + echo "EOF" >> "$GITHUB_OUTPUT" + + cp dist-manifest.json "$BUILD_MANIFEST_NAME" + - name: "Upload artifacts" + uses: actions/upload-artifact@v4 + with: + name: artifacts-build-global + path: | + ${{ steps.cargo-dist.outputs.paths }} + ${{ env.BUILD_MANIFEST_NAME }} + # Determines if we should publish/announce + host: + needs: + - plan + - build-local-artifacts + - build-global-artifacts + # Only run if we're "publishing", and only if local and global didn't fail (skipped is fine) + if: ${{ always() && needs.plan.outputs.publishing == 'true' && (needs.build-global-artifacts.result == 'skipped' || needs.build-global-artifacts.result == 'success') && (needs.build-local-artifacts.result == 'skipped' || needs.build-local-artifacts.result == 'success') }} + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + runs-on: "ubuntu-20.04" + outputs: + val: ${{ steps.host.outputs.manifest }} + steps: + - uses: actions/checkout@v4 + with: + submodules: recursive + - name: Install cargo-dist + run: "curl --proto '=https' --tlsv1.2 -LsSf https://github.com/axodotdev/cargo-dist/releases/download/v0.15.1/cargo-dist-installer.sh | sh" + # Fetch artifacts from scratch-storage + - name: Fetch artifacts + uses: actions/download-artifact@v4 + with: + pattern: artifacts-* + path: target/distrib/ + merge-multiple: true + # This is a harmless no-op for GitHub Releases, hosting for that happens in "announce" + - id: host + shell: bash + run: | + cargo dist host ${{ needs.plan.outputs.tag-flag }} --steps=upload --steps=release --output-format=json > dist-manifest.json + echo "artifacts uploaded and released successfully" + cat dist-manifest.json + echo "manifest=$(jq -c "." dist-manifest.json)" >> "$GITHUB_OUTPUT" + - name: "Upload dist-manifest.json" + uses: actions/upload-artifact@v4 + with: + # Overwrite the previous copy + name: artifacts-dist-manifest + path: dist-manifest.json + + # Create a GitHub Release while uploading all files to it + announce: + needs: + - plan + - host + # use "always() && ..." to allow us to wait for all publish jobs while + # still allowing individual publish jobs to skip themselves (for prereleases). + # "host" however must run to completion, no skipping allowed! + if: ${{ always() && needs.host.result == 'success' }} + runs-on: "ubuntu-20.04" + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + steps: + - uses: actions/checkout@v4 + with: + submodules: recursive + - name: "Download GitHub Artifacts" + uses: actions/download-artifact@v4 + with: + pattern: artifacts-* + path: artifacts + merge-multiple: true + - name: Cleanup + run: | + # Remove the granular manifests + rm -f artifacts/*-dist-manifest.json + - name: Create GitHub Release + uses: ncipollo/release-action@v1 + with: + tag: ${{ needs.plan.outputs.tag }} + name: ${{ fromJson(needs.host.outputs.val).announcement_title }} + body: ${{ fromJson(needs.host.outputs.val).announcement_github_body }} + prerelease: ${{ fromJson(needs.host.outputs.val).announcement_is_prerelease }} + artifacts: "artifacts/*" diff --git a/.gitignore b/.gitignore index ea8c4bf..2c6d35b 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,3 @@ -/target +target +node_modules +dist \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock index 5c80580..5740be1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3,5 +3,2154 @@ version = 3 [[package]] -name = "rqjs" +name = "addr2line" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e4503c46a5c0c7844e948c9a4d6acd9f50cccb4de1c48eb9e291ea17470c678" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + +[[package]] +name = "ahash" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" +dependencies = [ + "cfg-if", + "once_cell", + "version_check", + "zerocopy", +] + +[[package]] +name = "aho-corasick" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +dependencies = [ + "memchr", +] + +[[package]] +name = "allocator-api2" +version = "0.2.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f" + +[[package]] +name = "android-tzdata" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" + +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + +[[package]] +name = "anstream" +version = "0.6.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "418c75fa768af9c03be99d17643f93f79bbba589895012a80e3452a19ddda15b" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "038dfcf04a5feb68e9c60b21c9625a54c2c0616e79b72b0fd87075a056ae1d1b" + +[[package]] +name = "anstyle-parse" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c03a11a9034d92058ceb6ee011ce58af4a9bf61491aa7e1e59ecd24bd40d22d4" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad186efb764318d35165f1758e7dcef3b10628e26d41a44bc5550652e6804391" +dependencies = [ + "windows-sys 0.52.0", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61a38449feb7068f52bb06c12759005cf459ee52bb4adc1d5a7c4322d716fb19" +dependencies = [ + "anstyle", + "windows-sys 0.52.0", +] + +[[package]] +name = "async-lock" +version = "3.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff6e472cdea888a4bd64f342f09b3f50e1886d32afe8df3d663c01140b811b18" +dependencies = [ + "event-listener", + "event-listener-strategy", + "pin-project-lite", +] + +[[package]] +name = "atomic" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c59bdb34bc650a32731b31bd8f0829cc15d24a708ee31559e0bb34f2bc320cba" + +[[package]] +name = "atomic-waker" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" + +[[package]] +name = "autocfg" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" + +[[package]] +name = "backtrace" +version = "0.3.73" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5cc23269a4f8976d0a4d2e7109211a419fe30e8d88d677cd60b6bc79c5732e0a" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", +] + +[[package]] +name = "base64-simd" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "339abbe78e73178762e23bea9dfd08e697eb3f3301cd4be981c0f78ba5859195" +dependencies = [ + "outref", + "vsimd", +] + +[[package]] +name = "bindgen" +version = "0.69.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a00dc851838a2120612785d195287475a3ac45514741da670b735818822129a0" +dependencies = [ + "bitflags", + "cexpr", + "clang-sys", + "itertools", + "lazy_static", + "lazycell", + "log", + "prettyplease", + "proc-macro2 1.0.86", + "quote 1.0.36", + "regex", + "rustc-hash", + "shlex", + "syn 2.0.67", + "which", +] + +[[package]] +name = "bitflags" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[package]] +name = "bumpalo" +version = "3.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "bytes" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" + +[[package]] +name = "cc" +version = "1.0.99" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96c51067fd44124faa7f870b4b1c969379ad32b2ba805aa959430ceaa384f695" + +[[package]] +name = "cexpr" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" +dependencies = [ + "nom", +] + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "cfg_aliases" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e" + +[[package]] +name = "chrono" +version = "0.4.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401" +dependencies = [ + "android-tzdata", + "iana-time-zone", + "js-sys", + "num-traits", + "wasm-bindgen", + "windows-targets 0.52.5", +] + +[[package]] +name = "clang-sys" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4" +dependencies = [ + "glob", + "libc", + "libloading", +] + +[[package]] +name = "clap" +version = "4.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5db83dced34638ad474f39f250d7fea9598bdd239eaced1bdf45d597da0f433f" +dependencies = [ + "clap_builder", + "clap_derive", +] + +[[package]] +name = "clap_builder" +version = "4.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7e204572485eb3fbf28f871612191521df159bc3e15a9f5064c66dba3a8c05f" +dependencies = [ + "anstream", + "anstyle", + "clap_lex", + "strsim", +] + +[[package]] +name = "clap_derive" +version = "4.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c780290ccf4fb26629baa7a1081e68ced113f1d3ec302fa5948f1c381ebf06c6" +dependencies = [ + "heck", + "proc-macro2 1.0.86", + "quote 1.0.36", + "syn 2.0.67", +] + +[[package]] +name = "clap_lex" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b82cf0babdbd58558212896d1a4272303a57bdb245c2bf1147185fb45640e70" + +[[package]] +name = "colorchoice" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b6a852b24ab71dffc585bcb46eaf7959d175cb865a7152e35b348d1b2960422" + +[[package]] +name = "concurrent-queue" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "convert_case" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec182b0ca2f35d8fc196cf3404988fd8b8c739a4d270ff118a398feb0cbec1ca" +dependencies = [ + "unicode-segmentation", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" + +[[package]] +name = "crc32c" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a47af21622d091a8f0fb295b88bc886ac74efcc613efc19f5d0b21de5c89e47" +dependencies = [ + "rustc_version", +] + +[[package]] +name = "crc32fast" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "cross-uname" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff7bb10673cca006046a1ec932de4637ab04fc224cae6f83134bce596f5d1389" + +[[package]] +name = "crossbeam-utils" +version = "0.8.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "ctrlc" +version = "3.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "672465ae37dc1bc6380a6547a8883d5dd397b0f1faaad4f265726cc7042a5345" +dependencies = [ + "nix", + "windows-sys 0.52.0", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "crypto-common", +] + +[[package]] +name = "dlopen" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71e80ad39f814a9abe68583cd50a2d45c8a67561c3361ab8da240587dda80937" +dependencies = [ + "dlopen_derive", + "lazy_static", + "libc", + "winapi", +] + +[[package]] +name = "dlopen_derive" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f236d9e1b1fbd81cea0f9cbdc8dcc7e8ebcd80e6659cd7cb2ad5f6c05946c581" +dependencies = [ + "libc", + "quote 0.6.13", + "syn 0.15.44", +] + +[[package]] +name = "either" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3dca9240753cf90908d7e4aac30f630662b02aebaa1b58a3cadabdb23385b58b" + +[[package]] +name = "encoding_rs" +version = "0.8.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b45de904aa0b010bce2ab45264d0631681847fa7b6f2eaa7dab7619943bc4f59" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + +[[package]] +name = "errno" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "event-listener" +version = "5.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6032be9bd27023a771701cc49f9f053c751055f71efb2e0ae5c15809093675ba" +dependencies = [ + "concurrent-queue", + "parking", + "pin-project-lite", +] + +[[package]] +name = "event-listener-strategy" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f214dc438f977e6d4e3500aaa277f5ad94ca83fbbd9b1a15713ce2344ccc5a1" +dependencies = [ + "event-listener", + "pin-project-lite", +] + +[[package]] +name = "float-cmp" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98de4bbd547a563b716d8dfa9aad1cb19bfab00f4fa09a6a4ed21dbcf44ce9c4" +dependencies = [ + "num-traits", +] + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "futures-channel" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" +dependencies = [ + "futures-core", +] + +[[package]] +name = "futures-core" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" + +[[package]] +name = "futures-sink" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" + +[[package]] +name = "futures-task" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" + +[[package]] +name = "futures-util" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" +dependencies = [ + "futures-core", + "futures-task", + "pin-project-lite", + "pin-utils", +] + +[[package]] +name = "fxhash" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c" +dependencies = [ + "byteorder", +] + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] +name = "getrandom" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" +dependencies = [ + "cfg-if", + "js-sys", + "libc", + "wasi", + "wasm-bindgen", +] + +[[package]] +name = "gimli" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd" + +[[package]] +name = "glob" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" + +[[package]] +name = "h2" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa82e28a107a8cc405f0839610bdc9b15f1e25ec7d696aa5cf173edbcb1486ab" +dependencies = [ + "atomic-waker", + "bytes", + "fnv", + "futures-core", + "futures-sink", + "http", + "indexmap", + "slab", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "halfbrown" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8588661a8607108a5ca69cab034063441a0413a0b041c13618a7dd348021ef6f" +dependencies = [ + "hashbrown", + "serde", +] + +[[package]] +name = "hashbrown" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" +dependencies = [ + "ahash", + "allocator-api2", +] + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "hermit-abi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" + +[[package]] +name = "hex-simd" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f7685beb53fc20efc2605f32f5d51e9ba18b8ef237961d1760169d2290d3bee" +dependencies = [ + "outref", + "vsimd", +] + +[[package]] +name = "home" +version = "0.5.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5" +dependencies = [ + "windows-sys 0.52.0", +] + +[[package]] +name = "http" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "http-body" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cac85db508abc24a2e48553ba12a996e87244a0395ce011e62b37158745d643" +dependencies = [ + "bytes", + "http", +] + +[[package]] +name = "httparse" +version = "1.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fcc0b4a115bf80b728eb8ea024ad5bd707b615bfed49e0665b6e0f86fd082d9" + +[[package]] +name = "hyper" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe575dd17d0862a9a33781c8c4696a55c320909004a67a00fb286ba8b1bc496d" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "h2", + "http", + "http-body", + "httparse", + "itoa", + "pin-project-lite", + "smallvec", + "tokio", + "want", +] + +[[package]] +name = "hyper-rustls" +version = "0.27.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ee4be2c948921a1a5320b629c4193916ed787a7f7f293fd3f7f5a6c9de74155" +dependencies = [ + "futures-util", + "http", + "hyper", + "hyper-util", + "rustls", + "rustls-pki-types", + "tokio", + "tokio-rustls", + "tower-service", + "webpki-roots", +] + +[[package]] +name = "hyper-util" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b875924a60b96e5d7b9ae7b066540b1dd1cbd90d1828f54c92e02a283351c56" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "http", + "http-body", + "hyper", + "pin-project-lite", + "socket2", + "tokio", + "tower", + "tower-service", + "tracing", +] + +[[package]] +name = "iana-time-zone" +version = "0.1.60" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "wasm-bindgen", + "windows-core", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" +dependencies = [ + "cc", +] + +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + +[[package]] +name = "indexmap" +version = "2.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" +dependencies = [ + "equivalent", + "hashbrown", +] + +[[package]] +name = "is_terminal_polyfill" +version = "1.70.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8478577c03552c21db0e2724ffb8986a5ce7af88107e6be5d2ee6e158c12800" + +[[package]] +name = "itertools" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" + +[[package]] +name = "js-sys" +version = "0.3.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d" +dependencies = [ + "wasm-bindgen", +] + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "lazycell" +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.155" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" + +[[package]] +name = "libloading" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c2a198fb6b0eada2a8df47933734e6d35d350665a33a3593d7164fa52c75c19" +dependencies = [ + "cfg-if", + "windows-targets 0.52.5", +] + +[[package]] +name = "linux-raw-sys" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" + +[[package]] +name = "lock_api" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" +dependencies = [ + "autocfg", + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" + +[[package]] +name = "md-5" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d89e7ee0cfbedfc4da3340218492196241d89eefb6dab27de5df917a6d2e78cf" +dependencies = [ + "cfg-if", + "digest", +] + +[[package]] +name = "memchr" +version = "2.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" + +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + +[[package]] +name = "miniz_oxide" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08" +dependencies = [ + "adler", +] + +[[package]] +name = "mio" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" +dependencies = [ + "libc", + "wasi", + "windows-sys 0.48.0", +] + +[[package]] +name = "nix" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab2156c4fce2f8df6c499cc1c763e4394b7482525bf2a9701c9d79d215f519e4" +dependencies = [ + "bitflags", + "cfg-if", + "cfg_aliases", + "libc", +] + +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + +[[package]] +name = "num_cpus" +version = "1.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" +dependencies = [ + "hermit-abi", + "libc", +] + +[[package]] +name = "object" +version = "0.36.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "576dfe1fc8f9df304abb159d767a29d0476f7750fbf8aa7ad07816004a207434" +dependencies = [ + "memchr", +] + +[[package]] +name = "once_cell" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" + +[[package]] +name = "outref" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4030760ffd992bef45b0ae3f10ce1aba99e33464c90d14dd7c039884963ddc7a" + +[[package]] +name = "parking" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb813b8af86854136c6922af0598d719255ecb2179515e6e7730d468f05c9cae" + +[[package]] +name = "parking_lot" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-targets 0.52.5", +] + +[[package]] +name = "phf" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc" +dependencies = [ + "phf_shared", +] + +[[package]] +name = "phf_generator" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48e4cc64c2ad9ebe670cb8fd69dd50ae301650392e81c05f9bfcb2d5bdbc24b0" +dependencies = [ + "phf_shared", + "rand", +] + +[[package]] +name = "phf_shared" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90fcb95eef784c2ac79119d1dd819e162b5da872ce6f3c3abe1e8ca1c082f72b" +dependencies = [ + "siphasher", +] + +[[package]] +name = "pin-project" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6bf43b791c5b9e34c3d182969b4abb522f9343702850a2e57f460d00d09b4b3" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" +dependencies = [ + "proc-macro2 1.0.86", + "quote 1.0.36", + "syn 2.0.67", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "ppv-lite86" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" + +[[package]] +name = "prettyplease" +version = "0.2.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f12335488a2f3b0a83b14edad48dca9879ce89b2edd10e80237e4e852dd645e" +dependencies = [ + "proc-macro2 1.0.86", + "syn 2.0.67", +] + +[[package]] +name = "proc-macro-crate" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919" +dependencies = [ + "once_cell", + "toml_edit", +] + +[[package]] +name = "proc-macro-error" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" +dependencies = [ + "proc-macro-error-attr", + "proc-macro2 1.0.86", + "quote 1.0.36", + "syn 1.0.109", + "version_check", +] + +[[package]] +name = "proc-macro-error-attr" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" +dependencies = [ + "proc-macro2 1.0.86", + "quote 1.0.36", + "version_check", +] + +[[package]] +name = "proc-macro2" +version = "0.4.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759" +dependencies = [ + "unicode-xid", +] + +[[package]] +name = "proc-macro2" +version = "1.0.86" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quick-xml" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d3a6e5838b60e0e8fa7a43f22ade549a37d61f8bdbe636d0d7816191de969c2" +dependencies = [ + "memchr", +] + +[[package]] +name = "quote" +version = "0.6.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1" +dependencies = [ + "proc-macro2 0.4.30", +] + +[[package]] +name = "quote" +version = "1.0.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" +dependencies = [ + "proc-macro2 1.0.86", +] + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + +[[package]] +name = "redox_syscall" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c82cf8cff14456045f55ec4241383baeff27af886adb72ffb2162f99911de0fd" +dependencies = [ + "bitflags", +] + +[[package]] +name = "ref-cast" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccf0a6f84d5f1d581da8b41b47ec8600871962f2a528115b542b362d4b744931" +dependencies = [ + "ref-cast-impl", +] + +[[package]] +name = "ref-cast-impl" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bcc303e793d3734489387d205e9b186fac9c6cfacedd98cbb2e8a5943595f3e6" +dependencies = [ + "proc-macro2 1.0.86", + "quote 1.0.36", + "syn 2.0.67", +] + +[[package]] +name = "regex" +version = "1.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b91213439dad192326a0d7c6ee3955910425f441d7038e0d6933b0aec5c4517f" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" + +[[package]] +name = "relative-path" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba39f3699c378cd8970968dcbff9c43159ea4cfbd88d43c00b22f2ef10a435d2" + +[[package]] +name = "ring" +version = "0.17.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" +dependencies = [ + "cc", + "cfg-if", + "getrandom", + "libc", + "spin", + "untrusted", + "windows-sys 0.52.0", +] + +[[package]] +name = "rqjs-cli" +version = "0.1.3" +dependencies = [ + "clap", + "ctrlc", + "rqjs-ext", + "rquickjs", + "tokio", +] + +[[package]] +name = "rqjs-ext" +version = "0.1.3" +dependencies = [ + "base64-simd", + "chrono", + "clap", + "crc32c", + "crc32fast", + "cross-uname", + "ctrlc", + "encoding_rs", + "fxhash", + "hex-simd", + "hyper", + "hyper-rustls", + "itoa", + "md-5", + "once_cell", + "phf", + "quick-xml", + "rand", + "ring", + "rquickjs", + "rustls", + "ryu", + "simd-json", + "tokio", + "uuid", + "uuid-simd", +] + +[[package]] +name = "rquickjs" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9cbd33e0b668aea0ab238b9164523aca929096f9f40834700d71d91dd4888882" +dependencies = [ + "either", + "indexmap", + "rquickjs-core", + "rquickjs-macro", +] + +[[package]] +name = "rquickjs-core" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e9129d69b7b8f7ee8ad1da5b12c7f4a8a8acd45f2e6dd9cb2ee1bc5a1f2fa3d" +dependencies = [ + "async-lock", + "chrono", + "dlopen", + "either", + "indexmap", + "phf", + "relative-path", + "rquickjs-sys", +] + +[[package]] +name = "rquickjs-macro" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7d2ecaf7c9eda262e02a91e9541989a9dd18984d17d0d97f99f33b464318057" +dependencies = [ + "convert_case", + "fnv", + "ident_case", + "indexmap", + "phf_generator", + "phf_shared", + "proc-macro-crate", + "proc-macro-error", + "proc-macro2 1.0.86", + "quote 1.0.36", + "rquickjs-core", + "syn 2.0.67", +] + +[[package]] +name = "rquickjs-sys" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf6f2288d8e7fbb5130f62cf720451641e99d55f6fde9db86aa2914ecb553fd2" +dependencies = [ + "bindgen", + "cc", +] + +[[package]] +name = "rustc-demangle" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" + +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + +[[package]] +name = "rustc_version" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +dependencies = [ + "semver", +] + +[[package]] +name = "rustix" +version = "0.38.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" +dependencies = [ + "bitflags", + "errno", + "libc", + "linux-raw-sys", + "windows-sys 0.52.0", +] + +[[package]] +name = "rustls" +version = "0.23.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05cff451f60db80f490f3c182b77c35260baace73209e9cdbbe526bfe3a4d402" +dependencies = [ + "once_cell", + "ring", + "rustls-pki-types", + "rustls-webpki", + "subtle", + "zeroize", +] + +[[package]] +name = "rustls-pki-types" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "976295e77ce332211c0d24d92c0e83e50f5c5f046d11082cea19f3df13a3562d" + +[[package]] +name = "rustls-webpki" +version = "0.102.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff448f7e92e913c4b7d4c6d8e4540a1724b319b4152b8aef6d4cf8339712b33e" +dependencies = [ + "ring", + "rustls-pki-types", + "untrusted", +] + +[[package]] +name = "ryu" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "semver" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" + +[[package]] +name = "serde" +version = "1.0.203" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7253ab4de971e72fb7be983802300c30b5a7f0c2e56fab8abfc6a214307c0094" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.203" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "500cbc0ebeb6f46627f50f3f5811ccf6bf00643be300b4c3eabc0ef55dc5b5ba" +dependencies = [ + "proc-macro2 1.0.86", + "quote 1.0.36", + "syn 2.0.67", +] + +[[package]] +name = "serde_json" +version = "1.0.117" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "455182ea6142b14f93f4bc5320a2b31c1f266b66a4a5c858b013302a5d8cbfc3" +dependencies = [ + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "sha1_smol" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae1a47186c03a32177042e55dbc5fd5aee900b8e0069a8d70fba96a9375cd012" + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "signal-hook-registry" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" +dependencies = [ + "libc", +] + +[[package]] +name = "simd-json" +version = "0.13.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "570c430b3d902ea083097e853263ae782dfe40857d93db019a12356c8e8143fa" +dependencies = [ + "getrandom", + "halfbrown", + "lexical-core", + "ref-cast", + "serde", + "serde_json", + "simdutf8", + "value-trait", +] + +[[package]] +name = "simdutf8" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f27f6278552951f1f2b8cf9da965d10969b2efdea95a6ec47987ab46edfe263a" + +[[package]] +name = "siphasher" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" + +[[package]] +name = "slab" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +dependencies = [ + "autocfg", +] + +[[package]] +name = "smallvec" +version = "1.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" + +[[package]] +name = "socket2" +version = "0.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "spin" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" + +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + +[[package]] +name = "subtle" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d0208408ba0c3df17ed26eb06992cb1a1268d41b2c0e12e65203fbe3972cee5" + +[[package]] +name = "syn" +version = "0.15.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ca4b3b69a77cbe1ffc9e198781b7acb0c7365a883670e8f1c1bc66fba79a5c5" +dependencies = [ + "proc-macro2 0.4.30", + "quote 0.6.13", + "unicode-xid", +] + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2 1.0.86", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.67" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff8655ed1d86f3af4ee3fd3263786bc14245ad17c4c7e85ba7187fb3ae028c90" +dependencies = [ + "proc-macro2 1.0.86", + "quote 1.0.36", + "unicode-ident", +] + +[[package]] +name = "tokio" +version = "1.38.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba4f4a02a7a80d6f274636f0aa95c7e383b912d41fe721a31f29e29698585a4a" +dependencies = [ + "backtrace", + "bytes", + "libc", + "mio", + "num_cpus", + "parking_lot", + "pin-project-lite", + "signal-hook-registry", + "socket2", + "tokio-macros", + "windows-sys 0.48.0", +] + +[[package]] +name = "tokio-macros" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f5ae998a069d4b5aba8ee9dad856af7d520c3699e6159b185c2acd48155d39a" +dependencies = [ + "proc-macro2 1.0.86", + "quote 1.0.36", + "syn 2.0.67", +] + +[[package]] +name = "tokio-rustls" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4" +dependencies = [ + "rustls", + "rustls-pki-types", + "tokio", +] + +[[package]] +name = "tokio-util" +version = "0.7.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9cf6b47b3771c49ac75ad09a6162f53ad4b8088b76ac60e8ec1455b31a189fe1" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "toml_datetime" +version = "0.6.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4badfd56924ae69bcc9039335b2e017639ce3f9b001c393c1b2d1ef846ce2cbf" + +[[package]] +name = "toml_edit" +version = "0.19.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" +dependencies = [ + "indexmap", + "toml_datetime", + "winnow", +] + +[[package]] +name = "tower" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" +dependencies = [ + "futures-core", + "futures-util", + "pin-project", + "pin-project-lite", + "tokio", + "tower-layer", + "tower-service", +] + +[[package]] +name = "tower-layer" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0" + +[[package]] +name = "tower-service" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" + +[[package]] +name = "tracing" +version = "0.1.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" +dependencies = [ + "pin-project-lite", + "tracing-core", +] + +[[package]] +name = "tracing-core" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" +dependencies = [ + "once_cell", +] + +[[package]] +name = "try-lock" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" + +[[package]] +name = "typenum" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + +[[package]] +name = "unicode-segmentation" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202" + +[[package]] +name = "unicode-xid" version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" + +[[package]] +name = "untrusted" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" + +[[package]] +name = "utf8parse" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" + +[[package]] +name = "uuid" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a183cf7feeba97b4dd1c0d46788634f6221d87fa961b305bed08c851829efcc0" +dependencies = [ + "atomic", + "getrandom", + "md-5", + "rand", + "sha1_smol", +] + +[[package]] +name = "uuid-simd" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23b082222b4f6619906941c17eb2297fff4c2fb96cb60164170522942a200bd8" +dependencies = [ + "outref", + "uuid", + "vsimd", +] + +[[package]] +name = "value-trait" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dad8db98c1e677797df21ba03fca7d3bf9bec3ca38db930954e4fe6e1ea27eb4" +dependencies = [ + "float-cmp", + "halfbrown", + "itoa", + "ryu", +] + +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + +[[package]] +name = "vsimd" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c3082ca00d5a5ef149bb8b555a72ae84c9c59f7250f013ac822ac2e49b19c64" + +[[package]] +name = "want" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" +dependencies = [ + "try-lock", +] + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "wasm-bindgen" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" +dependencies = [ + "cfg-if", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2 1.0.86", + "quote 1.0.36", + "syn 2.0.67", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726" +dependencies = [ + "quote 1.0.36", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" +dependencies = [ + "proc-macro2 1.0.86", + "quote 1.0.36", + "syn 2.0.67", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" + +[[package]] +name = "webpki-roots" +version = "0.26.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd7c23921eeb1713a4e851530e9b9756e4fb0e89978582942612524cf09f01cd" +dependencies = [ + "rustls-pki-types", +] + +[[package]] +name = "which" +version = "4.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87ba24419a2078cd2b0f2ede2691b6c66d8e47836da3b6db8265ebad47afbfc7" +dependencies = [ + "either", + "home", + "once_cell", + "rustix", +] + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows-core" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" +dependencies = [ + "windows-targets 0.52.5", +] + +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets 0.48.5", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.5", +] + +[[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", +] + +[[package]] +name = "windows-targets" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb" +dependencies = [ + "windows_aarch64_gnullvm 0.52.5", + "windows_aarch64_msvc 0.52.5", + "windows_i686_gnu 0.52.5", + "windows_i686_gnullvm", + "windows_i686_msvc 0.52.5", + "windows_x86_64_gnu 0.52.5", + "windows_x86_64_gnullvm 0.52.5", + "windows_x86_64_msvc 0.52.5", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6" + +[[package]] +name = "windows_i686_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9" + +[[package]] +name = "windows_i686_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" + +[[package]] +name = "winnow" +version = "0.5.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f593a95398737aeed53e489c785df13f3618e41dbcd6718c6addbf1395aa6876" +dependencies = [ + "memchr", +] + +[[package]] +name = "zerocopy" +version = "0.7.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae87e3fcd617500e5d106f0380cf7b77f3c6092aae37191433159dda23cfb087" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15e934569e47891f7d9411f1a451d947a60e000ab3bd24fbb970f000387d1b3b" +dependencies = [ + "proc-macro2 1.0.86", + "quote 1.0.36", + "syn 2.0.67", +] + +[[package]] +name = "zeroize" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" diff --git a/Cargo.toml b/Cargo.toml index cc5f735..bc3263a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,8 +1,21 @@ -[package] -name = "rqjs" -version = "0.1.0" -edition = "2021" -description = "rqjs" -license = "MIT" +[workspace] +members = ["rqjs-cli", "rqjs-ext"] +resolver = "2" -[dependencies] +# Config for 'cargo dist' +[workspace.metadata.dist] +# The preferred cargo-dist version to use in CI (Cargo.toml SemVer syntax) +cargo-dist-version = "0.15.1" +# CI backends to support +ci = "github" +# The installers to generate for each app +installers = [] +# Target platforms to build apps for (Rust target-triple syntax) +targets = ["aarch64-apple-darwin", "x86_64-apple-darwin", "x86_64-unknown-linux-musl", "x86_64-pc-windows-msvc"] +# Publish jobs to run in CI +pr-run-mode = "plan" + +# The profile that 'cargo dist' will build with +[profile.dist] +inherits = "release" +lto = "thin" diff --git a/rqjs-cli/Cargo.lock b/rqjs-cli/Cargo.lock new file mode 100644 index 0000000..a5050e0 --- /dev/null +++ b/rqjs-cli/Cargo.lock @@ -0,0 +1,2156 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "addr2line" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e4503c46a5c0c7844e948c9a4d6acd9f50cccb4de1c48eb9e291ea17470c678" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + +[[package]] +name = "ahash" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" +dependencies = [ + "cfg-if", + "once_cell", + "version_check", + "zerocopy", +] + +[[package]] +name = "aho-corasick" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +dependencies = [ + "memchr", +] + +[[package]] +name = "allocator-api2" +version = "0.2.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f" + +[[package]] +name = "android-tzdata" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" + +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + +[[package]] +name = "anstream" +version = "0.6.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "418c75fa768af9c03be99d17643f93f79bbba589895012a80e3452a19ddda15b" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "038dfcf04a5feb68e9c60b21c9625a54c2c0616e79b72b0fd87075a056ae1d1b" + +[[package]] +name = "anstyle-parse" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c03a11a9034d92058ceb6ee011ce58af4a9bf61491aa7e1e59ecd24bd40d22d4" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad186efb764318d35165f1758e7dcef3b10628e26d41a44bc5550652e6804391" +dependencies = [ + "windows-sys 0.52.0", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61a38449feb7068f52bb06c12759005cf459ee52bb4adc1d5a7c4322d716fb19" +dependencies = [ + "anstyle", + "windows-sys 0.52.0", +] + +[[package]] +name = "async-lock" +version = "3.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff6e472cdea888a4bd64f342f09b3f50e1886d32afe8df3d663c01140b811b18" +dependencies = [ + "event-listener", + "event-listener-strategy", + "pin-project-lite", +] + +[[package]] +name = "atomic" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c59bdb34bc650a32731b31bd8f0829cc15d24a708ee31559e0bb34f2bc320cba" + +[[package]] +name = "atomic-waker" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" + +[[package]] +name = "autocfg" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" + +[[package]] +name = "backtrace" +version = "0.3.73" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5cc23269a4f8976d0a4d2e7109211a419fe30e8d88d677cd60b6bc79c5732e0a" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", +] + +[[package]] +name = "base64-simd" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "339abbe78e73178762e23bea9dfd08e697eb3f3301cd4be981c0f78ba5859195" +dependencies = [ + "outref", + "vsimd", +] + +[[package]] +name = "bindgen" +version = "0.69.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a00dc851838a2120612785d195287475a3ac45514741da670b735818822129a0" +dependencies = [ + "bitflags", + "cexpr", + "clang-sys", + "itertools", + "lazy_static", + "lazycell", + "log", + "prettyplease", + "proc-macro2 1.0.86", + "quote 1.0.36", + "regex", + "rustc-hash", + "shlex", + "syn 2.0.67", + "which", +] + +[[package]] +name = "bitflags" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[package]] +name = "bumpalo" +version = "3.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "bytes" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" + +[[package]] +name = "cc" +version = "1.0.99" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96c51067fd44124faa7f870b4b1c969379ad32b2ba805aa959430ceaa384f695" + +[[package]] +name = "cexpr" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" +dependencies = [ + "nom", +] + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "cfg_aliases" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e" + +[[package]] +name = "chrono" +version = "0.4.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401" +dependencies = [ + "android-tzdata", + "iana-time-zone", + "js-sys", + "num-traits", + "wasm-bindgen", + "windows-targets 0.52.5", +] + +[[package]] +name = "clang-sys" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4" +dependencies = [ + "glob", + "libc", + "libloading", +] + +[[package]] +name = "clap" +version = "4.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5db83dced34638ad474f39f250d7fea9598bdd239eaced1bdf45d597da0f433f" +dependencies = [ + "clap_builder", + "clap_derive", +] + +[[package]] +name = "clap_builder" +version = "4.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7e204572485eb3fbf28f871612191521df159bc3e15a9f5064c66dba3a8c05f" +dependencies = [ + "anstream", + "anstyle", + "clap_lex", + "strsim", +] + +[[package]] +name = "clap_derive" +version = "4.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c780290ccf4fb26629baa7a1081e68ced113f1d3ec302fa5948f1c381ebf06c6" +dependencies = [ + "heck", + "proc-macro2 1.0.86", + "quote 1.0.36", + "syn 2.0.67", +] + +[[package]] +name = "clap_lex" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b82cf0babdbd58558212896d1a4272303a57bdb245c2bf1147185fb45640e70" + +[[package]] +name = "colorchoice" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b6a852b24ab71dffc585bcb46eaf7959d175cb865a7152e35b348d1b2960422" + +[[package]] +name = "concurrent-queue" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "convert_case" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec182b0ca2f35d8fc196cf3404988fd8b8c739a4d270ff118a398feb0cbec1ca" +dependencies = [ + "unicode-segmentation", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" + +[[package]] +name = "crc32c" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a47af21622d091a8f0fb295b88bc886ac74efcc613efc19f5d0b21de5c89e47" +dependencies = [ + "rustc_version", +] + +[[package]] +name = "crc32fast" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "cross-uname" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff7bb10673cca006046a1ec932de4637ab04fc224cae6f83134bce596f5d1389" + +[[package]] +name = "crossbeam-utils" +version = "0.8.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "ctrlc" +version = "3.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "672465ae37dc1bc6380a6547a8883d5dd397b0f1faaad4f265726cc7042a5345" +dependencies = [ + "nix", + "windows-sys 0.52.0", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "crypto-common", +] + +[[package]] +name = "dlopen" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71e80ad39f814a9abe68583cd50a2d45c8a67561c3361ab8da240587dda80937" +dependencies = [ + "dlopen_derive", + "lazy_static", + "libc", + "winapi", +] + +[[package]] +name = "dlopen_derive" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f236d9e1b1fbd81cea0f9cbdc8dcc7e8ebcd80e6659cd7cb2ad5f6c05946c581" +dependencies = [ + "libc", + "quote 0.6.13", + "syn 0.15.44", +] + +[[package]] +name = "either" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3dca9240753cf90908d7e4aac30f630662b02aebaa1b58a3cadabdb23385b58b" + +[[package]] +name = "encoding_rs" +version = "0.8.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b45de904aa0b010bce2ab45264d0631681847fa7b6f2eaa7dab7619943bc4f59" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + +[[package]] +name = "errno" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "event-listener" +version = "5.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6032be9bd27023a771701cc49f9f053c751055f71efb2e0ae5c15809093675ba" +dependencies = [ + "concurrent-queue", + "parking", + "pin-project-lite", +] + +[[package]] +name = "event-listener-strategy" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f214dc438f977e6d4e3500aaa277f5ad94ca83fbbd9b1a15713ce2344ccc5a1" +dependencies = [ + "event-listener", + "pin-project-lite", +] + +[[package]] +name = "float-cmp" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98de4bbd547a563b716d8dfa9aad1cb19bfab00f4fa09a6a4ed21dbcf44ce9c4" +dependencies = [ + "num-traits", +] + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "futures-channel" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" +dependencies = [ + "futures-core", +] + +[[package]] +name = "futures-core" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" + +[[package]] +name = "futures-sink" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" + +[[package]] +name = "futures-task" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" + +[[package]] +name = "futures-util" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" +dependencies = [ + "futures-core", + "futures-task", + "pin-project-lite", + "pin-utils", +] + +[[package]] +name = "fxhash" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c" +dependencies = [ + "byteorder", +] + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] +name = "getrandom" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" +dependencies = [ + "cfg-if", + "js-sys", + "libc", + "wasi", + "wasm-bindgen", +] + +[[package]] +name = "gimli" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd" + +[[package]] +name = "glob" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" + +[[package]] +name = "h2" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa82e28a107a8cc405f0839610bdc9b15f1e25ec7d696aa5cf173edbcb1486ab" +dependencies = [ + "atomic-waker", + "bytes", + "fnv", + "futures-core", + "futures-sink", + "http", + "indexmap", + "slab", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "halfbrown" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8588661a8607108a5ca69cab034063441a0413a0b041c13618a7dd348021ef6f" +dependencies = [ + "hashbrown", + "serde", +] + +[[package]] +name = "hashbrown" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" +dependencies = [ + "ahash", + "allocator-api2", +] + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "hermit-abi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" + +[[package]] +name = "hex-simd" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f7685beb53fc20efc2605f32f5d51e9ba18b8ef237961d1760169d2290d3bee" +dependencies = [ + "outref", + "vsimd", +] + +[[package]] +name = "home" +version = "0.5.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5" +dependencies = [ + "windows-sys 0.52.0", +] + +[[package]] +name = "http" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "http-body" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cac85db508abc24a2e48553ba12a996e87244a0395ce011e62b37158745d643" +dependencies = [ + "bytes", + "http", +] + +[[package]] +name = "httparse" +version = "1.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fcc0b4a115bf80b728eb8ea024ad5bd707b615bfed49e0665b6e0f86fd082d9" + +[[package]] +name = "hyper" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe575dd17d0862a9a33781c8c4696a55c320909004a67a00fb286ba8b1bc496d" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "h2", + "http", + "http-body", + "httparse", + "itoa", + "pin-project-lite", + "smallvec", + "tokio", + "want", +] + +[[package]] +name = "hyper-rustls" +version = "0.27.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ee4be2c948921a1a5320b629c4193916ed787a7f7f293fd3f7f5a6c9de74155" +dependencies = [ + "futures-util", + "http", + "hyper", + "hyper-util", + "rustls", + "rustls-pki-types", + "tokio", + "tokio-rustls", + "tower-service", + "webpki-roots", +] + +[[package]] +name = "hyper-util" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b875924a60b96e5d7b9ae7b066540b1dd1cbd90d1828f54c92e02a283351c56" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "http", + "http-body", + "hyper", + "pin-project-lite", + "socket2", + "tokio", + "tower", + "tower-service", + "tracing", +] + +[[package]] +name = "iana-time-zone" +version = "0.1.60" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "wasm-bindgen", + "windows-core", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" +dependencies = [ + "cc", +] + +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + +[[package]] +name = "indexmap" +version = "2.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" +dependencies = [ + "equivalent", + "hashbrown", +] + +[[package]] +name = "is_terminal_polyfill" +version = "1.70.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8478577c03552c21db0e2724ffb8986a5ce7af88107e6be5d2ee6e158c12800" + +[[package]] +name = "itertools" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" + +[[package]] +name = "js-sys" +version = "0.3.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d" +dependencies = [ + "wasm-bindgen", +] + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "lazycell" +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.155" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" + +[[package]] +name = "libloading" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c2a198fb6b0eada2a8df47933734e6d35d350665a33a3593d7164fa52c75c19" +dependencies = [ + "cfg-if", + "windows-targets 0.52.5", +] + +[[package]] +name = "linux-raw-sys" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" + +[[package]] +name = "lock_api" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" +dependencies = [ + "autocfg", + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" + +[[package]] +name = "md-5" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d89e7ee0cfbedfc4da3340218492196241d89eefb6dab27de5df917a6d2e78cf" +dependencies = [ + "cfg-if", + "digest", +] + +[[package]] +name = "memchr" +version = "2.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" + +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + +[[package]] +name = "miniz_oxide" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08" +dependencies = [ + "adler", +] + +[[package]] +name = "mio" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" +dependencies = [ + "libc", + "wasi", + "windows-sys 0.48.0", +] + +[[package]] +name = "nix" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab2156c4fce2f8df6c499cc1c763e4394b7482525bf2a9701c9d79d215f519e4" +dependencies = [ + "bitflags", + "cfg-if", + "cfg_aliases", + "libc", +] + +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + +[[package]] +name = "num_cpus" +version = "1.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" +dependencies = [ + "hermit-abi", + "libc", +] + +[[package]] +name = "object" +version = "0.36.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "576dfe1fc8f9df304abb159d767a29d0476f7750fbf8aa7ad07816004a207434" +dependencies = [ + "memchr", +] + +[[package]] +name = "once_cell" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" + +[[package]] +name = "outref" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4030760ffd992bef45b0ae3f10ce1aba99e33464c90d14dd7c039884963ddc7a" + +[[package]] +name = "parking" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb813b8af86854136c6922af0598d719255ecb2179515e6e7730d468f05c9cae" + +[[package]] +name = "parking_lot" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-targets 0.52.5", +] + +[[package]] +name = "phf" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc" +dependencies = [ + "phf_shared", +] + +[[package]] +name = "phf_generator" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48e4cc64c2ad9ebe670cb8fd69dd50ae301650392e81c05f9bfcb2d5bdbc24b0" +dependencies = [ + "phf_shared", + "rand", +] + +[[package]] +name = "phf_shared" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90fcb95eef784c2ac79119d1dd819e162b5da872ce6f3c3abe1e8ca1c082f72b" +dependencies = [ + "siphasher", +] + +[[package]] +name = "pin-project" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6bf43b791c5b9e34c3d182969b4abb522f9343702850a2e57f460d00d09b4b3" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" +dependencies = [ + "proc-macro2 1.0.86", + "quote 1.0.36", + "syn 2.0.67", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "ppv-lite86" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" + +[[package]] +name = "prettyplease" +version = "0.2.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f12335488a2f3b0a83b14edad48dca9879ce89b2edd10e80237e4e852dd645e" +dependencies = [ + "proc-macro2 1.0.86", + "syn 2.0.67", +] + +[[package]] +name = "proc-macro-crate" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919" +dependencies = [ + "once_cell", + "toml_edit", +] + +[[package]] +name = "proc-macro-error" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" +dependencies = [ + "proc-macro-error-attr", + "proc-macro2 1.0.86", + "quote 1.0.36", + "syn 1.0.109", + "version_check", +] + +[[package]] +name = "proc-macro-error-attr" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" +dependencies = [ + "proc-macro2 1.0.86", + "quote 1.0.36", + "version_check", +] + +[[package]] +name = "proc-macro2" +version = "0.4.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759" +dependencies = [ + "unicode-xid", +] + +[[package]] +name = "proc-macro2" +version = "1.0.86" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quick-xml" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d3a6e5838b60e0e8fa7a43f22ade549a37d61f8bdbe636d0d7816191de969c2" +dependencies = [ + "memchr", +] + +[[package]] +name = "quote" +version = "0.6.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1" +dependencies = [ + "proc-macro2 0.4.30", +] + +[[package]] +name = "quote" +version = "1.0.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" +dependencies = [ + "proc-macro2 1.0.86", +] + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + +[[package]] +name = "redox_syscall" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c82cf8cff14456045f55ec4241383baeff27af886adb72ffb2162f99911de0fd" +dependencies = [ + "bitflags", +] + +[[package]] +name = "ref-cast" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccf0a6f84d5f1d581da8b41b47ec8600871962f2a528115b542b362d4b744931" +dependencies = [ + "ref-cast-impl", +] + +[[package]] +name = "ref-cast-impl" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bcc303e793d3734489387d205e9b186fac9c6cfacedd98cbb2e8a5943595f3e6" +dependencies = [ + "proc-macro2 1.0.86", + "quote 1.0.36", + "syn 2.0.67", +] + +[[package]] +name = "regex" +version = "1.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b91213439dad192326a0d7c6ee3955910425f441d7038e0d6933b0aec5c4517f" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" + +[[package]] +name = "relative-path" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba39f3699c378cd8970968dcbff9c43159ea4cfbd88d43c00b22f2ef10a435d2" + +[[package]] +name = "ring" +version = "0.17.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" +dependencies = [ + "cc", + "cfg-if", + "getrandom", + "libc", + "spin", + "untrusted", + "windows-sys 0.52.0", +] + +[[package]] +name = "rqjs-cli" +version = "0.1.2" +dependencies = [ + "clap", + "ctrlc", + "rqjs-ext", + "rquickjs", + "tokio", +] + +[[package]] +name = "rqjs-ext" +version = "0.1.2" +dependencies = [ + "base64-simd", + "chrono", + "clap", + "crc32c", + "crc32fast", + "cross-uname", + "ctrlc", + "encoding_rs", + "fxhash", + "hex-simd", + "hyper", + "hyper-rustls", + "itoa", + "md-5", + "once_cell", + "phf", + "quick-xml", + "rand", + "ring", + "rquickjs", + "rustls", + "ryu", + "simd-json", + "tokio", + "uuid", + "uuid-simd", +] + +[[package]] +name = "rquickjs" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9cbd33e0b668aea0ab238b9164523aca929096f9f40834700d71d91dd4888882" +dependencies = [ + "either", + "indexmap", + "rquickjs-core", + "rquickjs-macro", +] + +[[package]] +name = "rquickjs-core" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e9129d69b7b8f7ee8ad1da5b12c7f4a8a8acd45f2e6dd9cb2ee1bc5a1f2fa3d" +dependencies = [ + "async-lock", + "chrono", + "dlopen", + "either", + "indexmap", + "phf", + "relative-path", + "rquickjs-sys", +] + +[[package]] +name = "rquickjs-macro" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7d2ecaf7c9eda262e02a91e9541989a9dd18984d17d0d97f99f33b464318057" +dependencies = [ + "convert_case", + "fnv", + "ident_case", + "indexmap", + "phf_generator", + "phf_shared", + "proc-macro-crate", + "proc-macro-error", + "proc-macro2 1.0.86", + "quote 1.0.36", + "rquickjs-core", + "syn 2.0.67", +] + +[[package]] +name = "rquickjs-sys" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf6f2288d8e7fbb5130f62cf720451641e99d55f6fde9db86aa2914ecb553fd2" +dependencies = [ + "bindgen", + "cc", +] + +[[package]] +name = "rustc-demangle" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" + +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + +[[package]] +name = "rustc_version" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +dependencies = [ + "semver", +] + +[[package]] +name = "rustix" +version = "0.38.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" +dependencies = [ + "bitflags", + "errno", + "libc", + "linux-raw-sys", + "windows-sys 0.52.0", +] + +[[package]] +name = "rustls" +version = "0.23.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05cff451f60db80f490f3c182b77c35260baace73209e9cdbbe526bfe3a4d402" +dependencies = [ + "once_cell", + "ring", + "rustls-pki-types", + "rustls-webpki", + "subtle", + "zeroize", +] + +[[package]] +name = "rustls-pki-types" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "976295e77ce332211c0d24d92c0e83e50f5c5f046d11082cea19f3df13a3562d" + +[[package]] +name = "rustls-webpki" +version = "0.102.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff448f7e92e913c4b7d4c6d8e4540a1724b319b4152b8aef6d4cf8339712b33e" +dependencies = [ + "ring", + "rustls-pki-types", + "untrusted", +] + +[[package]] +name = "ryu" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "semver" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" + +[[package]] +name = "serde" +version = "1.0.203" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7253ab4de971e72fb7be983802300c30b5a7f0c2e56fab8abfc6a214307c0094" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.203" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "500cbc0ebeb6f46627f50f3f5811ccf6bf00643be300b4c3eabc0ef55dc5b5ba" +dependencies = [ + "proc-macro2 1.0.86", + "quote 1.0.36", + "syn 2.0.67", +] + +[[package]] +name = "serde_json" +version = "1.0.117" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "455182ea6142b14f93f4bc5320a2b31c1f266b66a4a5c858b013302a5d8cbfc3" +dependencies = [ + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "sha1_smol" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae1a47186c03a32177042e55dbc5fd5aee900b8e0069a8d70fba96a9375cd012" + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "signal-hook-registry" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" +dependencies = [ + "libc", +] + +[[package]] +name = "simd-json" +version = "0.13.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "570c430b3d902ea083097e853263ae782dfe40857d93db019a12356c8e8143fa" +dependencies = [ + "getrandom", + "halfbrown", + "lexical-core", + "ref-cast", + "serde", + "serde_json", + "simdutf8", + "value-trait", +] + +[[package]] +name = "simdutf8" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f27f6278552951f1f2b8cf9da965d10969b2efdea95a6ec47987ab46edfe263a" + +[[package]] +name = "siphasher" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" + +[[package]] +name = "slab" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +dependencies = [ + "autocfg", +] + +[[package]] +name = "smallvec" +version = "1.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" + +[[package]] +name = "socket2" +version = "0.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "spin" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" + +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + +[[package]] +name = "subtle" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d0208408ba0c3df17ed26eb06992cb1a1268d41b2c0e12e65203fbe3972cee5" + +[[package]] +name = "syn" +version = "0.15.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ca4b3b69a77cbe1ffc9e198781b7acb0c7365a883670e8f1c1bc66fba79a5c5" +dependencies = [ + "proc-macro2 0.4.30", + "quote 0.6.13", + "unicode-xid", +] + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2 1.0.86", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.67" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff8655ed1d86f3af4ee3fd3263786bc14245ad17c4c7e85ba7187fb3ae028c90" +dependencies = [ + "proc-macro2 1.0.86", + "quote 1.0.36", + "unicode-ident", +] + +[[package]] +name = "tokio" +version = "1.38.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba4f4a02a7a80d6f274636f0aa95c7e383b912d41fe721a31f29e29698585a4a" +dependencies = [ + "backtrace", + "bytes", + "libc", + "mio", + "num_cpus", + "parking_lot", + "pin-project-lite", + "signal-hook-registry", + "socket2", + "tokio-macros", + "windows-sys 0.48.0", +] + +[[package]] +name = "tokio-macros" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f5ae998a069d4b5aba8ee9dad856af7d520c3699e6159b185c2acd48155d39a" +dependencies = [ + "proc-macro2 1.0.86", + "quote 1.0.36", + "syn 2.0.67", +] + +[[package]] +name = "tokio-rustls" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4" +dependencies = [ + "rustls", + "rustls-pki-types", + "tokio", +] + +[[package]] +name = "tokio-util" +version = "0.7.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9cf6b47b3771c49ac75ad09a6162f53ad4b8088b76ac60e8ec1455b31a189fe1" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "toml_datetime" +version = "0.6.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4badfd56924ae69bcc9039335b2e017639ce3f9b001c393c1b2d1ef846ce2cbf" + +[[package]] +name = "toml_edit" +version = "0.19.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" +dependencies = [ + "indexmap", + "toml_datetime", + "winnow", +] + +[[package]] +name = "tower" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" +dependencies = [ + "futures-core", + "futures-util", + "pin-project", + "pin-project-lite", + "tokio", + "tower-layer", + "tower-service", +] + +[[package]] +name = "tower-layer" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0" + +[[package]] +name = "tower-service" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" + +[[package]] +name = "tracing" +version = "0.1.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" +dependencies = [ + "pin-project-lite", + "tracing-core", +] + +[[package]] +name = "tracing-core" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" +dependencies = [ + "once_cell", +] + +[[package]] +name = "try-lock" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" + +[[package]] +name = "typenum" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + +[[package]] +name = "unicode-segmentation" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202" + +[[package]] +name = "unicode-xid" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" + +[[package]] +name = "untrusted" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" + +[[package]] +name = "utf8parse" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" + +[[package]] +name = "uuid" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a183cf7feeba97b4dd1c0d46788634f6221d87fa961b305bed08c851829efcc0" +dependencies = [ + "atomic", + "getrandom", + "md-5", + "rand", + "sha1_smol", +] + +[[package]] +name = "uuid-simd" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23b082222b4f6619906941c17eb2297fff4c2fb96cb60164170522942a200bd8" +dependencies = [ + "outref", + "uuid", + "vsimd", +] + +[[package]] +name = "value-trait" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dad8db98c1e677797df21ba03fca7d3bf9bec3ca38db930954e4fe6e1ea27eb4" +dependencies = [ + "float-cmp", + "halfbrown", + "itoa", + "ryu", +] + +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + +[[package]] +name = "vsimd" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c3082ca00d5a5ef149bb8b555a72ae84c9c59f7250f013ac822ac2e49b19c64" + +[[package]] +name = "want" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" +dependencies = [ + "try-lock", +] + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "wasm-bindgen" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" +dependencies = [ + "cfg-if", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2 1.0.86", + "quote 1.0.36", + "syn 2.0.67", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726" +dependencies = [ + "quote 1.0.36", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" +dependencies = [ + "proc-macro2 1.0.86", + "quote 1.0.36", + "syn 2.0.67", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" + +[[package]] +name = "webpki-roots" +version = "0.26.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd7c23921eeb1713a4e851530e9b9756e4fb0e89978582942612524cf09f01cd" +dependencies = [ + "rustls-pki-types", +] + +[[package]] +name = "which" +version = "4.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87ba24419a2078cd2b0f2ede2691b6c66d8e47836da3b6db8265ebad47afbfc7" +dependencies = [ + "either", + "home", + "once_cell", + "rustix", +] + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows-core" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" +dependencies = [ + "windows-targets 0.52.5", +] + +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets 0.48.5", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.5", +] + +[[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", +] + +[[package]] +name = "windows-targets" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb" +dependencies = [ + "windows_aarch64_gnullvm 0.52.5", + "windows_aarch64_msvc 0.52.5", + "windows_i686_gnu 0.52.5", + "windows_i686_gnullvm", + "windows_i686_msvc 0.52.5", + "windows_x86_64_gnu 0.52.5", + "windows_x86_64_gnullvm 0.52.5", + "windows_x86_64_msvc 0.52.5", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6" + +[[package]] +name = "windows_i686_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9" + +[[package]] +name = "windows_i686_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" + +[[package]] +name = "winnow" +version = "0.5.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f593a95398737aeed53e489c785df13f3618e41dbcd6718c6addbf1395aa6876" +dependencies = [ + "memchr", +] + +[[package]] +name = "zerocopy" +version = "0.7.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae87e3fcd617500e5d106f0380cf7b77f3c6092aae37191433159dda23cfb087" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15e934569e47891f7d9411f1a451d947a60e000ab3bd24fbb970f000387d1b3b" +dependencies = [ + "proc-macro2 1.0.86", + "quote 1.0.36", + "syn 2.0.67", +] + +[[package]] +name = "zeroize" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" diff --git a/rqjs-cli/Cargo.toml b/rqjs-cli/Cargo.toml new file mode 100644 index 0000000..c21c32d --- /dev/null +++ b/rqjs-cli/Cargo.toml @@ -0,0 +1,17 @@ +[package] +name = "rqjs-cli" +version = "0.1.3" +edition = "2021" +license = "MIT" +description = "rqjs-cli" +authors = ["ahaoboy"] +repository = "https://github.com/ahaoboy/rqjs" +homepage = "https://github.com/ahaoboy/rqjs" + + +[dependencies] +clap = { version = "4", features = ["derive"] } +rquickjs = { version = "0.6.2", features = ["full-async", "bindgen"] } +ctrlc = "3.4.4" +tokio = { version = "1", features = ["full"] } +rqjs-ext = { version = "0.1.3", path = "../rqjs-ext" } \ No newline at end of file diff --git a/rqjs-cli/js/buffer.js b/rqjs-cli/js/buffer.js new file mode 100644 index 0000000..9652cef --- /dev/null +++ b/rqjs-cli/js/buffer.js @@ -0,0 +1,8 @@ +import { Buffer } from 'buffer' + +const buf = Buffer.from("hello") +console.log(buf) +const base64 = buf.toString('base64') +console.log(base64) +const s = Buffer.from(base64, 'base64').toString() +console.log(s) diff --git a/rqjs-cli/js/encoding.js b/rqjs-cli/js/encoding.js new file mode 100644 index 0000000..a679e2e --- /dev/null +++ b/rqjs-cli/js/encoding.js @@ -0,0 +1,4 @@ +const base64 = btoa("hello") +console.log(base64) +const s = atob(base64) +console.log(s) \ No newline at end of file diff --git a/rqjs-cli/js/exception.js b/rqjs-cli/js/exception.js new file mode 100644 index 0000000..38811fd --- /dev/null +++ b/rqjs-cli/js/exception.js @@ -0,0 +1 @@ +console.log(DOMException) diff --git a/rqjs-cli/js/fs.js b/rqjs-cli/js/fs.js new file mode 100644 index 0000000..c4f974a --- /dev/null +++ b/rqjs-cli/js/fs.js @@ -0,0 +1,27 @@ +import * as fs from 'fs' +import * as fsp from 'fs/promises' +console.log(Object.keys(fs)) +console.log(Object.keys(fsp)) + +const txt = fs.readFileSync("./Cargo.toml", 'utf8') +console.log(txt.length) +const p = fsp.readFile("./Cargo.toml", 'utf8') +console.log(typeof p) + +// TODO: fix bug +// console.log(Promise.resolve(1), Promise) +console.log(p instanceof Promise) +// console.log(Object.keys(Promise)) + +p.then(textPromise => { + console.log(text === textPromise) +}) +console.log("end") + +Promise.resolve(1).then(i => console.log(i)) + +// import * as fs from 'fs/promises' +// const p = fs.readFile("./Cargo.toml") +// console.log(p instanceof Promise) + +// p.then((t) => console.log(t.toString())) \ No newline at end of file diff --git a/rqjs-cli/js/hello.js b/rqjs-cli/js/hello.js new file mode 100644 index 0000000..5be36cc --- /dev/null +++ b/rqjs-cli/js/hello.js @@ -0,0 +1 @@ +console.log("hello") \ No newline at end of file diff --git a/rqjs-cli/js/os.js b/rqjs-cli/js/os.js new file mode 100644 index 0000000..4cbb96e --- /dev/null +++ b/rqjs-cli/js/os.js @@ -0,0 +1,2 @@ +import os from 'os' +console.log(os.platform()) \ No newline at end of file diff --git a/rqjs-cli/js/promise.js b/rqjs-cli/js/promise.js new file mode 100644 index 0000000..03692cf --- /dev/null +++ b/rqjs-cli/js/promise.js @@ -0,0 +1,4 @@ +console.log(Promise.resolve) +Promise.resolve().then(() => { + console.log(1) +}) \ No newline at end of file diff --git a/rqjs-cli/js/util.js b/rqjs-cli/js/util.js new file mode 100644 index 0000000..0268f7f --- /dev/null +++ b/rqjs-cli/js/util.js @@ -0,0 +1,6 @@ +import { TextEncoder, TextDecoder } from 'util' + +const buf = new TextEncoder().encode("hello") +console.log(buf) +const s = new TextDecoder().decode(buf) +console.log(s) \ No newline at end of file diff --git a/rqjs-cli/js/uuid.js b/rqjs-cli/js/uuid.js new file mode 100644 index 0000000..a85d67c --- /dev/null +++ b/rqjs-cli/js/uuid.js @@ -0,0 +1,4 @@ +import * as uid from 'uuid' + +console.log(Object.keys(uid)) +console.log(uid.version('6ec0bd7f-11c0-43da-975e-2a8ad9ebae0b')) \ No newline at end of file diff --git a/rqjs-cli/js/xml.js b/rqjs-cli/js/xml.js new file mode 100644 index 0000000..8423dba --- /dev/null +++ b/rqjs-cli/js/xml.js @@ -0,0 +1,7 @@ +import * as xml from 'xml' + +console.log(Object.keys(xml)) + +// import * as t from 'test' + +// console.log(Object.keys(t)) \ No newline at end of file diff --git a/rqjs-cli/package.json b/rqjs-cli/package.json new file mode 100644 index 0000000..e88d21c --- /dev/null +++ b/rqjs-cli/package.json @@ -0,0 +1,21 @@ +{ + "name": "rqjs-cli", + "private": true, + "version": "0.0.0", + "description": "rqjs-cli", + "type": "module", + "main": "index.js", + "scripts": { + "build:console": "esbuild ./deno-scripts/00_core.ts --bundle --format=iife --outdir=./deno-scripts", + "test": "echo \"Error: no test specified\" && exit 1" + }, + "keywords": [], + "author": "", + "license": "ISC", + "devDependencies": { + "@inquirer/prompts": "^5.0.6", + "@types/node": "^20.14.5", + "deno-console": "^0.1.3", + "esbuild": "^0.21.5" + } +} \ No newline at end of file diff --git a/rqjs-cli/pnpm-lock.yaml b/rqjs-cli/pnpm-lock.yaml new file mode 100644 index 0000000..e2261ee --- /dev/null +++ b/rqjs-cli/pnpm-lock.yaml @@ -0,0 +1,598 @@ +lockfileVersion: '9.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +importers: + + .: + devDependencies: + '@inquirer/prompts': + specifier: ^5.0.6 + version: 5.0.6 + '@types/node': + specifier: ^20.14.5 + version: 20.14.5 + deno-console: + specifier: ^0.1.3 + version: 0.1.3 + esbuild: + specifier: ^0.21.5 + version: 0.21.5 + +packages: + + '@esbuild/aix-ppc64@0.21.5': + resolution: {integrity: sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==} + engines: {node: '>=12'} + cpu: [ppc64] + os: [aix] + + '@esbuild/android-arm64@0.21.5': + resolution: {integrity: sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==} + engines: {node: '>=12'} + cpu: [arm64] + os: [android] + + '@esbuild/android-arm@0.21.5': + resolution: {integrity: sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==} + engines: {node: '>=12'} + cpu: [arm] + os: [android] + + '@esbuild/android-x64@0.21.5': + resolution: {integrity: sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==} + engines: {node: '>=12'} + cpu: [x64] + os: [android] + + '@esbuild/darwin-arm64@0.21.5': + resolution: {integrity: sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==} + engines: {node: '>=12'} + cpu: [arm64] + os: [darwin] + + '@esbuild/darwin-x64@0.21.5': + resolution: {integrity: sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==} + engines: {node: '>=12'} + cpu: [x64] + os: [darwin] + + '@esbuild/freebsd-arm64@0.21.5': + resolution: {integrity: sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==} + engines: {node: '>=12'} + cpu: [arm64] + os: [freebsd] + + '@esbuild/freebsd-x64@0.21.5': + resolution: {integrity: sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [freebsd] + + '@esbuild/linux-arm64@0.21.5': + resolution: {integrity: sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==} + engines: {node: '>=12'} + cpu: [arm64] + os: [linux] + + '@esbuild/linux-arm@0.21.5': + resolution: {integrity: sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==} + engines: {node: '>=12'} + cpu: [arm] + os: [linux] + + '@esbuild/linux-ia32@0.21.5': + resolution: {integrity: sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==} + engines: {node: '>=12'} + cpu: [ia32] + os: [linux] + + '@esbuild/linux-loong64@0.21.5': + resolution: {integrity: sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==} + engines: {node: '>=12'} + cpu: [loong64] + os: [linux] + + '@esbuild/linux-mips64el@0.21.5': + resolution: {integrity: sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==} + engines: {node: '>=12'} + cpu: [mips64el] + os: [linux] + + '@esbuild/linux-ppc64@0.21.5': + resolution: {integrity: sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==} + engines: {node: '>=12'} + cpu: [ppc64] + os: [linux] + + '@esbuild/linux-riscv64@0.21.5': + resolution: {integrity: sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==} + engines: {node: '>=12'} + cpu: [riscv64] + os: [linux] + + '@esbuild/linux-s390x@0.21.5': + resolution: {integrity: sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==} + engines: {node: '>=12'} + cpu: [s390x] + os: [linux] + + '@esbuild/linux-x64@0.21.5': + resolution: {integrity: sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [linux] + + '@esbuild/netbsd-x64@0.21.5': + resolution: {integrity: sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==} + engines: {node: '>=12'} + cpu: [x64] + os: [netbsd] + + '@esbuild/openbsd-x64@0.21.5': + resolution: {integrity: sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==} + engines: {node: '>=12'} + cpu: [x64] + os: [openbsd] + + '@esbuild/sunos-x64@0.21.5': + resolution: {integrity: sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==} + engines: {node: '>=12'} + cpu: [x64] + os: [sunos] + + '@esbuild/win32-arm64@0.21.5': + resolution: {integrity: sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==} + engines: {node: '>=12'} + cpu: [arm64] + os: [win32] + + '@esbuild/win32-ia32@0.21.5': + resolution: {integrity: sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==} + engines: {node: '>=12'} + cpu: [ia32] + os: [win32] + + '@esbuild/win32-x64@0.21.5': + resolution: {integrity: sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==} + engines: {node: '>=12'} + cpu: [x64] + os: [win32] + + '@inquirer/checkbox@2.3.6': + resolution: {integrity: sha512-BziU88BEwBaGclY0RM59QOop2zyPgAr1EH/czvW6/J9ELXYN4vbGTI4KM/ogNnh+Y0yNnVvKxAQqFsI2Ra2BtA==} + engines: {node: '>=18'} + + '@inquirer/confirm@3.1.10': + resolution: {integrity: sha512-/aAHu83Njy6yf44T+ZrRPUkMcUqprrOiIKsyMvf9jOV+vF5BNb2ja1aLP33MK36W8eaf91MTL/mU/e6METuENg==} + engines: {node: '>=18'} + + '@inquirer/core@8.2.3': + resolution: {integrity: sha512-WrpDVPAaxJQjHid3Ra4FhUO70YBzkHSYVyW5X48L5zHYdudoPISJqTRRWSeamHfaXda7PNNaC5Py5MEo7QwBNA==} + engines: {node: '>=18'} + + '@inquirer/editor@2.1.10': + resolution: {integrity: sha512-5e4OlRNzi1TFVKJVBk4WtWYPtVqpKyIGvltP/bqnZ0AQ9bA9Cgukcs8LniUXsgkw3+IAPFQfP8yBxFX/qIz+2g==} + engines: {node: '>=18'} + + '@inquirer/expand@2.1.10': + resolution: {integrity: sha512-5wyrw7wH24DqACWnwRhdZioCS4Bq8tvkh2BDyz2a827Zn2QAxZ/o+m17GBD9xPfvTdtxlfYsyKPTSQmGvG+BJA==} + engines: {node: '>=18'} + + '@inquirer/figures@1.0.3': + resolution: {integrity: sha512-ErXXzENMH5pJt5/ssXV0DfWUZqly8nGzf0UcBV9xTnP+KyffE2mqyxIMBrZ8ijQck2nU0TQm40EQB53YreyWHw==} + engines: {node: '>=18'} + + '@inquirer/input@2.1.10': + resolution: {integrity: sha512-KEnho7O0YBj+peA40ZGOuBYf00EQnYbQlPsORgZYdjdUVUrMqQPW3qIvRNJIq+lYlc9RZrfHeMoAv+tWAoZFQg==} + engines: {node: '>=18'} + + '@inquirer/password@2.1.10': + resolution: {integrity: sha512-hwRi8bITIloH7+30inpIkS0C/+lsdM+HSS/6F5J46Jdo9JLRnUwV4D9ovc4pz6zf2vjCFH/MYlxUBOFe/ix3Tw==} + engines: {node: '>=18'} + + '@inquirer/prompts@5.0.6': + resolution: {integrity: sha512-1Fc/8d8tCoYuMXJSG0C5F7Bzs4ViL4VNyOJr35FNnnEvx2GX/unBJDL9ZcYHx/Ps7yQuRAUr50SOvw8QbmJxvg==} + engines: {node: '>=18'} + + '@inquirer/rawlist@2.1.10': + resolution: {integrity: sha512-tGi2O9DP+jDw2/lXKdRlv0YcCfwHcEZAzM+fRe5YjoDyBwUbKzYrDlD4xa6H9hIpPSrOpSpncTEDL9lbUDwXFw==} + engines: {node: '>=18'} + + '@inquirer/select@2.3.6': + resolution: {integrity: sha512-eLqlZXre69Jenmar5s+3018xF3lpaGfxVZLHkCzkrhtuTuFjpYtb0YpiYeZNKZm9pa+ih3s9acN/zRt+dDh+qA==} + engines: {node: '>=18'} + + '@inquirer/type@1.3.3': + resolution: {integrity: sha512-xTUt0NulylX27/zMx04ZYar/kr1raaiFTVvQ5feljQsiAgdm0WPj4S73/ye0fbslh+15QrIuDvfCXTek7pMY5A==} + engines: {node: '>=18'} + + '@types/mute-stream@0.0.4': + resolution: {integrity: sha512-CPM9nzrCPPJHQNA9keH9CVkVI+WR5kMa+7XEs5jcGQ0VoAGnLv242w8lIVgwAEfmE4oufJRaTc9PNLQl0ioAow==} + + '@types/node@20.14.5': + resolution: {integrity: sha512-aoRR+fJkZT2l0aGOJhuA8frnCSoNX6W7U2mpNq63+BxBIj5BQFt8rHy627kijCmm63ijdSdwvGgpUsU6MBsZZA==} + + '@types/node@20.14.6': + resolution: {integrity: sha512-JbA0XIJPL1IiNnU7PFxDXyfAwcwVVrOoqyzzyQTyMeVhBzkJVMSkC1LlVsRQ2lpqiY4n6Bb9oCS6lzDKVQxbZw==} + + '@types/wrap-ansi@3.0.0': + resolution: {integrity: sha512-ltIpx+kM7g/MLRZfkbL7EsCEjfzCcScLpkg37eXEtx5kmrAKBkTJwd1GIAjDSL8wTpM6Hzn5YO4pSb91BEwu1g==} + + ansi-escapes@4.3.2: + resolution: {integrity: sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==} + engines: {node: '>=8'} + + ansi-regex@5.0.1: + resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} + engines: {node: '>=8'} + + ansi-styles@4.3.0: + resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} + engines: {node: '>=8'} + + chalk@4.1.2: + resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} + engines: {node: '>=10'} + + chardet@0.7.0: + resolution: {integrity: sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==} + + cli-spinners@2.9.2: + resolution: {integrity: sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==} + engines: {node: '>=6'} + + cli-width@4.1.0: + resolution: {integrity: sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==} + engines: {node: '>= 12'} + + color-convert@2.0.1: + resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} + engines: {node: '>=7.0.0'} + + color-name@1.1.4: + resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + + deno-console@0.1.3: + resolution: {integrity: sha512-p3uY5vQTka+IiNEuqCPK8AHSQB300nUJQe8Oo+P/U5JJTQtAzJW032paTovLT+hru5kR6VQbOEX9kBH2dX5elg==} + + emoji-regex@8.0.0: + resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} + + esbuild@0.21.5: + resolution: {integrity: sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==} + engines: {node: '>=12'} + hasBin: true + + external-editor@3.1.0: + resolution: {integrity: sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==} + engines: {node: '>=4'} + + has-flag@4.0.0: + resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} + engines: {node: '>=8'} + + iconv-lite@0.4.24: + resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} + engines: {node: '>=0.10.0'} + + is-fullwidth-code-point@3.0.0: + resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} + engines: {node: '>=8'} + + mute-stream@1.0.0: + resolution: {integrity: sha512-avsJQhyd+680gKXyG/sQc0nXaC6rBkPOfyHYcFb9+hdkqQkR9bdnkJ0AMZhke0oesPqIO+mFFJ+IdBc7mst4IA==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + os-tmpdir@1.0.2: + resolution: {integrity: sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==} + engines: {node: '>=0.10.0'} + + safer-buffer@2.1.2: + resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} + + signal-exit@4.1.0: + resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} + engines: {node: '>=14'} + + string-width@4.2.3: + resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} + engines: {node: '>=8'} + + strip-ansi@6.0.1: + resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} + engines: {node: '>=8'} + + supports-color@7.2.0: + resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} + engines: {node: '>=8'} + + tmp@0.0.33: + resolution: {integrity: sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==} + engines: {node: '>=0.6.0'} + + type-fest@0.21.3: + resolution: {integrity: sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==} + engines: {node: '>=10'} + + undici-types@5.26.5: + resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} + + wrap-ansi@6.2.0: + resolution: {integrity: sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==} + engines: {node: '>=8'} + +snapshots: + + '@esbuild/aix-ppc64@0.21.5': + optional: true + + '@esbuild/android-arm64@0.21.5': + optional: true + + '@esbuild/android-arm@0.21.5': + optional: true + + '@esbuild/android-x64@0.21.5': + optional: true + + '@esbuild/darwin-arm64@0.21.5': + optional: true + + '@esbuild/darwin-x64@0.21.5': + optional: true + + '@esbuild/freebsd-arm64@0.21.5': + optional: true + + '@esbuild/freebsd-x64@0.21.5': + optional: true + + '@esbuild/linux-arm64@0.21.5': + optional: true + + '@esbuild/linux-arm@0.21.5': + optional: true + + '@esbuild/linux-ia32@0.21.5': + optional: true + + '@esbuild/linux-loong64@0.21.5': + optional: true + + '@esbuild/linux-mips64el@0.21.5': + optional: true + + '@esbuild/linux-ppc64@0.21.5': + optional: true + + '@esbuild/linux-riscv64@0.21.5': + optional: true + + '@esbuild/linux-s390x@0.21.5': + optional: true + + '@esbuild/linux-x64@0.21.5': + optional: true + + '@esbuild/netbsd-x64@0.21.5': + optional: true + + '@esbuild/openbsd-x64@0.21.5': + optional: true + + '@esbuild/sunos-x64@0.21.5': + optional: true + + '@esbuild/win32-arm64@0.21.5': + optional: true + + '@esbuild/win32-ia32@0.21.5': + optional: true + + '@esbuild/win32-x64@0.21.5': + optional: true + + '@inquirer/checkbox@2.3.6': + dependencies: + '@inquirer/core': 8.2.3 + '@inquirer/figures': 1.0.3 + '@inquirer/type': 1.3.3 + ansi-escapes: 4.3.2 + chalk: 4.1.2 + + '@inquirer/confirm@3.1.10': + dependencies: + '@inquirer/core': 8.2.3 + '@inquirer/type': 1.3.3 + + '@inquirer/core@8.2.3': + dependencies: + '@inquirer/figures': 1.0.3 + '@inquirer/type': 1.3.3 + '@types/mute-stream': 0.0.4 + '@types/node': 20.14.6 + '@types/wrap-ansi': 3.0.0 + ansi-escapes: 4.3.2 + chalk: 4.1.2 + cli-spinners: 2.9.2 + cli-width: 4.1.0 + mute-stream: 1.0.0 + signal-exit: 4.1.0 + strip-ansi: 6.0.1 + wrap-ansi: 6.2.0 + + '@inquirer/editor@2.1.10': + dependencies: + '@inquirer/core': 8.2.3 + '@inquirer/type': 1.3.3 + external-editor: 3.1.0 + + '@inquirer/expand@2.1.10': + dependencies: + '@inquirer/core': 8.2.3 + '@inquirer/type': 1.3.3 + chalk: 4.1.2 + + '@inquirer/figures@1.0.3': {} + + '@inquirer/input@2.1.10': + dependencies: + '@inquirer/core': 8.2.3 + '@inquirer/type': 1.3.3 + + '@inquirer/password@2.1.10': + dependencies: + '@inquirer/core': 8.2.3 + '@inquirer/type': 1.3.3 + ansi-escapes: 4.3.2 + + '@inquirer/prompts@5.0.6': + dependencies: + '@inquirer/checkbox': 2.3.6 + '@inquirer/confirm': 3.1.10 + '@inquirer/editor': 2.1.10 + '@inquirer/expand': 2.1.10 + '@inquirer/input': 2.1.10 + '@inquirer/password': 2.1.10 + '@inquirer/rawlist': 2.1.10 + '@inquirer/select': 2.3.6 + + '@inquirer/rawlist@2.1.10': + dependencies: + '@inquirer/core': 8.2.3 + '@inquirer/type': 1.3.3 + chalk: 4.1.2 + + '@inquirer/select@2.3.6': + dependencies: + '@inquirer/core': 8.2.3 + '@inquirer/figures': 1.0.3 + '@inquirer/type': 1.3.3 + ansi-escapes: 4.3.2 + chalk: 4.1.2 + + '@inquirer/type@1.3.3': {} + + '@types/mute-stream@0.0.4': + dependencies: + '@types/node': 20.14.6 + + '@types/node@20.14.5': + dependencies: + undici-types: 5.26.5 + + '@types/node@20.14.6': + dependencies: + undici-types: 5.26.5 + + '@types/wrap-ansi@3.0.0': {} + + ansi-escapes@4.3.2: + dependencies: + type-fest: 0.21.3 + + ansi-regex@5.0.1: {} + + ansi-styles@4.3.0: + dependencies: + color-convert: 2.0.1 + + chalk@4.1.2: + dependencies: + ansi-styles: 4.3.0 + supports-color: 7.2.0 + + chardet@0.7.0: {} + + cli-spinners@2.9.2: {} + + cli-width@4.1.0: {} + + color-convert@2.0.1: + dependencies: + color-name: 1.1.4 + + color-name@1.1.4: {} + + deno-console@0.1.3: {} + + emoji-regex@8.0.0: {} + + esbuild@0.21.5: + optionalDependencies: + '@esbuild/aix-ppc64': 0.21.5 + '@esbuild/android-arm': 0.21.5 + '@esbuild/android-arm64': 0.21.5 + '@esbuild/android-x64': 0.21.5 + '@esbuild/darwin-arm64': 0.21.5 + '@esbuild/darwin-x64': 0.21.5 + '@esbuild/freebsd-arm64': 0.21.5 + '@esbuild/freebsd-x64': 0.21.5 + '@esbuild/linux-arm': 0.21.5 + '@esbuild/linux-arm64': 0.21.5 + '@esbuild/linux-ia32': 0.21.5 + '@esbuild/linux-loong64': 0.21.5 + '@esbuild/linux-mips64el': 0.21.5 + '@esbuild/linux-ppc64': 0.21.5 + '@esbuild/linux-riscv64': 0.21.5 + '@esbuild/linux-s390x': 0.21.5 + '@esbuild/linux-x64': 0.21.5 + '@esbuild/netbsd-x64': 0.21.5 + '@esbuild/openbsd-x64': 0.21.5 + '@esbuild/sunos-x64': 0.21.5 + '@esbuild/win32-arm64': 0.21.5 + '@esbuild/win32-ia32': 0.21.5 + '@esbuild/win32-x64': 0.21.5 + + external-editor@3.1.0: + dependencies: + chardet: 0.7.0 + iconv-lite: 0.4.24 + tmp: 0.0.33 + + has-flag@4.0.0: {} + + iconv-lite@0.4.24: + dependencies: + safer-buffer: 2.1.2 + + is-fullwidth-code-point@3.0.0: {} + + mute-stream@1.0.0: {} + + os-tmpdir@1.0.2: {} + + safer-buffer@2.1.2: {} + + signal-exit@4.1.0: {} + + string-width@4.2.3: + dependencies: + emoji-regex: 8.0.0 + is-fullwidth-code-point: 3.0.0 + strip-ansi: 6.0.1 + + strip-ansi@6.0.1: + dependencies: + ansi-regex: 5.0.1 + + supports-color@7.2.0: + dependencies: + has-flag: 4.0.0 + + tmp@0.0.33: + dependencies: + os-tmpdir: 1.0.2 + + type-fest@0.21.3: {} + + undici-types@5.26.5: {} + + wrap-ansi@6.2.0: + dependencies: + ansi-styles: 4.3.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 diff --git a/rqjs-cli/src/lib.rs b/rqjs-cli/src/lib.rs new file mode 100644 index 0000000..78d4375 --- /dev/null +++ b/rqjs-cli/src/lib.rs @@ -0,0 +1 @@ +pub mod start; \ No newline at end of file diff --git a/rqjs-cli/src/main.rs b/rqjs-cli/src/main.rs new file mode 100644 index 0000000..7e1fefe --- /dev/null +++ b/rqjs-cli/src/main.rs @@ -0,0 +1,8 @@ +use clap::Parser; +use rqjs_cli::start::{self, Args}; + +#[tokio::main] +async fn main() { + let args = Args::parse(); + start::start(args).await; +} diff --git a/rqjs-cli/src/start.rs b/rqjs-cli/src/start.rs new file mode 100644 index 0000000..d875e57 --- /dev/null +++ b/rqjs-cli/src/start.rs @@ -0,0 +1,97 @@ +use std::{ + io::{stdout, Write}, + process, + str::FromStr, +}; +#[derive(Parser, Debug, Clone)] +#[command(version, about, long_about = None)] +#[clap(name = "rqjs", version = env!("CARGO_PKG_VERSION"), bin_name = "rqjs")] +pub struct Args { + #[clap()] + file: Option, +} + +use clap::Parser; +use rquickjs::{ + async_with, + loader::{BuiltinResolver, ModuleLoader}, + AsyncContext, AsyncRuntime, Ctx, Function, Module, Object, Result, Value, +}; + + +use rqjs_ext::modules; + +pub async fn start(args: Args) { + let Args { file } = args; + let resolver = ( + BuiltinResolver::default().with_module("os"), + BuiltinResolver::default().with_module("path"), + BuiltinResolver::default().with_module("buffer"), + BuiltinResolver::default().with_module("util"), + BuiltinResolver::default().with_module("uuid"), + BuiltinResolver::default().with_module("xml"), + BuiltinResolver::default().with_module("fs"), + BuiltinResolver::default().with_module("fs/promises"), + ); + + let loader = ( + ModuleLoader::default().with_module("os", modules::os::OsModule), + ModuleLoader::default().with_module("path", modules::path::PathModule), + ModuleLoader::default().with_module("buffer", modules::buffer::BufferModule), + ModuleLoader::default().with_module("util", modules::util::UtilModule), + ModuleLoader::default().with_module("uuid", modules::uuid::UuidModule), + ModuleLoader::default().with_module("xml", modules::xml::XmlModule), + ModuleLoader::default().with_module("fs", modules::fs::FsModule), + ModuleLoader::default().with_module("fs/promises", modules::fs::FsPromisesModule), + ); + + let init_global: Vec) -> Result<()>> = vec![ + modules::buffer::init, + modules::exceptions::init, + modules::encoding::init, + modules::console::init, + ]; + let rt = AsyncRuntime::new().unwrap(); + rt.set_loader(resolver, loader).await; + let ctx = AsyncContext::full(&rt).await.unwrap(); + + if let Some(path) = file { + let path = std::path::PathBuf::from_str(&path).unwrap(); + let path = std::path::Path::new(&path); + let name = path.file_name().expect("filename error"); + let code = std::fs::read_to_string(path).expect("read file error"); + async_with!(ctx => |ctx| { + for i in init_global { + i(&ctx).unwrap(); + } + + Module::evaluate(ctx.clone(), name.to_string_lossy().to_string(), code) + .unwrap() + .finish::<()>() + .unwrap(); + }) + .await; + rt.idle().await; + } else { + ctrlc::set_handler(move || { + process::exit(0); + }) + .expect("Error setting Ctrl-C handler"); + + loop { + stdout().write_all(b"> ").unwrap(); + stdout().flush().unwrap(); + let mut input = String::new(); + std::io::stdin().read_line(&mut input).unwrap(); + + ctx.with(|ctx| { + let r = ctx.eval::(input.as_bytes()).unwrap(); + let g = ctx.globals(); + let console: Object = g.get("console").unwrap(); + let log: Function = console.get("log").unwrap(); + log.call::<(Value<'_>,), ()>((r,)).unwrap(); + }) + .await; + } + } +} diff --git a/rqjs-cli/ts/inquirer.ts b/rqjs-cli/ts/inquirer.ts new file mode 100644 index 0000000..25216ab --- /dev/null +++ b/rqjs-cli/ts/inquirer.ts @@ -0,0 +1,5 @@ +import { input } from '@inquirer/prompts'; + +input({ message: 'Enter your name' }).then(text => { + console.log(text) +}) \ No newline at end of file diff --git a/rqjs-ext/Cargo.lock b/rqjs-ext/Cargo.lock new file mode 100644 index 0000000..67300c4 --- /dev/null +++ b/rqjs-ext/Cargo.lock @@ -0,0 +1,2145 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "addr2line" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e4503c46a5c0c7844e948c9a4d6acd9f50cccb4de1c48eb9e291ea17470c678" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + +[[package]] +name = "ahash" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" +dependencies = [ + "cfg-if", + "once_cell", + "version_check", + "zerocopy", +] + +[[package]] +name = "aho-corasick" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +dependencies = [ + "memchr", +] + +[[package]] +name = "allocator-api2" +version = "0.2.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f" + +[[package]] +name = "android-tzdata" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" + +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + +[[package]] +name = "anstream" +version = "0.6.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "418c75fa768af9c03be99d17643f93f79bbba589895012a80e3452a19ddda15b" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "038dfcf04a5feb68e9c60b21c9625a54c2c0616e79b72b0fd87075a056ae1d1b" + +[[package]] +name = "anstyle-parse" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c03a11a9034d92058ceb6ee011ce58af4a9bf61491aa7e1e59ecd24bd40d22d4" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad186efb764318d35165f1758e7dcef3b10628e26d41a44bc5550652e6804391" +dependencies = [ + "windows-sys 0.52.0", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61a38449feb7068f52bb06c12759005cf459ee52bb4adc1d5a7c4322d716fb19" +dependencies = [ + "anstyle", + "windows-sys 0.52.0", +] + +[[package]] +name = "async-lock" +version = "3.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff6e472cdea888a4bd64f342f09b3f50e1886d32afe8df3d663c01140b811b18" +dependencies = [ + "event-listener", + "event-listener-strategy", + "pin-project-lite", +] + +[[package]] +name = "atomic" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c59bdb34bc650a32731b31bd8f0829cc15d24a708ee31559e0bb34f2bc320cba" + +[[package]] +name = "atomic-waker" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" + +[[package]] +name = "autocfg" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" + +[[package]] +name = "backtrace" +version = "0.3.73" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5cc23269a4f8976d0a4d2e7109211a419fe30e8d88d677cd60b6bc79c5732e0a" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", +] + +[[package]] +name = "base64-simd" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "339abbe78e73178762e23bea9dfd08e697eb3f3301cd4be981c0f78ba5859195" +dependencies = [ + "outref", + "vsimd", +] + +[[package]] +name = "bindgen" +version = "0.69.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a00dc851838a2120612785d195287475a3ac45514741da670b735818822129a0" +dependencies = [ + "bitflags", + "cexpr", + "clang-sys", + "itertools", + "lazy_static", + "lazycell", + "log", + "prettyplease", + "proc-macro2 1.0.85", + "quote 1.0.36", + "regex", + "rustc-hash", + "shlex", + "syn 2.0.66", + "which", +] + +[[package]] +name = "bitflags" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[package]] +name = "bumpalo" +version = "3.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "bytes" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" + +[[package]] +name = "cc" +version = "1.0.99" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96c51067fd44124faa7f870b4b1c969379ad32b2ba805aa959430ceaa384f695" + +[[package]] +name = "cexpr" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" +dependencies = [ + "nom", +] + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "cfg_aliases" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e" + +[[package]] +name = "chrono" +version = "0.4.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401" +dependencies = [ + "android-tzdata", + "iana-time-zone", + "js-sys", + "num-traits", + "wasm-bindgen", + "windows-targets 0.52.5", +] + +[[package]] +name = "clang-sys" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4" +dependencies = [ + "glob", + "libc", + "libloading", +] + +[[package]] +name = "clap" +version = "4.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5db83dced34638ad474f39f250d7fea9598bdd239eaced1bdf45d597da0f433f" +dependencies = [ + "clap_builder", + "clap_derive", +] + +[[package]] +name = "clap_builder" +version = "4.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7e204572485eb3fbf28f871612191521df159bc3e15a9f5064c66dba3a8c05f" +dependencies = [ + "anstream", + "anstyle", + "clap_lex", + "strsim", +] + +[[package]] +name = "clap_derive" +version = "4.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c780290ccf4fb26629baa7a1081e68ced113f1d3ec302fa5948f1c381ebf06c6" +dependencies = [ + "heck", + "proc-macro2 1.0.85", + "quote 1.0.36", + "syn 2.0.66", +] + +[[package]] +name = "clap_lex" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b82cf0babdbd58558212896d1a4272303a57bdb245c2bf1147185fb45640e70" + +[[package]] +name = "colorchoice" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b6a852b24ab71dffc585bcb46eaf7959d175cb865a7152e35b348d1b2960422" + +[[package]] +name = "concurrent-queue" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "convert_case" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec182b0ca2f35d8fc196cf3404988fd8b8c739a4d270ff118a398feb0cbec1ca" +dependencies = [ + "unicode-segmentation", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" + +[[package]] +name = "crc32c" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a47af21622d091a8f0fb295b88bc886ac74efcc613efc19f5d0b21de5c89e47" +dependencies = [ + "rustc_version", +] + +[[package]] +name = "crc32fast" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "cross-uname" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff7bb10673cca006046a1ec932de4637ab04fc224cae6f83134bce596f5d1389" + +[[package]] +name = "crossbeam-utils" +version = "0.8.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "ctrlc" +version = "3.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "672465ae37dc1bc6380a6547a8883d5dd397b0f1faaad4f265726cc7042a5345" +dependencies = [ + "nix", + "windows-sys 0.52.0", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "crypto-common", +] + +[[package]] +name = "dlopen" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71e80ad39f814a9abe68583cd50a2d45c8a67561c3361ab8da240587dda80937" +dependencies = [ + "dlopen_derive", + "lazy_static", + "libc", + "winapi", +] + +[[package]] +name = "dlopen_derive" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f236d9e1b1fbd81cea0f9cbdc8dcc7e8ebcd80e6659cd7cb2ad5f6c05946c581" +dependencies = [ + "libc", + "quote 0.6.13", + "syn 0.15.44", +] + +[[package]] +name = "either" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3dca9240753cf90908d7e4aac30f630662b02aebaa1b58a3cadabdb23385b58b" + +[[package]] +name = "encoding_rs" +version = "0.8.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b45de904aa0b010bce2ab45264d0631681847fa7b6f2eaa7dab7619943bc4f59" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + +[[package]] +name = "errno" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "event-listener" +version = "5.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6032be9bd27023a771701cc49f9f053c751055f71efb2e0ae5c15809093675ba" +dependencies = [ + "concurrent-queue", + "parking", + "pin-project-lite", +] + +[[package]] +name = "event-listener-strategy" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f214dc438f977e6d4e3500aaa277f5ad94ca83fbbd9b1a15713ce2344ccc5a1" +dependencies = [ + "event-listener", + "pin-project-lite", +] + +[[package]] +name = "float-cmp" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98de4bbd547a563b716d8dfa9aad1cb19bfab00f4fa09a6a4ed21dbcf44ce9c4" +dependencies = [ + "num-traits", +] + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "futures-channel" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" +dependencies = [ + "futures-core", +] + +[[package]] +name = "futures-core" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" + +[[package]] +name = "futures-sink" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" + +[[package]] +name = "futures-task" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" + +[[package]] +name = "futures-util" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" +dependencies = [ + "futures-core", + "futures-task", + "pin-project-lite", + "pin-utils", +] + +[[package]] +name = "fxhash" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c" +dependencies = [ + "byteorder", +] + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] +name = "getrandom" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" +dependencies = [ + "cfg-if", + "js-sys", + "libc", + "wasi", + "wasm-bindgen", +] + +[[package]] +name = "gimli" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd" + +[[package]] +name = "glob" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" + +[[package]] +name = "h2" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa82e28a107a8cc405f0839610bdc9b15f1e25ec7d696aa5cf173edbcb1486ab" +dependencies = [ + "atomic-waker", + "bytes", + "fnv", + "futures-core", + "futures-sink", + "http", + "indexmap", + "slab", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "halfbrown" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8588661a8607108a5ca69cab034063441a0413a0b041c13618a7dd348021ef6f" +dependencies = [ + "hashbrown", + "serde", +] + +[[package]] +name = "hashbrown" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" +dependencies = [ + "ahash", + "allocator-api2", +] + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "hermit-abi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" + +[[package]] +name = "hex-simd" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f7685beb53fc20efc2605f32f5d51e9ba18b8ef237961d1760169d2290d3bee" +dependencies = [ + "outref", + "vsimd", +] + +[[package]] +name = "home" +version = "0.5.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5" +dependencies = [ + "windows-sys 0.52.0", +] + +[[package]] +name = "http" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "http-body" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cac85db508abc24a2e48553ba12a996e87244a0395ce011e62b37158745d643" +dependencies = [ + "bytes", + "http", +] + +[[package]] +name = "httparse" +version = "1.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fcc0b4a115bf80b728eb8ea024ad5bd707b615bfed49e0665b6e0f86fd082d9" + +[[package]] +name = "hyper" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe575dd17d0862a9a33781c8c4696a55c320909004a67a00fb286ba8b1bc496d" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "h2", + "http", + "http-body", + "httparse", + "itoa", + "pin-project-lite", + "smallvec", + "tokio", + "want", +] + +[[package]] +name = "hyper-rustls" +version = "0.27.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ee4be2c948921a1a5320b629c4193916ed787a7f7f293fd3f7f5a6c9de74155" +dependencies = [ + "futures-util", + "http", + "hyper", + "hyper-util", + "rustls", + "rustls-pki-types", + "tokio", + "tokio-rustls", + "tower-service", + "webpki-roots", +] + +[[package]] +name = "hyper-util" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b875924a60b96e5d7b9ae7b066540b1dd1cbd90d1828f54c92e02a283351c56" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "http", + "http-body", + "hyper", + "pin-project-lite", + "socket2", + "tokio", + "tower", + "tower-service", + "tracing", +] + +[[package]] +name = "iana-time-zone" +version = "0.1.60" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "wasm-bindgen", + "windows-core", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" +dependencies = [ + "cc", +] + +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + +[[package]] +name = "indexmap" +version = "2.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" +dependencies = [ + "equivalent", + "hashbrown", +] + +[[package]] +name = "is_terminal_polyfill" +version = "1.70.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8478577c03552c21db0e2724ffb8986a5ce7af88107e6be5d2ee6e158c12800" + +[[package]] +name = "itertools" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" + +[[package]] +name = "js-sys" +version = "0.3.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d" +dependencies = [ + "wasm-bindgen", +] + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "lazycell" +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.155" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" + +[[package]] +name = "libloading" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c2a198fb6b0eada2a8df47933734e6d35d350665a33a3593d7164fa52c75c19" +dependencies = [ + "cfg-if", + "windows-targets 0.48.5", +] + +[[package]] +name = "linux-raw-sys" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" + +[[package]] +name = "lock_api" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" +dependencies = [ + "autocfg", + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" + +[[package]] +name = "md-5" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d89e7ee0cfbedfc4da3340218492196241d89eefb6dab27de5df917a6d2e78cf" +dependencies = [ + "cfg-if", + "digest", +] + +[[package]] +name = "memchr" +version = "2.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" + +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + +[[package]] +name = "miniz_oxide" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08" +dependencies = [ + "adler", +] + +[[package]] +name = "mio" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" +dependencies = [ + "libc", + "wasi", + "windows-sys 0.48.0", +] + +[[package]] +name = "nix" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab2156c4fce2f8df6c499cc1c763e4394b7482525bf2a9701c9d79d215f519e4" +dependencies = [ + "bitflags", + "cfg-if", + "cfg_aliases", + "libc", +] + +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + +[[package]] +name = "num_cpus" +version = "1.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" +dependencies = [ + "hermit-abi", + "libc", +] + +[[package]] +name = "object" +version = "0.36.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "576dfe1fc8f9df304abb159d767a29d0476f7750fbf8aa7ad07816004a207434" +dependencies = [ + "memchr", +] + +[[package]] +name = "once_cell" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" + +[[package]] +name = "outref" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4030760ffd992bef45b0ae3f10ce1aba99e33464c90d14dd7c039884963ddc7a" + +[[package]] +name = "parking" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb813b8af86854136c6922af0598d719255ecb2179515e6e7730d468f05c9cae" + +[[package]] +name = "parking_lot" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-targets 0.52.5", +] + +[[package]] +name = "phf" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc" +dependencies = [ + "phf_shared", +] + +[[package]] +name = "phf_generator" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48e4cc64c2ad9ebe670cb8fd69dd50ae301650392e81c05f9bfcb2d5bdbc24b0" +dependencies = [ + "phf_shared", + "rand", +] + +[[package]] +name = "phf_shared" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90fcb95eef784c2ac79119d1dd819e162b5da872ce6f3c3abe1e8ca1c082f72b" +dependencies = [ + "siphasher", +] + +[[package]] +name = "pin-project" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6bf43b791c5b9e34c3d182969b4abb522f9343702850a2e57f460d00d09b4b3" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" +dependencies = [ + "proc-macro2 1.0.85", + "quote 1.0.36", + "syn 2.0.66", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "ppv-lite86" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" + +[[package]] +name = "prettyplease" +version = "0.2.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f12335488a2f3b0a83b14edad48dca9879ce89b2edd10e80237e4e852dd645e" +dependencies = [ + "proc-macro2 1.0.85", + "syn 2.0.66", +] + +[[package]] +name = "proc-macro-crate" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919" +dependencies = [ + "once_cell", + "toml_edit", +] + +[[package]] +name = "proc-macro-error" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" +dependencies = [ + "proc-macro-error-attr", + "proc-macro2 1.0.85", + "quote 1.0.36", + "syn 1.0.109", + "version_check", +] + +[[package]] +name = "proc-macro-error-attr" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" +dependencies = [ + "proc-macro2 1.0.85", + "quote 1.0.36", + "version_check", +] + +[[package]] +name = "proc-macro2" +version = "0.4.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759" +dependencies = [ + "unicode-xid", +] + +[[package]] +name = "proc-macro2" +version = "1.0.85" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22244ce15aa966053a896d1accb3a6e68469b97c7f33f284b99f0d576879fc23" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quick-xml" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d3a6e5838b60e0e8fa7a43f22ade549a37d61f8bdbe636d0d7816191de969c2" +dependencies = [ + "memchr", +] + +[[package]] +name = "quote" +version = "0.6.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1" +dependencies = [ + "proc-macro2 0.4.30", +] + +[[package]] +name = "quote" +version = "1.0.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" +dependencies = [ + "proc-macro2 1.0.85", +] + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + +[[package]] +name = "redox_syscall" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c82cf8cff14456045f55ec4241383baeff27af886adb72ffb2162f99911de0fd" +dependencies = [ + "bitflags", +] + +[[package]] +name = "ref-cast" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccf0a6f84d5f1d581da8b41b47ec8600871962f2a528115b542b362d4b744931" +dependencies = [ + "ref-cast-impl", +] + +[[package]] +name = "ref-cast-impl" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bcc303e793d3734489387d205e9b186fac9c6cfacedd98cbb2e8a5943595f3e6" +dependencies = [ + "proc-macro2 1.0.85", + "quote 1.0.36", + "syn 2.0.66", +] + +[[package]] +name = "regex" +version = "1.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b91213439dad192326a0d7c6ee3955910425f441d7038e0d6933b0aec5c4517f" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" + +[[package]] +name = "relative-path" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba39f3699c378cd8970968dcbff9c43159ea4cfbd88d43c00b22f2ef10a435d2" + +[[package]] +name = "ring" +version = "0.17.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" +dependencies = [ + "cc", + "cfg-if", + "getrandom", + "libc", + "spin", + "untrusted", + "windows-sys 0.52.0", +] + +[[package]] +name = "rqjs-ext" +version = "0.1.3" +dependencies = [ + "base64-simd", + "chrono", + "clap", + "crc32c", + "crc32fast", + "cross-uname", + "ctrlc", + "encoding_rs", + "fxhash", + "hex-simd", + "hyper", + "hyper-rustls", + "itoa", + "md-5", + "once_cell", + "phf", + "quick-xml", + "rand", + "ring", + "rquickjs", + "rustls", + "ryu", + "simd-json", + "tokio", + "uuid", + "uuid-simd", +] + +[[package]] +name = "rquickjs" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9cbd33e0b668aea0ab238b9164523aca929096f9f40834700d71d91dd4888882" +dependencies = [ + "either", + "indexmap", + "rquickjs-core", + "rquickjs-macro", +] + +[[package]] +name = "rquickjs-core" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e9129d69b7b8f7ee8ad1da5b12c7f4a8a8acd45f2e6dd9cb2ee1bc5a1f2fa3d" +dependencies = [ + "async-lock", + "chrono", + "dlopen", + "either", + "indexmap", + "phf", + "relative-path", + "rquickjs-sys", +] + +[[package]] +name = "rquickjs-macro" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7d2ecaf7c9eda262e02a91e9541989a9dd18984d17d0d97f99f33b464318057" +dependencies = [ + "convert_case", + "fnv", + "ident_case", + "indexmap", + "phf_generator", + "phf_shared", + "proc-macro-crate", + "proc-macro-error", + "proc-macro2 1.0.85", + "quote 1.0.36", + "rquickjs-core", + "syn 2.0.66", +] + +[[package]] +name = "rquickjs-sys" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf6f2288d8e7fbb5130f62cf720451641e99d55f6fde9db86aa2914ecb553fd2" +dependencies = [ + "bindgen", + "cc", +] + +[[package]] +name = "rustc-demangle" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" + +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + +[[package]] +name = "rustc_version" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +dependencies = [ + "semver", +] + +[[package]] +name = "rustix" +version = "0.38.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" +dependencies = [ + "bitflags", + "errno", + "libc", + "linux-raw-sys", + "windows-sys 0.52.0", +] + +[[package]] +name = "rustls" +version = "0.23.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05cff451f60db80f490f3c182b77c35260baace73209e9cdbbe526bfe3a4d402" +dependencies = [ + "once_cell", + "ring", + "rustls-pki-types", + "rustls-webpki", + "subtle", + "zeroize", +] + +[[package]] +name = "rustls-pki-types" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "976295e77ce332211c0d24d92c0e83e50f5c5f046d11082cea19f3df13a3562d" + +[[package]] +name = "rustls-webpki" +version = "0.102.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff448f7e92e913c4b7d4c6d8e4540a1724b319b4152b8aef6d4cf8339712b33e" +dependencies = [ + "ring", + "rustls-pki-types", + "untrusted", +] + +[[package]] +name = "ryu" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "semver" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" + +[[package]] +name = "serde" +version = "1.0.203" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7253ab4de971e72fb7be983802300c30b5a7f0c2e56fab8abfc6a214307c0094" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.203" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "500cbc0ebeb6f46627f50f3f5811ccf6bf00643be300b4c3eabc0ef55dc5b5ba" +dependencies = [ + "proc-macro2 1.0.85", + "quote 1.0.36", + "syn 2.0.66", +] + +[[package]] +name = "serde_json" +version = "1.0.117" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "455182ea6142b14f93f4bc5320a2b31c1f266b66a4a5c858b013302a5d8cbfc3" +dependencies = [ + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "sha1_smol" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae1a47186c03a32177042e55dbc5fd5aee900b8e0069a8d70fba96a9375cd012" + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "signal-hook-registry" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" +dependencies = [ + "libc", +] + +[[package]] +name = "simd-json" +version = "0.13.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "570c430b3d902ea083097e853263ae782dfe40857d93db019a12356c8e8143fa" +dependencies = [ + "getrandom", + "halfbrown", + "lexical-core", + "ref-cast", + "serde", + "serde_json", + "simdutf8", + "value-trait", +] + +[[package]] +name = "simdutf8" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f27f6278552951f1f2b8cf9da965d10969b2efdea95a6ec47987ab46edfe263a" + +[[package]] +name = "siphasher" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" + +[[package]] +name = "slab" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +dependencies = [ + "autocfg", +] + +[[package]] +name = "smallvec" +version = "1.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" + +[[package]] +name = "socket2" +version = "0.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "spin" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" + +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + +[[package]] +name = "subtle" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d0208408ba0c3df17ed26eb06992cb1a1268d41b2c0e12e65203fbe3972cee5" + +[[package]] +name = "syn" +version = "0.15.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ca4b3b69a77cbe1ffc9e198781b7acb0c7365a883670e8f1c1bc66fba79a5c5" +dependencies = [ + "proc-macro2 0.4.30", + "quote 0.6.13", + "unicode-xid", +] + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2 1.0.85", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.66" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c42f3f41a2de00b01c0aaad383c5a45241efc8b2d1eda5661812fda5f3cdcff5" +dependencies = [ + "proc-macro2 1.0.85", + "quote 1.0.36", + "unicode-ident", +] + +[[package]] +name = "tokio" +version = "1.38.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba4f4a02a7a80d6f274636f0aa95c7e383b912d41fe721a31f29e29698585a4a" +dependencies = [ + "backtrace", + "bytes", + "libc", + "mio", + "num_cpus", + "parking_lot", + "pin-project-lite", + "signal-hook-registry", + "socket2", + "tokio-macros", + "windows-sys 0.48.0", +] + +[[package]] +name = "tokio-macros" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f5ae998a069d4b5aba8ee9dad856af7d520c3699e6159b185c2acd48155d39a" +dependencies = [ + "proc-macro2 1.0.85", + "quote 1.0.36", + "syn 2.0.66", +] + +[[package]] +name = "tokio-rustls" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4" +dependencies = [ + "rustls", + "rustls-pki-types", + "tokio", +] + +[[package]] +name = "tokio-util" +version = "0.7.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9cf6b47b3771c49ac75ad09a6162f53ad4b8088b76ac60e8ec1455b31a189fe1" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "toml_datetime" +version = "0.6.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4badfd56924ae69bcc9039335b2e017639ce3f9b001c393c1b2d1ef846ce2cbf" + +[[package]] +name = "toml_edit" +version = "0.19.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" +dependencies = [ + "indexmap", + "toml_datetime", + "winnow", +] + +[[package]] +name = "tower" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" +dependencies = [ + "futures-core", + "futures-util", + "pin-project", + "pin-project-lite", + "tokio", + "tower-layer", + "tower-service", +] + +[[package]] +name = "tower-layer" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0" + +[[package]] +name = "tower-service" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" + +[[package]] +name = "tracing" +version = "0.1.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" +dependencies = [ + "pin-project-lite", + "tracing-core", +] + +[[package]] +name = "tracing-core" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" +dependencies = [ + "once_cell", +] + +[[package]] +name = "try-lock" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" + +[[package]] +name = "typenum" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + +[[package]] +name = "unicode-segmentation" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202" + +[[package]] +name = "unicode-xid" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" + +[[package]] +name = "untrusted" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" + +[[package]] +name = "utf8parse" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" + +[[package]] +name = "uuid" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a183cf7feeba97b4dd1c0d46788634f6221d87fa961b305bed08c851829efcc0" +dependencies = [ + "atomic", + "getrandom", + "md-5", + "rand", + "sha1_smol", +] + +[[package]] +name = "uuid-simd" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23b082222b4f6619906941c17eb2297fff4c2fb96cb60164170522942a200bd8" +dependencies = [ + "outref", + "uuid", + "vsimd", +] + +[[package]] +name = "value-trait" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dad8db98c1e677797df21ba03fca7d3bf9bec3ca38db930954e4fe6e1ea27eb4" +dependencies = [ + "float-cmp", + "halfbrown", + "itoa", + "ryu", +] + +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + +[[package]] +name = "vsimd" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c3082ca00d5a5ef149bb8b555a72ae84c9c59f7250f013ac822ac2e49b19c64" + +[[package]] +name = "want" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" +dependencies = [ + "try-lock", +] + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "wasm-bindgen" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" +dependencies = [ + "cfg-if", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2 1.0.85", + "quote 1.0.36", + "syn 2.0.66", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726" +dependencies = [ + "quote 1.0.36", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" +dependencies = [ + "proc-macro2 1.0.85", + "quote 1.0.36", + "syn 2.0.66", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" + +[[package]] +name = "webpki-roots" +version = "0.26.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd7c23921eeb1713a4e851530e9b9756e4fb0e89978582942612524cf09f01cd" +dependencies = [ + "rustls-pki-types", +] + +[[package]] +name = "which" +version = "4.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87ba24419a2078cd2b0f2ede2691b6c66d8e47836da3b6db8265ebad47afbfc7" +dependencies = [ + "either", + "home", + "once_cell", + "rustix", +] + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows-core" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" +dependencies = [ + "windows-targets 0.52.5", +] + +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets 0.48.5", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.5", +] + +[[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", +] + +[[package]] +name = "windows-targets" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb" +dependencies = [ + "windows_aarch64_gnullvm 0.52.5", + "windows_aarch64_msvc 0.52.5", + "windows_i686_gnu 0.52.5", + "windows_i686_gnullvm", + "windows_i686_msvc 0.52.5", + "windows_x86_64_gnu 0.52.5", + "windows_x86_64_gnullvm 0.52.5", + "windows_x86_64_msvc 0.52.5", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6" + +[[package]] +name = "windows_i686_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9" + +[[package]] +name = "windows_i686_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" + +[[package]] +name = "winnow" +version = "0.5.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f593a95398737aeed53e489c785df13f3618e41dbcd6718c6addbf1395aa6876" +dependencies = [ + "memchr", +] + +[[package]] +name = "zerocopy" +version = "0.7.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae87e3fcd617500e5d106f0380cf7b77f3c6092aae37191433159dda23cfb087" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15e934569e47891f7d9411f1a451d947a60e000ab3bd24fbb970f000387d1b3b" +dependencies = [ + "proc-macro2 1.0.85", + "quote 1.0.36", + "syn 2.0.66", +] + +[[package]] +name = "zeroize" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" diff --git a/rqjs-ext/Cargo.toml b/rqjs-ext/Cargo.toml new file mode 100644 index 0000000..0d44f9c --- /dev/null +++ b/rqjs-ext/Cargo.toml @@ -0,0 +1,54 @@ +[package] +name = "rqjs-ext" +version = "0.1.3" +edition = "2021" +license = "MIT" +description = "rqjs-ext" +authors = ["ahaoboy"] +repository = "https://github.com/ahaoboy/rqjs" +homepage = "https://github.com/ahaoboy/rqjs" + +[dependencies] +clap = { version = "4", features = ["derive"] } +rquickjs = { version = "0.6.2", features = ["full-async","bindgen"] } +ctrlc = "3.4.4" +once_cell = "1" +cross-uname = "0.1.0" +tokio = { version = "1", features = ["full"] } +fxhash = "0.2" +phf = "0.11" +encoding_rs = "0.8" +hex-simd = "0.8" +base64-simd = "0.8" +simd-json = "0.13" +itoa = "1.0.11" +ryu = "1.0.18" +rand = "0.8.5" +uuid = { version = "1.8.0", default-features = false, features = [ + "v1", + "v3", + "v4", + "v5", + "fast-rng", +] } +uuid-simd = "0.8.0" +ring = "0.17.8" +rustls = { version = "0.23.10", default-features = false, features = [ + "tls12", + "ring", +] } +hyper = { version = "1.3.1", features = ["client", "http1", "http2"] } +hyper-rustls = { version = "0.27.2", default-features = false, features = [ + "http2", + "http1", + "webpki-roots", + "webpki-tokio", + "ring", +] } +chrono = { version = "0.4.38", default-features = false, features = ["std"] } +quick-xml = "0.32.0" +crc32c = { version = "0.6.8" } +crc32fast = "1.4.2" +# md-5 = { version = "0.10.6", features = ["asm"] } +md-5 = { version = "0.10.6" } + diff --git a/rqjs-ext/biome.json b/rqjs-ext/biome.json new file mode 100644 index 0000000..a15584c --- /dev/null +++ b/rqjs-ext/biome.json @@ -0,0 +1,61 @@ +{ + "$schema": "https://biomejs.dev/schemas/1.8.1/schema.json", + "organizeImports": { + "enabled": true + }, + "javascript": { + "formatter": { + "semicolons": "asNeeded" + } + }, + "formatter": { + "enabled": true, + "indentStyle": "space", + "indentWidth": 2 + }, + "files": { + "ignore": [ + "*.sh", + "target", + "output", + "*.stackdump", + "*.ps1", + "*.yaml", + "./mpv-*/dist/**", + "./mpv-*/es/**", + "node_modules", + ".vscode", + ".github", + "./common", + "./coverage", + "./html", + "CHANGELOG.json" + ] + }, + "linter": { + "enabled": true, + "rules": { + "style": { + "useNodejsImportProtocol": "off", + "noNonNullAssertion": "off", + "noParameterAssign": "off" + }, + "complexity": { + "noBannedTypes": "off" + }, + "suspicious": { + "noArrayIndexKey": "off", + "noRedeclare": "off", + "noUnsafeDeclarationMerging": "off", + "noExplicitAny": "off", + "noImplicitAnyLet": "off", + "noFallthroughSwitchClause": "off", + "noAssignInExpressions": "off" + }, + "correctness": { + "useExhaustiveDependencies": "off" + }, + "recommended": true + } + } +} \ No newline at end of file diff --git a/rqjs-ext/deno-scripts/00_console.js b/rqjs-ext/deno-scripts/00_console.js new file mode 100644 index 0000000..69505ed --- /dev/null +++ b/rqjs-ext/deno-scripts/00_console.js @@ -0,0 +1,3355 @@ +(() => { + // node_modules/.pnpm/deno-console@0.1.3/node_modules/deno-console/dist/index.js + function isAnyArrayBuffer(value) { + return value instanceof ArrayBuffer || value instanceof SharedArrayBuffer; + } + function isArgumentsObject(value) { + return Object.prototype.toString.call(value) === "[object Arguments]"; + } + function isArrayBuffer(value) { + return value instanceof ArrayBuffer; + } + function isAsyncFunction(value) { + return typeof value === "function" && value.constructor && value.constructor.name === "AsyncFunction"; + } + function isBigIntObject(value) { + return typeof value === "object" && value !== null && typeof value.bigIntValue === "bigint"; + } + function isBooleanObject(value) { + return typeof value === "object" && value !== null && typeof value.valueOf() === "boolean"; + } + function isBoxedPrimitive(value) { + return typeof value === "object" && value !== null && Object(value) === value; + } + function isDataView(value) { + return value instanceof DataView; + } + function isDate(value) { + return value instanceof Date; + } + function isGeneratorFunction(value) { + return typeof value === "function" && value.constructor && value.constructor.name === "GeneratorFunction"; + } + function isGeneratorObject(value) { + return typeof value === "object" && typeof value.next === "function" && typeof value.throw === "function"; + } + function isMapIterator(value) { + return typeof value === "object" && value !== null && typeof value.next === "function"; + } + function isModuleNamespaceObject(value) { + return typeof value === "object" && value !== null && typeof value === "object" && "exports" in value; + } + function isNativeError(value) { + return typeof value === "object" && value !== null && value instanceof Error; + } + function isNumberObject(value) { + return typeof value === "object" && value !== null && value instanceof Number; + } + function isPromise(value) { + return typeof value === "object" && value !== null && typeof value.then === "function"; + } + function isProxy(value) { + return typeof value === "function" && typeof value.revocable === "function"; + } + function isMap(value) { + return value instanceof Map; + } + function isRegExp(value) { + return value instanceof RegExp; + } + function isSet(value) { + return value instanceof Set; + } + function isSetIterator(value) { + return typeof value === "object" && value !== null && typeof value.next === "function"; + } + function isSharedArrayBuffer(value) { + return value instanceof SharedArrayBuffer; + } + function isStringObject(value) { + return typeof value === "object" && value !== null && typeof value.valueOf === "function" && typeof value.toString === "function"; + } + function isSymbolObject(value) { + return typeof value === "object" && value !== null && typeof value.valueOf === "function" && typeof value.toString === "function"; + } + function isTypedArray(value) { + return ArrayBuffer.isView(value); + } + function isWeakMap(value) { + return value instanceof WeakMap; + } + function isWeakSet(value) { + return value instanceof WeakSet; + } + var core_default = () => { + const ALL_PROPERTIES = 0; + const ONLY_WRITABLE = 1; + const ONLY_ENUMERABLE = 2; + const ONLY_CONFIGURABLE = 4; + const ONLY_ENUM_WRITABLE = 6; + const SKIP_STRINGS = 8; + const SKIP_SYMBOLS = 16; + const isNumericLookup = {}; + function isArrayIndex(value) { + switch (typeof value) { + case "number": + return value >= 0 && (value | 0) === value; + case "string": { + const result = isNumericLookup[value]; + if (result !== void 0) { + return result; + } + const length = value.length; + if (length === 0) { + return isNumericLookup[value] = false; + } + let ch = 0; + let i = 0; + for (; i < length; ++i) { + ch = value.charCodeAt(i); + if (i === 0 && ch === 48 && length > 1 || ch < 48 || ch > 57) { + return isNumericLookup[value] = false; + } + } + return isNumericLookup[value] = true; + } + default: + return false; + } + } + function getOwnNonIndexProperties(obj, filter) { + let allProperties = [ + ...Object.getOwnPropertyNames(obj), + ...Object.getOwnPropertySymbols(obj) + ]; + if (Array.isArray(obj)) { + allProperties = allProperties.filter((k) => !isArrayIndex(k)); + } + if (filter === ALL_PROPERTIES) { + return allProperties; + } + const result = []; + for (const key of allProperties) { + const desc = Object.getOwnPropertyDescriptor(obj, key); + if (desc === void 0) { + continue; + } + if (filter & ONLY_WRITABLE && !desc.writable) { + continue; + } + if (filter & ONLY_ENUMERABLE && !desc.enumerable) { + continue; + } + if (filter & ONLY_CONFIGURABLE && !desc.configurable) { + continue; + } + if (filter & SKIP_STRINGS && typeof key === "string") { + continue; + } + if (filter & SKIP_SYMBOLS && typeof key === "symbol") { + continue; + } + result.push(key); + } + return result; + } + const internals = {}; + const primordials = {}; + primordials.ArrayBufferPrototypeGetByteLength = (that) => { + if (!ArrayBuffer.isView(that)) { + throw new Error(); + } + that.byteLength; + }; + primordials.ArrayPrototypePushApply = (that, ...args) => that.push(...args); + primordials.MapPrototypeGetSize = (that) => that.size; + primordials.RegExpPrototypeSymbolReplace = (that, ...args) => RegExp.prototype[Symbol.replace].call(that, ...args); + primordials.SafeArrayIterator = class SafeArrayIterator { + constructor(array) { + this.array = [...array]; + this.index = 0; + } + next() { + if (this.index < this.array.length) { + return { value: this.array[this.index++], done: false }; + } else { + return { done: true }; + } + } + [Symbol.iterator]() { + return this; + } + }; + primordials.SafeMap = Map; + primordials.SafeMapIterator = class SafeMapIterator { + get [Symbol.toStringTag]() { + return "Map Iterator"; + } + constructor(map) { + this.map = map; + this.keys = Array.from(map.keys()); + this.index = 0; + } + next() { + if (this.index < this.keys.length) { + const key = this.keys[this.index]; + const value = this.map.get(key); + this.index++; + return { value: [key, value], done: false }; + } else { + return { done: true }; + } + } + [Symbol.iterator]() { + return this; + } + }; + primordials.SafeRegExp = RegExp; + primordials.SafeSet = Set; + primordials.SafeSetIterator = class SafeSetIterator { + get [Symbol.toStringTag]() { + return "Set Iterator"; + } + constructor(set) { + this.set = set; + this.values = Array.from(set); + this.index = 0; + } + next() { + if (this.index < this.values.length) { + const value = this.values[this.index]; + this.index++; + return { value, done: false }; + } else { + return { done: true }; + } + } + [Symbol.iterator]() { + return this; + } + }; + primordials.SafeStringIterator = class SafeStringIterator { + get [Symbol.toStringTag]() { + return "String Iterator"; + } + constructor(str) { + this.str = str; + this.index = 0; + } + next() { + if (this.index < this.str.length) { + const char = this.str[this.index]; + this.index++; + return { value: char, done: false }; + } else { + return { done: true }; + } + } + [Symbol.iterator]() { + return this; + } + }; + primordials.SetPrototypeGetSize = (that) => that.size; + primordials.SymbolPrototypeGetDescription = (that) => that.description; + primordials.TypedArrayPrototypeGetByteLength = (that) => that.byteLength; + primordials.TypedArrayPrototypeGetLength = (that) => that.length; + primordials.TypedArrayPrototypeGetSymbolToStringTag = (that) => { + if (ArrayBuffer.isView(that)) { + return that[Symbol.toStringTag]; + } + }; + primordials.ObjectPrototype = Object.prototype; + primordials.ObjectPrototypeIsPrototypeOf = (that, ...args) => Object.prototype.isPrototypeOf.call(that, ...args); + primordials.ObjectPrototypePropertyIsEnumerable = (that, ...args) => Object.prototype.propertyIsEnumerable.call(that, ...args); + primordials.ObjectPrototypeToString = (that, ...args) => Object.prototype.toString.call(that, ...args); + primordials.ObjectAssign = (...args) => Object.assign(...args); + primordials.ObjectGetOwnPropertyDescriptor = (...args) => Object.getOwnPropertyDescriptor(...args); + primordials.ObjectGetOwnPropertyNames = (...args) => Object.getOwnPropertyNames(...args); + primordials.ObjectGetOwnPropertySymbols = (...args) => Object.getOwnPropertySymbols(...args); + primordials.ObjectHasOwn = (...args) => Object.hasOwn(...args); + primordials.ObjectIs = (...args) => Object.is(...args); + primordials.ObjectCreate = (...args) => Object.create(...args); + primordials.ObjectDefineProperty = (...args) => Object.defineProperty(...args); + primordials.ObjectFreeze = (...args) => Object.freeze(...args); + primordials.ObjectGetPrototypeOf = (...args) => Object.getPrototypeOf(...args); + primordials.ObjectSetPrototypeOf = (...args) => Object.setPrototypeOf(...args); + primordials.ObjectKeys = (...args) => Object.keys(...args); + primordials.ObjectFromEntries = (...args) => Object.fromEntries(...args); + primordials.ObjectValues = (...args) => Object.values(...args); + primordials.FunctionPrototypeBind = (that, ...args) => Function.prototype.bind.call(that, ...args); + primordials.FunctionPrototypeCall = (that, ...args) => Function.prototype.call.call(that, ...args); + primordials.FunctionPrototypeToString = (that, ...args) => Function.prototype.toString.call(that, ...args); + primordials.Array = Array; + primordials.ArrayPrototypeFill = (that, ...args) => Array.prototype.fill.call(that, ...args); + primordials.ArrayPrototypeFind = (that, ...args) => Array.prototype.find.call(that, ...args); + primordials.ArrayPrototypePop = (that, ...args) => Array.prototype.pop.call(that, ...args); + primordials.ArrayPrototypePush = (that, ...args) => Array.prototype.push.call(that, ...args); + primordials.ArrayPrototypeShift = (that, ...args) => Array.prototype.shift.call(that, ...args); + primordials.ArrayPrototypeUnshift = (that, ...args) => Array.prototype.unshift.call(that, ...args); + primordials.ArrayPrototypeSlice = (that, ...args) => Array.prototype.slice.call(that, ...args); + primordials.ArrayPrototypeSort = (that, ...args) => Array.prototype.sort.call(that, ...args); + primordials.ArrayPrototypeSplice = (that, ...args) => Array.prototype.splice.call(that, ...args); + primordials.ArrayPrototypeIncludes = (that, ...args) => Array.prototype.includes.call(that, ...args); + primordials.ArrayPrototypeJoin = (that, ...args) => Array.prototype.join.call(that, ...args); + primordials.ArrayPrototypeForEach = (that, ...args) => Array.prototype.forEach.call(that, ...args); + primordials.ArrayPrototypeFilter = (that, ...args) => Array.prototype.filter.call(that, ...args); + primordials.ArrayPrototypeMap = (that, ...args) => Array.prototype.map.call(that, ...args); + primordials.ArrayPrototypeReduce = (that, ...args) => Array.prototype.reduce.call(that, ...args); + primordials.ArrayIsArray = (...args) => Array.isArray(...args); + primordials.Number = Number; + primordials.NumberPrototypeToString = (that, ...args) => Number.prototype.toString.call(that, ...args); + primordials.NumberPrototypeValueOf = (that, ...args) => Number.prototype.valueOf.call(that, ...args); + primordials.NumberIsInteger = (...args) => Number.isInteger(...args); + primordials.NumberParseInt = (...args) => Number.parseInt(...args); + primordials.Boolean = Boolean; + primordials.BooleanPrototypeValueOf = (that, ...args) => Boolean.prototype.valueOf.call(that, ...args); + primordials.String = String; + primordials.StringPrototypeCharCodeAt = (that, ...args) => String.prototype.charCodeAt.call(that, ...args); + primordials.StringPrototypeCodePointAt = (that, ...args) => String.prototype.codePointAt.call(that, ...args); + primordials.StringPrototypeEndsWith = (that, ...args) => String.prototype.endsWith.call(that, ...args); + primordials.StringPrototypeIncludes = (that, ...args) => String.prototype.includes.call(that, ...args); + primordials.StringPrototypeIndexOf = (that, ...args) => String.prototype.indexOf.call(that, ...args); + primordials.StringPrototypeLastIndexOf = (that, ...args) => String.prototype.lastIndexOf.call(that, ...args); + primordials.StringPrototypeMatch = (that, ...args) => String.prototype.match.call(that, ...args); + primordials.StringPrototypeNormalize = (that, ...args) => String.prototype.normalize.call(that, ...args); + primordials.StringPrototypePadEnd = (that, ...args) => String.prototype.padEnd.call(that, ...args); + primordials.StringPrototypePadStart = (that, ...args) => String.prototype.padStart.call(that, ...args); + primordials.StringPrototypeRepeat = (that, ...args) => String.prototype.repeat.call(that, ...args); + primordials.StringPrototypeReplace = (that, ...args) => String.prototype.replace.call(that, ...args); + primordials.StringPrototypeReplaceAll = (that, ...args) => String.prototype.replaceAll.call(that, ...args); + primordials.StringPrototypeSlice = (that, ...args) => String.prototype.slice.call(that, ...args); + primordials.StringPrototypeSplit = (that, ...args) => String.prototype.split.call(that, ...args); + primordials.StringPrototypeStartsWith = (that, ...args) => String.prototype.startsWith.call(that, ...args); + primordials.StringPrototypeTrim = (that, ...args) => String.prototype.trim.call(that, ...args); + primordials.StringPrototypeToLowerCase = (that, ...args) => String.prototype.toLowerCase.call(that, ...args); + primordials.StringPrototypeValueOf = (that, ...args) => String.prototype.valueOf.call(that, ...args); + primordials.Symbol = Symbol; + primordials.SymbolPrototypeToString = (that, ...args) => Symbol.prototype.toString.call(that, ...args); + primordials.SymbolPrototypeValueOf = (that, ...args) => Symbol.prototype.valueOf.call(that, ...args); + primordials.SymbolFor = (...args) => Symbol.for(...args); + primordials.SymbolHasInstance = Symbol.hasInstance; + primordials.SymbolIterator = Symbol.iterator; + primordials.SymbolToStringTag = Symbol.toStringTag; + primordials.DatePrototype = Date.prototype; + primordials.DatePrototypeToISOString = (that, ...args) => Date.prototype.toISOString.call(that, ...args); + primordials.DatePrototypeGetTime = (that, ...args) => Date.prototype.getTime.call(that, ...args); + primordials.DateNow = (...args) => Date.now(...args); + primordials.RegExpPrototypeExec = (that, ...args) => RegExp.prototype.exec.call(that, ...args); + primordials.RegExpPrototypeToString = (that, ...args) => RegExp.prototype.toString.call(that, ...args); + primordials.RegExpPrototypeTest = (that, ...args) => RegExp.prototype.test.call(that, ...args); + primordials.Error = Error; + primordials.ErrorPrototype = Error.prototype; + primordials.ErrorPrototypeToString = (that, ...args) => Error.prototype.toString.call(that, ...args); + primordials.ErrorCaptureStackTrace = (...args) => Error.captureStackTrace(...args); + primordials.AggregateErrorPrototype = AggregateError.prototype; + primordials.MathAbs = (...args) => Math.abs(...args); + primordials.MathFloor = (...args) => Math.floor(...args); + primordials.MathMax = (...args) => Math.max(...args); + primordials.MathMin = (...args) => Math.min(...args); + primordials.MathRound = (...args) => Math.round(...args); + primordials.MathSqrt = (...args) => Math.sqrt(...args); + primordials.ArrayBufferIsView = (...args) => ArrayBuffer.isView(...args); + primordials.Uint8Array = Uint8Array; + primordials.MapPrototype = Map.prototype; + primordials.MapPrototypeGet = (that, ...args) => Map.prototype.get.call(that, ...args); + primordials.MapPrototypeSet = (that, ...args) => Map.prototype.set.call(that, ...args); + primordials.MapPrototypeHas = (that, ...args) => Map.prototype.has.call(that, ...args); + primordials.MapPrototypeDelete = (that, ...args) => Map.prototype.delete.call(that, ...args); + primordials.MapPrototypeEntries = (that, ...args) => Map.prototype.entries.call(that, ...args); + primordials.MapPrototypeForEach = (that, ...args) => Map.prototype.forEach.call(that, ...args); + primordials.BigIntPrototypeValueOf = (that, ...args) => BigInt.prototype.valueOf.call(that, ...args); + primordials.SetPrototype = Set.prototype; + primordials.SetPrototypeHas = (that, ...args) => Set.prototype.has.call(that, ...args); + primordials.SetPrototypeAdd = (that, ...args) => Set.prototype.add.call(that, ...args); + primordials.SetPrototypeValues = (that, ...args) => Set.prototype.values.call(that, ...args); + primordials.WeakMapPrototypeHas = (that, ...args) => WeakMap.prototype.has.call(that, ...args); + primordials.WeakSetPrototypeHas = (that, ...args) => WeakSet.prototype.has.call(that, ...args); + primordials.Proxy = Proxy; + primordials.ReflectGet = (...args) => Reflect.get(...args); + primordials.ReflectGetOwnPropertyDescriptor = (...args) => Reflect.getOwnPropertyDescriptor(...args); + primordials.ReflectGetPrototypeOf = (...args) => Reflect.getPrototypeOf(...args); + primordials.ReflectHas = (...args) => Reflect.has(...args); + primordials.ReflectOwnKeys = (...args) => Reflect.ownKeys(...args); + const ops = { + op_get_non_index_property_names: getOwnNonIndexProperties, + op_get_constructor_name(v) { + return Object.prototype.toString.call(v).slice(8, -1); + } + }; + globalThis.Deno = { + core: { + ops, + getPromiseDetails() { + return [-1, Symbol("UNKNOWN")]; + }, + // TODO: support proxy details + getProxyDetails() { + return null; + }, + isAnyArrayBuffer, + isArgumentsObject, + isArrayBuffer, + isAsyncFunction, + isBigIntObject, + isBooleanObject, + isBoxedPrimitive, + isDataView, + isDate, + isGeneratorFunction, + isGeneratorObject, + isMap, + isMapIterator, + isModuleNamespaceObject, + isNativeError, + isNumberObject, + isPromise, + isProxy, + isRegExp, + isSet, + isSetIterator, + isSharedArrayBuffer, + isStringObject, + isSymbolObject, + isTypedArray, + isWeakMap, + isWeakSet, + op_get_non_index_property_names: getOwnNonIndexProperties + } + }; + globalThis.__bootstrap = { + internals, + primordials + }; + }; + var console_default = (noColorStdout, noColorStderr) => { + const core = globalThis.Deno.core; + const primordials = globalThis.__bootstrap.primordials; + const { + isAnyArrayBuffer: isAnyArrayBuffer2, + isArgumentsObject: isArgumentsObject2, + isArrayBuffer: isArrayBuffer2, + isAsyncFunction: isAsyncFunction2, + isBigIntObject: isBigIntObject2, + isBooleanObject: isBooleanObject2, + isBoxedPrimitive: isBoxedPrimitive2, + isDataView: isDataView2, + isDate: isDate2, + isGeneratorFunction: isGeneratorFunction2, + isMap: isMap2, + isMapIterator: isMapIterator2, + isModuleNamespaceObject: isModuleNamespaceObject2, + isNativeError: isNativeError2, + isNumberObject: isNumberObject2, + isPromise: isPromise2, + isRegExp: isRegExp2, + isSet: isSet2, + isSetIterator: isSetIterator2, + isStringObject: isStringObject2, + isTypedArray: isTypedArray2, + isWeakMap: isWeakMap2, + isWeakSet: isWeakSet2 + } = core; + const { + op_get_constructor_name, + op_get_non_index_property_names, + op_preview_entries + } = core; + const { + Array: Array2, + ArrayBufferPrototypeGetByteLength, + ArrayIsArray, + ArrayPrototypeFill, + ArrayPrototypeFilter, + ArrayPrototypeFind, + ArrayPrototypeForEach, + ArrayPrototypeIncludes, + ArrayPrototypeJoin, + ArrayPrototypeMap, + ArrayPrototypePop, + ArrayPrototypePush, + ArrayPrototypePushApply, + ArrayPrototypeReduce, + ArrayPrototypeShift, + ArrayPrototypeSlice, + ArrayPrototypeSort, + ArrayPrototypeSplice, + ArrayPrototypeUnshift, + BigIntPrototypeValueOf, + Boolean: Boolean2, + BooleanPrototypeValueOf, + DateNow, + DatePrototypeGetTime, + DatePrototypeToISOString, + Error: Error2, + ErrorCaptureStackTrace, + ErrorPrototype, + ErrorPrototypeToString, + FunctionPrototypeBind, + FunctionPrototypeCall, + FunctionPrototypeToString, + MapPrototypeDelete, + MapPrototypeEntries, + MapPrototypeForEach, + MapPrototypeGet, + MapPrototypeGetSize, + MapPrototypeHas, + MapPrototypeSet, + MathAbs, + MathFloor, + MathMax, + MathMin, + MathRound, + MathSqrt, + Number: Number2, + NumberIsInteger, + NumberIsNaN, + NumberParseInt, + NumberPrototypeToString, + NumberPrototypeValueOf, + ObjectAssign, + ObjectCreate, + ObjectDefineProperty, + ObjectFreeze, + ObjectFromEntries, + ObjectGetOwnPropertyDescriptor, + ObjectGetOwnPropertyNames, + ObjectGetOwnPropertySymbols, + ObjectGetPrototypeOf, + ObjectHasOwn, + ObjectIs, + ObjectKeys, + ObjectPrototype, + ObjectPrototypeIsPrototypeOf, + ObjectPrototypePropertyIsEnumerable, + ObjectSetPrototypeOf, + ObjectValues, + Proxy: Proxy2, + ReflectGet, + ReflectGetOwnPropertyDescriptor, + ReflectGetPrototypeOf, + ReflectHas, + ReflectOwnKeys, + RegExpPrototypeExec, + RegExpPrototypeSymbolReplace, + RegExpPrototypeTest, + RegExpPrototypeToString, + SafeArrayIterator, + SafeMap, + SafeMapIterator, + SafeRegExp, + SafeSet, + SafeSetIterator, + SafeStringIterator, + SetPrototypeAdd, + SetPrototypeGetSize, + SetPrototypeHas, + SetPrototypeValues, + String: String2, + StringPrototypeCharCodeAt, + StringPrototypeCodePointAt, + StringPrototypeEndsWith, + StringPrototypeIncludes, + StringPrototypeIndexOf, + StringPrototypeLastIndexOf, + StringPrototypeMatch, + StringPrototypeNormalize, + StringPrototypePadEnd, + StringPrototypePadStart, + StringPrototypeRepeat, + StringPrototypeReplace, + StringPrototypeReplaceAll, + StringPrototypeSlice, + StringPrototypeSplit, + StringPrototypeStartsWith, + StringPrototypeToLowerCase, + StringPrototypeTrim, + StringPrototypeValueOf, + Symbol: Symbol2, + SymbolFor, + SymbolHasInstance, + SymbolIterator, + SymbolPrototypeGetDescription, + SymbolPrototypeToString, + SymbolPrototypeValueOf, + SymbolToStringTag, + TypedArrayPrototypeGetByteLength, + TypedArrayPrototypeGetLength, + Uint8Array: Uint8Array2 + } = primordials; + class AssertionError extends Error2 { + name = "AssertionError"; + constructor(message) { + super(message); + } + } + function assert(cond, msg = "Assertion failed.") { + if (!cond) { + throw new AssertionError(msg); + } + } + const styles = { + special: "cyan", + number: "yellow", + bigint: "yellow", + boolean: "yellow", + undefined: "grey", + null: "bold", + string: "green", + symbol: "green", + date: "magenta", + // "name": intentionally not styling + // TODO(BridgeAR): Highlight regular expressions properly. + regexp: "red", + module: "underline", + internalError: "red", + temporal: "magenta" + }; + const defaultFG = 39; + const defaultBG = 49; + const colors = { + reset: [0, 0], + bold: [1, 22], + dim: [2, 22], + // Alias: faint + italic: [3, 23], + underline: [4, 24], + blink: [5, 25], + // Swap foreground and background colors + inverse: [7, 27], + // Alias: swapcolors, swapColors + hidden: [8, 28], + // Alias: conceal + strikethrough: [9, 29], + // Alias: strikeThrough, crossedout, crossedOut + doubleunderline: [21, 24], + // Alias: doubleUnderline + black: [30, defaultFG], + red: [31, defaultFG], + green: [32, defaultFG], + yellow: [33, defaultFG], + blue: [34, defaultFG], + magenta: [35, defaultFG], + cyan: [36, defaultFG], + white: [37, defaultFG], + bgBlack: [40, defaultBG], + bgRed: [41, defaultBG], + bgGreen: [42, defaultBG], + bgYellow: [43, defaultBG], + bgBlue: [44, defaultBG], + bgMagenta: [45, defaultBG], + bgCyan: [46, defaultBG], + bgWhite: [47, defaultBG], + framed: [51, 54], + overlined: [53, 55], + gray: [90, defaultFG], + // Alias: grey, blackBright + redBright: [91, defaultFG], + greenBright: [92, defaultFG], + yellowBright: [93, defaultFG], + blueBright: [94, defaultFG], + magentaBright: [95, defaultFG], + cyanBright: [96, defaultFG], + whiteBright: [97, defaultFG], + bgGray: [100, defaultBG], + // Alias: bgGrey, bgBlackBright + bgRedBright: [101, defaultBG], + bgGreenBright: [102, defaultBG], + bgYellowBright: [103, defaultBG], + bgBlueBright: [104, defaultBG], + bgMagentaBright: [105, defaultBG], + bgCyanBright: [106, defaultBG], + bgWhiteBright: [107, defaultBG] + }; + function defineColorAlias(target, alias) { + ObjectDefineProperty(colors, alias, { + get() { + return this[target]; + }, + set(value) { + this[target] = value; + }, + configurable: true, + enumerable: false + }); + } + defineColorAlias("gray", "grey"); + defineColorAlias("gray", "blackBright"); + defineColorAlias("bgGray", "bgGrey"); + defineColorAlias("bgGray", "bgBlackBright"); + defineColorAlias("dim", "faint"); + defineColorAlias("strikethrough", "crossedout"); + defineColorAlias("strikethrough", "strikeThrough"); + defineColorAlias("strikethrough", "crossedOut"); + defineColorAlias("hidden", "conceal"); + defineColorAlias("inverse", "swapColors"); + defineColorAlias("inverse", "swapcolors"); + defineColorAlias("doubleunderline", "doubleUnderline"); + let _getSharedArrayBufferByteLength; + function getSharedArrayBufferByteLength(value) { + _getSharedArrayBufferByteLength ??= ObjectGetOwnPropertyDescriptor( + // deno-lint-ignore prefer-primordials + SharedArrayBuffer.prototype, + "byteLength" + ).get; + return FunctionPrototypeCall(_getSharedArrayBufferByteLength, value); + } + function isAggregateError(value) { + return isNativeError2(value) && value.name === "AggregateError" && ArrayIsArray(value.errors); + } + const kObjectType = 0; + const kArrayType = 1; + const kArrayExtrasType = 2; + const kMinLineLength = 16; + const kWeak = 0; + const kIterator = 1; + const kMapEntries = 2; + const meta = [ + "\\x00", + "\\x01", + "\\x02", + "\\x03", + "\\x04", + "\\x05", + "\\x06", + "\\x07", + // x07 + "\\b", + "\\t", + "\\n", + "\\x0B", + "\\f", + "\\r", + "\\x0E", + "\\x0F", + // x0F + "\\x10", + "\\x11", + "\\x12", + "\\x13", + "\\x14", + "\\x15", + "\\x16", + "\\x17", + // x17 + "\\x18", + "\\x19", + "\\x1A", + "\\x1B", + "\\x1C", + "\\x1D", + "\\x1E", + "\\x1F", + // x1F + "", + "", + "", + "", + "", + "", + "", + "\\'", + "", + "", + "", + "", + "", + "", + "", + "", + // x2F + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + // x3F + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + // x4F + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "\\\\", + "", + "", + "", + // x5F + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + // x6F + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "\\x7F", + // x7F + "\\x80", + "\\x81", + "\\x82", + "\\x83", + "\\x84", + "\\x85", + "\\x86", + "\\x87", + // x87 + "\\x88", + "\\x89", + "\\x8A", + "\\x8B", + "\\x8C", + "\\x8D", + "\\x8E", + "\\x8F", + // x8F + "\\x90", + "\\x91", + "\\x92", + "\\x93", + "\\x94", + "\\x95", + "\\x96", + "\\x97", + // x97 + "\\x98", + "\\x99", + "\\x9A", + "\\x9B", + "\\x9C", + "\\x9D", + "\\x9E", + "\\x9F" + // x9F + ]; + const isUndetectableObject = (v) => typeof v === "undefined" && v !== void 0; + const strEscapeSequencesReplacer = new SafeRegExp( + "[\0-'\\\x7F-\x9F]", + "g" + ); + const keyStrRegExp = new SafeRegExp("^[a-zA-Z_][a-zA-Z_0-9]*$"); + const numberRegExp = new SafeRegExp("^(0|[1-9][0-9]*)$"); + const escapeFn = (str) => meta[StringPrototypeCharCodeAt(str, 0)]; + function stylizeNoColor(str) { + return str; + } + const nodeCustomInspectSymbol = SymbolFor("nodejs.util.inspect.custom"); + const privateCustomInspect = SymbolFor("Deno.privateCustomInspect"); + function getUserOptions(ctx, isCrossContext) { + const ret = { + stylize: ctx.stylize, + showHidden: ctx.showHidden, + depth: ctx.depth, + colors: ctx.colors, + customInspect: ctx.customInspect, + showProxy: ctx.showProxy, + maxArrayLength: ctx.maxArrayLength, + maxStringLength: ctx.maxStringLength, + breakLength: ctx.breakLength, + compact: ctx.compact, + sorted: ctx.sorted, + getters: ctx.getters, + numericSeparator: ctx.numericSeparator, + ...ctx.userOptions + }; + if (isCrossContext) { + ObjectSetPrototypeOf(ret, null); + for (const key of new SafeArrayIterator(ObjectKeys(ret))) { + if ((typeof ret[key] === "object" || typeof ret[key] === "function") && ret[key] !== null) { + delete ret[key]; + } + } + ret.stylize = ObjectSetPrototypeOf((value, flavour) => { + let stylized; + try { + stylized = `${ctx.stylize(value, flavour)}`; + } catch { + } + if (typeof stylized !== "string") + return value; + return stylized; + }, null); + } + return ret; + } + function formatValue(ctx, value, recurseTimes, typedArray) { + if (typeof value !== "object" && typeof value !== "function" && !isUndetectableObject(value)) { + return formatPrimitive(ctx.stylize, value, ctx); + } + if (value === null) { + return ctx.stylize("null", "null"); + } + const context = value; + const proxyDetails = core.getProxyDetails(value); + if (ctx.customInspect) { + if (ReflectHas(value, customInspect) && typeof value[customInspect] === "function") { + return String2(value[customInspect](inspect, ctx)); + } else if (ReflectHas(value, privateCustomInspect) && typeof value[privateCustomInspect] === "function") { + return String2(value[privateCustomInspect](inspect, ctx)); + } else if (ReflectHas(value, nodeCustomInspectSymbol)) { + const maybeCustom = value[nodeCustomInspectSymbol]; + if (typeof maybeCustom === "function" && // Filter out the util module, its inspect function is special. + maybeCustom !== ctx.inspect && // Also filter out any prototype objects using the circular check. + !(value.constructor && value.constructor.prototype === value)) { + const depth = ctx.depth === null ? null : ctx.depth - recurseTimes; + const isCrossContext = !ObjectPrototypeIsPrototypeOf( + ObjectPrototype, + context + ); + const ret = FunctionPrototypeCall( + maybeCustom, + context, + depth, + getUserOptions(ctx, isCrossContext), + ctx.inspect + ); + if (ret !== context) { + if (typeof ret !== "string") { + return formatValue(ctx, ret, recurseTimes); + } + return StringPrototypeReplaceAll( + ret, + "\n", + ` +${StringPrototypeRepeat(" ", ctx.indentationLvl)}` + ); + } + } + } + } + if (ArrayPrototypeIncludes(ctx.seen, value)) { + let index = 1; + if (ctx.circular === void 0) { + ctx.circular = new SafeMap(); + MapPrototypeSet(ctx.circular, value, index); + } else { + index = ctx.circular.get(value); + if (index === void 0) { + index = ctx.circular.size + 1; + MapPrototypeSet(ctx.circular, value, index); + } + } + return ctx.stylize(`[Circular *${index}]`, "special"); + } + return formatRaw(ctx, value, recurseTimes, typedArray, proxyDetails); + } + function getClassBase(value, constructor, tag) { + const hasName = ObjectHasOwn(value, "name"); + const name = hasName && value.name || "(anonymous)"; + let base = `class ${name}`; + if (constructor !== "Function" && constructor !== null) { + base += ` [${constructor}]`; + } + if (tag !== "" && constructor !== tag) { + base += ` [${tag}]`; + } + if (constructor !== null) { + const superName = ObjectGetPrototypeOf(value).name; + if (superName) { + base += ` extends ${superName}`; + } + } else { + base += " extends [null prototype]"; + } + return `[${base}]`; + } + const stripCommentsRegExp = new SafeRegExp( + "(\\/\\/.*?\\n)|(\\/\\*(.|\\n)*?\\*\\/)", + "g" + ); + const classRegExp = new SafeRegExp("^(\\s+[^(]*?)\\s*{"); + function getFunctionBase(value, constructor, tag) { + const stringified = FunctionPrototypeToString(value); + if (StringPrototypeStartsWith(stringified, "class") && StringPrototypeEndsWith(stringified, "}")) { + const slice = StringPrototypeSlice(stringified, 5, -1); + const bracketIndex = StringPrototypeIndexOf(slice, "{"); + if (bracketIndex !== -1 && (!StringPrototypeIncludes( + StringPrototypeSlice(slice, 0, bracketIndex), + "(" + ) || // Slow path to guarantee that it's indeed a class. + RegExpPrototypeExec( + classRegExp, + RegExpPrototypeSymbolReplace(stripCommentsRegExp, slice) + ) !== null)) { + return getClassBase(value, constructor, tag); + } + } + let type = "Function"; + if (isGeneratorFunction2(value)) { + type = `Generator${type}`; + } + if (isAsyncFunction2(value)) { + type = `Async${type}`; + } + let base = `[${type}`; + if (constructor === null) { + base += " (null prototype)"; + } + if (value.name === "") { + base += " (anonymous)"; + } else { + base += `: ${value.name}`; + } + base += "]"; + if (constructor !== type && constructor !== null) { + base += ` ${constructor}`; + } + if (tag !== "" && constructor !== tag) { + base += ` [${tag}]`; + } + return base; + } + function formatRaw(ctx, value, recurseTimes, typedArray, proxyDetails) { + let keys; + let protoProps; + if (ctx.showHidden && (recurseTimes <= ctx.depth || ctx.depth === null)) { + protoProps = []; + } + const constructor = getConstructorName(value, ctx, recurseTimes, protoProps); + if (protoProps !== void 0 && protoProps.length === 0) { + protoProps = void 0; + } + let tag = value[SymbolToStringTag]; + if (typeof tag !== "string") { + tag = ""; + } + let base = ""; + let formatter = () => []; + let braces; + let noIterator = true; + let i = 0; + const filter = ctx.showHidden ? 0 : 2; + let extrasType = kObjectType; + if (proxyDetails !== null && ctx.showProxy) { + return `Proxy ` + formatValue(ctx, proxyDetails, recurseTimes); + } else { + if (ReflectHas(value, SymbolIterator) || constructor === null) { + noIterator = false; + if (ArrayIsArray(value)) { + const prefix = constructor !== "Array" || tag !== "" ? getPrefix(constructor, tag, "Array", `(${value.length})`) : ""; + keys = op_get_non_index_property_names(value, filter); + braces = [`${prefix}[`, "]"]; + if (value.length === 0 && keys.length === 0 && protoProps === void 0) { + return `${braces[0]}]`; + } + extrasType = kArrayExtrasType; + formatter = formatArray; + } else if (proxyDetails === null && isSet2(value) || proxyDetails !== null && isSet2(proxyDetails[0])) { + const set = proxyDetails?.[0] ?? value; + const size = SetPrototypeGetSize(set); + const prefix = getPrefix(constructor, tag, "Set", `(${size})`); + keys = getKeys(set, ctx.showHidden); + formatter = constructor !== null ? FunctionPrototypeBind(formatSet, null, set) : FunctionPrototypeBind(formatSet, null, SetPrototypeValues(set)); + if (size === 0 && keys.length === 0 && protoProps === void 0) { + return `${prefix}{}`; + } + braces = [`${prefix}{`, "}"]; + } else if (proxyDetails === null && isMap2(value) || proxyDetails !== null && isMap2(proxyDetails[0])) { + const map = proxyDetails?.[0] ?? value; + const size = MapPrototypeGetSize(map); + const prefix = getPrefix(constructor, tag, "Map", `(${size})`); + keys = getKeys(map, ctx.showHidden); + formatter = constructor !== null ? FunctionPrototypeBind(formatMap, null, map) : FunctionPrototypeBind(formatMap, null, MapPrototypeEntries(map)); + if (size === 0 && keys.length === 0 && protoProps === void 0) { + return `${prefix}{}`; + } + braces = [`${prefix}{`, "}"]; + } else if (proxyDetails === null && isTypedArray2(value) || proxyDetails !== null && isTypedArray2(proxyDetails[0])) { + const typedArray2 = proxyDetails?.[0] ?? value; + keys = op_get_non_index_property_names(typedArray2, filter); + const bound = typedArray2; + const fallback = ""; + if (constructor === null) { + } + const size = TypedArrayPrototypeGetLength(typedArray2); + const prefix = getPrefix(constructor, tag, fallback, `(${size})`); + braces = [`${prefix}[`, "]"]; + if (typedArray2.length === 0 && keys.length === 0 && !ctx.showHidden) { + return `${braces[0]}]`; + } + formatter = FunctionPrototypeBind(formatTypedArray, null, bound, size); + extrasType = kArrayExtrasType; + } else if (proxyDetails === null && isMapIterator2(value) || proxyDetails !== null && isMapIterator2(proxyDetails[0])) { + const mapIterator = proxyDetails?.[0] ?? value; + keys = getKeys(mapIterator, ctx.showHidden); + braces = getIteratorBraces("Map", tag); + formatter = FunctionPrototypeBind(formatIterator, null, braces); + } else if (proxyDetails === null && isSetIterator2(value) || proxyDetails !== null && isSetIterator2(proxyDetails[0])) { + const setIterator = proxyDetails?.[0] ?? value; + keys = getKeys(setIterator, ctx.showHidden); + braces = getIteratorBraces("Set", tag); + formatter = FunctionPrototypeBind(formatIterator, null, braces); + } else { + noIterator = true; + } + } + if (noIterator) { + keys = getKeys(value, ctx.showHidden); + braces = ["{", "}"]; + if (constructor === "Object") { + if (isArgumentsObject2(value)) { + braces[0] = "[Arguments] {"; + } else if (tag !== "") { + braces[0] = `${getPrefix(constructor, tag, "Object")}{`; + } + if (keys.length === 0 && protoProps === void 0) { + return `${braces[0]}}`; + } + } else if (typeof value === "function") { + base = getFunctionBase(value, constructor, tag); + if (keys.length === 0 && protoProps === void 0) { + return ctx.stylize(base, "special"); + } + } else if (proxyDetails === null && isRegExp2(value) || proxyDetails !== null && isRegExp2(proxyDetails[0])) { + const regExp = proxyDetails?.[0] ?? value; + base = RegExpPrototypeToString( + constructor !== null ? regExp : new SafeRegExp(regExp) + ); + const prefix = getPrefix(constructor, tag, "RegExp"); + if (prefix !== "RegExp ") { + base = `${prefix}${base}`; + } + if (keys.length === 0 && protoProps === void 0 || recurseTimes > ctx.depth && ctx.depth !== null) { + return ctx.stylize(base, "regexp"); + } + } else if (proxyDetails === null && isDate2(value) || proxyDetails !== null && isDate2(proxyDetails[0])) { + const date = proxyDetails?.[0] ?? value; + if (NumberIsNaN(DatePrototypeGetTime(date))) { + return ctx.stylize("Invalid Date", "date"); + } else { + base = DatePrototypeToISOString(date); + if (keys.length === 0 && protoProps === void 0) { + return ctx.stylize(base, "date"); + } + } + } else if (proxyDetails === null && typeof globalThis.Temporal !== "undefined" && (ObjectPrototypeIsPrototypeOf( + globalThis.Temporal.Instant.prototype, + value + ) || ObjectPrototypeIsPrototypeOf( + globalThis.Temporal.ZonedDateTime.prototype, + value + ) || ObjectPrototypeIsPrototypeOf( + globalThis.Temporal.PlainDate.prototype, + value + ) || ObjectPrototypeIsPrototypeOf( + globalThis.Temporal.PlainTime.prototype, + value + ) || ObjectPrototypeIsPrototypeOf( + globalThis.Temporal.PlainDateTime.prototype, + value + ) || ObjectPrototypeIsPrototypeOf( + globalThis.Temporal.PlainYearMonth.prototype, + value + ) || ObjectPrototypeIsPrototypeOf( + globalThis.Temporal.PlainMonthDay.prototype, + value + ) || ObjectPrototypeIsPrototypeOf( + globalThis.Temporal.Duration.prototype, + value + ) || ObjectPrototypeIsPrototypeOf( + globalThis.Temporal.TimeZone.prototype, + value + ) || ObjectPrototypeIsPrototypeOf( + globalThis.Temporal.Calendar.prototype, + value + ))) { + return ctx.stylize(value.toString(), "temporal"); + } else if (proxyDetails === null && (isNativeError2(value) || ObjectPrototypeIsPrototypeOf(ErrorPrototype, value)) || proxyDetails !== null && (isNativeError2(proxyDetails[0]) || ObjectPrototypeIsPrototypeOf(ErrorPrototype, proxyDetails[0]))) { + const error = proxyDetails?.[0] ?? value; + base = inspectError(error, ctx); + if (keys.length === 0 && protoProps === void 0) { + return base; + } + } else if (isAnyArrayBuffer2(value)) { + const arrayType = isArrayBuffer2(value) ? "ArrayBuffer" : "SharedArrayBuffer"; + const prefix = getPrefix(constructor, tag, arrayType); + if (typedArray === void 0) { + formatter = formatArrayBuffer; + } else if (keys.length === 0 && protoProps === void 0) { + return prefix + `{ byteLength: ${formatNumber( + ctx.stylize, + TypedArrayPrototypeGetByteLength(value) + )} }`; + } + braces[0] = `${prefix}{`; + ArrayPrototypeUnshift(keys, "byteLength"); + } else if (isDataView2(value)) { + braces[0] = `${getPrefix(constructor, tag, "DataView")}{`; + ArrayPrototypeUnshift(keys, "byteLength", "byteOffset", "buffer"); + } else if (isPromise2(value)) { + braces[0] = `${getPrefix(constructor, tag, "Promise")}{`; + formatter = formatPromise; + } else if (isWeakSet2(value)) { + braces[0] = `${getPrefix(constructor, tag, "WeakSet")}{`; + formatter = ctx.showHidden ? formatWeakSet : formatWeakCollection; + } else if (isWeakMap2(value)) { + braces[0] = `${getPrefix(constructor, tag, "WeakMap")}{`; + formatter = ctx.showHidden ? formatWeakMap : formatWeakCollection; + } else if (isModuleNamespaceObject2(value)) { + braces[0] = `${getPrefix(constructor, tag, "Module")}{`; + formatter = FunctionPrototypeBind(formatNamespaceObject, null, keys); + } else if (isBoxedPrimitive2(value)) { + base = getBoxedBase(value, ctx, keys, constructor, tag); + if (keys.length === 0 && protoProps === void 0) { + return base; + } + } else { + if (keys.length === 0 && protoProps === void 0) { + return `${getCtxStyle(value, constructor, tag)}{}`; + } + braces[0] = `${getCtxStyle(value, constructor, tag)}{`; + } + } + } + if (recurseTimes > ctx.depth && ctx.depth !== null) { + let constructorName = StringPrototypeSlice( + getCtxStyle(value, constructor, tag), + 0, + -1 + ); + if (constructor !== null) { + constructorName = `[${constructorName}]`; + } + return ctx.stylize(constructorName, "special"); + } + recurseTimes += 1; + ArrayPrototypePush(ctx.seen, value); + ctx.currentDepth = recurseTimes; + let output; + try { + output = formatter(ctx, value, recurseTimes); + for (i = 0; i < keys.length; i++) { + ArrayPrototypePush( + output, + formatProperty(ctx, value, recurseTimes, keys[i], extrasType) + ); + } + if (protoProps !== void 0) { + ArrayPrototypePushApply(output, protoProps); + } + } catch (error) { + return ctx.stylize( + `[Internal Formatting Error] ${error.stack}`, + "internalError" + ); + } + if (ctx.circular !== void 0) { + const index = ctx.circular.get(value); + if (index !== void 0) { + const reference = ctx.stylize(``, "special"); + if (ctx.compact !== true) { + base = base === "" ? reference : `${reference} ${base}`; + } else { + braces[0] = `${reference} ${braces[0]}`; + } + } + } + ArrayPrototypePop(ctx.seen); + if (ctx.sorted) { + const comparator = ctx.sorted === true ? void 0 : ctx.sorted; + if (extrasType === kObjectType) { + output = ArrayPrototypeSort(output, comparator); + } else if (keys.length > 1) { + const sorted = ArrayPrototypeSort( + ArrayPrototypeSlice(output, output.length - keys.length), + comparator + ); + ArrayPrototypeSplice( + output, + output.length - keys.length, + keys.length, + ...new SafeArrayIterator(sorted) + ); + } + } + const res = reduceToSingleString( + ctx, + output, + base, + braces, + extrasType, + recurseTimes, + value + ); + const budget = ctx.budget[ctx.indentationLvl] || 0; + const newLength = budget + res.length; + ctx.budget[ctx.indentationLvl] = newLength; + if (newLength > 2 ** 27) { + ctx.depth = -1; + } + return res; + } + const builtInObjectsRegExp = new SafeRegExp("^[A-Z][a-zA-Z0-9]+$"); + const builtInObjects = new SafeSet( + ArrayPrototypeFilter( + ObjectGetOwnPropertyNames(globalThis), + (e) => RegExpPrototypeTest(builtInObjectsRegExp, e) + ) + ); + function addPrototypeProperties(ctx, main, obj, recurseTimes, output) { + let depth = 0; + let keys; + let keySet; + do { + if (depth !== 0 || main === obj) { + obj = ObjectGetPrototypeOf(obj); + if (obj === null) { + return; + } + const descriptor = ObjectGetOwnPropertyDescriptor(obj, "constructor"); + if (descriptor !== void 0 && typeof descriptor.value === "function" && SetPrototypeHas(builtInObjects, descriptor.value.name)) { + return; + } + } + if (depth === 0) { + keySet = new SafeSet(); + } else { + ArrayPrototypeForEach(keys, (key) => SetPrototypeAdd(keySet, key)); + } + keys = ReflectOwnKeys(obj); + ArrayPrototypePush(ctx.seen, main); + for (const key of new SafeArrayIterator(keys)) { + if (key === "constructor" || ObjectHasOwn(main, key) || depth !== 0 && SetPrototypeHas(keySet, key)) { + continue; + } + const desc = ObjectGetOwnPropertyDescriptor(obj, key); + if (typeof desc.value === "function") { + continue; + } + const value = formatProperty( + ctx, + obj, + recurseTimes, + key, + kObjectType, + desc, + main + ); + if (ctx.colors) { + ArrayPrototypePush(output, `\x1B[2m${value}\x1B[22m`); + } else { + ArrayPrototypePush(output, value); + } + } + ArrayPrototypePop(ctx.seen); + } while (++depth !== 3); + } + function isInstanceof(proto, object) { + try { + return ObjectPrototypeIsPrototypeOf(proto, object); + } catch { + return false; + } + } + function getConstructorName(obj, ctx, recurseTimes, protoProps) { + let firstProto; + const tmp = obj; + while (obj || isUndetectableObject(obj)) { + let descriptor; + try { + descriptor = ObjectGetOwnPropertyDescriptor(obj, "constructor"); + } catch { + } + if (descriptor !== void 0 && typeof descriptor.value === "function" && descriptor.value.name !== "" && isInstanceof(descriptor.value.prototype, tmp)) { + if (protoProps !== void 0 && (firstProto !== obj || !SetPrototypeHas(builtInObjects, descriptor.value.name))) { + addPrototypeProperties( + ctx, + tmp, + firstProto || tmp, + recurseTimes, + protoProps + ); + } + return String2(descriptor.value.name); + } + obj = ObjectGetPrototypeOf(obj); + if (firstProto === void 0) { + firstProto = obj; + } + } + if (firstProto === null) { + return null; + } + const res = op_get_constructor_name(tmp); + if (recurseTimes > ctx.depth && ctx.depth !== null) { + return `${res} `; + } + const protoConstr = getConstructorName( + firstProto, + ctx, + recurseTimes + 1, + protoProps + ); + if (protoConstr === null) { + return `${res} <${inspect(firstProto, { + ...ctx, + customInspect: false, + depth: -1 + })}>`; + } + return `${res} <${protoConstr}>`; + } + const formatPrimitiveRegExp = new SafeRegExp("(?<=\n)"); + function formatPrimitive(fn, value, ctx) { + if (typeof value === "string") { + let trailer = ""; + if (value.length > ctx.maxStringLength) { + const remaining = value.length - ctx.maxStringLength; + value = StringPrototypeSlice(value, 0, ctx.maxStringLength); + trailer = `... ${remaining} more character${remaining > 1 ? "s" : ""}`; + } + if (ctx.compact !== true && // TODO(BridgeAR): Add unicode support. Use the readline getStringWidth + // function. + value.length > kMinLineLength && value.length > ctx.breakLength - ctx.indentationLvl - 4) { + return ArrayPrototypeJoin( + ArrayPrototypeMap( + StringPrototypeSplit(value, formatPrimitiveRegExp), + (line) => fn(quoteString(line, ctx), "string") + ), + ` + +${StringPrototypeRepeat(" ", ctx.indentationLvl + 2)}` + ) + trailer; + } + return fn(quoteString(value, ctx), "string") + trailer; + } + if (typeof value === "number") { + return formatNumber(fn, value); + } + if (typeof value === "bigint") { + return formatBigInt(fn, value); + } + if (typeof value === "boolean") { + return fn(`${value}`, "boolean"); + } + if (typeof value === "undefined") { + return fn("undefined", "undefined"); + } + return fn(maybeQuoteSymbol(value, ctx), "symbol"); + } + function getPrefix(constructor, tag, fallback, size = "") { + if (constructor === null) { + if (tag !== "" && fallback !== tag) { + return `[${fallback}${size}: null prototype] [${tag}] `; + } + return `[${fallback}${size}: null prototype] `; + } + if (tag !== "" && constructor !== tag) { + return `${constructor}${size} [${tag}] `; + } + return `${constructor}${size} `; + } + function formatArray(ctx, value, recurseTimes) { + const valLen = value.length; + const len = MathMin(MathMax(0, ctx.maxArrayLength), valLen); + const remaining = valLen - len; + const output = []; + for (let i = 0; i < len; i++) { + ArrayPrototypePush( + output, + formatProperty(ctx, value, recurseTimes, i, kArrayType) + ); + } + if (remaining > 0) { + ArrayPrototypePush( + output, + `... ${remaining} more item${remaining > 1 ? "s" : ""}` + ); + } + return output; + } + function getCtxStyle(value, constructor, tag) { + let fallback = ""; + if (constructor === null) { + fallback = op_get_constructor_name(value); + if (fallback === tag) { + fallback = "Object"; + } + } + return getPrefix(constructor, tag, fallback); + } + function getKeys(value, showHidden) { + let keys; + const symbols = ObjectGetOwnPropertySymbols(value); + if (showHidden) { + keys = ObjectGetOwnPropertyNames(value); + if (symbols.length !== 0) { + ArrayPrototypePushApply(keys, symbols); + } + } else { + try { + keys = ObjectKeys(value); + } catch (err) { + assert( + isNativeError2(err) && err.name === "ReferenceError" && isModuleNamespaceObject2(value) + ); + keys = ObjectGetOwnPropertyNames(value); + } + if (symbols.length !== 0) { + const filter = (key) => ObjectPrototypePropertyIsEnumerable(value, key); + ArrayPrototypePushApply(keys, ArrayPrototypeFilter(symbols, filter)); + } + } + return keys; + } + function formatSet(value, ctx, _ignored, recurseTimes) { + ctx.indentationLvl += 2; + const values = [...new SafeSetIterator(value)]; + const valLen = SetPrototypeGetSize(value); + const len = MathMin(MathMax(0, ctx.iterableLimit), valLen); + const remaining = valLen - len; + const output = []; + for (let i = 0; i < len; i++) { + ArrayPrototypePush(output, formatValue(ctx, values[i], recurseTimes)); + } + if (remaining > 0) { + ArrayPrototypePush( + output, + `... ${remaining} more item${remaining > 1 ? "s" : ""}` + ); + } + ctx.indentationLvl -= 2; + return output; + } + function formatMap(value, ctx, _ignored, recurseTimes) { + ctx.indentationLvl += 2; + const values = [...new SafeMapIterator(value)]; + const valLen = MapPrototypeGetSize(value); + const len = MathMin(MathMax(0, ctx.iterableLimit), valLen); + const remaining = valLen - len; + const output = []; + for (let i = 0; i < len; i++) { + ArrayPrototypePush( + output, + `${formatValue(ctx, values[i][0], recurseTimes)} => ${formatValue( + ctx, + values[i][1], + recurseTimes + )}` + ); + } + if (remaining > 0) { + ArrayPrototypePush( + output, + `... ${remaining} more item${remaining > 1 ? "s" : ""}` + ); + } + ctx.indentationLvl -= 2; + return output; + } + function formatTypedArray(value, length, ctx, _ignored, recurseTimes) { + const maxLength = MathMin(MathMax(0, ctx.maxArrayLength), length); + const remaining = value.length - maxLength; + const output = []; + const elementFormatter = value.length > 0 && typeof value[0] === "number" ? formatNumber : formatBigInt; + for (let i = 0; i < maxLength; ++i) { + output[i] = elementFormatter(ctx.stylize, value[i]); + } + if (remaining > 0) { + output[maxLength] = `... ${remaining} more item${remaining > 1 ? "s" : ""}`; + } + if (ctx.showHidden) { + ctx.indentationLvl += 2; + for (const key of new SafeArrayIterator([ + "BYTES_PER_ELEMENT", + "length", + "byteLength", + "byteOffset", + "buffer" + ])) { + const str = formatValue(ctx, value[key], recurseTimes, true); + ArrayPrototypePush(output, `[${key}]: ${str}`); + } + ctx.indentationLvl -= 2; + } + return output; + } + function getIteratorBraces(type, tag) { + if (tag !== `${type} Iterator`) { + if (tag !== "") { + tag += "] ["; + } + tag += `${type} Iterator`; + } + return [`[${tag}] {`, "}"]; + } + const iteratorRegExp = new SafeRegExp(" Iterator] {$"); + function formatIterator(braces, ctx, value, recurseTimes) { + const { 0: entries, 1: isKeyValue } = op_preview_entries(value, true); + if (isKeyValue) { + braces[0] = StringPrototypeReplace( + braces[0], + iteratorRegExp, + " Entries] {" + ); + return formatMapIterInner(ctx, recurseTimes, entries, kMapEntries); + } + return formatSetIterInner(ctx, recurseTimes, entries, kIterator); + } + function handleCircular(value, ctx) { + let index = 1; + if (ctx.circular === void 0) { + ctx.circular = new SafeMap(); + MapPrototypeSet(ctx.circular, value, index); + } else { + index = MapPrototypeGet(ctx.circular, value); + if (index === void 0) { + index = MapPrototypeGetSize(ctx.circular) + 1; + MapPrototypeSet(ctx.circular, value, index); + } + } + return ctx.stylize(`[Circular *${index}]`, "special"); + } + const AGGREGATE_ERROR_HAS_AT_PATTERN = new SafeRegExp(/\s+at/); + const AGGREGATE_ERROR_NOT_EMPTY_LINE_PATTERN = new SafeRegExp(/^(?!\s*$)/gm); + function inspectError(value, ctx) { + const causes = [value]; + let err = value; + while (err.cause) { + if (ArrayPrototypeIncludes(causes, err.cause)) { + ArrayPrototypePush(causes, handleCircular(err.cause, ctx)); + break; + } else { + ArrayPrototypePush(causes, err.cause); + err = err.cause; + } + } + const refMap = new SafeMap(); + for (let i = 0; i < causes.length; ++i) { + const cause = causes[i]; + if (ctx.circular !== void 0) { + const index = MapPrototypeGet(ctx.circular, cause); + if (index !== void 0) { + MapPrototypeSet( + refMap, + cause, + ctx.stylize(` `, "special") + ); + } + } + } + ArrayPrototypeShift(causes); + let finalMessage = MapPrototypeGet(refMap, value) ?? ""; + if (isAggregateError(value)) { + const stackLines = StringPrototypeSplit(value.stack, "\n"); + while (true) { + const line = ArrayPrototypeShift(stackLines); + if (RegExpPrototypeTest(AGGREGATE_ERROR_HAS_AT_PATTERN, line)) { + ArrayPrototypeUnshift(stackLines, line); + break; + } else if (typeof line === "undefined") { + break; + } + finalMessage += line; + finalMessage += "\n"; + } + const aggregateMessage = ArrayPrototypeJoin( + ArrayPrototypeMap( + value.errors, + (error) => StringPrototypeReplace( + inspectArgs([error]), + AGGREGATE_ERROR_NOT_EMPTY_LINE_PATTERN, + StringPrototypeRepeat(" ", 4) + ) + ), + "\n" + ); + finalMessage += aggregateMessage; + finalMessage += "\n"; + finalMessage += ArrayPrototypeJoin(stackLines, "\n"); + } else { + const stack = value.stack; + if (stack?.includes("\n at")) { + finalMessage += stack; + } else { + finalMessage += `[${stack || ErrorPrototypeToString(value)}]`; + } + } + finalMessage += ArrayPrototypeJoin( + ArrayPrototypeMap( + causes, + (cause) => "\nCaused by " + (MapPrototypeGet(refMap, cause) ?? "") + (cause?.stack ?? cause) + ), + "" + ); + return finalMessage; + } + const hexSliceLookupTable = function() { + const alphabet = "0123456789abcdef"; + const table = []; + for (let i = 0; i < 16; ++i) { + const i16 = i * 16; + for (let j = 0; j < 16; ++j) { + table[i16 + j] = alphabet[i] + alphabet[j]; + } + } + return table; + }(); + function hexSlice(buf, start, end) { + const len = TypedArrayPrototypeGetLength(buf); + if (!start || start < 0) { + start = 0; + } + if (!end || end < 0 || end > len) { + end = len; + } + let out = ""; + for (let i = start; i < end; ++i) { + out += hexSliceLookupTable[buf[i]]; + } + return out; + } + const arrayBufferRegExp = new SafeRegExp("(.{2})", "g"); + function formatArrayBuffer(ctx, value) { + let valLen; + try { + valLen = ArrayBufferPrototypeGetByteLength(value); + } catch { + valLen = getSharedArrayBufferByteLength(value); + } + const len = MathMin(MathMax(0, ctx.maxArrayLength), valLen); + let buffer; + try { + buffer = new Uint8Array2(value, 0, len); + } catch { + return [ctx.stylize("(detached)", "special")]; + } + let str = StringPrototypeTrim( + StringPrototypeReplace(hexSlice(buffer), arrayBufferRegExp, "$1 ") + ); + const remaining = valLen - len; + if (remaining > 0) { + str += ` ... ${remaining} more byte${remaining > 1 ? "s" : ""}`; + } + return [`${ctx.stylize("[Uint8Contents]", "special")}: <${str}>`]; + } + function formatNumber(fn, value) { + return fn(ObjectIs(value, -0) ? "-0" : `${value}`, "number"); + } + const PromiseState = { + Pending: 0, + Fulfilled: 1, + Rejected: 2 + }; + function formatPromise(ctx, value, recurseTimes) { + let output; + const { 0: state, 1: result } = core.getPromiseDetails(value); + if (state === PromiseState.Pending) { + output = [ctx.stylize("", "special")]; + } else { + ctx.indentationLvl += 2; + const str = formatValue(ctx, result, recurseTimes); + ctx.indentationLvl -= 2; + output = [ + state === PromiseState.Rejected ? `${ctx.stylize("", "special")} ${str}` : str + ]; + } + return output; + } + function formatWeakCollection(ctx) { + return [ctx.stylize("", "special")]; + } + function formatWeakSet(ctx, value, recurseTimes) { + const entries = op_preview_entries(value, false); + return formatSetIterInner(ctx, recurseTimes, entries, kWeak); + } + function formatWeakMap(ctx, value, recurseTimes) { + const entries = op_preview_entries(value, false); + return formatMapIterInner(ctx, recurseTimes, entries, kWeak); + } + function formatProperty(ctx, value, recurseTimes, key, type, desc, original = value) { + let name, str; + let extra = " "; + desc = desc || ObjectGetOwnPropertyDescriptor(value, key) || { + value: value[key], + enumerable: true + }; + if (desc.value !== void 0) { + const diff = ctx.compact !== true || type !== kObjectType ? 2 : 3; + ctx.indentationLvl += diff; + str = formatValue(ctx, desc.value, recurseTimes); + if (diff === 3 && ctx.breakLength < getStringWidth(str, ctx.colors)) { + extra = ` +${StringPrototypeRepeat(" ", ctx.indentationLvl)}`; + } + ctx.indentationLvl -= diff; + } else if (desc.get !== void 0) { + const label = desc.set !== void 0 ? "Getter/Setter" : "Getter"; + const s = ctx.stylize; + const sp = "special"; + if (ctx.getters && (ctx.getters === true || ctx.getters === "get" && desc.set === void 0 || ctx.getters === "set" && desc.set !== void 0)) { + try { + const tmp = FunctionPrototypeCall(desc.get, original); + ctx.indentationLvl += 2; + if (tmp === null) { + str = `${s(`[${label}:`, sp)} ${s("null", "null")}${s("]", sp)}`; + } else if (typeof tmp === "object") { + str = `${s(`[${label}]`, sp)} ${formatValue( + ctx, + tmp, + recurseTimes + )}`; + } else { + const primitive = formatPrimitive(s, tmp, ctx); + str = `${s(`[${label}:`, sp)} ${primitive}${s("]", sp)}`; + } + ctx.indentationLvl -= 2; + } catch (err) { + const message = ``; + str = `${s(`[${label}:`, sp)} ${message}${s("]", sp)}`; + } + } else { + str = ctx.stylize(`[${label}]`, sp); + } + } else if (desc.set !== void 0) { + str = ctx.stylize("[Setter]", "special"); + } else { + str = ctx.stylize("undefined", "undefined"); + } + if (type === kArrayType) { + return str; + } + if (typeof key === "symbol") { + name = `[${ctx.stylize(maybeQuoteSymbol(key, ctx), "symbol")}]`; + } else if (key === "__proto__") { + name = "['__proto__']"; + } else if (desc.enumerable === false) { + const tmp = StringPrototypeReplace( + key, + strEscapeSequencesReplacer, + escapeFn + ); + name = `[${tmp}]`; + } else if (keyStrRegExp.test(key)) { + name = ctx.stylize(key, "name"); + } else { + name = ctx.stylize(quoteString(key, ctx), "string"); + } + return `${name}:${extra}${str}`; + } + const colorRegExp = new SafeRegExp("\x1B\\[\\d\\d?m", "g"); + function removeColors(str) { + return StringPrototypeReplace(str, colorRegExp, ""); + } + function isBelowBreakLength(ctx, output, start, base) { + let totalLength = output.length + start; + if (totalLength + output.length > ctx.breakLength) { + return false; + } + for (let i = 0; i < output.length; i++) { + if (ctx.colors) { + totalLength += removeColors(output[i]).length; + } else { + totalLength += output[i].length; + } + if (totalLength > ctx.breakLength) { + return false; + } + } + return base === "" || !StringPrototypeIncludes(base, "\n"); + } + function formatBigInt(fn, value) { + return fn(`${value}n`, "bigint"); + } + function formatNamespaceObject(keys, ctx, value, recurseTimes) { + const output = []; + for (let i = 0; i < keys.length; i++) { + try { + output[i] = formatProperty( + ctx, + value, + recurseTimes, + keys[i], + kObjectType + ); + } catch (_err) { + const tmp = { [keys[i]]: "" }; + output[i] = formatProperty(ctx, tmp, recurseTimes, keys[i], kObjectType); + const pos = StringPrototypeLastIndexOf(output[i], " "); + output[i] = StringPrototypeSlice(output[i], 0, pos + 1) + ctx.stylize("", "special"); + } + } + keys.length = 0; + return output; + } + function formatSpecialArray(ctx, value, recurseTimes, maxLength, output, i) { + const keys = ObjectKeys(value); + let index = i; + for (; i < keys.length && output.length < maxLength; i++) { + const key = keys[i]; + const tmp = +key; + if (tmp > 2 ** 32 - 2) { + break; + } + if (`${index}` !== key) { + if (!numberRegExp.test(key)) { + break; + } + const emptyItems = tmp - index; + const ending = emptyItems > 1 ? "s" : ""; + const message = `<${emptyItems} empty item${ending}>`; + ArrayPrototypePush(output, ctx.stylize(message, "undefined")); + index = tmp; + if (output.length === maxLength) { + break; + } + } + ArrayPrototypePush( + output, + formatProperty(ctx, value, recurseTimes, key, kArrayType) + ); + index++; + } + const remaining = value.length - index; + if (output.length !== maxLength) { + if (remaining > 0) { + const ending = remaining > 1 ? "s" : ""; + const message = `<${remaining} empty item${ending}>`; + ArrayPrototypePush(output, ctx.stylize(message, "undefined")); + } + } else if (remaining > 0) { + ArrayPrototypePush( + output, + `... ${remaining} more item${remaining > 1 ? "s" : ""}` + ); + } + return output; + } + function getBoxedBase(value, ctx, keys, constructor, tag) { + let type, primitive; + if (isNumberObject2(value)) { + type = "Number"; + primitive = NumberPrototypeValueOf(value); + } else if (isStringObject2(value)) { + type = "String"; + primitive = StringPrototypeValueOf(value); + ArrayPrototypeSplice(keys, 0, value.length); + } else if (isBooleanObject2(value)) { + type = "Boolean"; + primitive = BooleanPrototypeValueOf(value); + } else if (isBigIntObject2(value)) { + type = "BigInt"; + primitive = BigIntPrototypeValueOf(value); + } else { + type = "Symbol"; + primitive = SymbolPrototypeValueOf(value); + } + let base = `[${type}`; + if (type !== constructor) { + if (constructor === null) { + base += " (null prototype)"; + } else { + base += ` (${constructor})`; + } + } + base += `: ${formatPrimitive(stylizeNoColor, primitive, ctx)}]`; + if (tag !== "" && tag !== constructor) { + base += ` [${tag}]`; + } + if (keys.length !== 0 || ctx.stylize === stylizeNoColor) { + return base; + } + return ctx.stylize(base, StringPrototypeToLowerCase(type)); + } + function reduceToSingleString(ctx, output, base, braces, extrasType, recurseTimes, value) { + if (ctx.compact !== true) { + if (typeof ctx.compact === "number" && ctx.compact >= 1) { + const entries = output.length; + if (extrasType === kArrayExtrasType && entries > 6) { + output = groupArrayElements(ctx, output, value); + } + if (ctx.currentDepth - recurseTimes < ctx.compact && entries === output.length) { + const start = output.length + ctx.indentationLvl + braces[0].length + base.length + 10; + if (isBelowBreakLength(ctx, output, start, base)) { + const joinedOutput = ArrayPrototypeJoin(output, ", "); + if (!StringPrototypeIncludes(joinedOutput, "\n")) { + return `${base ? `${base} ` : ""}${braces[0]} ${joinedOutput} ${braces[1]}`; + } + } + } + } + const indentation2 = ` +${StringPrototypeRepeat(" ", ctx.indentationLvl)}`; + return `${base ? `${base} ` : ""}${braces[0]}${indentation2} ${ArrayPrototypeJoin(output, `,${indentation2} `)}${ctx.trailingComma ? "," : ""}${indentation2}${braces[1]}`; + } + if (isBelowBreakLength(ctx, output, 0, base)) { + return `${braces[0]}${base ? ` ${base}` : ""} ${ArrayPrototypeJoin( + output, + ", " + )} ` + braces[1]; + } + const indentation = StringPrototypeRepeat(" ", ctx.indentationLvl); + const ln = base === "" && braces[0].length === 1 ? " " : `${base ? ` ${base}` : ""} +${indentation} `; + return `${braces[0]}${ln}${ArrayPrototypeJoin( + output, + `, +${indentation} ` + )} ${braces[1]}`; + } + function groupArrayElements(ctx, output, value) { + let totalLength = 0; + let maxLength = 0; + let i = 0; + let outputLength = output.length; + if (ctx.maxArrayLength < output.length) { + outputLength--; + } + const separatorSpace = 2; + const dataLen = []; + for (; i < outputLength; i++) { + const len = getStringWidth(output[i], ctx.colors); + dataLen[i] = len; + totalLength += len + separatorSpace; + if (maxLength < len) { + maxLength = len; + } + } + const actualMax = maxLength + separatorSpace; + if (actualMax * 3 + ctx.indentationLvl < ctx.breakLength && (totalLength / actualMax > 5 || maxLength <= 6)) { + const approxCharHeights = 2.5; + const averageBias = MathSqrt(actualMax - totalLength / output.length); + const biasedMax = MathMax(actualMax - 3 - averageBias, 1); + const columns = MathMin( + // Ideally a square should be drawn. We expect a character to be about 2.5 + // times as high as wide. This is the area formula to calculate a square + // which contains n rectangles of size `actualMax * approxCharHeights`. + // Divide that by `actualMax` to receive the correct number of columns. + // The added bias increases the columns for short entries. + MathRound( + MathSqrt(approxCharHeights * biasedMax * outputLength) / biasedMax + ), + // Do not exceed the breakLength. + MathFloor((ctx.breakLength - ctx.indentationLvl) / actualMax), + // Limit array grouping for small `compact` modes as the user requested + // minimal grouping. + ctx.compact * 4, + // Limit the columns to a maximum of fifteen. + 15 + ); + if (columns <= 1) { + return output; + } + const tmp = []; + const maxLineLength = []; + for (let i2 = 0; i2 < columns; i2++) { + let lineMaxLength = 0; + for (let j = i2; j < output.length; j += columns) { + if (dataLen[j] > lineMaxLength) { + lineMaxLength = dataLen[j]; + } + } + lineMaxLength += separatorSpace; + maxLineLength[i2] = lineMaxLength; + } + let order = StringPrototypePadStart; + if (value !== void 0) { + for (let i2 = 0; i2 < output.length; i2++) { + if (typeof value[i2] !== "number" && typeof value[i2] !== "bigint") { + order = StringPrototypePadEnd; + break; + } + } + } + for (let i2 = 0; i2 < outputLength; i2 += columns) { + const max = MathMin(i2 + columns, outputLength); + let str = ""; + let j = i2; + for (; j < max - 1; j++) { + const padding = maxLineLength[j - i2] + output[j].length - dataLen[j]; + str += order(`${output[j]}, `, padding, " "); + } + if (order === StringPrototypePadStart) { + const padding = maxLineLength[j - i2] + output[j].length - dataLen[j] - separatorSpace; + str += StringPrototypePadStart(output[j], padding, " "); + } else { + str += output[j]; + } + ArrayPrototypePush(tmp, str); + } + if (ctx.maxArrayLength < output.length) { + ArrayPrototypePush(tmp, output[outputLength]); + } + output = tmp; + } + return output; + } + function formatMapIterInner(ctx, recurseTimes, entries, state) { + const maxArrayLength = MathMax(ctx.maxArrayLength, 0); + const len = entries.length / 2; + const remaining = len - maxArrayLength; + const maxLength = MathMin(maxArrayLength, len); + const output = []; + let i = 0; + ctx.indentationLvl += 2; + if (state === kWeak) { + for (; i < maxLength; i++) { + const pos = i * 2; + output[i] = `${formatValue( + ctx, + entries[pos], + recurseTimes + )} => ${formatValue(ctx, entries[pos + 1], recurseTimes)}`; + } + if (!ctx.sorted) { + ArrayPrototypeSort(output); + } + } else { + for (; i < maxLength; i++) { + const pos = i * 2; + const res = [ + formatValue(ctx, entries[pos], recurseTimes), + formatValue(ctx, entries[pos + 1], recurseTimes) + ]; + output[i] = reduceToSingleString( + ctx, + res, + "", + ["[", "]"], + kArrayExtrasType, + recurseTimes + ); + } + } + ctx.indentationLvl -= 2; + if (remaining > 0) { + ArrayPrototypePush( + output, + `... ${remaining} more item${remaining > 1 ? "s" : ""}` + ); + } + return output; + } + function formatSetIterInner(ctx, recurseTimes, entries, state) { + const maxArrayLength = MathMax(ctx.maxArrayLength, 0); + const maxLength = MathMin(maxArrayLength, entries.length); + const output = []; + ctx.indentationLvl += 2; + for (let i = 0; i < maxLength; i++) { + output[i] = formatValue(ctx, entries[i], recurseTimes); + } + ctx.indentationLvl -= 2; + if (state === kWeak && !ctx.sorted) { + ArrayPrototypeSort(output); + } + const remaining = entries.length - maxLength; + if (remaining > 0) { + ArrayPrototypePush( + output, + `... ${remaining} more item${remaining > 1 ? "s" : ""}` + ); + } + return output; + } + const ansiPattern = "[\\u001B\\u009B][[\\]()#;?]*(?:(?:(?:(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]+)*|[a-zA-Z\\d]+(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]*)*)?\\u0007)|(?:(?:\\d{1,4}(?:;\\d{0,4})*)?[\\dA-PR-TZcf-ntqry=><~]))"; + const ansi = new SafeRegExp(ansiPattern, "g"); + function getStringWidth(str, removeControlChars = true) { + let width = 0; + if (removeControlChars) { + str = stripVTControlCharacters(str); + } + str = StringPrototypeNormalize(str, "NFC"); + for (const char of new SafeStringIterator(str)) { + const code = StringPrototypeCodePointAt(char, 0); + if (isFullWidthCodePoint(code)) { + width += 2; + } else if (!isZeroWidthCodePoint(code)) { + width++; + } + } + return width; + } + const isZeroWidthCodePoint = (code) => { + return code <= 31 || // C0 control codes + code >= 127 && code <= 159 || // C1 control codes + code >= 768 && code <= 879 || // Combining Diacritical Marks + code >= 8203 && code <= 8207 || // Modifying Invisible Characters + // Combining Diacritical Marks for Symbols + code >= 8400 && code <= 8447 || code >= 65024 && code <= 65039 || // Variation Selectors + code >= 65056 && code <= 65071 || // Combining Half Marks + code >= 917760 && code <= 917999; + }; + function stripVTControlCharacters(str) { + return StringPrototypeReplace(str, ansi, ""); + } + function hasOwnProperty(obj, v) { + if (obj == null) { + return false; + } + return ObjectHasOwn(obj, v); + } + const tableChars = { + middleMiddle: "\u2500", + rowMiddle: "\u253C", + topRight: "\u2510", + topLeft: "\u250C", + leftMiddle: "\u251C", + topMiddle: "\u252C", + bottomRight: "\u2518", + bottomLeft: "\u2514", + bottomMiddle: "\u2534", + rightMiddle: "\u2524", + left: "\u2502 ", + right: " \u2502", + middle: " \u2502 " + }; + function isFullWidthCodePoint(code) { + return code >= 4352 && (code <= 4447 || // Hangul Jamo + code === 9001 || // LEFT-POINTING ANGLE BRACKET + code === 9002 || // RIGHT-POINTING ANGLE BRACKET + // CJK Radicals Supplement .. Enclosed CJK Letters and Months + code >= 11904 && code <= 12871 && code !== 12351 || // Enclosed CJK Letters and Months .. CJK Unified Ideographs Extension A + code >= 12880 && code <= 19903 || // CJK Unified Ideographs .. Yi Radicals + code >= 19968 && code <= 42182 || // Hangul Jamo Extended-A + code >= 43360 && code <= 43388 || // Hangul Syllables + code >= 44032 && code <= 55203 || // CJK Compatibility Ideographs + code >= 63744 && code <= 64255 || // Vertical Forms + code >= 65040 && code <= 65049 || // CJK Compatibility Forms .. Small Form Variants + code >= 65072 && code <= 65131 || // Halfwidth and Fullwidth Forms + code >= 65281 && code <= 65376 || code >= 65504 && code <= 65510 || // Kana Supplement + code >= 110592 && code <= 110593 || // Enclosed Ideographic Supplement + code >= 127488 && code <= 127569 || // Miscellaneous Symbols and Pictographs 0x1f300 - 0x1f5ff + // Emoticons 0x1f600 - 0x1f64f + code >= 127744 && code <= 128591 || // CJK Unified Ideographs Extension B .. Tertiary Ideographic Plane + code >= 131072 && code <= 262141); + } + function renderRow(row, columnWidths, columnRightAlign) { + let out = tableChars.left; + for (let i = 0; i < row.length; i++) { + const cell = row[i]; + const len = getStringWidth(cell); + const padding = StringPrototypeRepeat(" ", columnWidths[i] - len); + if (columnRightAlign?.[i]) { + out += `${padding}${cell}`; + } else { + out += `${cell}${padding}`; + } + if (i !== row.length - 1) { + out += tableChars.middle; + } + } + out += tableChars.right; + return out; + } + function cliTable(head, columns) { + const rows = []; + const columnWidths = ArrayPrototypeMap(head, (h) => getStringWidth(h)); + const longestColumn = ArrayPrototypeReduce( + columns, + (n, a) => MathMax(n, a.length), + 0 + ); + const columnRightAlign = ArrayPrototypeFill( + new Array2(columnWidths.length), + true + ); + for (let i = 0; i < head.length; i++) { + const column = columns[i]; + for (let j = 0; j < longestColumn; j++) { + if (rows[j] === void 0) { + rows[j] = []; + } + const value = rows[j][i] = hasOwnProperty(column, j) ? column[j] : ""; + const width = columnWidths[i] || 0; + const counted = getStringWidth(value); + columnWidths[i] = MathMax(width, counted); + columnRightAlign[i] &= NumberIsInteger(+value); + } + } + const divider = ArrayPrototypeMap( + columnWidths, + (i) => StringPrototypeRepeat(tableChars.middleMiddle, i + 2) + ); + let result = `${tableChars.topLeft}${ArrayPrototypeJoin( + divider, + tableChars.topMiddle + )}${tableChars.topRight} +${renderRow(head, columnWidths)} +${tableChars.leftMiddle}${ArrayPrototypeJoin( + divider, + tableChars.rowMiddle + )}${tableChars.rightMiddle} +`; + for (let i = 0; i < rows.length; ++i) { + const row = rows[i]; + result += `${renderRow(row, columnWidths, columnRightAlign)} +`; + } + result += `${tableChars.bottomLeft}${ArrayPrototypeJoin( + divider, + tableChars.bottomMiddle + )}` + tableChars.bottomRight; + return result; + } + const denoInspectDefaultOptions = { + indentationLvl: 0, + currentDepth: 0, + stylize: stylizeNoColor, + showHidden: false, + depth: 4, + colors: false, + showProxy: false, + breakLength: 80, + escapeSequences: true, + compact: 3, + sorted: false, + getters: false, + // node only + maxArrayLength: 100, + maxStringLength: 1e4, + // deno: strAbbreviateSize: 10_000 + customInspect: true, + // deno only + /** You can override the quotes preference in inspectString. + * Used by util.inspect() */ + // TODO(kt3k): Consider using symbol as a key to hide this from the public + // API. + quotes: ['"', "'", "`"], + iterableLimit: 100, + // similar to node's maxArrayLength, but doesn't only apply to arrays + trailingComma: false, + inspect, + // TODO(@crowlKats): merge into indentationLvl + indentLevel: 0 + }; + function getDefaultInspectOptions() { + return { + budget: {}, + seen: [], + ...denoInspectDefaultOptions + }; + } + const DEFAULT_INDENT = " "; + const STR_ABBREVIATE_SIZE = 1e4; + class CSI { + static kClear = "\x1B[1;1H"; + static kClearScreenDown = "\x1B[0J"; + } + const QUOTE_SYMBOL_REG = new SafeRegExp(/^[a-zA-Z_][a-zA-Z_.0-9]*$/); + function maybeQuoteSymbol(symbol, ctx) { + const description = SymbolPrototypeGetDescription(symbol); + if (description === void 0) { + return SymbolPrototypeToString(symbol); + } + if (RegExpPrototypeTest(QUOTE_SYMBOL_REG, description)) { + return SymbolPrototypeToString(symbol); + } + return `Symbol(${quoteString(description, ctx)})`; + } + function quoteString(string, ctx) { + const quote = ArrayPrototypeFind( + ctx.quotes, + (c) => !StringPrototypeIncludes(string, c) + ) ?? ctx.quotes[0]; + const escapePattern = new SafeRegExp(`(?=[${quote}\\\\])`, "g"); + string = StringPrototypeReplace(string, escapePattern, "\\"); + if (ctx.escapeSequences) { + string = replaceEscapeSequences(string); + } + return `${quote}${string}${quote}`; + } + const ESCAPE_PATTERN = new SafeRegExp(/([\b\f\n\r\t\v])/g); + const ESCAPE_MAP = ObjectFreeze({ + "\b": "\\b", + "\f": "\\f", + "\n": "\\n", + "\r": "\\r", + " ": "\\t", + "\v": "\\v" + }); + const ESCAPE_PATTERN2 = new SafeRegExp("[\0-\x7F-\x9F]", "g"); + function replaceEscapeSequences(string) { + return StringPrototypeReplace( + StringPrototypeReplace(string, ESCAPE_PATTERN, (c) => ESCAPE_MAP[c]), + ESCAPE_PATTERN2, + (c) => "\\x" + StringPrototypePadStart( + NumberPrototypeToString(StringPrototypeCharCodeAt(c, 0), 16), + 2, + "0" + ) + ); + } + function inspectValueWithQuotes(value, ctx) { + const abbreviateSize = typeof ctx.strAbbreviateSize === "undefined" ? STR_ABBREVIATE_SIZE : ctx.strAbbreviateSize; + switch (typeof value) { + case "string": { + const trunc = value.length > abbreviateSize ? StringPrototypeSlice(value, 0, abbreviateSize) + "..." : value; + return ctx.stylize(quoteString(trunc, ctx), "string"); + } + default: + return formatValue(ctx, value, 0); + } + } + const colorKeywords = new SafeMap([ + ["black", "#000000"], + ["silver", "#c0c0c0"], + ["gray", "#808080"], + ["white", "#ffffff"], + ["maroon", "#800000"], + ["red", "#ff0000"], + ["purple", "#800080"], + ["fuchsia", "#ff00ff"], + ["green", "#008000"], + ["lime", "#00ff00"], + ["olive", "#808000"], + ["yellow", "#ffff00"], + ["navy", "#000080"], + ["blue", "#0000ff"], + ["teal", "#008080"], + ["aqua", "#00ffff"], + ["orange", "#ffa500"], + ["aliceblue", "#f0f8ff"], + ["antiquewhite", "#faebd7"], + ["aquamarine", "#7fffd4"], + ["azure", "#f0ffff"], + ["beige", "#f5f5dc"], + ["bisque", "#ffe4c4"], + ["blanchedalmond", "#ffebcd"], + ["blueviolet", "#8a2be2"], + ["brown", "#a52a2a"], + ["burlywood", "#deb887"], + ["cadetblue", "#5f9ea0"], + ["chartreuse", "#7fff00"], + ["chocolate", "#d2691e"], + ["coral", "#ff7f50"], + ["cornflowerblue", "#6495ed"], + ["cornsilk", "#fff8dc"], + ["crimson", "#dc143c"], + ["cyan", "#00ffff"], + ["darkblue", "#00008b"], + ["darkcyan", "#008b8b"], + ["darkgoldenrod", "#b8860b"], + ["darkgray", "#a9a9a9"], + ["darkgreen", "#006400"], + ["darkgrey", "#a9a9a9"], + ["darkkhaki", "#bdb76b"], + ["darkmagenta", "#8b008b"], + ["darkolivegreen", "#556b2f"], + ["darkorange", "#ff8c00"], + ["darkorchid", "#9932cc"], + ["darkred", "#8b0000"], + ["darksalmon", "#e9967a"], + ["darkseagreen", "#8fbc8f"], + ["darkslateblue", "#483d8b"], + ["darkslategray", "#2f4f4f"], + ["darkslategrey", "#2f4f4f"], + ["darkturquoise", "#00ced1"], + ["darkviolet", "#9400d3"], + ["deeppink", "#ff1493"], + ["deepskyblue", "#00bfff"], + ["dimgray", "#696969"], + ["dimgrey", "#696969"], + ["dodgerblue", "#1e90ff"], + ["firebrick", "#b22222"], + ["floralwhite", "#fffaf0"], + ["forestgreen", "#228b22"], + ["gainsboro", "#dcdcdc"], + ["ghostwhite", "#f8f8ff"], + ["gold", "#ffd700"], + ["goldenrod", "#daa520"], + ["greenyellow", "#adff2f"], + ["grey", "#808080"], + ["honeydew", "#f0fff0"], + ["hotpink", "#ff69b4"], + ["indianred", "#cd5c5c"], + ["indigo", "#4b0082"], + ["ivory", "#fffff0"], + ["khaki", "#f0e68c"], + ["lavender", "#e6e6fa"], + ["lavenderblush", "#fff0f5"], + ["lawngreen", "#7cfc00"], + ["lemonchiffon", "#fffacd"], + ["lightblue", "#add8e6"], + ["lightcoral", "#f08080"], + ["lightcyan", "#e0ffff"], + ["lightgoldenrodyellow", "#fafad2"], + ["lightgray", "#d3d3d3"], + ["lightgreen", "#90ee90"], + ["lightgrey", "#d3d3d3"], + ["lightpink", "#ffb6c1"], + ["lightsalmon", "#ffa07a"], + ["lightseagreen", "#20b2aa"], + ["lightskyblue", "#87cefa"], + ["lightslategray", "#778899"], + ["lightslategrey", "#778899"], + ["lightsteelblue", "#b0c4de"], + ["lightyellow", "#ffffe0"], + ["limegreen", "#32cd32"], + ["linen", "#faf0e6"], + ["magenta", "#ff00ff"], + ["mediumaquamarine", "#66cdaa"], + ["mediumblue", "#0000cd"], + ["mediumorchid", "#ba55d3"], + ["mediumpurple", "#9370db"], + ["mediumseagreen", "#3cb371"], + ["mediumslateblue", "#7b68ee"], + ["mediumspringgreen", "#00fa9a"], + ["mediumturquoise", "#48d1cc"], + ["mediumvioletred", "#c71585"], + ["midnightblue", "#191970"], + ["mintcream", "#f5fffa"], + ["mistyrose", "#ffe4e1"], + ["moccasin", "#ffe4b5"], + ["navajowhite", "#ffdead"], + ["oldlace", "#fdf5e6"], + ["olivedrab", "#6b8e23"], + ["orangered", "#ff4500"], + ["orchid", "#da70d6"], + ["palegoldenrod", "#eee8aa"], + ["palegreen", "#98fb98"], + ["paleturquoise", "#afeeee"], + ["palevioletred", "#db7093"], + ["papayawhip", "#ffefd5"], + ["peachpuff", "#ffdab9"], + ["peru", "#cd853f"], + ["pink", "#ffc0cb"], + ["plum", "#dda0dd"], + ["powderblue", "#b0e0e6"], + ["rosybrown", "#bc8f8f"], + ["royalblue", "#4169e1"], + ["saddlebrown", "#8b4513"], + ["salmon", "#fa8072"], + ["sandybrown", "#f4a460"], + ["seagreen", "#2e8b57"], + ["seashell", "#fff5ee"], + ["sienna", "#a0522d"], + ["skyblue", "#87ceeb"], + ["slateblue", "#6a5acd"], + ["slategray", "#708090"], + ["slategrey", "#708090"], + ["snow", "#fffafa"], + ["springgreen", "#00ff7f"], + ["steelblue", "#4682b4"], + ["tan", "#d2b48c"], + ["thistle", "#d8bfd8"], + ["tomato", "#ff6347"], + ["turquoise", "#40e0d0"], + ["violet", "#ee82ee"], + ["wheat", "#f5deb3"], + ["whitesmoke", "#f5f5f5"], + ["yellowgreen", "#9acd32"], + ["rebeccapurple", "#663399"] + ]); + const HASH_PATTERN = new SafeRegExp( + /^#([\dA-Fa-f]{2})([\dA-Fa-f]{2})([\dA-Fa-f]{2})([\dA-Fa-f]{2})?$/ + ); + const SMALL_HASH_PATTERN = new SafeRegExp( + /^#([\dA-Fa-f])([\dA-Fa-f])([\dA-Fa-f])([\dA-Fa-f])?$/ + ); + const RGB_PATTERN = new SafeRegExp( + /^rgba?\(\s*([+\-]?\d*\.?\d+)\s*,\s*([+\-]?\d*\.?\d+)\s*,\s*([+\-]?\d*\.?\d+)\s*(,\s*([+\-]?\d*\.?\d+)\s*)?\)$/ + ); + const HSL_PATTERN = new SafeRegExp( + /^hsla?\(\s*([+\-]?\d*\.?\d+)\s*,\s*([+\-]?\d*\.?\d+)%\s*,\s*([+\-]?\d*\.?\d+)%\s*(,\s*([+\-]?\d*\.?\d+)\s*)?\)$/ + ); + function parseCssColor(colorString) { + if (colorKeywords.has(colorString)) { + colorString = colorKeywords.get(colorString); + } + const hashMatch = StringPrototypeMatch(colorString, HASH_PATTERN); + if (hashMatch != null) { + return [ + NumberParseInt(hashMatch[1], 16), + NumberParseInt(hashMatch[2], 16), + NumberParseInt(hashMatch[3], 16) + ]; + } + const smallHashMatch = StringPrototypeMatch(colorString, SMALL_HASH_PATTERN); + if (smallHashMatch != null) { + return [ + NumberParseInt(`${smallHashMatch[1]}${smallHashMatch[1]}`, 16), + NumberParseInt(`${smallHashMatch[2]}${smallHashMatch[2]}`, 16), + NumberParseInt(`${smallHashMatch[3]}${smallHashMatch[3]}`, 16) + ]; + } + const rgbMatch = StringPrototypeMatch(colorString, RGB_PATTERN); + if (rgbMatch != null) { + return [ + MathRound(MathMax(0, MathMin(255, rgbMatch[1]))), + MathRound(MathMax(0, MathMin(255, rgbMatch[2]))), + MathRound(MathMax(0, MathMin(255, rgbMatch[3]))) + ]; + } + const hslMatch = StringPrototypeMatch(colorString, HSL_PATTERN); + if (hslMatch != null) { + let h = Number2(hslMatch[1]) % 360; + if (h < 0) { + h += 360; + } + const s = MathMax(0, MathMin(100, hslMatch[2])) / 100; + const l = MathMax(0, MathMin(100, hslMatch[3])) / 100; + const c = (1 - MathAbs(2 * l - 1)) * s; + const x = c * (1 - MathAbs(h / 60 % 2 - 1)); + const m = l - c / 2; + let r_; + let g_; + let b_; + if (h < 60) { + ; + ({ 0: r_, 1: g_, 2: b_ } = [c, x, 0]); + } else if (h < 120) { + ; + ({ 0: r_, 1: g_, 2: b_ } = [x, c, 0]); + } else if (h < 180) { + ; + ({ 0: r_, 1: g_, 2: b_ } = [0, c, x]); + } else if (h < 240) { + ; + ({ 0: r_, 1: g_, 2: b_ } = [0, x, c]); + } else if (h < 300) { + ; + ({ 0: r_, 1: g_, 2: b_ } = [x, 0, c]); + } else { + ; + ({ 0: r_, 1: g_, 2: b_ } = [c, 0, x]); + } + return [ + MathRound((r_ + m) * 255), + MathRound((g_ + m) * 255), + MathRound((b_ + m) * 255) + ]; + } + return null; + } + function getDefaultCss() { + return { + backgroundColor: null, + color: null, + fontWeight: null, + fontStyle: null, + textDecorationColor: null, + textDecorationLine: [] + }; + } + const SPACE_PATTERN = new SafeRegExp(/\s+/g); + function parseCss(cssString) { + const css = getDefaultCss(); + const rawEntries = []; + let inValue = false; + let currentKey = null; + let parenthesesDepth = 0; + let currentPart = ""; + for (let i = 0; i < cssString.length; i++) { + const c = cssString[i]; + if (c == "(") { + parenthesesDepth++; + } else if (parenthesesDepth > 0) { + if (c == ")") { + parenthesesDepth--; + } + } else if (inValue) { + if (c == ";") { + const value = StringPrototypeTrim(currentPart); + if (value != "") { + ArrayPrototypePush(rawEntries, [currentKey, value]); + } + currentKey = null; + currentPart = ""; + inValue = false; + continue; + } + } else if (c == ":") { + currentKey = StringPrototypeTrim(currentPart); + currentPart = ""; + inValue = true; + continue; + } + currentPart += c; + } + if (inValue && parenthesesDepth == 0) { + const value = StringPrototypeTrim(currentPart); + if (value != "") { + ArrayPrototypePush(rawEntries, [currentKey, value]); + } + currentKey = null; + currentPart = ""; + } + for (let i = 0; i < rawEntries.length; ++i) { + const { 0: key, 1: value } = rawEntries[i]; + if (key == "background-color") { + if (value != null) { + css.backgroundColor = value; + } + } else if (key == "color") { + if (value != null) { + css.color = value; + } + } else if (key == "font-weight") { + if (value == "bold") { + css.fontWeight = value; + } + } else if (key == "font-style") { + if (ArrayPrototypeIncludes(["italic", "oblique", "oblique 14deg"], value)) { + css.fontStyle = "italic"; + } + } else if (key == "text-decoration-line") { + css.textDecorationLine = []; + const lineTypes = StringPrototypeSplit(value, SPACE_PATTERN); + for (let i2 = 0; i2 < lineTypes.length; ++i2) { + const lineType = lineTypes[i2]; + if (ArrayPrototypeIncludes( + ["line-through", "overline", "underline"], + lineType + )) { + ArrayPrototypePush(css.textDecorationLine, lineType); + } + } + } else if (key == "text-decoration-color") { + const color = parseCssColor(value); + if (color != null) { + css.textDecorationColor = color; + } + } else if (key == "text-decoration") { + css.textDecorationColor = null; + css.textDecorationLine = []; + const args = StringPrototypeSplit(value, SPACE_PATTERN); + for (let i2 = 0; i2 < args.length; ++i2) { + const arg = args[i2]; + const maybeColor = parseCssColor(arg); + if (maybeColor != null) { + css.textDecorationColor = maybeColor; + } else if (ArrayPrototypeIncludes( + ["line-through", "overline", "underline"], + arg + )) { + ArrayPrototypePush(css.textDecorationLine, arg); + } + } + } + } + return css; + } + function colorEquals(color1, color2) { + return color1?.[0] == color2?.[0] && color1?.[1] == color2?.[1] && color1?.[2] == color2?.[2]; + } + function cssToAnsi(css, prevCss = null) { + prevCss = prevCss ?? getDefaultCss(); + let ansi2 = ""; + if (!colorEquals(css.backgroundColor, prevCss.backgroundColor)) { + if (css.backgroundColor == null) { + ansi2 += "\x1B[49m"; + } else if (css.backgroundColor == "black") { + ansi2 += `\x1B[40m`; + } else if (css.backgroundColor == "red") { + ansi2 += `\x1B[41m`; + } else if (css.backgroundColor == "green") { + ansi2 += `\x1B[42m`; + } else if (css.backgroundColor == "yellow") { + ansi2 += `\x1B[43m`; + } else if (css.backgroundColor == "blue") { + ansi2 += `\x1B[44m`; + } else if (css.backgroundColor == "magenta") { + ansi2 += `\x1B[45m`; + } else if (css.backgroundColor == "cyan") { + ansi2 += `\x1B[46m`; + } else if (css.backgroundColor == "white") { + ansi2 += `\x1B[47m`; + } else { + if (ArrayIsArray(css.backgroundColor)) { + const { 0: r, 1: g, 2: b } = css.backgroundColor; + ansi2 += `\x1B[48;2;${r};${g};${b}m`; + } else { + const parsed = parseCssColor(css.backgroundColor); + if (parsed !== null) { + const { 0: r, 1: g, 2: b } = parsed; + ansi2 += `\x1B[48;2;${r};${g};${b}m`; + } else { + ansi2 += "\x1B[49m"; + } + } + } + } + if (!colorEquals(css.color, prevCss.color)) { + if (css.color == null) { + ansi2 += "\x1B[39m"; + } else if (css.color == "black") { + ansi2 += `\x1B[30m`; + } else if (css.color == "red") { + ansi2 += `\x1B[31m`; + } else if (css.color == "green") { + ansi2 += `\x1B[32m`; + } else if (css.color == "yellow") { + ansi2 += `\x1B[33m`; + } else if (css.color == "blue") { + ansi2 += `\x1B[34m`; + } else if (css.color == "magenta") { + ansi2 += `\x1B[35m`; + } else if (css.color == "cyan") { + ansi2 += `\x1B[36m`; + } else if (css.color == "white") { + ansi2 += `\x1B[37m`; + } else { + if (ArrayIsArray(css.color)) { + const { 0: r, 1: g, 2: b } = css.color; + ansi2 += `\x1B[38;2;${r};${g};${b}m`; + } else { + const parsed = parseCssColor(css.color); + if (parsed !== null) { + const { 0: r, 1: g, 2: b } = parsed; + ansi2 += `\x1B[38;2;${r};${g};${b}m`; + } else { + ansi2 += "\x1B[39m"; + } + } + } + } + if (css.fontWeight != prevCss.fontWeight) { + if (css.fontWeight == "bold") { + ansi2 += `\x1B[1m`; + } else { + ansi2 += "\x1B[22m"; + } + } + if (css.fontStyle != prevCss.fontStyle) { + if (css.fontStyle == "italic") { + ansi2 += `\x1B[3m`; + } else { + ansi2 += "\x1B[23m"; + } + } + if (!colorEquals(css.textDecorationColor, prevCss.textDecorationColor)) { + if (css.textDecorationColor != null) { + const { 0: r, 1: g, 2: b } = css.textDecorationColor; + ansi2 += `\x1B[58;2;${r};${g};${b}m`; + } else { + ansi2 += "\x1B[59m"; + } + } + if (ArrayPrototypeIncludes(css.textDecorationLine, "line-through") != ArrayPrototypeIncludes(prevCss.textDecorationLine, "line-through")) { + if (ArrayPrototypeIncludes(css.textDecorationLine, "line-through")) { + ansi2 += "\x1B[9m"; + } else { + ansi2 += "\x1B[29m"; + } + } + if (ArrayPrototypeIncludes(css.textDecorationLine, "overline") != ArrayPrototypeIncludes(prevCss.textDecorationLine, "overline")) { + if (ArrayPrototypeIncludes(css.textDecorationLine, "overline")) { + ansi2 += "\x1B[53m"; + } else { + ansi2 += "\x1B[55m"; + } + } + if (ArrayPrototypeIncludes(css.textDecorationLine, "underline") != ArrayPrototypeIncludes(prevCss.textDecorationLine, "underline")) { + if (ArrayPrototypeIncludes(css.textDecorationLine, "underline")) { + ansi2 += "\x1B[4m"; + } else { + ansi2 += "\x1B[24m"; + } + } + return ansi2; + } + function inspectArgs(args, inspectOptions = { __proto__: null }) { + const ctx = { + ...getDefaultInspectOptions(), + colors: inspectOptions.colors ?? !noColorStdout(), + ...inspectOptions + }; + if (inspectOptions.iterableLimit !== void 0) { + ctx.maxArrayLength = inspectOptions.iterableLimit; + } + if (inspectOptions.strAbbreviateSize !== void 0) { + ctx.maxStringLength = inspectOptions.strAbbreviateSize; + } + if (ctx.colors) + ctx.stylize = createStylizeWithColor(styles, colors); + if (ctx.maxArrayLength === null) + ctx.maxArrayLength = Infinity; + if (ctx.maxStringLength === null) + ctx.maxStringLength = Infinity; + const noColor = !ctx.colors; + const first = args[0]; + let a = 0; + let string = ""; + if (typeof first == "string" && args.length > 1) { + a++; + let appendedChars = 0; + let usedStyle = false; + let prevCss = null; + for (let i = 0; i < first.length - 1; i++) { + if (first[i] == "%") { + const char = first[++i]; + if (a < args.length) { + let formattedArg = null; + if (char == "s") { + formattedArg = String2(args[a++]); + } else if (ArrayPrototypeIncludes(["d", "i"], char)) { + const value = args[a++]; + if (typeof value == "bigint") { + formattedArg = `${value}n`; + } else if (typeof value == "number") { + formattedArg = `${NumberParseInt(String2(value))}`; + } else { + formattedArg = "NaN"; + } + } else if (char == "f") { + const value = args[a++]; + if (typeof value == "number") { + formattedArg = `${value}`; + } else { + formattedArg = "NaN"; + } + } else if (ArrayPrototypeIncludes(["O", "o"], char)) { + formattedArg = formatValue(ctx, args[a++], 0); + } else if (char == "c") { + const value = args[a++]; + if (!noColor) { + const css = parseCss(value); + formattedArg = cssToAnsi(css, prevCss); + if (formattedArg != "") { + usedStyle = true; + prevCss = css; + } + } else { + formattedArg = ""; + } + } + if (formattedArg != null) { + string += StringPrototypeSlice(first, appendedChars, i - 1) + formattedArg; + appendedChars = i + 1; + } + } + if (char == "%") { + string += StringPrototypeSlice(first, appendedChars, i - 1) + "%"; + appendedChars = i + 1; + } + } + } + string += StringPrototypeSlice(first, appendedChars); + if (usedStyle) { + string += "\x1B[0m"; + } + } + for (; a < args.length; a++) { + if (a > 0) { + string += " "; + } + if (typeof args[a] == "string") { + string += args[a]; + } else { + string += formatValue(ctx, args[a], 0); + } + } + if (ctx.indentLevel > 0) { + const groupIndent = StringPrototypeRepeat(DEFAULT_INDENT, ctx.indentLevel); + string = groupIndent + StringPrototypeReplaceAll(string, "\n", ` +${groupIndent}`); + } + return string; + } + function createStylizeWithColor(styles2, colors2) { + return function stylizeWithColor(str, styleType) { + const style = styles2[styleType]; + if (style !== void 0) { + const color = colors2[style]; + if (color !== void 0) { + return `\x1B[${color[0]}m${str}\x1B[${color[1]}m`; + } + } + return str; + }; + } + const countMap = new SafeMap(); + const timerMap = new SafeMap(); + const isConsoleInstance = Symbol2("isConsoleInstance"); + function getConsoleInspectOptions(noColor) { + return { + ...getDefaultInspectOptions(), + colors: !noColor, + stylize: noColor ? stylizeNoColor : createStylizeWithColor(styles, colors) + }; + } + class Console2 { + #printFunc = null; + [isConsoleInstance] = false; + constructor(printFunc) { + this.#printFunc = printFunc; + this.indentLevel = 0; + this[isConsoleInstance] = true; + const console = ObjectCreate( + {}, + { + [SymbolToStringTag]: { + enumerable: false, + writable: false, + configurable: true, + value: "console" + } + } + ); + ObjectAssign(console, this); + return console; + } + log = (...args) => { + this.#printFunc( + inspectArgs(args, { + ...getConsoleInspectOptions(noColorStdout()), + indentLevel: this.indentLevel + }) + "\n", + 1 + ); + }; + debug = (...args) => { + this.#printFunc( + inspectArgs(args, { + ...getConsoleInspectOptions(noColorStdout()), + indentLevel: this.indentLevel + }) + "\n", + 0 + ); + }; + info = (...args) => { + this.#printFunc( + inspectArgs(args, { + ...getConsoleInspectOptions(noColorStdout()), + indentLevel: this.indentLevel + }) + "\n", + 1 + ); + }; + dir = (obj = void 0, options = { __proto__: null }) => { + this.#printFunc( + inspectArgs([obj], { + ...getConsoleInspectOptions(noColorStdout()), + ...options + }) + "\n", + 1 + ); + }; + dirxml = this.dir; + warn = (...args) => { + this.#printFunc( + inspectArgs(args, { + ...getConsoleInspectOptions(noColorStderr()), + indentLevel: this.indentLevel + }) + "\n", + 2 + ); + }; + error = (...args) => { + this.#printFunc( + inspectArgs(args, { + ...getConsoleInspectOptions(noColorStderr()), + indentLevel: this.indentLevel + }) + "\n", + 3 + ); + }; + assert = (condition = false, ...args) => { + if (condition) { + return; + } + if (args.length === 0) { + this.error("Assertion failed"); + return; + } + const [first, ...rest] = new SafeArrayIterator(args); + if (typeof first === "string") { + this.error(`Assertion failed: ${first}`, ...new SafeArrayIterator(rest)); + return; + } + this.error(`Assertion failed:`, ...new SafeArrayIterator(args)); + }; + count = (label = "default") => { + label = String2(label); + if (MapPrototypeHas(countMap, label)) { + const current = MapPrototypeGet(countMap, label) || 0; + MapPrototypeSet(countMap, label, current + 1); + } else { + MapPrototypeSet(countMap, label, 1); + } + this.info(`${label}: ${MapPrototypeGet(countMap, label)}`); + }; + countReset = (label = "default") => { + label = String2(label); + if (MapPrototypeHas(countMap, label)) { + MapPrototypeSet(countMap, label, 0); + } else { + this.warn(`Count for '${label}' does not exist`); + } + }; + table = (data = void 0, properties = void 0) => { + if (properties !== void 0 && !ArrayIsArray(properties)) { + throw new Error2( + "The 'properties' argument must be of type Array. Received type " + typeof properties + ); + } + if (data === null || typeof data !== "object") { + return this.log(data); + } + const stringifyValue = (value) => inspectValueWithQuotes(value, { + ...getDefaultInspectOptions(), + depth: 1, + compact: true + }); + const toTable = (header2, body2) => this.log(cliTable(header2, body2)); + let resultData; + const isSetObject = isSet2(data); + const isMapObject = isMap2(data); + const valuesKey = "Values"; + const indexKey = isSetObject || isMapObject ? "(iter idx)" : "(idx)"; + if (isSetObject) { + resultData = [...new SafeSetIterator(data)]; + } else if (isMapObject) { + let idx = 0; + resultData = { __proto__: null }; + MapPrototypeForEach(data, (v, k) => { + resultData[idx] = { Key: k, Values: v }; + idx++; + }); + } else { + resultData = data; + } + const keys = ObjectKeys(resultData); + const numRows = keys.length; + const objectValues = properties ? ObjectFromEntries( + ArrayPrototypeMap(properties, (name) => [ + name, + ArrayPrototypeFill(new Array2(numRows), "") + ]) + ) : {}; + const indexKeys = []; + const values = []; + let hasPrimitives = false; + ArrayPrototypeForEach(keys, (k, idx) => { + const value = resultData[k]; + const primitive = value === null || typeof value !== "function" && typeof value !== "object"; + if (properties === void 0 && primitive) { + hasPrimitives = true; + ArrayPrototypePush(values, stringifyValue(value)); + } else { + const valueObj = value || {}; + const keys2 = properties || ObjectKeys(valueObj); + for (let i = 0; i < keys2.length; ++i) { + const k2 = keys2[i]; + if (!primitive && ReflectHas(valueObj, k2)) { + if (!ReflectHas(objectValues, k2)) { + objectValues[k2] = ArrayPrototypeFill(new Array2(numRows), ""); + } + objectValues[k2][idx] = stringifyValue(valueObj[k2]); + } + } + ArrayPrototypePush(values, ""); + } + ArrayPrototypePush(indexKeys, k); + }); + const headerKeys = ObjectKeys(objectValues); + const bodyValues = ObjectValues(objectValues); + const headerProps = properties || [ + ...new SafeArrayIterator(headerKeys), + !isMapObject && hasPrimitives && valuesKey + ]; + const header = ArrayPrototypeFilter( + [indexKey, ...new SafeArrayIterator(headerProps)], + Boolean2 + ); + const body = [indexKeys, ...new SafeArrayIterator(bodyValues), values]; + toTable(header, body); + }; + time = (label = "default") => { + label = String2(label); + if (MapPrototypeHas(timerMap, label)) { + this.warn(`Timer '${label}' already exists`); + return; + } + MapPrototypeSet(timerMap, label, DateNow()); + }; + timeLog = (label = "default", ...args) => { + label = String2(label); + if (!MapPrototypeHas(timerMap, label)) { + this.warn(`Timer '${label}' does not exist`); + return; + } + const startTime = MapPrototypeGet(timerMap, label); + const duration = DateNow() - startTime; + this.info(`${label}: ${duration}ms`, ...new SafeArrayIterator(args)); + }; + timeEnd = (label = "default") => { + label = String2(label); + if (!MapPrototypeHas(timerMap, label)) { + this.warn(`Timer '${label}' does not exist`); + return; + } + const startTime = MapPrototypeGet(timerMap, label); + MapPrototypeDelete(timerMap, label); + const duration = DateNow() - startTime; + this.info(`${label}: ${duration}ms`); + }; + group = (...label) => { + if (label.length > 0) { + this.log(...new SafeArrayIterator(label)); + } + this.indentLevel += 2; + }; + groupCollapsed = this.group; + groupEnd = () => { + if (this.indentLevel > 0) { + this.indentLevel -= 2; + } + }; + clear = () => { + this.indentLevel = 0; + this.#printFunc(CSI.kClear, 1); + this.#printFunc(CSI.kClearScreenDown, 1); + }; + trace = (...args) => { + const message = inspectArgs(args, { + ...getConsoleInspectOptions(noColorStderr()), + indentLevel: 0 + }); + const err = { + name: "Trace", + message + }; + ErrorCaptureStackTrace(err, this.trace); + this.error(err.stack); + }; + // These methods are noops, but when the inspector is connected, they + // call into V8. + profile = (_label) => { + }; + profileEnd = (_label) => { + }; + timeStamp = (_label) => { + }; + static [SymbolHasInstance](instance) { + return instance[isConsoleInstance]; + } + } + const customInspect = SymbolFor("Deno.customInspect"); + function inspect(value, inspectOptions = { __proto__: null }) { + const ctx = { + ...getDefaultInspectOptions(), + ...inspectOptions + }; + if (inspectOptions.iterableLimit !== void 0) { + ctx.maxArrayLength = inspectOptions.iterableLimit; + } + if (inspectOptions.strAbbreviateSize !== void 0) { + ctx.maxStringLength = inspectOptions.strAbbreviateSize; + } + if (ctx.colors) + ctx.stylize = createStylizeWithColor(styles, colors); + if (ctx.maxArrayLength === null) + ctx.maxArrayLength = Infinity; + if (ctx.maxStringLength === null) + ctx.maxStringLength = Infinity; + return formatValue(ctx, value, 0); + } + function createFilteredInspectProxy({ object, keys, evaluate }) { + const obj = class { + }; + if (object.constructor?.name) { + ObjectDefineProperty(obj, "name", { value: object.constructor.name }); + } + return new Proxy2(new obj(), { + get(_target, key) { + if (key === SymbolToStringTag) { + return object.constructor?.name; + } else if (ArrayPrototypeIncludes(keys, key)) { + return ReflectGet(object, key); + } else { + return void 0; + } + }, + getOwnPropertyDescriptor(_target, key) { + if (!ArrayPrototypeIncludes(keys, key)) { + return void 0; + } else if (evaluate) { + return getEvaluatedDescriptor(object, key); + } else { + return getDescendantPropertyDescriptor(object, key) ?? getEvaluatedDescriptor(object, key); + } + }, + has(_target, key) { + return ArrayPrototypeIncludes(keys, key); + }, + ownKeys() { + return keys; + } + }); + function getDescendantPropertyDescriptor(object2, key) { + let propertyDescriptor = ReflectGetOwnPropertyDescriptor(object2, key); + if (!propertyDescriptor) { + const prototype = ReflectGetPrototypeOf(object2); + if (prototype) { + propertyDescriptor = getDescendantPropertyDescriptor(prototype, key); + } + } + return propertyDescriptor; + } + function getEvaluatedDescriptor(object2, key) { + return { + configurable: true, + enumerable: true, + value: object2[key] + }; + } + } + return Console2; + }; + function createConsole(noColorStdout = () => false, noColorStderr = () => false) { + core_default(); + return console_default(noColorStdout, noColorStderr); + } + + // deno-scripts/00_console.ts + var Console = createConsole(() => false, () => false); + globalThis.console = new Console(globalThis.__print); + globalThis.Console = Console; +})(); diff --git a/rqjs-ext/deno-scripts/00_console.ts b/rqjs-ext/deno-scripts/00_console.ts new file mode 100644 index 0000000..4ff6e5a --- /dev/null +++ b/rqjs-ext/deno-scripts/00_console.ts @@ -0,0 +1,5 @@ +import { createConsole } from "deno-console" +const Console = createConsole(() => false, () => false) +// @ts-ignore +globalThis.console = new Console(globalThis.__print) +globalThis.Console = Console \ No newline at end of file diff --git a/rqjs-ext/package.json b/rqjs-ext/package.json new file mode 100644 index 0000000..65b1872 --- /dev/null +++ b/rqjs-ext/package.json @@ -0,0 +1,21 @@ +{ + "name": "rqjs-ext", + "private": true, + "version": "0.0.0", + "description": "rqjs-ext", + "type": "module", + "main": "index.js", + "scripts": { + "build:console": "esbuild ./deno-scripts/00_console.ts --bundle --format=iife --outdir=./deno-scripts", + "test": "echo \"Error: no test specified\" && exit 1" + }, + "keywords": [], + "author": "", + "license": "ISC", + "devDependencies": { + "@inquirer/prompts": "^5.0.6", + "@types/node": "^20.14.5", + "deno-console": "^0.1.3", + "esbuild": "^0.21.5" + } +} \ No newline at end of file diff --git a/rqjs-ext/pnpm-lock.yaml b/rqjs-ext/pnpm-lock.yaml new file mode 100644 index 0000000..e2261ee --- /dev/null +++ b/rqjs-ext/pnpm-lock.yaml @@ -0,0 +1,598 @@ +lockfileVersion: '9.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +importers: + + .: + devDependencies: + '@inquirer/prompts': + specifier: ^5.0.6 + version: 5.0.6 + '@types/node': + specifier: ^20.14.5 + version: 20.14.5 + deno-console: + specifier: ^0.1.3 + version: 0.1.3 + esbuild: + specifier: ^0.21.5 + version: 0.21.5 + +packages: + + '@esbuild/aix-ppc64@0.21.5': + resolution: {integrity: sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==} + engines: {node: '>=12'} + cpu: [ppc64] + os: [aix] + + '@esbuild/android-arm64@0.21.5': + resolution: {integrity: sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==} + engines: {node: '>=12'} + cpu: [arm64] + os: [android] + + '@esbuild/android-arm@0.21.5': + resolution: {integrity: sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==} + engines: {node: '>=12'} + cpu: [arm] + os: [android] + + '@esbuild/android-x64@0.21.5': + resolution: {integrity: sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==} + engines: {node: '>=12'} + cpu: [x64] + os: [android] + + '@esbuild/darwin-arm64@0.21.5': + resolution: {integrity: sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==} + engines: {node: '>=12'} + cpu: [arm64] + os: [darwin] + + '@esbuild/darwin-x64@0.21.5': + resolution: {integrity: sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==} + engines: {node: '>=12'} + cpu: [x64] + os: [darwin] + + '@esbuild/freebsd-arm64@0.21.5': + resolution: {integrity: sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==} + engines: {node: '>=12'} + cpu: [arm64] + os: [freebsd] + + '@esbuild/freebsd-x64@0.21.5': + resolution: {integrity: sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [freebsd] + + '@esbuild/linux-arm64@0.21.5': + resolution: {integrity: sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==} + engines: {node: '>=12'} + cpu: [arm64] + os: [linux] + + '@esbuild/linux-arm@0.21.5': + resolution: {integrity: sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==} + engines: {node: '>=12'} + cpu: [arm] + os: [linux] + + '@esbuild/linux-ia32@0.21.5': + resolution: {integrity: sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==} + engines: {node: '>=12'} + cpu: [ia32] + os: [linux] + + '@esbuild/linux-loong64@0.21.5': + resolution: {integrity: sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==} + engines: {node: '>=12'} + cpu: [loong64] + os: [linux] + + '@esbuild/linux-mips64el@0.21.5': + resolution: {integrity: sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==} + engines: {node: '>=12'} + cpu: [mips64el] + os: [linux] + + '@esbuild/linux-ppc64@0.21.5': + resolution: {integrity: sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==} + engines: {node: '>=12'} + cpu: [ppc64] + os: [linux] + + '@esbuild/linux-riscv64@0.21.5': + resolution: {integrity: sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==} + engines: {node: '>=12'} + cpu: [riscv64] + os: [linux] + + '@esbuild/linux-s390x@0.21.5': + resolution: {integrity: sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==} + engines: {node: '>=12'} + cpu: [s390x] + os: [linux] + + '@esbuild/linux-x64@0.21.5': + resolution: {integrity: sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [linux] + + '@esbuild/netbsd-x64@0.21.5': + resolution: {integrity: sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==} + engines: {node: '>=12'} + cpu: [x64] + os: [netbsd] + + '@esbuild/openbsd-x64@0.21.5': + resolution: {integrity: sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==} + engines: {node: '>=12'} + cpu: [x64] + os: [openbsd] + + '@esbuild/sunos-x64@0.21.5': + resolution: {integrity: sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==} + engines: {node: '>=12'} + cpu: [x64] + os: [sunos] + + '@esbuild/win32-arm64@0.21.5': + resolution: {integrity: sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==} + engines: {node: '>=12'} + cpu: [arm64] + os: [win32] + + '@esbuild/win32-ia32@0.21.5': + resolution: {integrity: sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==} + engines: {node: '>=12'} + cpu: [ia32] + os: [win32] + + '@esbuild/win32-x64@0.21.5': + resolution: {integrity: sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==} + engines: {node: '>=12'} + cpu: [x64] + os: [win32] + + '@inquirer/checkbox@2.3.6': + resolution: {integrity: sha512-BziU88BEwBaGclY0RM59QOop2zyPgAr1EH/czvW6/J9ELXYN4vbGTI4KM/ogNnh+Y0yNnVvKxAQqFsI2Ra2BtA==} + engines: {node: '>=18'} + + '@inquirer/confirm@3.1.10': + resolution: {integrity: sha512-/aAHu83Njy6yf44T+ZrRPUkMcUqprrOiIKsyMvf9jOV+vF5BNb2ja1aLP33MK36W8eaf91MTL/mU/e6METuENg==} + engines: {node: '>=18'} + + '@inquirer/core@8.2.3': + resolution: {integrity: sha512-WrpDVPAaxJQjHid3Ra4FhUO70YBzkHSYVyW5X48L5zHYdudoPISJqTRRWSeamHfaXda7PNNaC5Py5MEo7QwBNA==} + engines: {node: '>=18'} + + '@inquirer/editor@2.1.10': + resolution: {integrity: sha512-5e4OlRNzi1TFVKJVBk4WtWYPtVqpKyIGvltP/bqnZ0AQ9bA9Cgukcs8LniUXsgkw3+IAPFQfP8yBxFX/qIz+2g==} + engines: {node: '>=18'} + + '@inquirer/expand@2.1.10': + resolution: {integrity: sha512-5wyrw7wH24DqACWnwRhdZioCS4Bq8tvkh2BDyz2a827Zn2QAxZ/o+m17GBD9xPfvTdtxlfYsyKPTSQmGvG+BJA==} + engines: {node: '>=18'} + + '@inquirer/figures@1.0.3': + resolution: {integrity: sha512-ErXXzENMH5pJt5/ssXV0DfWUZqly8nGzf0UcBV9xTnP+KyffE2mqyxIMBrZ8ijQck2nU0TQm40EQB53YreyWHw==} + engines: {node: '>=18'} + + '@inquirer/input@2.1.10': + resolution: {integrity: sha512-KEnho7O0YBj+peA40ZGOuBYf00EQnYbQlPsORgZYdjdUVUrMqQPW3qIvRNJIq+lYlc9RZrfHeMoAv+tWAoZFQg==} + engines: {node: '>=18'} + + '@inquirer/password@2.1.10': + resolution: {integrity: sha512-hwRi8bITIloH7+30inpIkS0C/+lsdM+HSS/6F5J46Jdo9JLRnUwV4D9ovc4pz6zf2vjCFH/MYlxUBOFe/ix3Tw==} + engines: {node: '>=18'} + + '@inquirer/prompts@5.0.6': + resolution: {integrity: sha512-1Fc/8d8tCoYuMXJSG0C5F7Bzs4ViL4VNyOJr35FNnnEvx2GX/unBJDL9ZcYHx/Ps7yQuRAUr50SOvw8QbmJxvg==} + engines: {node: '>=18'} + + '@inquirer/rawlist@2.1.10': + resolution: {integrity: sha512-tGi2O9DP+jDw2/lXKdRlv0YcCfwHcEZAzM+fRe5YjoDyBwUbKzYrDlD4xa6H9hIpPSrOpSpncTEDL9lbUDwXFw==} + engines: {node: '>=18'} + + '@inquirer/select@2.3.6': + resolution: {integrity: sha512-eLqlZXre69Jenmar5s+3018xF3lpaGfxVZLHkCzkrhtuTuFjpYtb0YpiYeZNKZm9pa+ih3s9acN/zRt+dDh+qA==} + engines: {node: '>=18'} + + '@inquirer/type@1.3.3': + resolution: {integrity: sha512-xTUt0NulylX27/zMx04ZYar/kr1raaiFTVvQ5feljQsiAgdm0WPj4S73/ye0fbslh+15QrIuDvfCXTek7pMY5A==} + engines: {node: '>=18'} + + '@types/mute-stream@0.0.4': + resolution: {integrity: sha512-CPM9nzrCPPJHQNA9keH9CVkVI+WR5kMa+7XEs5jcGQ0VoAGnLv242w8lIVgwAEfmE4oufJRaTc9PNLQl0ioAow==} + + '@types/node@20.14.5': + resolution: {integrity: sha512-aoRR+fJkZT2l0aGOJhuA8frnCSoNX6W7U2mpNq63+BxBIj5BQFt8rHy627kijCmm63ijdSdwvGgpUsU6MBsZZA==} + + '@types/node@20.14.6': + resolution: {integrity: sha512-JbA0XIJPL1IiNnU7PFxDXyfAwcwVVrOoqyzzyQTyMeVhBzkJVMSkC1LlVsRQ2lpqiY4n6Bb9oCS6lzDKVQxbZw==} + + '@types/wrap-ansi@3.0.0': + resolution: {integrity: sha512-ltIpx+kM7g/MLRZfkbL7EsCEjfzCcScLpkg37eXEtx5kmrAKBkTJwd1GIAjDSL8wTpM6Hzn5YO4pSb91BEwu1g==} + + ansi-escapes@4.3.2: + resolution: {integrity: sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==} + engines: {node: '>=8'} + + ansi-regex@5.0.1: + resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} + engines: {node: '>=8'} + + ansi-styles@4.3.0: + resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} + engines: {node: '>=8'} + + chalk@4.1.2: + resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} + engines: {node: '>=10'} + + chardet@0.7.0: + resolution: {integrity: sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==} + + cli-spinners@2.9.2: + resolution: {integrity: sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==} + engines: {node: '>=6'} + + cli-width@4.1.0: + resolution: {integrity: sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==} + engines: {node: '>= 12'} + + color-convert@2.0.1: + resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} + engines: {node: '>=7.0.0'} + + color-name@1.1.4: + resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + + deno-console@0.1.3: + resolution: {integrity: sha512-p3uY5vQTka+IiNEuqCPK8AHSQB300nUJQe8Oo+P/U5JJTQtAzJW032paTovLT+hru5kR6VQbOEX9kBH2dX5elg==} + + emoji-regex@8.0.0: + resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} + + esbuild@0.21.5: + resolution: {integrity: sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==} + engines: {node: '>=12'} + hasBin: true + + external-editor@3.1.0: + resolution: {integrity: sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==} + engines: {node: '>=4'} + + has-flag@4.0.0: + resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} + engines: {node: '>=8'} + + iconv-lite@0.4.24: + resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} + engines: {node: '>=0.10.0'} + + is-fullwidth-code-point@3.0.0: + resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} + engines: {node: '>=8'} + + mute-stream@1.0.0: + resolution: {integrity: sha512-avsJQhyd+680gKXyG/sQc0nXaC6rBkPOfyHYcFb9+hdkqQkR9bdnkJ0AMZhke0oesPqIO+mFFJ+IdBc7mst4IA==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + os-tmpdir@1.0.2: + resolution: {integrity: sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==} + engines: {node: '>=0.10.0'} + + safer-buffer@2.1.2: + resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} + + signal-exit@4.1.0: + resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} + engines: {node: '>=14'} + + string-width@4.2.3: + resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} + engines: {node: '>=8'} + + strip-ansi@6.0.1: + resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} + engines: {node: '>=8'} + + supports-color@7.2.0: + resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} + engines: {node: '>=8'} + + tmp@0.0.33: + resolution: {integrity: sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==} + engines: {node: '>=0.6.0'} + + type-fest@0.21.3: + resolution: {integrity: sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==} + engines: {node: '>=10'} + + undici-types@5.26.5: + resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} + + wrap-ansi@6.2.0: + resolution: {integrity: sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==} + engines: {node: '>=8'} + +snapshots: + + '@esbuild/aix-ppc64@0.21.5': + optional: true + + '@esbuild/android-arm64@0.21.5': + optional: true + + '@esbuild/android-arm@0.21.5': + optional: true + + '@esbuild/android-x64@0.21.5': + optional: true + + '@esbuild/darwin-arm64@0.21.5': + optional: true + + '@esbuild/darwin-x64@0.21.5': + optional: true + + '@esbuild/freebsd-arm64@0.21.5': + optional: true + + '@esbuild/freebsd-x64@0.21.5': + optional: true + + '@esbuild/linux-arm64@0.21.5': + optional: true + + '@esbuild/linux-arm@0.21.5': + optional: true + + '@esbuild/linux-ia32@0.21.5': + optional: true + + '@esbuild/linux-loong64@0.21.5': + optional: true + + '@esbuild/linux-mips64el@0.21.5': + optional: true + + '@esbuild/linux-ppc64@0.21.5': + optional: true + + '@esbuild/linux-riscv64@0.21.5': + optional: true + + '@esbuild/linux-s390x@0.21.5': + optional: true + + '@esbuild/linux-x64@0.21.5': + optional: true + + '@esbuild/netbsd-x64@0.21.5': + optional: true + + '@esbuild/openbsd-x64@0.21.5': + optional: true + + '@esbuild/sunos-x64@0.21.5': + optional: true + + '@esbuild/win32-arm64@0.21.5': + optional: true + + '@esbuild/win32-ia32@0.21.5': + optional: true + + '@esbuild/win32-x64@0.21.5': + optional: true + + '@inquirer/checkbox@2.3.6': + dependencies: + '@inquirer/core': 8.2.3 + '@inquirer/figures': 1.0.3 + '@inquirer/type': 1.3.3 + ansi-escapes: 4.3.2 + chalk: 4.1.2 + + '@inquirer/confirm@3.1.10': + dependencies: + '@inquirer/core': 8.2.3 + '@inquirer/type': 1.3.3 + + '@inquirer/core@8.2.3': + dependencies: + '@inquirer/figures': 1.0.3 + '@inquirer/type': 1.3.3 + '@types/mute-stream': 0.0.4 + '@types/node': 20.14.6 + '@types/wrap-ansi': 3.0.0 + ansi-escapes: 4.3.2 + chalk: 4.1.2 + cli-spinners: 2.9.2 + cli-width: 4.1.0 + mute-stream: 1.0.0 + signal-exit: 4.1.0 + strip-ansi: 6.0.1 + wrap-ansi: 6.2.0 + + '@inquirer/editor@2.1.10': + dependencies: + '@inquirer/core': 8.2.3 + '@inquirer/type': 1.3.3 + external-editor: 3.1.0 + + '@inquirer/expand@2.1.10': + dependencies: + '@inquirer/core': 8.2.3 + '@inquirer/type': 1.3.3 + chalk: 4.1.2 + + '@inquirer/figures@1.0.3': {} + + '@inquirer/input@2.1.10': + dependencies: + '@inquirer/core': 8.2.3 + '@inquirer/type': 1.3.3 + + '@inquirer/password@2.1.10': + dependencies: + '@inquirer/core': 8.2.3 + '@inquirer/type': 1.3.3 + ansi-escapes: 4.3.2 + + '@inquirer/prompts@5.0.6': + dependencies: + '@inquirer/checkbox': 2.3.6 + '@inquirer/confirm': 3.1.10 + '@inquirer/editor': 2.1.10 + '@inquirer/expand': 2.1.10 + '@inquirer/input': 2.1.10 + '@inquirer/password': 2.1.10 + '@inquirer/rawlist': 2.1.10 + '@inquirer/select': 2.3.6 + + '@inquirer/rawlist@2.1.10': + dependencies: + '@inquirer/core': 8.2.3 + '@inquirer/type': 1.3.3 + chalk: 4.1.2 + + '@inquirer/select@2.3.6': + dependencies: + '@inquirer/core': 8.2.3 + '@inquirer/figures': 1.0.3 + '@inquirer/type': 1.3.3 + ansi-escapes: 4.3.2 + chalk: 4.1.2 + + '@inquirer/type@1.3.3': {} + + '@types/mute-stream@0.0.4': + dependencies: + '@types/node': 20.14.6 + + '@types/node@20.14.5': + dependencies: + undici-types: 5.26.5 + + '@types/node@20.14.6': + dependencies: + undici-types: 5.26.5 + + '@types/wrap-ansi@3.0.0': {} + + ansi-escapes@4.3.2: + dependencies: + type-fest: 0.21.3 + + ansi-regex@5.0.1: {} + + ansi-styles@4.3.0: + dependencies: + color-convert: 2.0.1 + + chalk@4.1.2: + dependencies: + ansi-styles: 4.3.0 + supports-color: 7.2.0 + + chardet@0.7.0: {} + + cli-spinners@2.9.2: {} + + cli-width@4.1.0: {} + + color-convert@2.0.1: + dependencies: + color-name: 1.1.4 + + color-name@1.1.4: {} + + deno-console@0.1.3: {} + + emoji-regex@8.0.0: {} + + esbuild@0.21.5: + optionalDependencies: + '@esbuild/aix-ppc64': 0.21.5 + '@esbuild/android-arm': 0.21.5 + '@esbuild/android-arm64': 0.21.5 + '@esbuild/android-x64': 0.21.5 + '@esbuild/darwin-arm64': 0.21.5 + '@esbuild/darwin-x64': 0.21.5 + '@esbuild/freebsd-arm64': 0.21.5 + '@esbuild/freebsd-x64': 0.21.5 + '@esbuild/linux-arm': 0.21.5 + '@esbuild/linux-arm64': 0.21.5 + '@esbuild/linux-ia32': 0.21.5 + '@esbuild/linux-loong64': 0.21.5 + '@esbuild/linux-mips64el': 0.21.5 + '@esbuild/linux-ppc64': 0.21.5 + '@esbuild/linux-riscv64': 0.21.5 + '@esbuild/linux-s390x': 0.21.5 + '@esbuild/linux-x64': 0.21.5 + '@esbuild/netbsd-x64': 0.21.5 + '@esbuild/openbsd-x64': 0.21.5 + '@esbuild/sunos-x64': 0.21.5 + '@esbuild/win32-arm64': 0.21.5 + '@esbuild/win32-ia32': 0.21.5 + '@esbuild/win32-x64': 0.21.5 + + external-editor@3.1.0: + dependencies: + chardet: 0.7.0 + iconv-lite: 0.4.24 + tmp: 0.0.33 + + has-flag@4.0.0: {} + + iconv-lite@0.4.24: + dependencies: + safer-buffer: 2.1.2 + + is-fullwidth-code-point@3.0.0: {} + + mute-stream@1.0.0: {} + + os-tmpdir@1.0.2: {} + + safer-buffer@2.1.2: {} + + signal-exit@4.1.0: {} + + string-width@4.2.3: + dependencies: + emoji-regex: 8.0.0 + is-fullwidth-code-point: 3.0.0 + strip-ansi: 6.0.1 + + strip-ansi@6.0.1: + dependencies: + ansi-regex: 5.0.1 + + supports-color@7.2.0: + dependencies: + has-flag: 4.0.0 + + tmp@0.0.33: + dependencies: + os-tmpdir: 1.0.2 + + type-fest@0.21.3: {} + + undici-types@5.26.5: {} + + wrap-ansi@6.2.0: + dependencies: + ansi-styles: 4.3.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 diff --git a/rqjs-ext/readme.md b/rqjs-ext/readme.md new file mode 100644 index 0000000..0c73752 --- /dev/null +++ b/rqjs-ext/readme.md @@ -0,0 +1,10 @@ +## install + +```rs +cargo install rqjs-cli + +rqjs + + +rqjs ./a.js +``` \ No newline at end of file diff --git a/rqjs-ext/src/bytearray_buffer.rs b/rqjs-ext/src/bytearray_buffer.rs new file mode 100644 index 0000000..486a336 --- /dev/null +++ b/rqjs-ext/src/bytearray_buffer.rs @@ -0,0 +1,222 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +use std::{ + cmp::min, + collections::VecDeque, + sync::{ + atomic::{AtomicBool, AtomicUsize, Ordering}, + Arc, Mutex, + }, +}; + +use tokio::sync::{Notify, Semaphore}; + +#[derive(Clone)] +pub struct BytearrayBuffer { + inner: Arc>>, + max_capacity: Arc, + len: Arc, + notify: Arc, + closed: Arc, + write_semaphore: Arc, +} + +impl BytearrayBuffer { + pub fn new(capacity: usize) -> Self { + let queue = VecDeque::with_capacity(capacity); + let capacity = queue.capacity(); + Self { + inner: Arc::new(Mutex::new(queue)), + len: Arc::new(AtomicUsize::new(0)), + max_capacity: Arc::new(AtomicUsize::new(capacity)), + notify: Arc::new(Notify::new()), + closed: Arc::new(AtomicBool::new(false)), + write_semaphore: Arc::new(Semaphore::new(1)), + } + } + + pub fn len(&self) -> usize { + self.len.load(Ordering::Relaxed) + } + + #[allow(dead_code)] + pub fn write_forced(&self, item: &[u8]) { + let mut inner = self.inner.lock().unwrap(); + inner.extend(item); + let capacity = inner.capacity(); + self.len.fetch_add(item.len(), Ordering::Relaxed); + self.max_capacity.store(capacity, Ordering::Relaxed); + } + + pub async fn write(&self, item: &mut [u8]) -> usize { + let _ = self.write_semaphore.acquire().await.unwrap(); + let mut slice_index = 0; + loop { + let max_capacity = self.max_capacity.load(Ordering::Relaxed); + if self.closed.load(Ordering::Relaxed) { + return max_capacity; + } + + let len = self.len.load(Ordering::Relaxed); + + let available = max_capacity - len; + + if available > 0 { + let end_index = min(item.len() - 1, slice_index + available - 1); + let sub_slice = &item[slice_index..=end_index]; + let slice_length = sub_slice.len(); + slice_index += slice_length; + + self.inner.lock().unwrap().extend(sub_slice); + self.len.fetch_add(slice_length, Ordering::Relaxed); + + if slice_index == item.len() { + return max_capacity; + } + } + self.notify.notified().await; + } + } + + #[allow(dead_code)] + pub fn is_closed(&self) -> bool { + self.closed.load(Ordering::Relaxed) + } + + pub async fn close(&self) { + self.closed.store(true, Ordering::Relaxed); + self.notify.notify_one(); + //wait for write to finish + let _ = self.write_semaphore.acquire().await.unwrap(); + } + + pub async fn clear(&self) { + self.closed.store(false, Ordering::Relaxed); + self.notify.notify_one(); + //wait for write to finish + let _ = self.write_semaphore.acquire().await.unwrap(); + self.len.store(0, Ordering::Relaxed); + self.inner.lock().unwrap().clear(); + self.closed.store(false, Ordering::Relaxed); + } + + pub fn read(&self, desired_size: Option) -> Option> { + let mut inner = self.inner.lock().unwrap(); + let done = self.closed.load(Ordering::Relaxed); + + let items = if done { + Some(inner.drain(0..).collect()) + } else if let Some(desired_len) = desired_size { + let max_capacity = self.max_capacity.load(Ordering::Relaxed); + if desired_len > max_capacity { + let diff = desired_len - max_capacity; + inner.reserve(diff - 1); + let mut max_capacity = inner.capacity(); + if desired_len > max_capacity { + inner.reserve(desired_len - max_capacity); + max_capacity = inner.capacity(); + } + drop(inner); + self.max_capacity.store(max_capacity, Ordering::Relaxed); + self.notify.notify_one(); + return None; + } + + let len = self.len.load(Ordering::Relaxed); + if desired_len > len { + self.notify.notify_one(); + return None; + } + + Some(inner.drain(0..desired_len).collect()) + } else { + Some(inner.drain(0..).collect()) + }; + self.len.store(inner.len(), Ordering::Relaxed); + drop(inner); + self.notify.notify_one(); + items + } +} + +#[cfg(test)] +mod tests { + use crate::bytearray_buffer::BytearrayBuffer; + + #[tokio::test] + async fn clear_while_writing() { + let queue = BytearrayBuffer::new(8); + let queue2 = queue.clone(); + + tokio::task::spawn(async move { + let mut vec: Vec = (0..=255).collect(); + queue.write(&mut vec).await; + }); + + queue2.clear().await + } + + #[tokio::test] + async fn write_one_at_a_time() { + let queue = BytearrayBuffer::new(8); + let queue2 = queue.clone(); + let queue3 = queue.clone(); + + tokio::task::spawn(async move { + let mut vec: Vec = (0..=127).collect(); + queue.write(&mut vec).await; + }); + + tokio::task::spawn(async move { + let mut vec: Vec = (128..=255).collect(); + queue2.write(&mut vec).await; + }); + + let mut data = Vec::::new(); + + loop { + tokio::task::yield_now().await; + if let Some(bytes) = queue3.read(Some(256)) { + data.extend(bytes); + break; + } + } + + //assert that data in vec is increment from 0 to 255 + for i in 0..=255 { + assert_eq!(data[i as usize], i); + } + } + + #[tokio::test] + async fn queue() { + let queue = BytearrayBuffer::new(8); + let queue2 = queue.clone(); + + let write_task = tokio::task::spawn(async move { + for _ in 0..=255 { + let mut vec: Vec = (0..=255).collect(); + queue.write(&mut vec).await; + } + queue.close().await; + }); + + let mut data = Vec::::new(); + + loop { + let done = queue2.is_closed(); + + tokio::task::yield_now().await; + if let Some(bytes) = queue2.read(Some(9)) { + data.extend(bytes); + } + if done { + break; + } + } + + let _ = write_task.await; + + assert_eq!(data.len(), 256 * 256) + } +} diff --git a/rqjs-ext/src/bytecode_cache.rs b/rqjs-ext/src/bytecode_cache.rs new file mode 100644 index 0000000..1e11a7c --- /dev/null +++ b/rqjs-ext/src/bytecode_cache.rs @@ -0,0 +1,9 @@ +// @generated by build.rs + +pub static BYTECODE_CACHE: phf::Map<&'static str, &[u8]> = ::phf::Map { + key: 0, + disps: &[ + ], + entries: &[ + ], +}; diff --git a/rqjs-ext/src/json/escape.rs b/rqjs-ext/src/json/escape.rs new file mode 100644 index 0000000..85bbab5 --- /dev/null +++ b/rqjs-ext/src/json/escape.rs @@ -0,0 +1,233 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +#[cfg(rust_nightly)] //FIXME remove when std::simd is stable +use std::simd::{ + prelude::{SimdPartialEq, SimdPartialOrd}, + u8x16, Simd, +}; +//use std::simd::{u8x16, Mask, Simd, SimdPartialEq, SimdPartialOrd, ToBitMask}; + +static JSON_ESCAPE_CHARS: [u8; 256] = [ + 0u8, 1u8, 2u8, 3u8, 4u8, 5u8, 6u8, 7u8, 8u8, 9u8, 10u8, 11u8, 12u8, 13u8, 14u8, 15u8, 16u8, + 17u8, 18u8, 19u8, 20u8, 21u8, 22u8, 23u8, 24u8, 25u8, 26u8, 27u8, 28u8, 29u8, 30u8, 31u8, 34u8, + 34u8, 32u8, 34u8, 34u8, 34u8, 34u8, 34u8, 34u8, 34u8, 34u8, 34u8, 34u8, 34u8, 34u8, 34u8, 34u8, + 34u8, 34u8, 34u8, 34u8, 34u8, 34u8, 34u8, 34u8, 34u8, 34u8, 34u8, 34u8, 34u8, 34u8, 34u8, 34u8, + 34u8, 34u8, 34u8, 34u8, 34u8, 34u8, 34u8, 34u8, 34u8, 34u8, 34u8, 34u8, 34u8, 34u8, 34u8, 34u8, + 34u8, 34u8, 34u8, 34u8, 34u8, 34u8, 34u8, 34u8, 34u8, 34u8, 34u8, 33u8, 34u8, 34u8, 34u8, 34u8, + 34u8, 34u8, 34u8, 34u8, 34u8, 34u8, 34u8, 34u8, 34u8, 34u8, 34u8, 34u8, 34u8, 34u8, 34u8, 34u8, + 34u8, 34u8, 34u8, 34u8, 34u8, 34u8, 34u8, 34u8, 34u8, 34u8, 34u8, 34u8, 34u8, 34u8, 34u8, 34u8, + 34u8, 34u8, 34u8, 34u8, 34u8, 34u8, 34u8, 34u8, 34u8, 34u8, 34u8, 34u8, 34u8, 34u8, 34u8, 34u8, + 34u8, 34u8, 34u8, 34u8, 34u8, 34u8, 34u8, 34u8, 34u8, 34u8, 34u8, 34u8, 34u8, 34u8, 34u8, 34u8, + 34u8, 34u8, 34u8, 34u8, 34u8, 34u8, 34u8, 34u8, 34u8, 34u8, 34u8, 34u8, 34u8, 34u8, 34u8, 34u8, + 34u8, 34u8, 34u8, 34u8, 34u8, 34u8, 34u8, 34u8, 34u8, 34u8, 34u8, 34u8, 34u8, 34u8, 34u8, 34u8, + 34u8, 34u8, 34u8, 34u8, 34u8, 34u8, 34u8, 34u8, 34u8, 34u8, 34u8, 34u8, 34u8, 34u8, 34u8, 34u8, + 34u8, 34u8, 34u8, 34u8, 34u8, 34u8, 34u8, 34u8, 34u8, 34u8, 34u8, 34u8, 34u8, 34u8, 34u8, 34u8, + 34u8, 34u8, 34u8, 34u8, 34u8, 34u8, 34u8, 34u8, 34u8, 34u8, 34u8, 34u8, 34u8, 34u8, 34u8, 34u8, + 34u8, 34u8, 34u8, 34u8, 34u8, 34u8, 34u8, 34u8, 34u8, 34u8, 34u8, 34u8, 34u8, 34u8, 34u8, +]; +static JSON_ESCAPE_QUOTES: [&str; 34usize] = [ + "\\u0000", "\\u0001", "\\u0002", "\\u0003", "\\u0004", "\\u0005", "\\u0006", "\\u0007", "\\b", + "\\t", "\\n", "\\u000b", "\\f", "\\r", "\\u000e", "\\u000f", "\\u0010", "\\u0011", "\\u0012", + "\\u0013", "\\u0014", "\\u0015", "\\u0016", "\\u0017", "\\u0018", "\\u0019", "\\u001a", + "\\u001b", "\\u001c", "\\u001d", "\\u001e", "\\u001f", "\\\"", "\\\\", +]; + +const ESCAPE_LEN: usize = 34; + +#[allow(dead_code)] +pub fn escape_json(bytes: &[u8]) -> String { + let mut result = String::new(); + escape_json_string(&mut result, bytes); + result +} + +#[inline(always)] +pub fn escape_json_string_simple(result: &mut String, bytes: &[u8]) { + let len = bytes.len(); + let mut start = 0; + result.reserve(len); + + for (i, byte) in bytes.iter().enumerate() { + let c = JSON_ESCAPE_CHARS[*byte as usize] as usize; + if c < ESCAPE_LEN { + if start < i { + result.push_str(unsafe { std::str::from_utf8_unchecked(&bytes[start..i]) }); + } + result.push_str(JSON_ESCAPE_QUOTES[c]); + start = i + 1; + } + } + if start < len { + result.push_str(unsafe { std::str::from_utf8_unchecked(&bytes[start..len]) }); + } +} + +#[cfg(not(rust_nightly))] +pub fn escape_json_string(result: &mut String, bytes: &[u8]) { + escape_json_string_simple(result, bytes); +} + +#[cfg(rust_nightly)] +pub fn escape_json_string(result: &mut String, bytes: &[u8]) { + use std::mem; + + const USIZE_BYTES: usize = mem::size_of::(); + + let len = bytes.len(); + if len < USIZE_BYTES * 2 { + return escape_json_string_simple(result, bytes); + } + + const ESCAPE_LEN: usize = 34; + const BELOW_SPACE: u8 = b' ' - 1; + const B: u8 = b'"'; + const C: u8 = b'\\'; + + let v_below_space: u8x16 = u8x16::splat(BELOW_SPACE); + let v_b: u8x16 = u8x16::splat(B); + let v_c: u8x16 = u8x16::splat(C); + + result.reserve(len); + + #[inline(always)] + fn process_padded_chunk( + bytes: &[u8], + result: &mut String, + v_below_space: u8x16, + v_b: u8x16, + v_c: u8x16, + ) { + let len = bytes.len(); + if len > 0 { + let mut padded_bytes = [b'_'; 16]; //can be max 16 *2 offset + padded_bytes[..len].copy_from_slice(bytes); + let byte_vector = u8x16::from_slice(&padded_bytes); + process_chunk( + &padded_bytes, + result, + byte_vector, + len, + v_below_space, + v_b, + v_c, + ); + } + } + + #[inline(always)] + fn process_chunk( + chunk: &[u8], + result: &mut String, + byte_vector: Simd, + max_len: usize, + v_below_space: u8x16, + v_b: u8x16, + v_c: u8x16, + ) { + let mut mask = (byte_vector.simd_eq(v_b) + | byte_vector.simd_eq(v_c) + | (byte_vector).simd_lt(v_below_space)) + .to_bitmask(); + + if mask != 0 { + let mut cur = mask.trailing_zeros() as usize; + let mut start = 0; + + while cur < max_len { + let c = JSON_ESCAPE_CHARS[chunk[cur] as usize] as usize; + if c < ESCAPE_LEN { + if start < cur { + result + .push_str(unsafe { std::str::from_utf8_unchecked(&chunk[start..cur]) }); + } + result.push_str(JSON_ESCAPE_QUOTES[c]); + start = cur + 1; + } + mask ^= 1 << cur; + if mask == 0 { + break; + } + cur = mask.trailing_zeros() as usize; + } + if start < max_len { + result.push_str(unsafe { std::str::from_utf8_unchecked(&chunk[start..max_len]) }); + } + } else { + result.push_str(unsafe { std::str::from_utf8_unchecked(&chunk[..max_len]) }); + } + } + + fn process(bytes: &[u8], result: &mut String, v_below_space: u8x16, v_b: u8x16, v_c: u8x16) { + let iter = bytes.chunks_exact(16); + + let rem = iter.remainder(); + + for chunk in iter { + let a = u8x16::from_slice(&chunk); + process_chunk(chunk, result, a, 16, v_below_space, v_b, v_c); + } + + process_padded_chunk(rem, result, v_below_space, v_b, v_c); + } + + if len < 16 { + process_padded_chunk(bytes, result, v_below_space, v_b, v_c); + return; + } + + process(bytes, result, v_below_space, v_b, v_c); +} + +#[cfg(test)] +mod tests { + use crate::json::escape::escape_json; + + #[test] + fn escape_json_simple() { + assert_eq!(escape_json(b"Hello, World!"), "Hello, World!"); + } + + #[test] + fn escape_json_quotes() { + assert_eq!(escape_json(b"\"quoted\""), "\\\"quoted\\\""); + } + + #[test] + fn escape_json_backslash() { + assert_eq!(escape_json(b"back\\slash"), "back\\\\slash"); + } + + #[test] + fn escape_json_newline() { + assert_eq!(escape_json(b"line\nbreak"), "line\\nbreak"); + } + + #[test] + fn escape_json_tab() { + assert_eq!(escape_json(b"tab\tcharacter"), "tab\\tcharacter"); + } + + #[test] + fn escape_json_unicode() { + assert_eq!( + escape_json("unicode: \u{1F609}".as_bytes()), + "unicode: \u{1F609}" + ); + } + + #[test] + fn escape_json_special_characters() { + assert_eq!( + escape_json(b"!@#$%^&*()_+-=[]{}|;':,.<>?/"), + "!@#$%^&*()_+-=[]{}|;':,.<>?/" + ); + } + + #[test] + fn escape_json_mixed_characters() { + assert_eq!( + escape_json(b"123\"\"45678901\"234567"), + "123\\\"\\\"45678901\\\"234567" + ); + } +} diff --git a/rqjs-ext/src/json/mod.rs b/rqjs-ext/src/json/mod.rs new file mode 100644 index 0000000..99339d2 --- /dev/null +++ b/rqjs-ext/src/json/mod.rs @@ -0,0 +1,168 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +pub mod escape; +pub mod parse; +pub mod stringify; + +// #[cfg(test)] +// mod tests { + +// use rquickjs::{Array, CatchResultExt, IntoJs, Null, Object, Undefined, Value}; + +// use crate::{ +// json::{ +// parse::json_parse, +// stringify::{json_stringify, json_stringify_replacer_space}, +// }, +// test_utils::utils::with_js_runtime, +// }; + +// static JSON: &str = r#"{"organization":{"name":"TechCorp","founding_year":2000,"departments":[{"name":"Engineering","head":{"name":"Alice Smith","title":"VP of Engineering","contact":{"email":"alice.smith@techcorp.com","phone":"+1 (555) 123-4567"}},"employees":[{"id":101,"name":"Bob Johnson","position":"Software Engineer","contact":{"email":"bob.johnson@techcorp.com","phone":"+1 (555) 234-5678"},"projects":[{"project_id":"P001","name":"Project A","status":"In Progress","description":"Developing a revolutionary software solution for clients.","start_date":"2023-01-15","end_date":null,"team":[{"id":201,"name":"Sara Davis","role":"UI/UX Designer"},{"id":202,"name":"Charlie Brown","role":"Quality Assurance Engineer"}]},{"project_id":"P002","name":"Project B","status":"Completed","description":"Upgrading existing systems to enhance performance.","start_date":"2022-05-01","end_date":"2022-11-30","team":[{"id":203,"name":"Emily White","role":"Systems Architect"},{"id":204,"name":"James Green","role":"Database Administrator"}]}]},{"id":102,"name":"Carol Williams","position":"Senior Software Engineer","contact":{"email":"carol.williams@techcorp.com","phone":"+1 (555) 345-6789"},"projects":[{"project_id":"P001","name":"Project A","status":"In Progress","description":"Working on the backend development of Project A.","start_date":"2023-01-15","end_date":null,"team":[{"id":205,"name":"Alex Turner","role":"DevOps Engineer"},{"id":206,"name":"Mia Garcia","role":"Software Developer"}]},{"project_id":"P003","name":"Project C","status":"Planning","description":"Researching and planning for a future project.","start_date":null,"end_date":null,"team":[]}]}]},{"name":"Marketing","head":{"name":"David Brown","title":"VP of Marketing","contact":{"email":"david.brown@techcorp.com","phone":"+1 (555) 456-7890"}},"employees":[{"id":201,"name":"Eva Miller","position":"Marketing Specialist","contact":{"email":"eva.miller@techcorp.com","phone":"+1 (555) 567-8901"},"campaigns":[{"campaign_id":"C001","name":"Product Launch","status":"Upcoming","description":"Planning for the launch of a new product line.","start_date":"2023-03-01","end_date":null,"team":[{"id":301,"name":"Oliver Martinez","role":"Graphic Designer"},{"id":302,"name":"Sophie Johnson","role":"Content Writer"}]},{"campaign_id":"C002","name":"Brand Awareness","status":"Ongoing","description":"Executing strategies to increase brand visibility.","start_date":"2022-11-15","end_date":"2023-01-31","team":[{"id":303,"name":"Liam Taylor","role":"Social Media Manager"},{"id":304,"name":"Ava Clark","role":"Marketing Analyst"}]}]}]}]}}"#; + +// #[tokio::test] +// async fn json_parser() { +// with_js_runtime(|ctx| { +// let json_data = [ +// r#"{"aa\"\"aaaaaaaaaaaaaaaa":"a","b":"bbb"}"#, +// r#"{"a":"aaaaaaaaaaaaaaaaaa","b":"bbb"}"#, +// r#"{"a":["a","a","aaaa","a"],"b":"b"}"#, +// r#"{"type":"Buffer","data":[10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10]}"#, +// r#"{"a":[{"object2":{"key1":"value1","key2":123,"key3":false,"nestedObject":{"nestedKey":"nestedValue"}},"string":"Hello, World!","emptyObj":{},"emptyArr":[],"number":42,"boolean":true,"nullValue":null,"array":[1,2,3,"four",5.5,true,null],"object":{"key1":"value1","key2":123,"key3":false,"nestedObject":{"nestedKey":"nestedValue"}}}]}"#, +// JSON, +// ]; + +// for json_str in json_data { +// let json = json_str.to_string(); +// let json2 = json.clone(); + +// let value = json_parse(&ctx, json2)?; +// let new_json = json_stringify_replacer_space(&ctx, value.clone(),None,Some(" ".into()))?.unwrap(); +// let builtin_json = ctx.json_stringify_replacer_space(value,Null," ".to_string())?.unwrap().to_string()?; +// assert_eq!(new_json, builtin_json); +// } + +// Ok(()) +// }) +// .await; +// } + +// #[tokio::test] +// async fn json_stringify_undefined() { +// with_js_runtime(|ctx| { +// let stringified = json_stringify(&ctx, Undefined.into_js(&ctx)?)?; +// let stringified_2 = ctx +// .json_stringify(Undefined)? +// .map(|v| v.to_string().unwrap()); +// assert_eq!(stringified, stringified_2); + +// let obj: Value = ctx.eval( +// r#"let obj = { value: undefined, array: [undefined, null, 1, true, "hello", { [Symbol("sym")]: 1, [undefined]: 2}] };obj;"#, +// )?; + +// let stringified = json_stringify(&ctx, obj.clone())?; +// let stringified_2 = ctx +// .json_stringify(obj)? +// .map(|v| v.to_string().unwrap()); +// assert_eq!(stringified, stringified_2); + +// Ok(()) +// }) +// .await; +// } + +// #[tokio::test] +// async fn json_stringify_objects() { +// with_js_runtime(|ctx| { +// let date: Value = ctx.eval("let obj = { date: new Date(0) };obj;")?; +// let stringified = json_stringify(&ctx, date.clone())?.unwrap(); +// let stringified_2 = ctx.json_stringify(date)?.unwrap().to_string()?; +// assert_eq!(stringified, stringified_2); +// Ok(()) +// }) +// .await; +// } + +// #[tokio::test] +// async fn huge_numbers() { +// with_js_runtime(|ctx| { + +// let big_int_value = json_parse(&ctx, b"99999999999999999999999999999999999999999999999999999999999999999999999999999999999")?; + +// let stringified = json_stringify(&ctx, big_int_value.clone())?.unwrap(); +// let stringified_2 = ctx.json_stringify(big_int_value)?.unwrap().to_string()?.replace("e+", "e"); +// assert_eq!(stringified, stringified_2); + +// let big_int_value: Value = ctx.eval("999999999999")?; +// let stringified = json_stringify(&ctx, big_int_value.clone())?.unwrap(); +// let stringified_2 = ctx.json_stringify(big_int_value)?.unwrap().to_string()?; +// assert_eq!(stringified, stringified_2); + +// Ok(()) +// }) +// .await; +// } + +// #[tokio::test] +// async fn json_circular_ref() { +// with_js_runtime(|ctx| { +// let obj1 = Object::new(ctx.clone())?; +// let obj2 = Object::new(ctx.clone())?; +// let obj3 = Object::new(ctx.clone())?; +// let obj4 = Object::new(ctx.clone())?; +// obj4.set("key", "value")?; +// obj3.set("sub2", obj4.clone())?; +// obj2.set("sub1", obj3)?; +// obj1.set("root1", obj2.clone())?; +// obj1.set("root2", obj2.clone())?; +// obj1.set("root3", obj2.clone())?; + +// let value = obj1.clone().into_value(); + +// let stringified = json_stringify(&ctx, value.clone())?.unwrap(); +// let stringified_2 = ctx.json_stringify(value.clone())?.unwrap().to_string()?; +// assert_eq!(stringified, stringified_2); + +// obj4.set("recursive", obj1.clone())?; + +// let stringified = json_stringify(&ctx, value.clone()); + +// if let Err(error_message) = stringified.catch(&ctx) { +// let error_str = error_message.to_string(); +// assert_eq!( +// "Error: Circular reference detected at: \"...root1.sub1.sub2.recursive\"\n", +// error_str +// ) +// } else { +// panic!("Expected an error, but got Ok"); +// } + +// let array1 = Array::new(ctx.clone())?; +// let array2 = Array::new(ctx.clone())?; +// let array3 = Array::new(ctx.clone())?; + +// let obj5 = Object::new(ctx.clone())?; +// obj5.set("key", obj1.clone())?; +// array3.set(2, obj5)?; +// array2.set(1, array3)?; +// array1.set(0, array2)?; + +// obj4.remove("recursive")?; +// obj1.set("recursiveArray", array1)?; + +// let stringified = json_stringify(&ctx, value.clone()); + +// if let Err(error_message) = stringified.catch(&ctx) { +// let error_str = error_message.to_string(); +// assert_eq!( +// "Error: Circular reference detected at: \"...recursiveArray[0][1][2].key\"\n", +// error_str +// ) +// } else { +// panic!("Expected an error, but got Ok"); +// } + +// Ok(()) +// }) +// .await; +// } +// } diff --git a/rqjs-ext/src/json/parse.rs b/rqjs-ext/src/json/parse.rs new file mode 100644 index 0000000..544866b --- /dev/null +++ b/rqjs-ext/src/json/parse.rs @@ -0,0 +1,64 @@ +use crate::utils::result::ResultExt; +use rquickjs::{Array, Ctx, IntoJs, Null, Object, Result, Undefined, Value}; +use simd_json::{Node, StaticNode}; + +pub fn json_parse<'js, T: Into>>(ctx: &Ctx<'js>, json: T) -> Result> { + let mut json: Vec = json.into(); + let tape = simd_json::to_tape(&mut json).or_throw(ctx)?; + let tape = tape.0; + + if let Some(first) = tape.first() { + return match first { + Node::String(value) => value.into_js(ctx), + Node::Static(node) => static_node_to_value(ctx, *node), + _ => parse_node(ctx, &tape, 0).map(|(value, _)| value), + }; + } + + Undefined.into_js(ctx) +} + +#[inline(always)] +fn static_node_to_value<'js>(ctx: &Ctx<'js>, node: StaticNode) -> Result> { + match node { + StaticNode::I64(value) => value.into_js(ctx), + StaticNode::U64(value) => value.into_js(ctx), + StaticNode::F64(value) => value.into_js(ctx), + StaticNode::Bool(value) => value.into_js(ctx), + StaticNode::Null => Null.into_js(ctx), + } +} + +fn parse_node<'js>(ctx: &Ctx<'js>, tape: &[Node], index: usize) -> Result<(Value<'js>, usize)> { + match &tape[index] { + Node::String(value) => Ok((value.into_js(ctx)?, index + 1)), + Node::Static(node) => Ok((static_node_to_value(ctx, *node)?, index + 1)), + Node::Object { len, .. } => { + let js_object = Object::new(ctx.clone())?; + let mut current_index = index + 1; + + for _ in 0..*len { + if let Node::String(key) = &tape[current_index] { + current_index += 1; + let (value, new_index) = parse_node(ctx, tape, current_index)?; + current_index = new_index; + js_object.set(*key, value)?; + } + } + + Ok((js_object.into_value(), current_index)) + } + Node::Array { len, .. } => { + let js_array = Array::new(ctx.clone())?; + let mut current_index = index + 1; + + for i in 0..*len { + let (value, new_index) = parse_node(ctx, tape, current_index)?; + current_index = new_index; + js_array.set(i, value)?; + } + + Ok((js_array.into_value(), current_index)) + } + } +} diff --git a/rqjs-ext/src/json/stringify.rs b/rqjs-ext/src/json/stringify.rs new file mode 100644 index 0000000..d22e2c9 --- /dev/null +++ b/rqjs-ext/src/json/stringify.rs @@ -0,0 +1,494 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +use std::collections::HashSet; + +use rquickjs::{ + atom::PredefinedAtom, function::This, Ctx, Exception, Function, Object, Result, Type, Value, +}; + +use crate::json::escape::escape_json_string; + +const CIRCULAR_REF_DETECTION_DEPTH: usize = 20; + +struct StringifyContext<'a, 'js> { + ctx: &'a Ctx<'js>, + result: &'a mut String, + value: &'a Value<'js>, + depth: usize, + indentation: Option<&'a str>, + key: Option<&'a str>, + index: Option, + parent: Option<&'a Object<'js>>, + ancestors: &'a mut Vec<(usize, String)>, + replacer_fn: Option<&'a Function<'js>>, + include_keys_replacer: Option<&'a HashSet>, +} + +#[allow(dead_code)] +pub fn json_stringify<'js>(ctx: &Ctx<'js>, value: Value<'js>) -> Result> { + json_stringify_replacer_space(ctx, value, None, None) +} + +#[allow(dead_code)] +pub fn json_stringify_replacer<'js>( + ctx: &Ctx<'js>, + value: Value<'js>, + replacer: Option>, +) -> Result> { + json_stringify_replacer_space(ctx, value, replacer, None) +} + +pub fn json_stringify_replacer_space<'js>( + ctx: &Ctx<'js>, + value: Value<'js>, + replacer: Option>, + indentation: Option, +) -> Result> { + let mut result = String::with_capacity(128); + let mut replacer_fn = None; + let mut include_keys_replacer = None; + + let tmp_function; + + if let Some(replacer) = replacer { + if let Some(function) = replacer.as_function() { + tmp_function = function.clone(); + replacer_fn = Some(&tmp_function); + } else if let Some(array) = replacer.as_array() { + let mut filter = HashSet::with_capacity(array.len()); + for value in array.clone().into_iter() { + let value = value?; + if let Some(string) = value.as_string() { + filter.insert(string.to_string()?); + } else if let Some(number) = value.as_int() { + let mut buffer = itoa::Buffer::new(); + filter.insert(buffer.format(number).to_string()); + } else if let Some(number) = value.as_float() { + let mut buffer = ryu::Buffer::new(); + filter.insert(buffer.format(number).to_string()); + } + } + include_keys_replacer = Some(filter); + } + } + + let indentation = indentation.as_deref(); + let include_keys_replacer = include_keys_replacer.as_ref(); + + let mut ancestors = Vec::with_capacity(10); + + let mut context = StringifyContext { + ctx, + result: &mut result, + value: &value, + depth: 0, + indentation: None, + key: None, + index: None, + parent: None, + ancestors: &mut ancestors, + replacer_fn, + include_keys_replacer, + }; + + match write_primitive(&mut context, false)? { + PrimitiveStatus::Written => { + return Ok(Some(result)); + } + PrimitiveStatus::Ignored => { + return Ok(None); + } + _ => {} + } + + context.depth += 1; + context.indentation = indentation; + iterate(&mut context)?; + Ok(Some(result)) +} + +#[inline(always)] +#[cold] +fn write_indentation(result: &mut String, indentation: Option<&str>, depth: usize) { + if let Some(indentation) = indentation { + result.push('\n'); + result.push_str(&indentation.repeat(depth - 1)); + } +} + +#[inline(always)] +#[cold] +fn run_to_json<'js>( + context: &mut StringifyContext<'_, 'js>, + js_object: &Object<'js>, +) -> Result<()> { + let to_json = js_object.get::<_, Function>(PredefinedAtom::ToJSON)?; + let val = to_json.call((This(js_object.clone()),))?; + append_value( + &mut StringifyContext { + ctx: context.ctx, + result: context.result, + value: &val, + depth: context.depth, + indentation: context.indentation, + key: None, + index: None, + parent: Some(js_object), + ancestors: context.ancestors, + replacer_fn: context.replacer_fn, + include_keys_replacer: context.include_keys_replacer, + }, + false, + )?; + Ok(()) +} + +#[derive(PartialEq)] +enum PrimitiveStatus { + Written, + Ignored, + Iterate, +} + +#[inline(always)] +#[cold] +fn run_replacer<'js>( + context: &mut StringifyContext<'_, 'js>, + replacer_fn: &Function<'js>, + add_comma: bool, +) -> Result { + let parent = context.parent; + let ctx = context.ctx; + let value = context.value; + let key = context.key; + let index = context.index; + let parent = if let Some(parent) = parent { + parent.clone() + } else { + let parent = Object::new(ctx.clone())?; + parent.set("", value.clone())?; + parent + }; + let new_value = replacer_fn.call((This(parent), get_key_or_index(key, index), value))?; + write_primitive( + &mut StringifyContext { + ctx, + result: context.result, + value: &new_value, + replacer_fn: None, + key, + index: None, + indentation: context.indentation, + parent: None, + include_keys_replacer: None, + depth: context.depth, + ancestors: context.ancestors, + }, + add_comma, + ) +} + +#[inline(always)] +fn write_primitive(context: &mut StringifyContext, add_comma: bool) -> Result { + if let Some(replacer_fn) = context.replacer_fn { + return run_replacer(context, replacer_fn, add_comma); + } + + let include_keys_replacer = context.include_keys_replacer; + let value = context.value; + let key = context.key; + let index = context.index; + let indentation = context.indentation; + let depth = context.depth; + + let type_of = value.type_of(); + + if matches!(type_of, Type::Symbol | Type::Undefined) && context.index.is_none() { + return Ok(PrimitiveStatus::Ignored); + } + + if let Some(include_keys_replacer) = include_keys_replacer { + let key = get_key_or_index(key, index); + if !include_keys_replacer.contains(&key) { + return Ok(PrimitiveStatus::Ignored); + } + }; + + if let Some(indentation) = indentation { + write_indented_separator(context.result, key, add_comma, indentation, depth); + } else { + write_sep(context.result, add_comma, false); + if let Some(key) = key { + write_key(context.result, key, false); + } + } + + match type_of { + Type::Null | Type::Undefined => context.result.push_str("null"), + Type::Bool => { + const BOOL_STRINGS: [&str; 2] = ["false", "true"]; + context + .result + .push_str(BOOL_STRINGS[value.as_bool().unwrap() as usize]); + } + Type::Int => { + let mut buffer = itoa::Buffer::new(); + context + .result + .push_str(buffer.format(value.as_int().unwrap())) + } + Type::Float => { + let float_value = value.as_float().unwrap(); + const EXP_MASK: u64 = 0x7ff0000000000000; + let bits = float_value.to_bits(); + if bits & EXP_MASK == EXP_MASK { + context.result.push_str("null"); + } else { + let mut buffer = ryu::Buffer::new(); + let str = buffer.format_finite(value.as_float().unwrap()); + + let bytes = str.as_bytes(); + let len = bytes.len(); + + context.result.push_str(str); + + if &bytes[len - 2..] == b".0" { + let len = context.result.len(); + unsafe { context.result.as_mut_vec().set_len(len - 2) } + } + } + } + Type::String => write_string(context.result, &value.as_string().unwrap().to_string()?), + _ => return Ok(PrimitiveStatus::Iterate), + } + Ok(PrimitiveStatus::Written) +} + +#[inline(always)] +#[cold] +fn write_indented_separator( + result: &mut String, + key: Option<&str>, + add_comma: bool, + indentation: &str, + depth: usize, +) { + write_sep(result, add_comma, true); + result.push_str(&indentation.repeat(depth)); + if let Some(key) = key { + write_key(result, key, true); + } +} + +#[cold] +#[inline(always)] +fn detect_circular_reference( + ctx: &Ctx<'_>, + value: &Object<'_>, + key: Option<&str>, + index: Option, + parent: Option<&Object<'_>>, + ancestors: &mut Vec<(usize, String)>, +) -> Result<()> { + let parent_ptr = unsafe { parent.unwrap().as_raw().u.ptr as usize }; + let current_ptr = unsafe { value.as_raw().u.ptr as usize }; + + while !ancestors.is_empty() + && match ancestors.last() { + Some((ptr, _)) => ptr != &parent_ptr, + _ => false, + } + { + ancestors.pop(); + } + + if ancestors.iter().any(|(ptr, _)| ptr == ¤t_ptr) { + let mut iter = ancestors.iter_mut(); + + let first = &iter.next().unwrap().1; + + let mut path = iter + .rev() + .take(4) + .rev() + .fold(String::new(), |mut acc, (_, key)| { + if !key.starts_with('[') { + acc.push('.'); + } + acc.push_str(key); + acc + }); + + if !first.starts_with('[') { + path.push('.'); + } + + path.push_str(first); + + return Err(Exception::throw_type( + ctx, + &format!("Circular reference detected at: \"..{}\"", path), + )); + } + ancestors.push(( + current_ptr, + key.map(|k| k.to_string()) + .unwrap_or_else(|| format!("[{}]", index.unwrap_or_default())), + )); + + Ok(()) +} + +#[inline(always)] +fn append_value(context: &mut StringifyContext<'_, '_>, add_comma: bool) -> Result { + match write_primitive(context, add_comma)? { + PrimitiveStatus::Written => Ok(true), + PrimitiveStatus::Ignored => Ok(false), + PrimitiveStatus::Iterate => { + context.depth += 1; + iterate(context)?; + Ok(true) + } + } +} + +#[inline(always)] +fn write_key(string: &mut String, key: &str, indent: bool) { + string.push('"'); + escape_json_string(string, key.as_bytes()); + const SUFFIXES: [&str; 2] = ["\":", "\": "]; + string.push_str(SUFFIXES[indent as usize]); +} + +#[inline(always)] +fn write_sep(result: &mut String, add_comma: bool, has_indentation: bool) { + const SEPARATOR_TABLE: [&str; 4] = [ + "", // add_comma = false, has_indentation = false + ",", // add_comma = false, has_indentation = true + "\n", // add_comma = true, has_indentation = false + ",\n", // add_comma = true, has_indentation = true + ]; + + let index = (add_comma as usize) | ((has_indentation as usize) << 1); + result.push_str(SEPARATOR_TABLE[index]); +} + +#[inline(always)] +fn write_string(string: &mut String, value: &str) { + string.push('"'); + escape_json_string(string, value.as_bytes()); + string.push('"'); +} + +#[inline(always)] +fn get_key_or_index(key: Option<&str>, index: Option) -> String { + key.map(|k| k.to_string()).unwrap_or_else(|| { + let mut buffer = itoa::Buffer::new(); + buffer.format(index.unwrap_or_default()).to_string() + }) +} + +#[inline(always)] +fn iterate(context: &mut StringifyContext<'_, '_>) -> Result<()> { + let mut add_comma; + let mut value_written; + let elem = context.value; + let depth = context.depth; + let ctx = context.ctx; + let indentation = context.indentation; + match elem.type_of() { + Type::Object => { + let js_object = elem.as_object().unwrap(); + if js_object.contains_key(PredefinedAtom::ToJSON)? { + return run_to_json(context, js_object); + } + + //only start detect circular reference at this level + if depth > CIRCULAR_REF_DETECTION_DEPTH { + detect_circular_reference( + ctx, + js_object, + context.key, + context.index, + context.parent, + context.ancestors, + )?; + } + + context.result.push('{'); + + value_written = false; + + for key in js_object.keys::() { + let key = key?; + let val = js_object.get(&key)?; + + add_comma = append_value( + &mut StringifyContext { + ctx, + result: context.result, + value: &val, + depth, + key: Some(&key), + indentation, + index: None, + parent: Some(js_object), + ancestors: context.ancestors, + replacer_fn: context.replacer_fn, + include_keys_replacer: context.include_keys_replacer, + }, + value_written, + )?; + value_written = value_written || add_comma; + } + + if value_written { + write_indentation(context.result, indentation, depth); + } + context.result.push('}'); + } + Type::Array => { + context.result.push('['); + add_comma = false; + value_written = false; + let js_array = elem.as_array().unwrap(); + //only start detect circular reference at this level + if depth > CIRCULAR_REF_DETECTION_DEPTH { + detect_circular_reference( + ctx, + js_array.as_object(), + context.key, + context.index, + context.parent, + context.ancestors, + )?; + } + for (i, val) in js_array.iter::().enumerate() { + let val = val?; + add_comma = append_value( + &mut StringifyContext { + ctx, + result: context.result, + value: &val, + depth, + key: None, + indentation, + index: Some(i), + parent: Some(js_array), + ancestors: context.ancestors, + replacer_fn: context.replacer_fn, + include_keys_replacer: context.include_keys_replacer, + }, + add_comma, + )?; + value_written = value_written || add_comma; + } + if value_written { + write_indentation(context.result, indentation, depth); + } + context.result.push(']'); + } + _ => {} + } + Ok(()) +} diff --git a/rqjs-ext/src/lib.rs b/rqjs-ext/src/lib.rs new file mode 100644 index 0000000..355379f --- /dev/null +++ b/rqjs-ext/src/lib.rs @@ -0,0 +1,25 @@ +#![allow(clippy::new_without_default)] +#![allow(clippy::inherent_to_string)] +#![cfg_attr(rust_nightly, feature(portable_simd))] + +#[macro_use] +mod macros; +mod bytearray_buffer; +// mod bytecode; +// #[cfg(not(feature = "lambda"))] +// pub mod compiler; +// #[cfg(not(feature = "lambda"))] +// mod compiler_common; +// pub mod environment; +pub mod json; +// mod minimal_tracer; +// mod module_builder; +pub mod modules; +pub mod number; +// pub mod runtime_client; +// mod security; +mod stream; +pub mod utils; +pub mod vm; +pub const VERSION: &str = env!("CARGO_PKG_VERSION"); + diff --git a/rqjs-ext/src/macros.rs b/rqjs-ext/src/macros.rs new file mode 100644 index 0000000..a5c403e --- /dev/null +++ b/rqjs-ext/src/macros.rs @@ -0,0 +1,25 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +macro_rules! iterable_enum { + ($visibility:vis, $name:ident, $($member:tt),*) => { + #[derive(Copy, Clone)] + $visibility enum $name {$($member),*} + impl $name { + pub fn iterate() -> Vec<$name> { + vec![$($name::$member,)*] + } + } + }; + ($name:ident, $($member:tt),*) => { + iterable_enum!(, $name, $($member),*) + }; +} +#[macro_use] +macro_rules! impl_stream_events { + + ($($struct:ident),*) => { + $( + impl<'js> $crate::stream::SteamEvents<'js> for $struct<'js> {} + )* + }; +} diff --git a/rqjs-ext/src/modules/buffer.rs b/rqjs-ext/src/modules/buffer.rs new file mode 100644 index 0000000..39d91bc --- /dev/null +++ b/rqjs-ext/src/modules/buffer.rs @@ -0,0 +1,300 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +use rquickjs::{ + atom::PredefinedAtom, + cstr, + function::{Constructor, Opt}, + module::{Declarations, Exports, ModuleDef}, + prelude::{Func, This}, + Array, ArrayBuffer, Ctx, Exception, IntoJs, Object, Result, TypedArray, Value, +}; + +use crate::{ + // module_builder::ModuleInfo, + modules::{encoding::encoder::Encoder, module::export_default}, + utils::{ + object::{ + get_array_buffer_bytes, get_array_bytes, get_bytes, get_coerced_string_bytes, + get_start_end_indexes, get_string_bytes, obj_to_array_buffer, + }, + result::ResultExt, + }, +}; + +pub struct Buffer(pub Vec); + +impl<'js> IntoJs<'js> for Buffer { + fn into_js(self, ctx: &Ctx<'js>) -> Result> { + let array_buffer = ArrayBuffer::new(ctx.clone(), self.0)?; + Self::from_array_buffer(ctx, array_buffer) + } +} + +impl<'js> Buffer { + pub fn to_string(&self, ctx: &Ctx<'js>, encoding: &str) -> Result { + Encoder::from_str(encoding) + .and_then(|enc| enc.encode_to_string(self.0.as_ref())) + .or_throw(ctx) + } + + fn from_array_buffer(ctx: &Ctx<'js>, buffer: ArrayBuffer<'js>) -> Result> { + let constructor: Constructor = ctx.globals().get(stringify!(Buffer))?; + constructor.construct((buffer,)) + } + + fn from_array_buffer_offset_length( + ctx: &Ctx<'js>, + array_buffer: ArrayBuffer<'js>, + offset: usize, + length: usize, + ) -> Result> { + let constructor: Constructor = ctx.globals().get(stringify!(Buffer))?; + constructor.construct((array_buffer, offset, length)) + } + + fn from_encoding( + ctx: &Ctx<'js>, + mut bytes: Vec, + encoding: Option, + ) -> Result> { + if let Some(encoding) = encoding { + let encoder = Encoder::from_str(&encoding).or_throw(ctx)?; + bytes = encoder.decode(bytes).or_throw(ctx)?; + } + Buffer(bytes).into_js(ctx) + } +} + +fn byte_length<'js>(ctx: Ctx<'js>, value: Value<'js>, encoding: Opt) -> Result { + //slow path + if let Some(encoding) = encoding.0 { + let encoder = Encoder::from_str(&encoding).or_throw(&ctx)?; + let bytes = get_bytes(&ctx, value)?; + return Ok(encoder.decode(bytes).or_throw(&ctx)?.len()); + } + //fast path + if let Some(val) = value.as_string() { + return Ok(val.to_string()?.len()); + } + + if value.is_array() { + let array = value.as_array().unwrap(); + + for val in array.iter::() { + val.or_throw_msg(&ctx, "array value is not u8")?; + } + + return Ok(array.len()); + } + + if let Some(obj) = value.as_object() { + if let Some((_, source_length, _)) = obj_to_array_buffer(obj)? { + return Ok(source_length); + } + } + + Err(Exception::throw_message( + &ctx, + "value must be typed DataView, Buffer, ArrayBuffer, Uint8Array or string", + )) +} + +fn to_string(this: This>, ctx: Ctx, encoding: Opt) -> Result { + let typed_array = TypedArray::::from_object(this.0)?; + let bytes: &[u8] = typed_array.as_ref(); + let encoding = encoding.0.unwrap_or_else(|| String::from("utf-8")); + let encoder = Encoder::from_str(&encoding).or_throw(&ctx)?; + encoder.encode_to_string(bytes).or_throw(&ctx) +} + +fn alloc<'js>( + ctx: Ctx<'js>, + length: usize, + fill: Opt>, + encoding: Opt, +) -> Result> { + if let Some(value) = fill.0 { + if let Some(value) = value.as_string() { + let string = value.to_string()?; + + if let Some(encoding) = encoding.0 { + let encoder = Encoder::from_str(&encoding).or_throw(&ctx)?; + let bytes = encoder.decode_from_string(string).or_throw(&ctx)?; + return alloc_byte_ref(&ctx, &bytes, length); + } + + let byte_ref = string.as_bytes(); + + return alloc_byte_ref(&ctx, byte_ref, length); + } + if let Some(value) = value.as_int() { + let bytes = vec![value as u8; length]; + return Buffer(bytes).into_js(&ctx); + } + if let Some(obj) = value.as_object() { + if let Some((array_buffer, source_length, offset)) = obj_to_array_buffer(obj)? { + let bytes: &[u8] = array_buffer.as_ref(); + return alloc_byte_ref(&ctx, &bytes[offset..offset + source_length], length); + } + } + } + + Buffer(vec![0; length]).into_js(&ctx) +} + +fn alloc_byte_ref<'js>(ctx: &Ctx<'js>, byte_ref: &[u8], length: usize) -> Result> { + let mut bytes = vec![0; length]; + let byte_ref_length = byte_ref.len(); + for i in 0..length { + bytes[i] = byte_ref[i % byte_ref_length]; + } + Buffer(bytes).into_js(ctx) +} + +fn concat<'js>(ctx: Ctx<'js>, list: Array<'js>, max_length: Opt) -> Result> { + let mut bytes = Vec::new(); + let mut total_length = 0; + let mut length; + for value in list.iter::() { + let typed_array = TypedArray::::from_object(value?)?; + let bytes_ref: &[u8] = typed_array.as_ref(); + + length = bytes_ref.len(); + + if length == 0 { + continue; + } + + if let Some(max_length) = max_length.0 { + total_length += length; + if total_length > max_length { + let diff = max_length - (total_length - length); + bytes.extend_from_slice(&bytes_ref[0..diff]); + break; + } + } + bytes.extend_from_slice(bytes_ref); + } + + Buffer(bytes).into_js(&ctx) +} + +fn from<'js>( + ctx: Ctx<'js>, + value: Value<'js>, + offset_or_encoding: Opt>, + length: Opt, +) -> Result> { + let mut encoding: Option = None; + let mut offset = 0; + + if let Some(offset_or_encoding) = offset_or_encoding.0 { + if offset_or_encoding.is_string() { + encoding = Some(offset_or_encoding.get()?); + } else if offset_or_encoding.is_number() { + offset = offset_or_encoding.get()?; + } + } + + println!("encoding {:?}", encoding); + + if let Some(bytes) = get_string_bytes(&value, offset, length.0)? { + return Buffer::from_encoding(&ctx, bytes, encoding)?.into_js(&ctx); + } + if let Some(bytes) = get_array_bytes(&ctx, &value, offset, length.0)? { + return Buffer::from_encoding(&ctx, bytes, encoding)?.into_js(&ctx); + } + + if let Some(obj) = value.as_object() { + if let Some((array_buffer, source_length, source_offset)) = obj_to_array_buffer(obj)? { + let (start, end) = get_start_end_indexes(source_length, length.0, offset); + + //buffers from buffer should be copied + if obj + .get::<_, Option>(PredefinedAtom::Meta)? + .as_deref() + == Some(stringify!(Buffer)) + || encoding.is_some() + { + let bytes = get_array_buffer_bytes( + array_buffer, + start + source_offset, + end - source_offset, + ); + return Buffer::from_encoding(&ctx, bytes, encoding)?.into_js(&ctx); + } else { + return Buffer::from_array_buffer_offset_length( + &ctx, + array_buffer, + start + source_offset, + end - start, + ); + } + } + } + + if let Some(bytes) = get_coerced_string_bytes(&value, offset, length.0) { + return Buffer::from_encoding(&ctx, bytes, encoding)?.into_js(&ctx); + } + + Err(Exception::throw_message( + &ctx, + "value must be typed DataView, Buffer, ArrayBuffer, Uint8Array or interpretable as string", + )) +} + +fn set_prototype<'js>(ctx: &Ctx<'js>, constructor: Object<'js>) -> Result<()> { + let _ = &constructor.set(PredefinedAtom::From, Func::from(from))?; + let _ = &constructor.set(stringify!(alloc), Func::from(alloc))?; + let _ = &constructor.set(stringify!(concat), Func::from(concat))?; + let _ = &constructor.set("byteLength", Func::from(byte_length))?; + + let prototype: &Object = &constructor.get(PredefinedAtom::Prototype)?; + prototype.set(PredefinedAtom::ToString, Func::from(to_string))?; + //not assessable from js + prototype.prop(PredefinedAtom::Meta, stringify!(Buffer))?; + + ctx.globals().set(stringify!(Buffer), constructor)?; + + Ok(()) +} + +pub fn init<'js>(ctx: &Ctx<'js>) -> Result<()> { + let buffer = ctx.eval::, &str>(&format!( + "class {0} extends Uint8Array {{}}\n{0}", + stringify!(Buffer) + ))?; + set_prototype(ctx, buffer) +} + +pub struct BufferModule; + +impl ModuleDef for BufferModule { + fn declare(declare: &Declarations<'_>) -> Result<()> { + declare.declare(stringify!(Buffer))?; + declare.declare(cstr!("default").to_bytes())?; + + Ok(()) + } + + fn evaluate<'js>(ctx: &Ctx<'js>, exports: &Exports<'js>) -> Result<()> { + let globals = ctx.globals(); + let buf: Constructor = globals.get(stringify!(Buffer))?; + + export_default(ctx, exports, |default| { + default.set(stringify!(Buffer), buf)?; + Ok(()) + })?; + + Ok(()) + } +} + +// impl From for ModuleInfo { +// fn from(val: BufferModule) -> Self { +// ModuleInfo { +// name: "buffer", +// module: val, +// } +// } +// } diff --git a/rqjs-ext/src/modules/bytearray_buffer.rs b/rqjs-ext/src/modules/bytearray_buffer.rs new file mode 100644 index 0000000..486a336 --- /dev/null +++ b/rqjs-ext/src/modules/bytearray_buffer.rs @@ -0,0 +1,222 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +use std::{ + cmp::min, + collections::VecDeque, + sync::{ + atomic::{AtomicBool, AtomicUsize, Ordering}, + Arc, Mutex, + }, +}; + +use tokio::sync::{Notify, Semaphore}; + +#[derive(Clone)] +pub struct BytearrayBuffer { + inner: Arc>>, + max_capacity: Arc, + len: Arc, + notify: Arc, + closed: Arc, + write_semaphore: Arc, +} + +impl BytearrayBuffer { + pub fn new(capacity: usize) -> Self { + let queue = VecDeque::with_capacity(capacity); + let capacity = queue.capacity(); + Self { + inner: Arc::new(Mutex::new(queue)), + len: Arc::new(AtomicUsize::new(0)), + max_capacity: Arc::new(AtomicUsize::new(capacity)), + notify: Arc::new(Notify::new()), + closed: Arc::new(AtomicBool::new(false)), + write_semaphore: Arc::new(Semaphore::new(1)), + } + } + + pub fn len(&self) -> usize { + self.len.load(Ordering::Relaxed) + } + + #[allow(dead_code)] + pub fn write_forced(&self, item: &[u8]) { + let mut inner = self.inner.lock().unwrap(); + inner.extend(item); + let capacity = inner.capacity(); + self.len.fetch_add(item.len(), Ordering::Relaxed); + self.max_capacity.store(capacity, Ordering::Relaxed); + } + + pub async fn write(&self, item: &mut [u8]) -> usize { + let _ = self.write_semaphore.acquire().await.unwrap(); + let mut slice_index = 0; + loop { + let max_capacity = self.max_capacity.load(Ordering::Relaxed); + if self.closed.load(Ordering::Relaxed) { + return max_capacity; + } + + let len = self.len.load(Ordering::Relaxed); + + let available = max_capacity - len; + + if available > 0 { + let end_index = min(item.len() - 1, slice_index + available - 1); + let sub_slice = &item[slice_index..=end_index]; + let slice_length = sub_slice.len(); + slice_index += slice_length; + + self.inner.lock().unwrap().extend(sub_slice); + self.len.fetch_add(slice_length, Ordering::Relaxed); + + if slice_index == item.len() { + return max_capacity; + } + } + self.notify.notified().await; + } + } + + #[allow(dead_code)] + pub fn is_closed(&self) -> bool { + self.closed.load(Ordering::Relaxed) + } + + pub async fn close(&self) { + self.closed.store(true, Ordering::Relaxed); + self.notify.notify_one(); + //wait for write to finish + let _ = self.write_semaphore.acquire().await.unwrap(); + } + + pub async fn clear(&self) { + self.closed.store(false, Ordering::Relaxed); + self.notify.notify_one(); + //wait for write to finish + let _ = self.write_semaphore.acquire().await.unwrap(); + self.len.store(0, Ordering::Relaxed); + self.inner.lock().unwrap().clear(); + self.closed.store(false, Ordering::Relaxed); + } + + pub fn read(&self, desired_size: Option) -> Option> { + let mut inner = self.inner.lock().unwrap(); + let done = self.closed.load(Ordering::Relaxed); + + let items = if done { + Some(inner.drain(0..).collect()) + } else if let Some(desired_len) = desired_size { + let max_capacity = self.max_capacity.load(Ordering::Relaxed); + if desired_len > max_capacity { + let diff = desired_len - max_capacity; + inner.reserve(diff - 1); + let mut max_capacity = inner.capacity(); + if desired_len > max_capacity { + inner.reserve(desired_len - max_capacity); + max_capacity = inner.capacity(); + } + drop(inner); + self.max_capacity.store(max_capacity, Ordering::Relaxed); + self.notify.notify_one(); + return None; + } + + let len = self.len.load(Ordering::Relaxed); + if desired_len > len { + self.notify.notify_one(); + return None; + } + + Some(inner.drain(0..desired_len).collect()) + } else { + Some(inner.drain(0..).collect()) + }; + self.len.store(inner.len(), Ordering::Relaxed); + drop(inner); + self.notify.notify_one(); + items + } +} + +#[cfg(test)] +mod tests { + use crate::bytearray_buffer::BytearrayBuffer; + + #[tokio::test] + async fn clear_while_writing() { + let queue = BytearrayBuffer::new(8); + let queue2 = queue.clone(); + + tokio::task::spawn(async move { + let mut vec: Vec = (0..=255).collect(); + queue.write(&mut vec).await; + }); + + queue2.clear().await + } + + #[tokio::test] + async fn write_one_at_a_time() { + let queue = BytearrayBuffer::new(8); + let queue2 = queue.clone(); + let queue3 = queue.clone(); + + tokio::task::spawn(async move { + let mut vec: Vec = (0..=127).collect(); + queue.write(&mut vec).await; + }); + + tokio::task::spawn(async move { + let mut vec: Vec = (128..=255).collect(); + queue2.write(&mut vec).await; + }); + + let mut data = Vec::::new(); + + loop { + tokio::task::yield_now().await; + if let Some(bytes) = queue3.read(Some(256)) { + data.extend(bytes); + break; + } + } + + //assert that data in vec is increment from 0 to 255 + for i in 0..=255 { + assert_eq!(data[i as usize], i); + } + } + + #[tokio::test] + async fn queue() { + let queue = BytearrayBuffer::new(8); + let queue2 = queue.clone(); + + let write_task = tokio::task::spawn(async move { + for _ in 0..=255 { + let mut vec: Vec = (0..=255).collect(); + queue.write(&mut vec).await; + } + queue.close().await; + }); + + let mut data = Vec::::new(); + + loop { + let done = queue2.is_closed(); + + tokio::task::yield_now().await; + if let Some(bytes) = queue2.read(Some(9)) { + data.extend(bytes); + } + if done { + break; + } + } + + let _ = write_task.await; + + assert_eq!(data.len(), 256 * 256) + } +} diff --git a/rqjs-ext/src/modules/bytecode_cache.rs b/rqjs-ext/src/modules/bytecode_cache.rs new file mode 100644 index 0000000..c9633f6 --- /dev/null +++ b/rqjs-ext/src/modules/bytecode_cache.rs @@ -0,0 +1,9 @@ +// @generated by build.rs + +pub static BYTECODE_CACHE: phf::Map<&'static str, &[u8]> = ::phf::Map { + key: 12913932095322966823, + disps: &[ + ], + entries: &[ + ], +}; diff --git a/rqjs-ext/src/modules/console.rs b/rqjs-ext/src/modules/console.rs new file mode 100644 index 0000000..7d32d10 --- /dev/null +++ b/rqjs-ext/src/modules/console.rs @@ -0,0 +1,34 @@ +use std::env; + +use crate::modules::module::export_default; +use once_cell::sync::Lazy; +use rquickjs::{ + atom::PredefinedAtom, + function::{Constructor, Opt}, + Class, Object, Value, +}; +use rquickjs::{ + module::{Declarations, Exports, ModuleDef}, + prelude::Func, + AsyncContext, Ctx, Function, Result, +}; + +pub struct ConsoleModule; +fn print(s: String) { + print!("{s}"); +} +pub fn init(ctx: &Ctx<'_>) -> Result<()> { + let core = include_str!("../../deno-scripts/00_console.js"); + let global = ctx.globals(); + global + .set( + "__print", + Function::new(ctx.clone(), print) + .unwrap() + .with_name("__print") + .unwrap(), + ) + .unwrap(); + let _: Value = ctx.eval(core.as_bytes()).unwrap(); + Ok(()) +} diff --git a/rqjs-ext/src/modules/crypto/crc32.rs b/rqjs-ext/src/modules/crypto/crc32.rs new file mode 100644 index 0000000..62ef31e --- /dev/null +++ b/rqjs-ext/src/modules/crypto/crc32.rs @@ -0,0 +1,74 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +use std::hash::Hasher; + +use crc32c::Crc32cHasher; +use rquickjs::{prelude::This, Class, Ctx, Result, Value}; + +use crate::utils::object::get_bytes; + +#[rquickjs::class] +#[derive(rquickjs::class::Trace)] +pub struct Crc32c { + #[qjs(skip_trace)] + hasher: crc32c::Crc32cHasher, +} + +#[rquickjs::methods] +impl Crc32c { + #[qjs(constructor)] + fn new() -> Self { + Self { + hasher: Crc32cHasher::default(), + } + } + + #[qjs(rename = "digest")] + fn crc32c_digest(&self, _ctx: Ctx<'_>) -> u64 { + self.hasher.finish() + } + + #[qjs(rename = "update")] + fn crc32c_update<'js>( + this: This>, + ctx: Ctx<'js>, + value: Value<'js>, + ) -> Result> { + let bytes = get_bytes(&ctx, value)?; + this.0.borrow_mut().hasher.write(&bytes); + Ok(this.0) + } +} + +#[rquickjs::class] +#[derive(rquickjs::class::Trace)] +pub struct Crc32 { + #[qjs(skip_trace)] + hasher: crc32fast::Hasher, +} + +#[rquickjs::methods] +impl Crc32 { + #[qjs(constructor)] + fn new() -> Self { + Self { + hasher: crc32fast::Hasher::new(), + } + } + + #[qjs(rename = "digest")] + fn crc32_digest(&self, _ctx: Ctx<'_>) -> u64 { + self.hasher.finish() + } + + #[qjs(rename = "update")] + fn crc32_update<'js>( + this: This>, + ctx: Ctx<'js>, + value: Value<'js>, + ) -> Result> { + let bytes = get_bytes(&ctx, value)?; + this.0.borrow_mut().hasher.write(&bytes); + Ok(this.0) + } +} diff --git a/rqjs-ext/src/modules/crypto/md5_hash.rs b/rqjs-ext/src/modules/crypto/md5_hash.rs new file mode 100644 index 0000000..65ebc9f --- /dev/null +++ b/rqjs-ext/src/modules/crypto/md5_hash.rs @@ -0,0 +1,48 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +use md5::{Digest as Md5Digest, Md5 as MdHasher}; + +use rquickjs::{function::Opt, prelude::This, Class, Ctx, Result, Value}; + +use crate::utils::object::{bytes_to_typed_array, get_bytes}; + +use super::encoded_bytes; + +#[rquickjs::class] +#[derive(rquickjs::class::Trace)] +pub struct Md5 { + #[qjs(skip_trace)] + hasher: MdHasher, +} + +#[rquickjs::methods] +impl Md5 { + #[qjs(constructor)] + fn new() -> Self { + Self { + hasher: MdHasher::new(), + } + } + + #[qjs(rename = "digest")] + fn md5_digest<'js>(&self, ctx: Ctx<'js>, encoding: Opt) -> Result> { + let digest = self.hasher.clone().finalize(); + let bytes: &[u8] = digest.as_ref(); + + match encoding.0 { + Some(encoding) => encoded_bytes(ctx, bytes, &encoding), + None => bytes_to_typed_array(ctx, bytes), + } + } + + #[qjs(rename = "update")] + fn md5_update<'js>( + this: This>, + ctx: Ctx<'js>, + value: Value<'js>, + ) -> Result> { + let bytes = get_bytes(&ctx, value)?; + this.0.borrow_mut().hasher.update(&bytes); + Ok(this.0) + } +} diff --git a/rqjs-ext/src/modules/crypto/mod.rs b/rqjs-ext/src/modules/crypto/mod.rs new file mode 100644 index 0000000..e4dbc77 --- /dev/null +++ b/rqjs-ext/src/modules/crypto/mod.rs @@ -0,0 +1,256 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +mod crc32; +mod md5_hash; +mod sha_hash; +use std::slice; + +use once_cell::sync::Lazy; +use rand::prelude::ThreadRng; +use rand::Rng; +use ring::rand::{SecureRandom, SystemRandom}; +use rquickjs::{ + function::{Constructor, Opt}, + module::{Declarations, Exports, ModuleDef}, + prelude::{Func, Rest}, + Class, Ctx, Exception, Function, IntoJs, Object, Result, Value, +}; + +use crate::{ + // module_builder::ModuleInfo, + modules::{ + buffer::Buffer, + encoding::encoder::{bytes_to_b64_string, bytes_to_hex_string}, + module::export_default, + uuid::uuidv4, + }, + utils::{ + class::get_class_name, + object::{bytes_to_typed_array, get_start_end_indexes, obj_to_array_buffer}, + result::ResultExt, + }, + // vm::{CtxExtension, ErrorExtensions}, +}; + +use self::{ + crc32::{Crc32, Crc32c}, + md5_hash::Md5, + sha_hash::{Hash, Hmac, ShaAlgorithm, ShaHash}, +}; + +pub static SYSTEM_RANDOM: Lazy = Lazy::new(SystemRandom::new); + +fn encoded_bytes<'js>(ctx: Ctx<'js>, bytes: &[u8], encoding: &str) -> Result> { + match encoding { + "hex" => { + let hex = bytes_to_hex_string(bytes); + let hex = rquickjs::String::from_str(ctx, &hex)?; + Ok(Value::from_string(hex)) + } + "base64" => { + let b64 = bytes_to_b64_string(bytes); + let b64 = rquickjs::String::from_str(ctx, &b64)?; + Ok(Value::from_string(b64)) + } + _ => bytes_to_typed_array(ctx, bytes), + } +} + +#[inline] +pub fn random_byte_array(length: usize) -> Vec { + let mut vec = vec![0; length]; + SYSTEM_RANDOM.fill(&mut vec).unwrap(); + vec +} + +fn get_random_bytes(ctx: Ctx, length: usize) -> Result { + let random_bytes = random_byte_array(length); + Buffer(random_bytes).into_js(&ctx) +} + +fn get_random_int(_ctx: Ctx, first: i64, second: Opt) -> Result { + let mut rng = ThreadRng::default(); + let random_number = match second.0 { + Some(max) => rng.gen_range(first..max), + None => rng.gen_range(0..first), + }; + + Ok(random_number) +} + +fn random_fill<'js>(ctx: Ctx<'js>, obj: Object<'js>, args: Rest>) -> Result<()> { + let args_iter = args.0.into_iter(); + let mut args_iter = args_iter.rev(); + + let callback: Function = args_iter + .next() + .and_then(|v| v.into_function()) + .or_throw_msg(&ctx, "Callback required")?; + let size = args_iter + .next() + .and_then(|arg| arg.as_int()) + .map(|i| i as usize); + let offset = args_iter + .next() + .and_then(|arg| arg.as_int()) + .map(|i| i as usize); + + todo!(); + // ctx.clone().spawn_exit(async move { + // if let Err(err) = random_fill_sync(ctx.clone(), obj.clone(), Opt(offset), Opt(size)) { + // let err = err.into_value(&ctx)?; + // () = callback.call((err,))?; + + // return Ok(()); + // } + // () = callback.call((Null.into_js(&ctx), obj))?; + // Ok::<_, Error>(()) + // })?; + // Ok(()) +} + +fn random_fill_sync<'js>( + ctx: Ctx<'js>, + obj: Object<'js>, + offset: Opt, + size: Opt, +) -> Result> { + let offset = offset.unwrap_or(0); + + if let Some((array_buffer, source_length, source_offset)) = obj_to_array_buffer(&obj)? { + let (start, end) = get_start_end_indexes(source_length, size.0, offset); + + let raw = array_buffer + .as_raw() + .ok_or("ArrayBuffer is detached") + .or_throw(&ctx)?; + let bytes = unsafe { slice::from_raw_parts_mut(raw.ptr.as_ptr(), source_length) }; + + SYSTEM_RANDOM + .fill(&mut bytes[start + source_offset..end - source_offset]) + .unwrap(); + } + + Ok(obj) +} + +fn get_random_values<'js>(ctx: Ctx<'js>, obj: Object<'js>) -> Result> { + if let Some((array_buffer, source_length, source_offset)) = obj_to_array_buffer(&obj)? { + let raw = array_buffer + .as_raw() + .ok_or("ArrayBuffer is detached") + .or_throw(&ctx)?; + + if source_length > 0x10000 { + return Err(Exception::throw_message( + &ctx, + "QuotaExceededError: The requested length exceeds 65,536 bytes", + )); + } + + let bytes = unsafe { + std::slice::from_raw_parts_mut(raw.ptr.as_ptr().add(source_offset), source_length) + }; + + match get_class_name(&obj)?.unwrap().as_str() { + "Int8Array" | "Uint8Array" | "Uint8ClampedArray" | "Int16Array" | "Uint16Array" + | "Int32Array" | "Uint32Array" | "BigInt64Array" | "BigUint64Array" => { + SYSTEM_RANDOM.fill(bytes).unwrap() + } + _ => return Err(Exception::throw_message(&ctx, "Unsupported TypedArray")), + } + } + + Ok(obj) +} + +pub fn init(ctx: &Ctx<'_>) -> Result<()> { + let globals = ctx.globals(); + + let crypto = Object::new(ctx.clone())?; + + crypto.set("createHash", Func::from(Hash::new))?; + crypto.set("createHmac", Func::from(Hmac::new))?; + crypto.set("randomBytes", Func::from(get_random_bytes))?; + crypto.set("randomInt", Func::from(get_random_int))?; + crypto.set("randomUUID", Func::from(uuidv4))?; + crypto.set("randomFillSync", Func::from(random_fill_sync))?; + crypto.set("randomFill", Func::from(random_fill))?; + crypto.set("getRandomValues", Func::from(get_random_values))?; + + globals.set("crypto", crypto)?; + + Ok(()) +} + +pub struct CryptoModule; + +impl ModuleDef for CryptoModule { + fn declare(declare: &Declarations<'_>) -> Result<()> { + declare.declare("createHash")?; + declare.declare("createHmac")?; + declare.declare("Crc32")?; + declare.declare("Crc32c")?; + declare.declare("Md5")?; + declare.declare("randomBytes")?; + declare.declare("randomUUID")?; + declare.declare("randomInt")?; + declare.declare("randomFillSync")?; + declare.declare("randomFill")?; + declare.declare("getRandomValues")?; + + for sha_algorithm in ShaAlgorithm::iterate() { + let class_name = sha_algorithm.class_name(); + declare.declare(class_name)?; + } + + declare.declare("default")?; + + Ok(()) + } + + fn evaluate<'js>(ctx: &Ctx<'js>, exports: &Exports<'js>) -> Result<()> { + Class::::register(ctx)?; + Class::::register(ctx)?; + Class::::register(ctx)?; + + export_default(ctx, exports, |default| { + for sha_algorithm in ShaAlgorithm::iterate() { + let class_name: &str = sha_algorithm.class_name(); + let algo = sha_algorithm; + + let ctor = + Constructor::new_class::(ctx.clone(), move |ctx, secret| { + ShaHash::new(ctx, algo, secret) + })?; + + default.set(class_name, ctor)?; + } + + Class::::define(default)?; + Class::::define(default)?; + Class::::define(default)?; + + default.set("createHash", Func::from(Hash::new))?; + default.set("createHmac", Func::from(Hmac::new))?; + default.set("randomBytes", Func::from(get_random_bytes))?; + default.set("randomInt", Func::from(get_random_int))?; + default.set("randomUUID", Func::from(uuidv4))?; + default.set("randomFillSync", Func::from(random_fill_sync))?; + default.set("randomFill", Func::from(random_fill))?; + default.set("getRandomValues", Func::from(get_random_values))?; + Ok(()) + })?; + + Ok(()) + } +} + +// impl From for ModuleInfo { +// fn from(val: CryptoModule) -> Self { +// ModuleInfo { +// name: "crypto", +// module: val, +// } +// } +// } diff --git a/rqjs-ext/src/modules/crypto/sha_hash.rs b/rqjs-ext/src/modules/crypto/sha_hash.rs new file mode 100644 index 0000000..96161d0 --- /dev/null +++ b/rqjs-ext/src/modules/crypto/sha_hash.rs @@ -0,0 +1,215 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +use ring::{ + digest::{self, Context as DigestContext}, + hmac::{self, Context as HmacContext}, +}; +use rquickjs::{function::Opt, prelude::This, Class, Ctx, Exception, Result, Value}; + +use crate::utils::object::{bytes_to_typed_array, get_bytes}; + +use super::encoded_bytes; + +#[rquickjs::class] +#[derive(rquickjs::class::Trace)] +pub struct Hmac { + #[qjs(skip_trace)] + context: HmacContext, +} + +#[rquickjs::methods] +impl Hmac { + #[qjs(skip)] + pub fn new<'js>(ctx: Ctx<'js>, algorithm: String, secret: Value<'js>) -> Result { + let key_value = get_bytes(&ctx, secret)?; + + let algorithm = match algorithm.to_lowercase().as_str() { + "sha1" => hmac::HMAC_SHA1_FOR_LEGACY_USE_ONLY, + "sha256" => hmac::HMAC_SHA256, + "sha384" => hmac::HMAC_SHA384, + "sha512" => hmac::HMAC_SHA512, + _ => { + return Err(Exception::throw_message( + &ctx, + &format!("Algorithm \"{}\" not supported", &algorithm), + )) + } + }; + + Ok(Self { + context: HmacContext::with_key(&hmac::Key::new(algorithm, &key_value)), + }) + } + + fn digest<'js>(&self, ctx: Ctx<'js>, encoding: Opt) -> Result> { + let signature = self.context.clone().sign(); + let bytes: &[u8] = signature.as_ref(); + + match encoding.into_inner() { + Some(encoding) => encoded_bytes(ctx, bytes, &encoding), + None => bytes_to_typed_array(ctx, bytes), + } + } + + fn update<'js>( + this: This>, + ctx: Ctx<'js>, + value: Value<'js>, + ) -> Result> { + let bytes = get_bytes(&ctx, value)?; + this.0.borrow_mut().context.update(&bytes); + + Ok(this.0) + } +} + +impl Clone for Hmac { + fn clone(&self) -> Self { + Self { + context: self.context.clone(), + } + } +} + +#[rquickjs::class] +#[derive(rquickjs::class::Trace)] +pub struct Hash { + #[qjs(skip_trace)] + context: DigestContext, +} + +#[rquickjs::methods] +impl Hash { + #[qjs(skip)] + pub fn new(ctx: Ctx<'_>, algorithm: String) -> Result { + let algorithm = match algorithm.to_lowercase().as_str() { + "sha1" => &digest::SHA1_FOR_LEGACY_USE_ONLY, + "sha256" => &digest::SHA256, + "sha512" => &digest::SHA512, + _ => { + return Err(Exception::throw_message( + &ctx, + &format!("Algorithm \"{}\" not supported", &algorithm), + )) + } + }; + + Ok(Self { + context: DigestContext::new(algorithm), + }) + } + + #[qjs(rename = "digest")] + fn hash_digest<'js>(&self, ctx: Ctx<'js>, encoding: Opt) -> Result> { + let digest = self.context.clone().finish(); + let bytes: &[u8] = digest.as_ref(); + + match encoding.0 { + Some(encoding) => encoded_bytes(ctx, bytes, &encoding), + None => bytes_to_typed_array(ctx, bytes), + } + } + + #[qjs(rename = "update")] + fn hash_update<'js>( + this: This>, + ctx: Ctx<'js>, + value: Value<'js>, + ) -> Result> { + let bytes = get_bytes(&ctx, value)?; + this.0.borrow_mut().context.update(&bytes); + Ok(this.0) + } +} + +iterable_enum!(pub, ShaAlgorithm, SHA1, SHA256, SHA384, SHA512); + +impl ShaAlgorithm { + pub fn class_name(&self) -> &'static str { + match self { + ShaAlgorithm::SHA1 => "Sha1", + ShaAlgorithm::SHA256 => "Sha256", + ShaAlgorithm::SHA384 => "Sha384", + ShaAlgorithm::SHA512 => "Sha512", + } + } + pub fn hmac_algorithm(&self) -> &'static hmac::Algorithm { + match self { + ShaAlgorithm::SHA1 => &hmac::HMAC_SHA1_FOR_LEGACY_USE_ONLY, + ShaAlgorithm::SHA256 => &hmac::HMAC_SHA256, + ShaAlgorithm::SHA384 => &hmac::HMAC_SHA384, + ShaAlgorithm::SHA512 => &hmac::HMAC_SHA512, + } + } + + fn digest_algorithm(&self) -> &'static digest::Algorithm { + match self { + ShaAlgorithm::SHA1 => &digest::SHA1_FOR_LEGACY_USE_ONLY, + ShaAlgorithm::SHA256 => &digest::SHA256, + ShaAlgorithm::SHA384 => &digest::SHA384, + ShaAlgorithm::SHA512 => &digest::SHA512, + } + } +} + +#[rquickjs::class] +#[derive(rquickjs::class::Trace)] +pub struct ShaHash { + #[qjs(skip_trace)] + secret: Option>, + #[qjs(skip_trace)] + bytes: Vec, + #[qjs(skip_trace)] + algorithm: ShaAlgorithm, +} + +#[rquickjs::methods] +impl ShaHash { + #[qjs(skip)] + pub fn new<'js>( + ctx: Ctx<'js>, + algorithm: ShaAlgorithm, + secret: Opt>, + ) -> Result { + let secret = secret.0; + let secret = match secret { + Some(secret) => { + let bytes = get_bytes(&ctx, secret)?; + Some(bytes) + } + None => None, + }; + + Ok(ShaHash { + secret, + bytes: Vec::new(), + algorithm, + }) + } + + #[qjs(rename = "digest")] + fn sha_digest<'js>(&self, ctx: Ctx<'js>) -> Result> { + if let Some(secret) = &self.secret { + let key_value = secret; + let key = hmac::Key::new(*self.algorithm.hmac_algorithm(), key_value); + + return bytes_to_typed_array(ctx, hmac::sign(&key, &self.bytes).as_ref()); + } + + bytes_to_typed_array( + ctx, + digest::digest(self.algorithm.digest_algorithm(), &self.bytes).as_ref(), + ) + } + + #[qjs(rename = "update")] + fn sha_update<'js>( + this: This>, + ctx: Ctx<'js>, + value: Value<'js>, + ) -> Result> { + let bytes = get_bytes(&ctx, value)?; + this.0.borrow_mut().bytes = bytes; + Ok(this.0) + } +} diff --git a/rqjs-ext/src/modules/encoding/encoder.rs b/rqjs-ext/src/modules/encoding/encoder.rs new file mode 100644 index 0000000..135c768 --- /dev/null +++ b/rqjs-ext/src/modules/encoding/encoder.rs @@ -0,0 +1,116 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +use hex_simd::AsciiCase; + +macro_rules! encoder_enum { + ( + $(#[$attr:meta])* + pub enum $enum_name:ident { + $($variant:ident),* $(,)? + } + ) => { + $(#[$attr])* + pub enum $enum_name { + $($variant),* + } + + impl $enum_name { + #[allow(clippy::should_implement_trait)] + pub fn from_str(encoding: &str) -> Result { + + let encoding:String = encoding.chars() + .enumerate() + .map(|(i, c)| { + if i == 0 { + c.to_ascii_uppercase() + } else { + c.to_ascii_lowercase() + } + }) + .filter(|&c| c != '-' && c != '_') + .collect(); + + match encoding.as_str() { + $( + stringify!($variant) => Ok(Self::$variant), + )* + _ => Err(format!("Unsupported encoding: {}", encoding)), + } + } + } + }; +} + +encoder_enum! { + #[derive(Debug)] + pub enum Encoder { + Hex, + Base64, + Utf8, + Iso88591, + } +} + +impl Encoder { + pub fn encode_to_string(&self, bytes: &[u8]) -> Result { + match self { + Self::Hex => Ok(bytes_to_hex_string(bytes)), + Self::Base64 => Ok(bytes_to_b64_string(bytes)), + Self::Utf8 | Self::Iso88591 => Ok(bytes_to_string(bytes)), + } + } + + #[allow(dead_code)] + pub fn encode(&self, bytes: &[u8]) -> Result, String> { + match self { + Self::Hex => Ok(bytes_to_hex(bytes)), + Self::Base64 => Ok(bytes_to_b64(bytes)), + Self::Utf8 | Self::Iso88591 => Ok(bytes.to_vec()), + } + } + + pub fn decode(&self, bytes: Vec) -> Result, String> { + match self { + Self::Hex => bytes_from_hex(&bytes), + Self::Base64 => bytes_from_b64(&bytes), + Self::Utf8 | Self::Iso88591 => Ok(bytes), + } + } + + #[allow(dead_code)] + pub fn decode_from_string(&self, string: String) -> Result, String> { + match self { + Self::Hex => bytes_from_hex(string.as_bytes()), + Self::Base64 => bytes_from_b64(string.as_bytes()), + Self::Utf8 | Self::Iso88591 => Ok(string.into_bytes()), + } + } +} + +pub fn bytes_to_hex(bytes: &[u8]) -> Vec { + hex_simd::encode_type(bytes, AsciiCase::Lower) +} + +pub fn bytes_from_hex(hex_bytes: &[u8]) -> Result, String> { + hex_simd::decode_to_vec(hex_bytes).map_err(|err| err.to_string()) +} + +pub fn bytes_to_b64_string(bytes: &[u8]) -> String { + base64_simd::STANDARD.encode_to_string(bytes) +} + +pub fn bytes_from_b64(bytes: &[u8]) -> Result, String> { + base64_simd::forgiving_decode_to_vec(bytes).map_err(|e| e.to_string()) +} + +pub fn bytes_to_b64(bytes: &[u8]) -> Vec { + base64_simd::STANDARD.encode_type(bytes) +} + +pub fn bytes_to_hex_string(bytes: &[u8]) -> String { + hex_simd::encode_to_string(bytes, AsciiCase::Lower) +} + +pub fn bytes_to_string(bytes: &[u8]) -> String { + String::from_utf8_lossy(bytes).to_string() +} diff --git a/rqjs-ext/src/modules/encoding/mod.rs b/rqjs-ext/src/modules/encoding/mod.rs new file mode 100644 index 0000000..227c8fa --- /dev/null +++ b/rqjs-ext/src/modules/encoding/mod.rs @@ -0,0 +1,89 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +pub mod encoder; +pub mod text_decoder; +pub mod text_encoder; + +use rquickjs::{ + module::{Declarations, Exports, ModuleDef}, + prelude::Func, + Class, Ctx, Result, Value, +}; + +use crate::{ + // module_builder::ModuleInfo, + modules::module::export_default, + utils::{ + object::{bytes_to_typed_array, get_bytes}, + result::ResultExt, + }, +}; + +use self::encoder::{bytes_from_b64, bytes_from_hex, bytes_to_b64_string, bytes_to_hex_string}; +use self::text_decoder::TextDecoder; +use self::text_encoder::TextEncoder; + +pub struct HexModule; + +impl HexModule { + pub fn encode<'js>(ctx: Ctx<'js>, buffer: Value<'js>) -> Result { + let bytes = get_bytes(&ctx, buffer)?; + Ok(bytes_to_hex_string(&bytes)) + } + + pub fn decode(ctx: Ctx, encoded: String) -> Result { + let bytes = bytes_from_hex(encoded.as_bytes()) + .or_throw_msg(&ctx, "Cannot decode unrecognized sequence")?; + + bytes_to_typed_array(ctx, &bytes) + } +} + +impl ModuleDef for HexModule { + fn declare(declare: &Declarations<'_>) -> Result<()> { + declare.declare(stringify!(encode))?; + declare.declare(stringify!(decode))?; + declare.declare("default")?; + Ok(()) + } + + fn evaluate<'js>(ctx: &Ctx<'js>, exports: &Exports<'js>) -> Result<()> { + export_default(ctx, exports, |default| { + default.set(stringify!(encode), Func::from(Self::encode))?; + default.set(stringify!(decode), Func::from(Self::decode))?; + Ok(()) + })?; + + Ok(()) + } +} + +// impl From for ModuleInfo { +// fn from(val: HexModule) -> Self { +// ModuleInfo { +// name: "hex", +// module: val, +// } +// } +// } + +pub fn atob(ctx: Ctx<'_>, encoded_value: String) -> Result { + let vec = bytes_from_b64(encoded_value.as_bytes()).or_throw(&ctx)?; + Ok(unsafe { String::from_utf8_unchecked(vec) }) +} + +pub fn btoa(value: String) -> String { + bytes_to_b64_string(value.as_bytes()) +} + +pub fn init(ctx: &Ctx<'_>) -> Result<()> { + let globals = ctx.globals(); + + globals.set("atob", Func::from(atob))?; + globals.set("btoa", Func::from(btoa))?; + + Class::::define(&globals)?; + Class::::define(&globals)?; + + Ok(()) +} diff --git a/rqjs-ext/src/modules/encoding/text_decoder.rs b/rqjs-ext/src/modules/encoding/text_decoder.rs new file mode 100644 index 0000000..83e4231 --- /dev/null +++ b/rqjs-ext/src/modules/encoding/text_decoder.rs @@ -0,0 +1,89 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +use rquickjs::{function::Opt, Ctx, Exception, Object, Result, Value}; + +use std::borrow::Cow; + +use crate::utils::{object::get_bytes, object::ObjectExt, result::ResultExt}; +use encoding_rs::Encoding; + +#[rquickjs::class] +#[derive(rquickjs::class::Trace)] +pub struct TextDecoder { + #[qjs(skip_trace)] + encoding: String, + fatal: bool, + ignore_bom: bool, +} + +#[rquickjs::methods] +impl<'js> TextDecoder { + #[qjs(constructor)] + pub fn new(ctx: Ctx<'js>, label: Opt, options: Opt>) -> Result { + let label = label + .0 + .filter(|lbl| !lbl.is_empty()) + .unwrap_or_else(|| String::from("utf-8")); + let mut fatal = false; + let mut ignore_bom = false; + + let encoding = Encoding::for_label(label.as_bytes()) + .map(|enc| enc.name().to_string()) + .or_throw_msg(&ctx, "Unsupported encoding label")?; + + if let Some(options) = options.0 { + if let Some(opt) = options.get_optional("fatal")? { + fatal = opt; + } + if let Some(opt) = options.get_optional("ignoreBOM")? { + ignore_bom = opt; + } + } + + Ok(TextDecoder { + encoding, + fatal, + ignore_bom, + }) + } + + #[qjs(get)] + fn encoding(&self) -> String { + let s = self.encoding.clone(); + s.replace('_', "-").to_ascii_lowercase() + } + + #[qjs(get)] + fn fatal(&self) -> bool { + self.fatal + } + + #[qjs(get, rename = "ignoreBOM")] + fn ignore_bom(&self) -> bool { + self.ignore_bom + } + + pub fn decode(&self, ctx: Ctx<'js>, buffer: Value<'js>) -> Result { + let bytes = get_bytes(&ctx, buffer)?; + + let decoder = Encoding::for_label(self.encoding.as_bytes()).unwrap(); + + let str: Cow; + let has_error: bool; + + if decoder == encoding_rs::UTF_8 { + (str, has_error) = match self.ignore_bom { + false => decoder.decode_with_bom_removal(&bytes), + true => decoder.decode_without_bom_handling(&bytes), + } + } else { + (str, _, has_error) = decoder.decode(&bytes); + } + + if self.fatal && has_error { + return Err(Exception::throw_message(&ctx, "Fatal error")); + } + + Ok(str.into_owned()) + } +} diff --git a/rqjs-ext/src/modules/encoding/text_encoder.rs b/rqjs-ext/src/modules/encoding/text_encoder.rs new file mode 100644 index 0000000..f146abd --- /dev/null +++ b/rqjs-ext/src/modules/encoding/text_encoder.rs @@ -0,0 +1,30 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +use rquickjs::{Ctx, Result, TypedArray, Value}; + +#[derive(rquickjs::class::Trace)] +#[rquickjs::class] +pub struct TextEncoder {} + +impl Default for TextEncoder { + fn default() -> Self { + Self::new() + } +} + +#[rquickjs::methods] +impl TextEncoder { + #[qjs(constructor)] + pub fn new() -> Self { + Self {} + } + + #[qjs(get)] + fn encoding(&self) -> String { + "utf-8".to_string() + } + + pub fn encode<'js>(&self, ctx: Ctx<'js>, string: String) -> Result> { + TypedArray::new(ctx, string.as_bytes()).map(|m| m.into_value()) + } +} diff --git a/rqjs-ext/src/modules/events.rs b/rqjs-ext/src/modules/events.rs new file mode 100644 index 0000000..78f2072 --- /dev/null +++ b/rqjs-ext/src/modules/events.rs @@ -0,0 +1,687 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +#![allow(clippy::mutable_key_type, clippy::for_kv_map)] + +use std::sync::{Arc, RwLock}; + +use rquickjs::{ + class::{JsClass, OwnedBorrow, Trace, Tracer}, + function::OnceFn, + module::{Declarations, Exports, ModuleDef}, + prelude::{Func, Opt, Rest, This}, + Array, Class, Ctx, Exception, Function, Object, Result, String as JsString, Symbol, Undefined, + Value, +}; + +use crate::modules::exceptions::DOMException; + +use crate::utils::{mc_oneshot, result::ResultExt}; + +// use tracing::trace; + +// use crate::{ +// module_builder::ModuleInfo, +// modules::exceptions::DOMException, +// utils::{mc_oneshot, result::ResultExt}, +// vm::{CtxExtension, ErrorExtensions}, +// }; + +#[derive(Clone, Debug)] +pub enum EventKey<'js> { + Symbol(Symbol<'js>), + String(String), +} + +impl<'js> EventKey<'js> { + fn from_value(ctx: &Ctx, value: Value<'js>) -> Result { + if value.is_string() { + let key: String = value.get()?; + Ok(EventKey::String(key)) + } else { + let sym = value.into_symbol().ok_or("Not a symbol").or_throw(ctx)?; + Ok(EventKey::Symbol(sym)) + } + } +} + +impl<'js> Eq for EventKey<'js> {} + +impl<'js> PartialEq for EventKey<'js> { + fn eq(&self, other: &Self) -> bool { + match (self, other) { + (EventKey::Symbol(symbol1), EventKey::Symbol(symbol2)) => symbol1 == symbol2, + (EventKey::String(str1), EventKey::String(str2)) => str1 == str2, + _ => false, + } + } +} + +pub struct EventItem<'js> { + callback: Function<'js>, + once: bool, +} + +pub type EventList<'js> = Vec<(EventKey<'js>, Vec>)>; +pub type Events<'js> = Arc>>; + +#[rquickjs::class] +#[derive(Clone)] +pub struct EventEmitter<'js> { + pub events: Events<'js>, +} + +impl<'js> Emitter<'js> for EventEmitter<'js> { + fn get_event_list(&self) -> Arc>> { + self.events.clone() + } +} + +impl<'js> Trace<'js> for EventEmitter<'js> { + fn trace<'a>(&self, tracer: Tracer<'a, 'js>) { + self.trace_event_emitter(tracer); + } +} + +pub trait EmitError<'js> { + fn emit_error(self, ctx: &Ctx<'js>, this: Class<'js, C>) -> Result + where + C: Emitter<'js>; +} + +// impl<'js, T> EmitError<'js> for Result { +// fn emit_error(self, ctx: &Ctx<'js>, this: Class<'js, C>) -> Result +// where +// C: Emitter<'js>, +// { +// if let Err(err) = self.catch(ctx) { +// if this.borrow().has_listener_str("error") { +// let error_value = err.into_value(ctx)?; +// C::emit_str(This(this), ctx, "error", vec![error_value], false)?; +// return Ok(true); +// } +// return Err(err.throw(ctx)); +// } +// Ok(false) +// } +// } + +pub trait Emitter<'js> +where + Self: JsClass<'js> + Sized + 'js, +{ + fn get_event_list(&self) -> Arc>>; + + fn on_event_changed(&mut self, _event: EventKey<'js>, _added: bool) -> Result<()> { + Ok(()) + } + + fn add_event_emitter_prototype(ctx: &Ctx<'js>) -> Result> { + let proto = Class::::prototype(ctx.clone()) + .or_throw_msg(ctx, "Prototype for EventEmitter not found")?; + + let on = Function::new(ctx.clone(), Self::on)?; + let off = Function::new(ctx.clone(), Self::remove_event_listener)?; + + proto.set("once", Func::from(Self::once))?; + + proto.set("on", on.clone())?; + + proto.set("emit", Func::from(Self::emit))?; + + proto.set("prependListener", Func::from(Self::prepend_listener))?; + + proto.set( + "prependOnceListener", + Func::from(Self::prepend_once_listener), + )?; + + proto.set("off", off.clone())?; + + proto.set("eventNames", Func::from(Self::event_names))?; + + proto.set("addListener", on)?; + + proto.set("removeListener", off)?; + + Ok(proto) + } + + fn trace_event_emitter<'a>(&self, tracer: Tracer<'a, 'js>) { + let events = self.get_event_list(); + let events = events.read().unwrap(); + for (key, items) in events.iter() { + if let EventKey::Symbol(sym) = &key { + tracer.mark(sym); + } + + for item in items { + tracer.mark(&item.callback); + } + } + } + + fn remove_event_listener( + this: This>, + ctx: Ctx<'js>, + event: Value<'js>, + listener: Function<'js>, + ) -> Result> { + let events = this.clone().borrow().get_event_list(); + let mut events = events.write().or_throw(&ctx)?; + + let key = EventKey::from_value(&ctx, event)?; + if let Some(index) = events.iter_mut().position(|(k, _)| k == &key) { + let items = &mut events[index].1; + if let Some(pos) = items.iter().position(|item| item.callback == listener) { + items.remove(pos); + if items.is_empty() { + events.remove(index); + } + } + }; + + Ok(this.0) + } + + fn add_event_listener_str( + this: This>, + ctx: &Ctx<'js>, + event: &str, + listener: Function<'js>, + prepend: bool, + once: bool, + ) -> Result> { + let event = to_event(ctx, event)?; + Self::add_event_listener(this, ctx.clone(), event, listener, prepend, once) + } + + fn once( + this: This>, + ctx: Ctx<'js>, + event: Value<'js>, + listener: Function<'js>, + ) -> Result> { + Self::add_event_listener(this, ctx, event, listener, false, true) + } + + fn on( + this: This>, + ctx: Ctx<'js>, + event: Value<'js>, + listener: Function<'js>, + ) -> Result> { + Self::add_event_listener(this, ctx, event, listener, false, false) + } + + fn prepend_listener( + this: This>, + ctx: Ctx<'js>, + event: Value<'js>, + listener: Function<'js>, + ) -> Result> { + Self::add_event_listener(this, ctx, event, listener, true, false) + } + + fn prepend_once_listener( + this: This>, + ctx: Ctx<'js>, + event: Value<'js>, + listener: Function<'js>, + ) -> Result> { + Self::add_event_listener(this, ctx, event, listener, true, true) + } + + fn add_event_listener( + this: This>, + ctx: Ctx<'js>, + event: Value<'js>, + listener: Function<'js>, + prepend: bool, + once: bool, + ) -> Result> { + let this2 = this.clone(); + let events = &this2.borrow().get_event_list(); + let mut events = events.write().or_throw(&ctx)?; + let key = EventKey::from_value(&ctx, event)?; + let mut is_new = false; + + let items = match events.iter_mut().find(|(k, _)| k == &key) { + Some((_, entry_items)) => entry_items, + None => { + let new_items = Vec::new(); + is_new = true; + events.push((key.clone(), new_items)); + &mut events.last_mut().unwrap().1 + } + }; + + let item = EventItem { + callback: listener, + once, + }; + if !prepend { + items.push(item); + } else { + items.insert(0, item); + } + if is_new { + this2.borrow_mut().on_event_changed(key, true)? + } + Ok(this.0) + } + + fn has_listener_str(&self, event: &str) -> bool { + let key = EventKey::String(String::from(event)); + has_key(self.get_event_list(), key) + } + + #[allow(dead_code)] + fn has_listener(&self, ctx: Ctx<'js>, event: Value<'js>) -> Result { + let key = EventKey::from_value(&ctx, event)?; + Ok(has_key(self.get_event_list(), key)) + } + + #[allow(dead_code)] + fn get_listeners(&self, ctx: &Ctx<'js>, event: Value<'js>) -> Result>> { + let key = EventKey::from_value(ctx, event)?; + Ok(find_all_listeners(self.get_event_list(), key)) + } + + fn get_listeners_str(&self, event: &str) -> Vec> { + let key = EventKey::String(String::from(event)); + find_all_listeners(self.get_event_list(), key) + } + + fn do_emit( + event: Value<'js>, + this: This>, + ctx: &Ctx<'js>, + args: Rest>, + defer: bool, + ) -> Result<()> { + // trace!("Emitting: {:?}", event); + let this2 = this.clone(); + let events = &this2.borrow().get_event_list(); + let mut events = events.write().or_throw(ctx)?; + let key = EventKey::from_value(ctx, event)?; + + if let Some(index) = events.iter_mut().position(|(k, _)| k == &key) { + let items = &mut events[index].1; + let mut callbacks = Vec::with_capacity(items.len()); + items.retain(|item: &EventItem<'_>| { + callbacks.push(item.callback.clone()); + !item.once + }); + if items.is_empty() { + events.remove(index); + this.borrow_mut().on_event_changed(key, false)?; + } + drop(events); + for callback in callbacks { + let args = args.iter().map(|arg| arg.to_owned()).collect(); + let args = Rest(args); + let this = This(this.clone()); + if defer { + callback.defer((this, args))?; + } else { + callback.call::<_, ()>((this, args))?; + } + } + } + + Ok(()) + } + + fn emit_str( + this: This>, + ctx: &Ctx<'js>, + event: &str, + args: Vec>, + defer: bool, + ) -> Result<()> { + let event = to_event(ctx, event)?; + Self::do_emit(event, this, ctx, args.into(), defer) + } + + fn emit( + this: This>, + ctx: Ctx<'js>, + event: Value<'js>, + args: Rest>, + ) -> Result<()> { + Self::do_emit(event, this, &ctx, args, false) + } + + fn event_names(this: This>, ctx: Ctx<'js>) -> Result>> { + let events = this.get_event_list(); + let events = events.read().or_throw(&ctx)?; + + let mut names = Vec::with_capacity(events.len()); + for (key, _entry) in events.iter() { + let value = match key { + EventKey::Symbol(symbol) => symbol.clone().into_value(), + EventKey::String(str) => JsString::from_str(ctx.clone(), str)?.into(), + }; + + names.push(value) + } + + Ok(names) + } +} + +fn find_all_listeners<'js>( + events: Arc>>, + key: EventKey<'js>, +) -> Vec> { + let events = events.read().unwrap(); + let items = events.iter().find(|(k, _)| k == &key); + if let Some((_, callbacks)) = items { + callbacks.iter().map(|item| item.callback.clone()).collect() + } else { + vec![] + } +} + +fn has_key<'js>(event_list: Arc>>, key: EventKey<'js>) -> bool { + event_list.read().unwrap().iter().any(|(k, _)| k == &key) +} + +fn to_event<'js>(ctx: &Ctx<'js>, event: &str) -> Result> { + let event = JsString::from_str(ctx.clone(), event)?; + Ok(event.into_value()) +} + +impl<'js> Default for EventEmitter<'js> { + fn default() -> Self { + Self::new() + } +} + +#[rquickjs::methods] +impl<'js> EventEmitter<'js> { + #[qjs(constructor)] + pub fn new() -> Self { + Self { + #[allow(clippy::arc_with_non_send_sync)] + events: Arc::new(RwLock::new(Vec::new())), + } + } +} + +#[rquickjs::class] +#[derive(rquickjs::class::Trace)] +pub struct AbortController<'js> { + signal: Class<'js, AbortSignal<'js>>, +} + +#[rquickjs::methods] +impl<'js> AbortController<'js> { + #[qjs(constructor)] + pub fn new(ctx: Ctx<'js>) -> Result { + let signal = AbortSignal::new(); + + let abort_controller = Self { + signal: Class::instance(ctx, signal)?, + }; + Ok(abort_controller) + } + + #[qjs(get)] + pub fn signal(&self) -> Class<'js, AbortSignal<'js>> { + self.signal.clone() + } + + pub fn abort( + ctx: Ctx<'js>, + this: This>, + reason: Opt>, + ) -> Result<()> { + let instance = this.0.borrow(); + let signal = instance.signal.clone(); + let mut signal_borrow = signal.borrow_mut(); + if signal_borrow.aborted { + //only once + return Ok(()); + } + signal_borrow.set_reason(reason); + drop(signal_borrow); + AbortSignal::send_aborted(This(signal), ctx)?; + + Ok(()) + } +} + +fn get_reason_or_dom_exception<'js>( + ctx: &Ctx<'js>, + reason: Option<&Value<'js>>, + name: &str, +) -> Result> { + let reason = if let Some(reason) = reason { + reason.clone() + } else { + let ex = DOMException::new(ctx.clone(), Opt(None), Opt(Some(name.into())))?; + Class::instance(ctx.clone(), ex)?.into_value() + }; + Ok(reason) +} + +#[derive(Clone)] +#[rquickjs::class] +pub struct AbortSignal<'js> { + emitter: EventEmitter<'js>, + aborted: bool, + reason: Option>, + pub sender: mc_oneshot::Sender>, +} + +impl<'js> Trace<'js> for AbortSignal<'js> { + fn trace<'a>(&self, tracer: Tracer<'a, 'js>) { + if let Some(reason) = &self.reason { + tracer.mark(reason); + } + } +} + +impl<'js> Emitter<'js> for AbortSignal<'js> { + fn get_event_list(&self) -> Arc>> { + self.emitter.get_event_list() + } +} + +impl<'js> Default for AbortSignal<'js> { + fn default() -> Self { + Self::new() + } +} + +#[rquickjs::methods(rename_all = "camelCase")] +impl<'js> AbortSignal<'js> { + #[qjs(constructor)] + pub fn new() -> Self { + let (sender, _) = mc_oneshot::channel::>(); + Self { + emitter: EventEmitter::new(), + aborted: false, + reason: None, + sender, + } + } + + #[qjs(get, rename = "onabort")] + pub fn get_on_abort(&self) -> Option> { + Self::get_listeners_str(self, "abort").first().cloned() + } + + #[qjs(set, rename = "onabort")] + pub fn set_on_abort( + this: This>, + ctx: Ctx<'js>, + listener: Function<'js>, + ) -> Result<()> { + Self::add_event_listener_str(this, &ctx, "abort", listener, false, false)?; + Ok(()) + } + + pub fn throw_if_aborted(&self, ctx: Ctx<'js>) -> Result<()> { + if self.aborted { + return Err(ctx.throw( + self.reason + .clone() + .unwrap_or_else(|| Undefined.into_value(ctx.clone())), + )); + } + Ok(()) + } + + #[qjs(static)] + pub fn any(ctx: Ctx<'js>, signals: Array<'js>) -> Result> { + let mut new_signal = AbortSignal::new(); + + let mut signal_instances = Vec::with_capacity(signals.len()); + + for signal in signals.iter() { + let signal: Value = signal?; + let signal: Class = Class::from_value(&signal) + .map_err(|_| Exception::throw_type(&ctx, "Value is not an AbortSignal instance"))?; + let signal_borrow = signal.borrow(); + if signal_borrow.aborted { + new_signal.aborted = true; + new_signal.reason.clone_from(&signal_borrow.reason); + let new_signal = Class::instance(ctx, new_signal)?; + return Ok(new_signal); + } else { + drop(signal_borrow); + signal_instances.push(signal); + } + } + + let new_signal_instance = Class::instance(ctx.clone(), new_signal)?; + for signal in signal_instances { + let signal_instance_2 = new_signal_instance.clone(); + Self::add_event_listener_str( + This(signal), + &ctx, + "abort", + Function::new( + ctx.clone(), + OnceFn::from(|ctx, signal| { + struct Args<'js>(Ctx<'js>, This>>); + let Args(ctx, signal) = Args(ctx, signal); + let mut borrow = signal_instance_2.borrow_mut(); + borrow.aborted = true; + borrow.reason.clone_from(&signal.borrow().reason); + drop(borrow); + Self::send_aborted(This(signal_instance_2), ctx) + }), + )?, + false, + true, + )?; + } + + Ok(new_signal_instance) + } + + #[qjs(get)] + pub fn aborted(&self) -> bool { + self.aborted + } + + #[qjs(get)] + pub fn reason(&self) -> Option> { + self.reason.clone() + } + + #[qjs(set, rename = "reason")] + pub fn set_reason(&mut self, reason: Opt>) { + if let Some(new_reason) = reason.0 { + self.reason.replace(new_reason); + } else { + self.reason.take(); + } + } + + #[qjs(skip)] + pub fn send_aborted(this: This>, ctx: Ctx<'js>) -> Result<()> { + let mut borrow = this.borrow_mut(); + borrow.aborted = true; + let reason = get_reason_or_dom_exception(&ctx, borrow.reason.as_ref(), "AbortError")?; + borrow.sender.send(reason); + drop(borrow); + Self::emit_str(this, &ctx, "abort", vec![], false)?; + Ok(()) + } + + #[qjs(static)] + pub fn abort(ctx: Ctx<'js>, reason: Opt>) -> Result> { + let mut signal = Self::new(); + signal.set_reason(reason); + let instance = Class::instance(ctx.clone(), signal)?; + Self::send_aborted(This(instance.clone()), ctx)?; + Ok(instance) + } + + #[qjs(static)] + pub fn timeout(ctx: Ctx<'js>, milliseconds: u64) -> Result> { + let timeout_error = get_reason_or_dom_exception(&ctx, None, "TimeoutError")?; + + let signal = Self::new(); + let signal_instance = Class::instance(ctx.clone(), signal)?; + let signal_instance2 = signal_instance.clone(); + + // ctx.clone().spawn_exit(async move { + // tokio::time::sleep(Duration::from_millis(milliseconds)).await; + // let mut borrow = signal_instance.borrow_mut(); + // borrow.set_reason(Opt(Some(timeout_error))); + // drop(borrow); + // Self::send_aborted(This(signal_instance), ctx)?; + // Ok(()) + // })?; + + Ok(signal_instance2) + } +} + +pub struct EventsModule; + +impl ModuleDef for EventsModule { + fn declare(declare: &Declarations<'_>) -> Result<()> { + declare.declare(stringify!(EventEmitter))?; + declare.declare("default")?; + + Ok(()) + } + + fn evaluate<'js>(ctx: &Ctx<'js>, exports: &Exports<'js>) -> Result<()> { + let ctor = Class::::create_constructor(ctx)? + .expect("Can't create EventEmitter constructor"); + ctor.set(stringify!(EventEmitter), ctor.clone())?; + exports.export(stringify!(EventEmitter), ctor.clone())?; + exports.export("default", ctor)?; + + EventEmitter::add_event_emitter_prototype(ctx)?; + + Ok(()) + } +} + +// impl From for ModuleInfo { +// fn from(val: EventsModule) -> Self { +// ModuleInfo { +// name: "events", +// module: val, +// } +// } +// } + +pub fn init(ctx: &Ctx<'_>) -> Result<()> { + let globals = ctx.globals(); + + Class::::define(&globals)?; + Class::::define(&globals)?; + + AbortSignal::add_event_emitter_prototype(ctx)?; + + Ok(()) +} diff --git a/rqjs-ext/src/modules/exceptions.rs b/rqjs-ext/src/modules/exceptions.rs new file mode 100644 index 0000000..f37c5ec --- /dev/null +++ b/rqjs-ext/src/modules/exceptions.rs @@ -0,0 +1,69 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +use rquickjs::{ + atom::PredefinedAtom, + function::{Constructor, Opt}, + Class, Ctx, Object, Result, +}; + +#[rquickjs::class] +#[derive(rquickjs::class::Trace)] +pub struct DOMException { + message: String, + name: String, + stack: String, +} + +#[rquickjs::methods] +impl DOMException { + #[qjs(constructor)] + pub fn new(ctx: Ctx<'_>, message: Opt, name: Opt) -> Result { + let error_ctor: Constructor = ctx.globals().get(PredefinedAtom::Error)?; + let new: Object = error_ctor.construct((message.clone(),))?; + + let message = message.0.unwrap_or(String::from("")); + let name = name.0.unwrap_or(String::from("Error")); + + Ok(Self { + message, + name, + stack: new.get::<_, String>(PredefinedAtom::Stack)?, + }) + } + + #[qjs(get)] + fn message(&self) -> String { + self.message.clone() + } + + #[qjs(get)] + fn name(&self) -> String { + self.name.clone() + } + + #[qjs(get)] + fn stack(&self) -> String { + self.stack.clone() + } + + #[qjs(rename = PredefinedAtom::ToString)] + pub fn to_string(&self) -> String { + if self.message.is_empty() { + return self.name.clone(); + } + + format!("{}: {}", &self.name, &self.message) + } +} + +pub fn init(ctx: &Ctx<'_>) -> Result<()> { + let globals = ctx.globals(); + Class::::define(&globals)?; + + let dom_ex_proto = Class::::prototype(ctx.clone()).unwrap(); + let error_ctor: Object = globals.get(PredefinedAtom::Error)?; + let error_proto = error_ctor.get_prototype(); + dom_ex_proto.set_prototype(error_proto.as_ref())?; + + Ok(()) +} diff --git a/rqjs-ext/src/modules/fs/access.rs b/rqjs-ext/src/modules/fs/access.rs new file mode 100644 index 0000000..1482b33 --- /dev/null +++ b/rqjs-ext/src/modules/fs/access.rs @@ -0,0 +1,66 @@ +use std::fs::Metadata; + +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +use rquickjs::{prelude::Opt, Ctx, Exception, Result}; +use tokio::fs; + +use crate::utils::result::ResultExt; + +#[allow(dead_code, unused_imports)] +use super::{CONSTANT_F_OK, CONSTANT_R_OK, CONSTANT_W_OK, CONSTANT_X_OK}; + +pub async fn access(ctx: Ctx<'_>, path: String, mode: Opt) -> Result<()> { + let metadata = fs::metadata(&path) + .await + .or_throw_msg(&ctx, &format!("No such file or directory \"{}\"", &path))?; + + verify_metadata(&ctx, mode, metadata) +} + +pub fn access_sync(ctx: Ctx<'_>, path: String, mode: Opt) -> Result<()> { + let metadata = std::fs::metadata(path.clone()) + .or_throw_msg(&ctx, &format!("No such file or directory \"{}\"", &path))?; + + verify_metadata(&ctx, mode, metadata) +} + +fn verify_metadata(ctx: &Ctx, mode: Opt, metadata: Metadata) -> Result<()> { + let permissions = metadata.permissions(); + + let mode = mode.unwrap_or(CONSTANT_F_OK); + + if mode & CONSTANT_W_OK != 0 && permissions.readonly() { + return Err(Exception::throw_message( + ctx, + "Permission denied. File not writable", + )); + } + + if mode & CONSTANT_X_OK != 0 { + #[cfg(unix)] + { + use std::os::unix::fs::PermissionsExt; + if permissions.mode() & 0o100 == 0 { + return Err(Exception::throw_message( + ctx, + "Permission denied. File not executable", + )); + } + } + #[cfg(windows)] + { + use std::os::windows::fs::MetadataExt; + const FILE_ATTRIBUTE_DIRECTORY: u32 = 0x10; + // Get the file attributes + let file_attributes = metadata.file_attributes(); + + // Check if the file has execute permissions + if file_attributes & FILE_ATTRIBUTE_DIRECTORY == 0 { + return Err(Exception::throw_message(ctx, "Permission denied")); + } + } + } + + Ok(()) +} diff --git a/rqjs-ext/src/modules/fs/mkdir.rs b/rqjs-ext/src/modules/fs/mkdir.rs new file mode 100644 index 0000000..65317c0 --- /dev/null +++ b/rqjs-ext/src/modules/fs/mkdir.rs @@ -0,0 +1,87 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +#[cfg(target_family = "unix")] +use std::os::unix::prelude::PermissionsExt; + +use ring::rand::{SecureRandom, SystemRandom}; +use rquickjs::{function::Opt, Ctx, Object, Result}; +use tokio::fs; + +use crate::utils::result::ResultExt; + +pub async fn mkdir<'js>(ctx: Ctx<'js>, path: String, options: Opt>) -> Result { + let (recursive, mode) = get_params(options); + + if recursive { + fs::create_dir_all(&path).await + } else { + fs::create_dir(&path).await + } + .or_throw_msg(&ctx, &format!("Can't create dir \"{}\"", &path))?; + + #[cfg(target_family = "unix")] + fs::set_permissions(&path, PermissionsExt::from_mode(mode)) + .await + .or_throw_msg(&ctx, &format!("Can't set permissions of \"{}\"", &path))?; + + Ok(path) +} + +pub fn mkdir_sync<'js>(ctx: Ctx<'js>, path: String, options: Opt>) -> Result { + let (recursive, mode) = get_params(options); + + if recursive { + std::fs::create_dir_all(&path) + } else { + std::fs::create_dir(&path) + } + .or_throw_msg(&ctx, &format!("Can't create dir \"{}\"", &path))?; + + #[cfg(target_family = "unix")] + std::fs::set_permissions(&path, PermissionsExt::from_mode(mode)) + .or_throw_msg(&ctx, &format!("Can't set permissions of \"{}\"", &path))?; + + Ok(path) +} + +fn get_params(options: Opt) -> (bool, u32) { + let mut recursive = false; + let mut mode = 0o777; + + if let Some(options) = options.0 { + recursive = options.get("recursive").unwrap_or_default(); + mode = options.get("mode").unwrap_or(0o777); + } + (recursive, mode) +} + +const CHARS: &[u8] = b"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; + +fn random_chars(len: usize) -> String { + let random = SystemRandom::new(); + + let mut bytes = vec![0u8; len]; + random.fill(&mut bytes).unwrap(); + bytes + .iter() + .map(|&byte| { + let idx = (byte as usize) % CHARS.len(); + CHARS[idx] as char + }) + .collect::() +} + +pub async fn mkdtemp(ctx: Ctx<'_>, prefix: String) -> Result { + let path = format!("{},{}", &prefix, &random_chars(6)); + fs::create_dir_all(&path) + .await + .or_throw_msg(&ctx, &format!("Can't create dir \"{}\"", &path))?; + Ok(path) +} + +pub fn mkdtemp_sync(ctx: Ctx<'_>, prefix: String) -> Result { + let path = format!("{},{}", &prefix, &random_chars(6)); + std::fs::create_dir_all(&path) + .or_throw_msg(&ctx, &format!("Can't create dir \"{}\"", &path))?; + Ok(path) +} diff --git a/rqjs-ext/src/modules/fs/mod.rs b/rqjs-ext/src/modules/fs/mod.rs new file mode 100644 index 0000000..29b6224 --- /dev/null +++ b/rqjs-ext/src/modules/fs/mod.rs @@ -0,0 +1,159 @@ +mod access; +mod mkdir; +mod read_dir; +mod read_file; +mod rm; +mod stats; +mod write_file; + +use rquickjs::{ + module::{Declarations, Exports, ModuleDef}, + prelude::Func, +}; +use rquickjs::{Class, Ctx, Object, Result}; + +use rquickjs::function::Async; + +// use crate::{module_builder::ModuleInfo, modules::module::export_default}; + +use self::access::access; +use self::read_dir::{read_dir, read_dir_sync, Dirent}; +use self::read_file::{read_file, read_file_sync}; +use self::rm::{rmdir, rmfile}; +use self::stats::{stat_fn, Stat}; +use self::write_file::write_file; + +use crate::modules::fs::{ + access::access_sync, + mkdir::{mkdir, mkdir_sync, mkdtemp, mkdtemp_sync}, + rm::{rmdir_sync, rmfile_sync}, + stats::stat_fn_sync, + write_file::write_file_sync, +}; + +use super::module::export_default; + +pub const CONSTANT_F_OK: u32 = 0; +pub const CONSTANT_R_OK: u32 = 4; +pub const CONSTANT_W_OK: u32 = 2; +pub const CONSTANT_X_OK: u32 = 1; + +pub struct FsPromisesModule; + +impl ModuleDef for FsPromisesModule { + fn declare(declare: &Declarations<'_>) -> Result<()> { + declare.declare("access")?; + declare.declare("open")?; + declare.declare("readFile")?; + declare.declare("writeFile")?; + declare.declare("appendFile")?; + declare.declare("copyFile")?; + declare.declare("rename")?; + declare.declare("readdir")?; + declare.declare("mkdir")?; + declare.declare("mkdtemp")?; + declare.declare("rm")?; + declare.declare("rmdir")?; + declare.declare("stat")?; + declare.declare("constants")?; + + declare.declare("default")?; + + Ok(()) + } + + fn evaluate<'js>(ctx: &Ctx<'js>, exports: &Exports<'js>) -> Result<()> { + Class::::register(ctx)?; + Class::::register(ctx)?; + + export_default(ctx, exports, |default| { + export_promises(ctx, default)?; + + Ok(()) + }) + } +} + +// impl From for ModuleInfo { +// fn from(val: FsPromisesModule) -> Self { +// ModuleInfo { +// name: "fs/promises", +// module: val, +// } +// } +// } + +pub struct FsModule; + +impl ModuleDef for FsModule { + fn declare(declare: &Declarations<'_>) -> Result<()> { + declare.declare("promises")?; + declare.declare("accessSync")?; + declare.declare("mkdirSync")?; + declare.declare("mkdtempSync")?; + declare.declare("readdirSync")?; + declare.declare("readFileSync")?; + declare.declare("rmdirSync")?; + declare.declare("rmSync")?; + declare.declare("statSync")?; + declare.declare("writeFileSync")?; + + declare.declare("default")?; + + Ok(()) + } + + fn evaluate<'js>(ctx: &Ctx<'js>, exports: &Exports<'js>) -> Result<()> { + Class::::register(ctx)?; + Class::::register(ctx)?; + + export_default(ctx, exports, |default| { + let promises = Object::new(ctx.clone())?; + export_promises(ctx, &promises)?; + + default.set("promises", promises)?; + default.set("accessSync", Func::from(access_sync))?; + default.set("mkdirSync", Func::from(mkdir_sync))?; + default.set("mkdtempSync", Func::from(mkdtemp_sync))?; + default.set("readdirSync", Func::from(read_dir_sync))?; + default.set("readFileSync", Func::from(read_file_sync))?; + default.set("rmdirSync", Func::from(rmdir_sync))?; + default.set("rmSync", Func::from(rmfile_sync))?; + default.set("statSync", Func::from(stat_fn_sync))?; + default.set("writeFileSync", Func::from(write_file_sync))?; + + Ok(()) + }) + } +} + +fn export_promises<'js>(ctx: &Ctx<'js>, exports: &Object<'js>) -> Result<()> { + let constants = Object::new(ctx.clone())?; + constants.set("F_OK", CONSTANT_F_OK)?; + constants.set("R_OK", CONSTANT_R_OK)?; + constants.set("W_OK", CONSTANT_W_OK)?; + constants.set("X_OK", CONSTANT_X_OK)?; + + exports.set("readdir", Func::from(Async(read_dir)))?; + exports.set("readFile", Func::from(Async(read_file)))?; + exports.set("writeFile", Func::from(Async(write_file)))?; + exports.set("mkdir", Func::from(Async(mkdir)))?; + exports.set("mkdtemp", Func::from(Async(mkdtemp)))?; + exports.set("rmdir", Func::from(Async(rmdir)))?; + exports.set("rm", Func::from(Async(rmfile)))?; + exports.set("stat", Func::from(Async(stat_fn)))?; + exports.set("access", Func::from(Async(access)))?; + + exports.set("constants", constants)?; + + Ok(()) +} + +// impl From for ModuleInfo { +// fn from(val: FsModule) -> Self { +// ModuleInfo { +// name: "fs", +// module: val, +// } +// } +// } diff --git a/rqjs-ext/src/modules/fs/read_dir.rs b/rqjs-ext/src/modules/fs/read_dir.rs new file mode 100644 index 0000000..5e1b2f7 --- /dev/null +++ b/rqjs-ext/src/modules/fs/read_dir.rs @@ -0,0 +1,225 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +use std::{fs::Metadata, path::PathBuf}; + +use rquickjs::{ + atom::PredefinedAtom, prelude::Opt, Array, Class, Ctx, IntoJs, Object, Result, Value, +}; + +#[cfg(unix)] +use std::os::unix::fs::FileTypeExt; + +use crate::{ + modules::path::{is_absolute, CURRENT_DIR_STR}, + utils::io::DirectoryWalker, +}; + +#[derive(rquickjs::class::Trace)] +#[rquickjs::class] +pub struct Dirent { + #[qjs(skip_trace)] + metadata: Metadata, +} + +#[rquickjs::methods(rename_all = "camelCase")] +impl Dirent { + pub fn is_file(&self) -> bool { + self.metadata.is_file() + } + pub fn is_directory(&self) -> bool { + self.metadata.is_dir() + } + + pub fn is_symbolic_link(&self) -> bool { + self.metadata.is_symlink() + } + + #[qjs(rename = "isFIFO")] + pub fn is_fifo(&self) -> bool { + #[cfg(unix)] + { + self.metadata.file_type().is_fifo() + } + #[cfg(not(unix))] + { + false + } + } + + pub fn is_block_device(&self) -> bool { + #[cfg(unix)] + { + self.metadata.file_type().is_block_device() + } + #[cfg(not(unix))] + { + false + } + } + + pub fn is_character_device(&self) -> bool { + #[cfg(unix)] + { + self.metadata.file_type().is_char_device() + } + #[cfg(not(unix))] + { + false + } + } + + pub fn is_socket(&self) -> bool { + #[cfg(unix)] + { + self.metadata.file_type().is_socket() + } + #[cfg(not(unix))] + { + false + } + } +} + +struct ReadDirItem { + name: String, + metadata: Option, +} + +pub struct ReadDir { + items: Vec, + root: String, +} + +impl<'js> IntoJs<'js> for ReadDir { + fn into_js(self, ctx: &Ctx<'js>) -> Result> { + let arr = Array::new(ctx.clone())?; + for (index, item) in self.items.into_iter().enumerate() { + if let Some(metadata) = item.metadata { + let dirent = Dirent { metadata }; + + let dirent = Class::instance(ctx.clone(), dirent)?; + dirent.set(PredefinedAtom::Name, item.name)?; + dirent.set("parentPath", &self.root)?; + arr.set(index, dirent)?; + } else { + arr.set(index, item.name)?; + } + } + arr.into_js(ctx) + } +} + +pub async fn read_dir<'js>( + _ctx: Ctx<'js>, + mut path: String, + options: Opt>, +) -> Result { + let (with_file_types, skip_root_pos, mut directory_walker) = + process_options_and_create_directory_walker(&mut path, options); + + let mut items = Vec::with_capacity(64); + + while let Some((child, metadata)) = directory_walker.walk().await? { + append_directory_and_metadata_to_vec( + with_file_types, + skip_root_pos, + &mut items, + child, + metadata, + ); + } + + items.sort_by(|a, b| a.name.partial_cmp(&b.name).unwrap()); + + Ok(ReadDir { items, root: path }) +} + +pub fn read_dir_sync<'js>( + _ctx: Ctx<'js>, + mut path: String, + options: Opt>, +) -> Result { + let (with_file_types, skip_root_pos, mut directory_walker) = + process_options_and_create_directory_walker(&mut path, options); + + let mut items = Vec::with_capacity(64); + while let Some((child, metadata)) = directory_walker.walk_sync()? { + append_directory_and_metadata_to_vec( + with_file_types, + skip_root_pos, + &mut items, + child, + metadata, + ); + } + + items.sort_by(|a, b| a.name.partial_cmp(&b.name).unwrap()); + + Ok(ReadDir { items, root: path }) +} + +type OptionsAndDirectoryWalker = (bool, usize, DirectoryWalker bool>); + +fn process_options_and_create_directory_walker( + path: &mut String, + options: Opt, +) -> OptionsAndDirectoryWalker { + let mut with_file_types = false; + let mut is_recursive = false; + + if let Some(options) = options.0 { + with_file_types = options + .get("withFileTypes") + .ok() + .and_then(|file_types: Value| file_types.as_bool()) + .unwrap_or_default(); + + is_recursive = options + .get("recursive") + .ok() + .and_then(|recursive: Value| recursive.as_bool()) + .unwrap_or_default(); + }; + + let skip_root_pos = { + match path.as_str() { + // . | ./ + "." | CURRENT_DIR_STR => CURRENT_DIR_STR.len(), + // ./path + _ if path.starts_with(CURRENT_DIR_STR) => path.len() + 1, + // path + _ => { + if !is_absolute(path.clone()) { + path.insert_str(0, CURRENT_DIR_STR); + } + path.len() + 1 + } + } + }; + + let mut directory_walker: DirectoryWalker bool> = + DirectoryWalker::new(PathBuf::from(&path), |_| true); + + if is_recursive { + directory_walker.set_recursive(true); + } + (with_file_types, skip_root_pos, directory_walker) +} + +fn append_directory_and_metadata_to_vec( + with_file_types: bool, + skip_root_pos: usize, + items: &mut Vec, + child: PathBuf, + metadata: Metadata, +) { + let metadata = if with_file_types { + Some(metadata) + } else { + None + }; + + let name = child.into_os_string().to_string_lossy()[skip_root_pos..].to_string(); + + items.push(ReadDirItem { name, metadata }) +} diff --git a/rqjs-ext/src/modules/fs/read_file.rs b/rqjs-ext/src/modules/fs/read_file.rs new file mode 100644 index 0000000..a50ec35 --- /dev/null +++ b/rqjs-ext/src/modules/fs/read_file.rs @@ -0,0 +1,54 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +use rquickjs::{function::Opt, Ctx, IntoJs, Result, Value}; +use tokio::fs; + +use crate::{ + modules::buffer::Buffer, + utils::{object::ObjectExt, result::ResultExt}, +}; + +pub async fn read_file<'js>( + ctx: Ctx<'js>, + path: String, + options: Opt>, +) -> Result> { + let bytes = fs::read(&path) + .await + .or_throw_msg(&ctx, &format!("Can't read \"{}\"", &path))?; + + handle_read_file_bytes(&ctx, options, bytes) +} + +pub fn read_file_sync<'js>( + ctx: Ctx<'js>, + path: String, + options: Opt>, +) -> Result> { + let bytes = std::fs::read(&path).or_throw_msg(&ctx, &format!("Can't read \"{}\"", &path))?; + + handle_read_file_bytes(&ctx, options, bytes) +} +fn handle_read_file_bytes<'a>( + ctx: &Ctx<'a>, + options: Opt, + bytes: Vec, +) -> Result> { + let buffer = Buffer(bytes); + + if let Some(options) = options.0 { + let encoding = if options.is_string() { + options.as_string().unwrap().to_string().map(Some)? + } else { + options.get_optional::<_, String>("encoding")? + }; + + if let Some(encoding) = encoding { + return buffer + .to_string(ctx, &encoding) + .and_then(|s| s.into_js(ctx)); + } + } + + buffer.into_js(ctx) +} diff --git a/rqjs-ext/src/modules/fs/rm.rs b/rqjs-ext/src/modules/fs/rm.rs new file mode 100644 index 0000000..16a9051 --- /dev/null +++ b/rqjs-ext/src/modules/fs/rm.rs @@ -0,0 +1,107 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +use rquickjs::{function::Opt, Ctx, Object, Result}; +use tokio::fs; + +use crate::utils::result::ResultExt; + +#[allow(clippy::manual_async_fn)] +pub async fn rmdir<'js>(ctx: Ctx<'js>, path: String, options: Opt>) -> Result<()> { + let recursive = get_params_rm_dir(options); + + if recursive { + fs::remove_dir_all(&path).await + } else { + fs::remove_dir(&path).await + } + .or_throw_msg(&ctx, &format!("Can't remove dir \"{}\"", &path))?; + + Ok(()) +} + +#[allow(clippy::manual_async_fn)] +pub fn rmdir_sync<'js>(ctx: Ctx<'js>, path: String, options: Opt>) -> Result<()> { + let recursive = get_params_rm_dir(options); + + if recursive { + std::fs::remove_dir_all(&path) + } else { + std::fs::remove_dir(&path) + } + .or_throw_msg(&ctx, &format!("Can't remove dir \"{}\"", &path))?; + + Ok(()) +} + +pub async fn rmfile<'js>(ctx: Ctx<'js>, path: String, options: Opt>) -> Result<()> { + let (recursive, force) = get_params_rm(options); + + let res = async move { + let is_dir = fs::metadata(&path) + .await + .map(|metadata| metadata.is_dir()) + .or_throw(&ctx)?; + + (if is_dir && recursive { + fs::remove_dir_all(&path).await + } else if is_dir && !recursive { + fs::remove_dir(&path).await + } else { + fs::remove_file(&path).await + }) + .or_throw_msg(&ctx, &format!("Can't remove file \"{}\"", &path))?; + + Ok(()) + } + .await; + + if !force { + return res; + } + + Ok(()) +} + +pub fn rmfile_sync<'js>(_ctx: Ctx<'js>, path: String, options: Opt>) -> Result<()> { + let (recursive, force) = get_params_rm(options); + + let res = (|| -> Result<()> { + let is_dir = std::fs::metadata(&path).map(|metadata| metadata.is_dir())?; + + (if is_dir && recursive { + std::fs::remove_dir_all(&path) + } else if is_dir && !recursive { + std::fs::remove_dir(&path) + } else { + std::fs::remove_file(&path) + })?; + + Ok(()) + })(); + + if !force { + return res; + } + + Ok(()) +} + +fn get_params_rm_dir(options: Opt) -> bool { + let mut recursive = false; + + if let Some(options) = options.0 { + recursive = options.get("recursive").unwrap_or_default(); + } + recursive +} + +fn get_params_rm(options: Opt) -> (bool, bool) { + let mut recursive = false; + let mut force = false; + + if let Some(options) = options.0 { + recursive = options.get("recursive").unwrap_or_default(); + force = options.get("force").unwrap_or_default(); + } + (recursive, force) +} diff --git a/rqjs-ext/src/modules/fs/stats.rs b/rqjs-ext/src/modules/fs/stats.rs new file mode 100644 index 0000000..2556a7a --- /dev/null +++ b/rqjs-ext/src/modules/fs/stats.rs @@ -0,0 +1,306 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +use crate::utils::result::ResultExt; + +use rquickjs::{Ctx, Result}; +use tokio::fs; + +use std::{ + fs::Metadata, + time::{SystemTime}, +}; + +#[cfg(unix)] +use std::os::unix::fs::FileTypeExt; +#[cfg(unix)] +use std::os::unix::fs::MetadataExt; + + +#[rquickjs::class] +#[derive(rquickjs::class::Trace)] +pub struct Stat { + #[qjs(skip_trace)] + metadata: Metadata, +} + +#[rquickjs::methods(rename_all = "camelCase")] +impl Stat { + #[qjs(skip)] + pub fn new(metadata: Metadata) -> Self { + Self { metadata } + } + + #[qjs(get, enumerable)] + pub fn dev(&self) -> u64 { + #[cfg(unix)] + { + self.metadata.dev() + } + #[cfg(not(unix))] + { + todo!() + } + } + + #[qjs(get, enumerable)] + pub fn ino(&self) -> u64 { + #[cfg(unix)] + { + self.metadata.ino() + } + #[cfg(not(unix))] + { + todo!() + } + } + + #[qjs(get, enumerable)] + pub fn mode(&self) -> u32 { + #[cfg(unix)] + { + self.metadata.mode() + } + #[cfg(not(unix))] + { + todo!() + } + } + + #[qjs(get, enumerable)] + pub fn nlink(&self) -> u64 { + #[cfg(unix)] + { + self.metadata.nlink() + } + #[cfg(not(unix))] + { + todo!() + } + } + + #[qjs(get, enumerable)] + pub fn uid(&self) -> u32 { + #[cfg(unix)] + { + self.metadata.uid() + } + #[cfg(not(unix))] + { + todo!() + } + } + + #[qjs(get, enumerable)] + pub fn gid(&self) -> u32 { + #[cfg(unix)] + { + self.metadata.gid() + } + #[cfg(not(unix))] + { + todo!() + } + } + + #[qjs(get, enumerable)] + pub fn rdev(&self) -> u64 { + #[cfg(unix)] + { + self.metadata.rdev() + } + #[cfg(not(unix))] + { + todo!() + } + } + + #[qjs(get, enumerable)] + pub fn size(&self) -> u64 { + #[cfg(unix)] + { + self.metadata.size() + } + #[cfg(not(unix))] + { + todo!() + } + } + + #[qjs(get, enumerable)] + pub fn blksize(&self) -> u64 { + #[cfg(unix)] + { + self.metadata.blksize() + } + #[cfg(not(unix))] + { + todo!() + } + } + + #[qjs(get, enumerable)] + pub fn blocks(&self) -> u64 { + #[cfg(unix)] + { + self.metadata.blocks() + } + #[cfg(not(unix))] + { + todo!() + } + } + + #[qjs(get, enumerable)] + pub fn atime_ms(&self) -> i64 { + #[cfg(unix)] + { + self.metadata.atime_nsec() / 1e6 as i64 + } + #[cfg(not(unix))] + { + todo!() + } + } + + #[qjs(get, enumerable)] + pub fn mtime_ms(&self) -> i64 { + #[cfg(unix)] + { + self.metadata.mtime_nsec() / 1e6 as i64 + } + #[cfg(not(unix))] + { + todo!() + } + } + + #[qjs(get, enumerable)] + pub fn ctime_ms(&self) -> i64 { + #[cfg(unix)] + { + self.metadata.ctime_nsec() / 1e6 as i64 + } + #[cfg(not(unix))] + { + todo!() + } + } + + #[qjs(get, enumerable)] + pub fn birthtime_ms(&self, ctx: Ctx<'_>) -> Result { + #[cfg(unix)] + { + self.metadata + .created() + .or_throw(&ctx) + .and_then(|c| c.elapsed().or_throw(&ctx)) + .map(|d| d.as_millis() as u64) + } + #[cfg(not(unix))] + { + todo!() + } + } + + #[qjs(get, enumerable)] + pub fn atime(&self, ctx: Ctx<'_>) -> Result { + self.metadata.accessed().or_throw(&ctx) + } + + #[qjs(get, enumerable)] + pub fn mtime(&self, ctx: Ctx<'_>) -> Result { + self.metadata.modified().or_throw(&ctx) + } + + #[qjs(get, enumerable)] + pub fn ctime(&self) -> SystemTime { + #[cfg(unix)] + { + SystemTime::UNIX_EPOCH + std::time::Duration::from_nanos(self.metadata.ctime_nsec() as u64) + } + #[cfg(not(unix))] + { + todo!() + } + } + + #[qjs(get, enumerable)] + pub fn birthtime(&self, ctx: Ctx<'_>) -> Result { + self.metadata.created().or_throw(&ctx) + } + + pub fn is_file(&self) -> bool { + self.metadata.is_file() + } + pub fn is_dir(&self) -> bool { + self.metadata.is_dir() + } + + pub fn is_symlink(&self) -> bool { + self.metadata.is_symlink() + } + + #[qjs(rename = "isFIFO")] + pub fn is_fifo(&self) -> bool { + #[cfg(unix)] + { + self.metadata.file_type().is_fifo() + } + #[cfg(not(unix))] + { + false + } + } + + pub fn is_block_device(&self) -> bool { + #[cfg(unix)] + { + self.metadata.file_type().is_block_device() + } + #[cfg(not(unix))] + { + false + } + } + + pub fn is_character_device(&self) -> bool { + #[cfg(unix)] + { + self.metadata.file_type().is_char_device() + } + #[cfg(not(unix))] + { + false + } + } + + pub fn is_socket(&self) -> bool { + #[cfg(unix)] + { + self.metadata.file_type().is_socket() + } + #[cfg(not(unix))] + { + false + } + } +} + +pub async fn stat_fn(ctx: Ctx<'_>, path: String) -> Result { + let metadata = fs::metadata(&path) + .await + .or_throw_msg(&ctx, &format!("Can't stat \"{}\"", &path))?; + + let stats = Stat::new(metadata); + + Ok(stats) +} + +pub fn stat_fn_sync(ctx: Ctx<'_>, path: String) -> Result { + let metadata = + std::fs::metadata(&path).or_throw_msg(&ctx, &format!("Can't stat \"{}\"", &path))?; + + let stats = Stat::new(metadata); + + Ok(stats) +} diff --git a/rqjs-ext/src/modules/fs/write_file.rs b/rqjs-ext/src/modules/fs/write_file.rs new file mode 100644 index 0000000..bc2c4b6 --- /dev/null +++ b/rqjs-ext/src/modules/fs/write_file.rs @@ -0,0 +1,32 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +use rquickjs::{Ctx, Result, Value}; +use tokio::fs; +use tokio::io::AsyncWriteExt; + +use crate::utils::object::get_bytes; +use crate::utils::result::ResultExt; + +pub async fn write_file<'js>(ctx: Ctx<'js>, path: String, data: Value<'js>) -> Result<()> { + let mut file = fs::File::create(&path) + .await + .or_throw_msg(&ctx, &format!("Can't create file \"{}\"", &path))?; + + let bytes = get_bytes(&ctx, data)?; + file.write_all(&bytes) + .await + .or_throw_msg(&ctx, &format!("Can't write \"{}\"", &path))?; + file.flush() + .await + .or_throw_msg(&ctx, &format!("Can't write \"{}\"", &path))?; + + Ok(()) +} + +pub fn write_file_sync<'js>(ctx: Ctx<'js>, path: String, data: Value<'js>) -> Result<()> { + let bytes = get_bytes(&ctx, data)?; + + std::fs::write(&path, bytes).or_throw_msg(&ctx, &format!("Can't write \"{}\"", &path))?; + + Ok(()) +} diff --git a/rqjs-ext/src/modules/macros.rs b/rqjs-ext/src/modules/macros.rs new file mode 100644 index 0000000..16c9be0 --- /dev/null +++ b/rqjs-ext/src/modules/macros.rs @@ -0,0 +1,25 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +macro_rules! iterable_enum { + ($visibility:vis, $name:ident, $($member:tt),*) => { + #[derive(Copy, Clone)] + $visibility enum $name {$($member),*} + impl $name { + pub fn iterate() -> Vec<$name> { + vec![$($name::$member,)*] + } + } + }; + ($name:ident, $($member:tt),*) => { + iterable_enum!(, $name, $($member),*) + }; +} + +macro_rules! impl_stream_events { + + ($($struct:ident),*) => { + $( + impl<'js> $crate::stream::SteamEvents<'js> for $struct<'js> {} + )* + }; +} diff --git a/rqjs-ext/src/modules/mod.rs b/rqjs-ext/src/modules/mod.rs new file mode 100644 index 0000000..fb8b0d5 --- /dev/null +++ b/rqjs-ext/src/modules/mod.rs @@ -0,0 +1,17 @@ +pub mod buffer; +pub mod bytearray_buffer; +pub mod crypto; +pub mod encoding; +pub mod events; +pub mod exceptions; +pub mod fs; +pub mod module; +pub mod os; +pub mod path; +pub mod timers; +pub mod util; +pub mod uuid; +pub mod xml; +pub mod console; + +pub(crate) mod macros; diff --git a/rqjs-ext/src/modules/module.rs b/rqjs-ext/src/modules/module.rs new file mode 100644 index 0000000..8ded14e --- /dev/null +++ b/rqjs-ext/src/modules/module.rs @@ -0,0 +1,19 @@ +use rquickjs::{module::Exports, Ctx, Object, Result, Value}; + +pub fn export_default<'js, F>(ctx: &Ctx<'js>, exports: &Exports<'js>, f: F) -> Result<()> +where + F: FnOnce(&Object<'js>) -> Result<()>, +{ + let default = Object::new(ctx.clone())?; + f(&default)?; + + for name in default.keys::() { + let name = name?; + let value: Value = default.get(&name)?; + exports.export(name, value)?; + } + + exports.export("default", default)?; + + Ok(()) +} diff --git a/rqjs-ext/src/modules/os.rs b/rqjs-ext/src/modules/os.rs new file mode 100644 index 0000000..4ba98d5 --- /dev/null +++ b/rqjs-ext/src/modules/os.rs @@ -0,0 +1,85 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +use std::env; + +use once_cell::sync::Lazy; +use rquickjs::{ + module::{Declarations, Exports, ModuleDef}, + prelude::Func, + Ctx, Result, +}; + +use crate::modules::module::export_default; + +pub fn get_platform() -> &'static str { + let platform = env::consts::OS; + match platform { + "macos" => "darwin", + "windows" => "win32", + _ => platform, + } +} + +static OS_INFO: Lazy<(String, String, String)> = Lazy::new(|| { + if let Ok(uts) = cross_uname::uname() { + return (uts.sysname, uts.release, uts.version); + } + ( + String::from("n/a"), + String::from("n/a"), + String::from("n/a"), + ) +}); + +fn get_type() -> &'static str { + &OS_INFO.0 +} + +fn get_release() -> &'static str { + &OS_INFO.1 +} + +fn get_version() -> &'static str { + &OS_INFO.2 +} + +fn get_tmp_dir() -> String { + env::temp_dir().to_string_lossy().to_string() +} + +pub struct OsModule; + +impl ModuleDef for OsModule { + fn declare(declare: &Declarations<'_>) -> Result<()> { + declare.declare("type")?; + declare.declare("release")?; + declare.declare("tmpdir")?; + declare.declare("platform")?; + declare.declare("version")?; + + declare.declare("default")?; + + Ok(()) + } + + fn evaluate<'js>(ctx: &Ctx<'js>, exports: &Exports<'js>) -> Result<()> { + export_default(ctx, exports, |default| { + default.set("type", Func::from(get_type))?; + default.set("release", Func::from(get_release))?; + default.set("tmpdir", Func::from(get_tmp_dir))?; + default.set("platform", Func::from(get_platform))?; + default.set("version", Func::from(get_version))?; + + Ok(()) + }) + } +} + +// impl From for ModuleInfo { +// fn from(val: OsModule) -> Self { +// ModuleInfo { +// name: "os", +// module: val, +// } +// } +// } diff --git a/rqjs-ext/src/modules/path.rs b/rqjs-ext/src/modules/path.rs new file mode 100644 index 0000000..11c7532 --- /dev/null +++ b/rqjs-ext/src/modules/path.rs @@ -0,0 +1,255 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +use std::{ + path::{Component, Path, PathBuf, MAIN_SEPARATOR, MAIN_SEPARATOR_STR}, + slice::Iter, +}; + +use rquickjs::{ + function::Opt, + module::{Declarations, Exports, ModuleDef}, + prelude::{Func, Rest}, + Ctx, Object, Result, +}; + +use crate::modules::module::export_default; + +pub struct PathModule; + +#[cfg(windows)] +const DELIMITER: char = ';'; +#[cfg(not(windows))] +const DELIMITER: char = ':'; + +#[cfg(windows)] +pub const CURRENT_DIR_STR: &str = ".\\"; +#[cfg(not(windows))] +pub const CURRENT_DIR_STR: &str = "./"; + +pub fn dirname(path: String) -> String { + if path == MAIN_SEPARATOR_STR { + return path; + } + let path = path.strip_suffix(MAIN_SEPARATOR).unwrap_or(&path); + match path.rfind(MAIN_SEPARATOR) { + Some(idx) => { + let parent = &path[..idx]; + if parent.is_empty() { + MAIN_SEPARATOR_STR + } else { + parent + } + } + None => ".", + } + .to_string() +} + +fn name_extname(path: &str) -> (&str, &str) { + let path = path.strip_suffix(MAIN_SEPARATOR).unwrap_or(path); + let path = match path.rfind(MAIN_SEPARATOR) { + Some(idx) => &path[idx + 1..], + None => path, + }; + if path.starts_with('.') { + return (path, ""); + } + match path.rfind('.') { + Some(idx) => path.split_at(idx), + None => (path, ""), + } +} + +fn basename(path: String, suffix: Opt) -> String { + if path == MAIN_SEPARATOR_STR { + return path; + } + if path.is_empty() { + return String::from("."); + } + let (base, ext) = name_extname(&path); + let name = format!("{}{}", base, ext); + if let Some(suffix) = suffix.0 { + name.strip_suffix(&suffix).unwrap_or(&name) + } else { + &name + } + .to_string() +} + +fn extname(path: String) -> String { + let (_, ext) = name_extname(&path); + ext.to_string() +} + +fn format(obj: Object) -> String { + let dir: String = obj.get("dir").unwrap_or_default(); + let root: String = obj.get("root").unwrap_or_default(); + let base: String = obj.get("base").unwrap_or_default(); + let name: String = obj.get("name").unwrap_or_default(); + let ext: String = obj.get("ext").unwrap_or_default(); + + let mut path = String::new(); + if !dir.is_empty() { + path.push_str(&dir); + if !dir.ends_with(MAIN_SEPARATOR) { + path.push(MAIN_SEPARATOR); + } + } else if !root.is_empty() { + path.push_str(&root); + if !root.ends_with(MAIN_SEPARATOR) { + path.push(MAIN_SEPARATOR); + } + } + if !base.is_empty() { + path.push_str(&base); + } else { + path.push_str(&name); + if !ext.is_empty() { + if !ext.starts_with('.') { + path.push('.'); + } + path.push_str(&ext); + } + } + path +} + +fn parse(ctx: Ctx, path_str: String) -> Result { + let obj = Object::new(ctx)?; + let path = Path::new(&path_str); + let parent = path + .parent() + .map(|p| p.to_str().unwrap()) + .unwrap_or_default(); + let filename = path + .file_name() + .map(|n| n.to_str().unwrap()) + .unwrap_or_default(); + + let (name, extension) = name_extname(filename); + + let root = path + .components() + .next() + .and_then(|c| match c { + Component::Prefix(prefix) => prefix.as_os_str().to_str(), + Component::RootDir => c.as_os_str().to_str(), + _ => Some(""), + }) + .unwrap_or_default(); + + obj.set("root", root)?; + obj.set("dir", parent)?; + obj.set("base", format!("{}{}", name, extension))?; + obj.set("ext", extension)?; + obj.set("name", name)?; + + Ok(obj) +} + +fn join(parts: Rest) -> String { + join_path(parts.0) +} + +pub fn join_path(parts: Vec) -> String { + let mut result = PathBuf::new(); + let mut empty = true; + for part in parts.iter() { + if part.starts_with(MAIN_SEPARATOR) && empty { + result.push(MAIN_SEPARATOR_STR); + empty = false; + } + for sub_part in part.split(MAIN_SEPARATOR) { + if !sub_part.is_empty() { + if sub_part.starts_with("..") { + empty = false; + result.pop(); + } else { + result.push(sub_part.strip_prefix('.').unwrap_or(sub_part)); + empty = false; + } + } + } + } + remove_trailing_slash(result) +} + +fn remove_trailing_slash(result: PathBuf) -> String { + let path = result.to_string_lossy().to_string(); + path.strip_suffix(MAIN_SEPARATOR) + .unwrap_or(&path) + .to_string() +} + +fn resolve(path: Rest) -> String { + resolve_path(path.iter()) +} + +pub fn resolve_path(iter: Iter<'_, String>) -> String { + let mut dir = std::env::current_dir().unwrap(); + for part in iter { + let p = part.strip_prefix(CURRENT_DIR_STR).unwrap_or(part); + if p.starts_with(MAIN_SEPARATOR) { + dir = PathBuf::from(p); + } else { + for sub_part in p.split(MAIN_SEPARATOR) { + if sub_part.starts_with("..") { + dir.pop(); + } else { + dir.push(sub_part.strip_prefix('.').unwrap_or(sub_part)) + } + } + } + } + + remove_trailing_slash(dir) +} + +fn normalize(path: String) -> String { + let path = PathBuf::from(path); + let parts = path + .components() + .map(|c| c.as_os_str().to_string_lossy().to_string()) + .collect::>(); + + join_path(parts) +} + +pub fn is_absolute(path: String) -> bool { + PathBuf::from(path).is_absolute() +} + +impl ModuleDef for PathModule { + fn declare(declare: &Declarations<'_>) -> Result<()> { + declare.declare("basename")?; + declare.declare("dirname")?; + declare.declare("extname")?; + declare.declare("format")?; + declare.declare("parse")?; + declare.declare("join")?; + declare.declare("resolve")?; + declare.declare("normalize")?; + declare.declare("isAbsolute")?; + declare.declare("delimiter")?; + + declare.declare("default")?; + Ok(()) + } + + fn evaluate<'js>(ctx: &Ctx<'js>, exports: &Exports<'js>) -> Result<()> { + export_default(ctx, exports, |default| { + default.set("dirname", Func::from(dirname))?; + default.set("basename", Func::from(basename))?; + default.set("extname", Func::from(extname))?; + default.set("format", Func::from(format))?; + default.set("parse", Func::from(parse))?; + default.set("join", Func::from(join))?; + default.set("resolve", Func::from(resolve))?; + default.set("normalize", Func::from(normalize))?; + default.set("isAbsolute", Func::from(is_absolute))?; + default.prop("delimiter", DELIMITER.to_string())?; + Ok(()) + }) + } +} diff --git a/rqjs-ext/src/modules/timers.rs b/rqjs-ext/src/modules/timers.rs new file mode 100644 index 0000000..a506233 --- /dev/null +++ b/rqjs-ext/src/modules/timers.rs @@ -0,0 +1,198 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +use std::{ + sync::{ + atomic::{AtomicBool, AtomicUsize, Ordering}, + Arc, Mutex, + }, + time::{SystemTime, UNIX_EPOCH}, +}; + +use rquickjs::{ + module::{Declarations, Exports, ModuleDef}, + Ctx, Function, Result, +}; + +use super::module::export_default; + +// use crate::{module_builder::ModuleInfo, modules::module::export_default, vm::CtxExtension}; + +static TIMER_ID: AtomicUsize = AtomicUsize::new(0); +static TIME_POLL_ACTIVE: AtomicBool = AtomicBool::new(false); + +#[derive(Debug)] +struct Timeout<'js> { + cb: Option>, + timeout: usize, + id: usize, + repeating: bool, + delay: usize, +} + +fn set_immediate(cb: Function) -> Result<()> { + cb.defer::<()>(())?; + Ok(()) +} + +fn get_current_time_millis() -> usize { + SystemTime::now() + .duration_since(UNIX_EPOCH) + .map(|t| t.as_millis() as usize) + .unwrap_or(0) +} + +fn set_timeout_interval<'js>( + ctx: &Ctx<'js>, + timeouts: &Arc>>>, + cb: Function<'js>, + delay: usize, + repeating: bool, +) -> Result { + let timeout = get_current_time_millis() + delay; + let id = TIMER_ID.fetch_add(1, Ordering::Relaxed); + timeouts.lock().unwrap().push(Timeout { + cb: Some(cb.clone()), + timeout, + id, + repeating, + delay, + }); + if !TIME_POLL_ACTIVE.load(Ordering::Relaxed) { + // poll_timers(ctx, timeouts.clone())? + } + + Ok(id) +} + +fn clear_timeout_interval(timeouts: &Arc>>, id: usize) { + let mut timeouts = timeouts.lock().unwrap(); + if let Some(timeout) = timeouts.iter_mut().find(|t| t.id == id) { + timeout.cb.take(); + timeout.timeout = 0; + timeout.repeating = false; + } +} + +pub struct TimersModule; + +impl ModuleDef for TimersModule { + fn declare(declare: &Declarations<'_>) -> Result<()> { + declare.declare("setTimeout")?; + declare.declare("clearTimeout")?; + declare.declare("setInterval")?; + declare.declare("clearInterval")?; + declare.declare("default")?; + Ok(()) + } + + fn evaluate<'js>(ctx: &Ctx<'js>, exports: &Exports<'js>) -> Result<()> { + let globals = ctx.globals(); + + export_default(ctx, exports, |default| { + let functions = ["setTimeout", "clearTimeout", "setInterval", "clearInterval"]; + for func_name in functions { + let function: Function = globals.get(func_name)?; + default.set(func_name, function)?; + } + Ok(()) + })?; + + Ok(()) + } +} + +// impl From for ModuleInfo { +// fn from(val: TimersModule) -> Self { +// ModuleInfo { +// name: "timers", +// module: val, +// } +// } +// } + +// pub fn init(ctx: &Ctx<'_>) -> Result<()> { +// let globals = ctx.globals(); + +// #[allow(clippy::arc_with_non_send_sync)] +// let timeouts = Arc::new(Mutex::new(Vec::::new())); +// let timeouts2 = timeouts.clone(); +// let timeouts3 = timeouts.clone(); +// let timeouts4 = timeouts.clone(); + +// globals.set( +// "setTimeout", +// Func::from(move |ctx, cb, delay| set_timeout_interval(&ctx, &timeouts, cb, delay, false)), +// )?; + +// globals.set( +// "setInterval", +// Func::from(move |ctx, cb, delay| set_timeout_interval(&ctx, &timeouts2, cb, delay, true)), +// )?; + +// globals.set( +// "clearTimeout", +// Func::from(move |id: usize| clear_timeout_interval(&timeouts3, id)), +// )?; + +// globals.set( +// "clearInterval", +// Func::from(move |id: usize| clear_timeout_interval(&timeouts4, id)), +// )?; + +// globals.set("setImmediate", Func::from(set_immediate))?; + +// Ok(()) +// } + +// #[inline(always)] +// fn poll_timers<'js>(ctx: &Ctx<'js>, timeouts: Arc>>>) -> Result<()> { +// TIME_POLL_ACTIVE.store(true, Ordering::Relaxed); + +// ctx.spawn_exit(async move { +// let mut interval = tokio::time::interval(Duration::from_millis(1)); +// let mut to_call = Some(Vec::new()); +// let mut exit_after_next_tick = false; +// loop { +// interval.tick().await; + +// let mut call_vec = to_call.take().unwrap(); //avoid creating a new vec +// let current_time = get_current_time_millis(); +// let mut had_items = false; + +// timeouts.lock().unwrap().retain_mut(|timeout| { +// had_items = true; +// exit_after_next_tick = false; +// if current_time > timeout.timeout { +// if !timeout.repeating { +// //do not clone if not not repeating +// call_vec.push(timeout.cb.take()); +// return false; +// } +// timeout.timeout = current_time + timeout.delay; +// call_vec.push(timeout.cb.clone()); +// } +// true +// }); + +// for cb in call_vec.iter_mut() { +// if let Some(cb) = cb.take() { +// cb.call::<(), ()>(())?; +// }; +// } + +// call_vec.clear(); +// to_call.replace(call_vec); + +// if !had_items { +// if exit_after_next_tick { +// break; +// } +// exit_after_next_tick = true; +// } +// } +// TIME_POLL_ACTIVE.store(false, Ordering::Relaxed); + +// Ok(()) +// })?; +// Ok(()) +// } diff --git a/rqjs-ext/src/modules/util.rs b/rqjs-ext/src/modules/util.rs new file mode 100644 index 0000000..707ba86 --- /dev/null +++ b/rqjs-ext/src/modules/util.rs @@ -0,0 +1,47 @@ +use rquickjs::{ + cstr, + module::{Declarations, Exports, ModuleDef}, + Ctx, Function, Result, +}; + +use super::module::export_default; + +// use crate::{module_builder::ModuleInfo, modules::module::export_default}; + +// use super::console::format_plain; + +pub struct UtilModule; + +impl ModuleDef for UtilModule { + fn declare(declare: &Declarations<'_>) -> Result<()> { + declare.declare(stringify!(TextDecoder))?; + declare.declare(stringify!(TextEncoder))?; + // declare.declare(stringify!(format))?; + declare.declare(cstr!("default").to_bytes())?; + Ok(()) + } + + fn evaluate<'js>(ctx: &Ctx<'js>, exports: &Exports<'js>) -> Result<()> { + export_default(ctx, exports, |default| { + let globals = ctx.globals(); + + let encoder: Function = globals.get(stringify!(TextEncoder))?; + let decoder: Function = globals.get(stringify!(TextDecoder))?; + + default.set(stringify!(TextEncoder), encoder)?; + default.set(stringify!(TextDecoder), decoder)?; + // default.set("format", Func::from(format_plain))?; + + Ok(()) + }) + } +} + +// impl From for ModuleInfo { +// fn from(val: UtilModule) -> Self { +// ModuleInfo { +// name: "util", +// module: val, +// } +// } +// } diff --git a/rqjs-ext/src/modules/uuid.rs b/rqjs-ext/src/modules/uuid.rs new file mode 100644 index 0000000..6864491 --- /dev/null +++ b/rqjs-ext/src/modules/uuid.rs @@ -0,0 +1,148 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +use once_cell::sync::Lazy; +use ring::rand::SecureRandom; +use rquickjs::{ + module::{Declarations, Exports, ModuleDef}, + prelude::{Func, Opt}, + Ctx, Function, Result, TypedArray, Value, +}; +use uuid::Uuid; +use uuid_simd::UuidExt; + +use crate::{ + // module_builder::ModuleInfo, + modules::{crypto::SYSTEM_RANDOM, encoding::encoder::bytes_to_hex, module::export_default}, + utils::{ + object::{get_bytes, get_bytes_offset_length}, + result::ResultExt, + }, +}; + +pub struct UuidModule; + +static ERROR_MESSAGE: &str = "Not a valid UUID"; + +static NODE_ID: Lazy<[u8; 6]> = Lazy::new(|| { + let mut bytes = [0; 6]; + SYSTEM_RANDOM.fill(&mut bytes).unwrap(); + bytes +}); + +fn from_value<'js>(ctx: &Ctx<'js>, value: Value<'js>) -> Result { + if value.is_string() { + Uuid::try_parse(&value.as_string().unwrap().to_string()?) + } else { + Uuid::from_slice(&get_bytes(ctx, value)?) + } + .or_throw_msg(ctx, ERROR_MESSAGE) +} + +fn uuidv1() -> String { + Uuid::now_v1(&NODE_ID).format_hyphenated().to_string() +} + +fn uuidv3<'js>(ctx: Ctx<'js>, name: String, namespace: Value<'js>) -> Result { + let uuid = Uuid::new_v3(&from_value(&ctx, namespace)?, name.as_bytes()) + .format_hyphenated() + .to_string(); + Ok(uuid) +} + +fn uuidv5<'js>(ctx: Ctx<'js>, name: String, namespace: Value<'js>) -> Result { + let uuid = Uuid::new_v5(&from_value(&ctx, namespace)?, name.as_bytes()) + .format_hyphenated() + .to_string(); + Ok(uuid) +} + +pub fn uuidv4() -> String { + Uuid::new_v4().format_hyphenated().to_string() +} + +fn parse(ctx: Ctx<'_>, value: String) -> Result> { + let uuid = Uuid::try_parse(&value).or_throw_msg(&ctx, ERROR_MESSAGE)?; + let bytes = uuid.as_bytes(); + TypedArray::::new(ctx, *bytes) +} + +fn stringify<'js>(ctx: Ctx<'js>, value: Value<'js>, offset: Opt) -> Result { + let value = get_bytes_offset_length( + &ctx, + value, + offset.0.map(|o| o.into()).unwrap_or_default(), + None, + )?; + let value = bytes_to_hex(&value); + + let uuid = Uuid::try_parse_ascii(&value) + .or_throw_msg(&ctx, ERROR_MESSAGE)? + .as_hyphenated() + .to_string(); + + Ok(uuid) +} + +fn validate(value: String) -> bool { + Uuid::parse_str(&value).is_ok() +} + +fn version(ctx: Ctx<'_>, value: String) -> Result { + let uuid = Uuid::parse_str(&value).or_throw_msg(&ctx, ERROR_MESSAGE)?; + Ok(uuid.get_version().map(|v| v as u8).unwrap_or(0)) +} + +impl ModuleDef for UuidModule { + fn declare(declare: &Declarations<'_>) -> Result<()> { + declare.declare("v1")?; + declare.declare("v3")?; + declare.declare("v4")?; + declare.declare("v5")?; + declare.declare("parse")?; + declare.declare("validate")?; + declare.declare("stringify")?; + declare.declare("version")?; + declare.declare("NIL")?; + declare.declare("default")?; + + Ok(()) + } + + fn evaluate<'js>(ctx: &Ctx<'js>, exports: &Exports<'js>) -> Result<()> { + export_default(ctx, exports, |default| { + let dns_namespace = Uuid::NAMESPACE_DNS.format_hyphenated().to_string(); + let url_namespace = Uuid::NAMESPACE_URL.format_hyphenated().to_string(); + + let v3_func = Function::new(ctx.clone(), uuidv3)?; + let v3_object = v3_func.as_object().unwrap(); + + let v5_func = Function::new(ctx.clone(), uuidv5)?; + let v5_object = v5_func.as_object().unwrap(); + + v3_object.set("DNS", dns_namespace.clone())?; + v3_object.set("URL", url_namespace.clone())?; + v5_object.set("DNS", dns_namespace)?; + v5_object.set("URL", url_namespace)?; + + default.set("v1", Func::from(uuidv1))?; + default.set("v3", v3_func)?; + default.set("v4", Func::from(uuidv4))?; + default.set("v5", v5_func)?; + default.set("NIL", "00000000-0000-0000-0000-000000000000")?; + default.set("parse", Func::from(parse))?; + default.set("stringify", Func::from(stringify))?; + default.set("validate", Func::from(validate))?; + default.set("version", Func::from(version))?; + Ok(()) + }) + } +} + +// impl From for ModuleInfo { +// fn from(val: UuidModule) -> Self { +// ModuleInfo { +// name: "uuid", +// module: val, +// } +// } +// } diff --git a/rqjs-ext/src/modules/xml.rs b/rqjs-ext/src/modules/xml.rs new file mode 100644 index 0000000..2901dfe --- /dev/null +++ b/rqjs-ext/src/modules/xml.rs @@ -0,0 +1,569 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +use std::collections::HashMap; + +use quick_xml::{ + events::{BytesStart, Event}, + Reader, +}; + +use rquickjs::{ + class::{Trace, Tracer}, + function::Opt, + module::{Declarations, Exports, ModuleDef}, + object::Property, + prelude::This, + Array, Class, Ctx, Error, Function, IntoJs, Object, Result, Value, +}; + +const AMP: &str = "&"; +const LT: &str = "<"; +const GT: &str = ">"; +const QUOT: &str = """; +const APOS: &str = "'"; +const CR: &str = " "; +const LF: &str = " "; +const NEL: &str = "…"; +const LS: &str = "
"; + +use crate::{ + // module_builder::ModuleInfo, + modules::module::export_default, + utils::{ + object::{get_bytes, ObjectExt}, + result::ResultExt, + string::JoinToString, + }, +}; + +#[rquickjs::class] +struct XMLParser<'js> { + tag_value_processor: Option>, + attribute_value_processor: Option>, + attribute_name_prefix: String, + ignore_attributes: bool, + text_node_name: String, + entities: HashMap, +} + +impl<'js> Trace<'js> for XMLParser<'js> { + fn trace<'a>(&self, tracer: Tracer<'a, 'js>) { + if let Some(tag_value_processor) = &self.tag_value_processor { + tracer.mark(tag_value_processor) + } + if let Some(attribute_value_processor) = &self.attribute_value_processor { + tracer.mark(attribute_value_processor) + } + } +} + +struct StackObject<'js> { + obj: Object<'js>, + has_value: bool, +} +impl<'js> StackObject<'js> { + fn new(ctx: Ctx<'js>) -> Result { + Ok(Self { + obj: Object::new(ctx)?, + has_value: false, + }) + } + + fn into_value(self, ctx: &Ctx<'js>) -> Result> { + if self.has_value { + return Ok(self.obj.into_value()); + } + "".into_js(ctx) + } +} + +#[rquickjs::methods(rename_all = "camelCase")] +impl<'js> XMLParser<'js> { + #[qjs(constructor)] + pub fn new(_ctx: Ctx<'js>, options: Opt>) -> Result { + let mut tag_value_processor = None; + let mut attribute_value_processor = None; + let mut attribute_name_prefix = String::from("@_"); + let mut ignore_attributes = true; + let mut text_node_name = String::from("#text"); + if let Some(options) = options.0 { + tag_value_processor = options.get_optional("tagValueProcessor")?; + attribute_value_processor = options.get_optional("attributeValueProcessor")?; + if let Some(prefix) = options.get_optional("attributeNamePrefix")? { + attribute_name_prefix = prefix; + } + if let Some(attributes_ignored) = options.get_optional("ignoreAttributes")? { + ignore_attributes = attributes_ignored + } + if let Some(name) = options.get_optional("textNodeName")? { + text_node_name = name + } + } + + Ok(XMLParser { + tag_value_processor, + attribute_value_processor, + entities: HashMap::new(), + attribute_name_prefix, + ignore_attributes, + text_node_name, + }) + } + + pub fn add_entity(&mut self, key: String, value: String) { + self.entities.insert(key, value); + } + + pub fn parse(&self, ctx: Ctx<'js>, xml: Value<'js>) -> Result> { + let bytes = get_bytes(&ctx, xml)?; + let mut reader = Reader::from_reader(bytes.as_ref()); + reader.config_mut().trim_text(true); + + let mut current_obj = StackObject::new(ctx.clone())?; + current_obj.has_value = true; + let mut buf = Vec::new(); + let mut current_key = String::new(); + let mut current_value: Option = None; + let mut path: Vec<(String, StackObject<'js>)> = vec![]; + let mut has_attributes = false; + + loop { + buf.clear(); + + match reader.read_event_into(&mut buf) { + Ok(Event::Empty(ref tag)) => { + current_key = Self::get_tag_name(&ctx, &reader, tag)?; + + let mut obj = StackObject::new(ctx.clone())?; + self.process_attributes(&ctx, &reader, &path, tag, &mut obj, &mut false)?; + current_obj.has_value = true; + + Self::process_end(&ctx, ¤t_obj, obj.into_value(&ctx)?, ¤t_key)?; + } + Ok(Event::Start(ref tag)) => { + has_attributes = false; + current_key = Self::get_tag_name(&ctx, &reader, tag)?; + path.push((current_key.clone(), current_obj)); + + let obj = StackObject::new(ctx.clone())?; + current_obj = obj; + + self.process_attributes( + &ctx, + &reader, + &path, + tag, + &mut current_obj, + &mut has_attributes, + )?; + } + Ok(Event::End(_)) => { + let (parent_tag, mut parent_obj) = path.pop().unwrap(); + parent_obj.has_value = true; + let value = if let Some(value) = current_value.take() { + value.into_js(&ctx)? + } else { + current_obj.into_value(&ctx)? + }; + + current_obj = parent_obj; + + Self::process_end(&ctx, ¤t_obj, value, &parent_tag)?; + } + Ok(Event::CData(text)) => { + let text = text.escape().or_throw(&ctx)?; + let tag_value = String::from_utf8_lossy(text.as_ref()).to_string(); + let tag_value = + self.process_tag_value(&path, ¤t_key, tag_value, has_attributes)?; + if has_attributes { + current_obj.has_value = true; + current_obj.obj.set(&self.text_node_name, tag_value)?; + } else { + current_value = Some(tag_value) + } + } + Ok(Event::Text(ref text)) => { + let tag_value = text + .unescape_with(|v| self.entities.get(v).map(|x| x.as_str())) + .or_throw(&ctx)? + .to_string(); + let tag_value = + self.process_tag_value(&path, ¤t_key, tag_value, has_attributes)?; + + if has_attributes { + current_obj.has_value = true; + current_obj.obj.set(&self.text_node_name, tag_value)?; + } else { + current_value = Some(tag_value) + } + } + Err(e) => panic!("Error at position {}: {:?}", reader.buffer_position(), e), + Ok(Event::Eof) => break, + _ => {} + } + } + Ok(current_obj.obj) + } +} + +impl<'js> XMLParser<'js> { + fn get_tag_name( + ctx: &Ctx<'js>, + reader: &Reader<&[u8]>, + tag: &BytesStart<'_>, + ) -> Result { + let tag = tag.name(); + let tag_name = reader.decoder().decode(tag.as_ref()).or_throw(ctx)?; + + Ok(tag_name.to_string()) + } + + fn process_end( + ctx: &Ctx<'js>, + current_obj: &StackObject<'js>, + value: Value<'js>, + tag: &str, + ) -> Result<()> { + if current_obj.obj.contains_key(tag)? { + let parent_value: Value = current_obj.obj.get(tag)?; + if !parent_value.is_array() { + let array = Array::new(ctx.clone())?; + array.set(0, parent_value)?; + array.set(1, value)?; + current_obj.obj.set(tag, array.as_value())?; + } else { + let array = parent_value.as_array().or_throw(ctx)?; + array.set(array.len(), value)?; + current_obj.obj.set(tag, array.as_value())?; + } + } else { + current_obj.obj.prop( + tag, + Property::from(value).configurable().enumerable().writable(), + )?; + } + Ok(()) + } + + fn process_attributes( + &self, + ctx: &Ctx<'js>, + reader: &Reader<&[u8]>, + path: &[(String, StackObject<'js>)], + tag: &BytesStart<'_>, + stack_object: &mut StackObject<'js>, + has_attributes: &mut bool, + ) -> Result<()> { + if !self.ignore_attributes { + for attribute in tag.attributes() { + stack_object.has_value = true; + *has_attributes = true; + let attr = attribute.or_throw(ctx)?; + + let key_slice = attr.key.as_ref(); + let key = if !self.attribute_name_prefix.is_empty() { + let prefix_bytes = self.attribute_name_prefix.as_bytes(); + let mut key_bytes = Vec::with_capacity(prefix_bytes.len() + key_slice.len()); + key_bytes.extend_from_slice(prefix_bytes); + key_bytes.extend_from_slice(key_slice); + + reader + .decoder() + .decode(&key_bytes) + .or_throw(ctx)? + .to_string() + } else { + reader + .decoder() + .decode(key_slice) + .or_throw(ctx)? + .to_string() + }; + + let mut value = reader + .decoder() + .decode(attr.value.as_ref()) + .or_throw(ctx)? + .to_string(); + + if let Some(attribute_value_processor) = &self.attribute_value_processor { + let jpath: String = path.iter().join_to_string(".", |(k, _)| k); + if let Some(new_value) = + attribute_value_processor.call((key.clone(), value.clone(), jpath))? + { + value = new_value + } + } + stack_object.obj.set(key, value)?; + } + } + Ok(()) + } + + fn process_tag_value( + &self, + path: &[(String, StackObject<'js>)], + key: &String, + value: String, + has_attributes: bool, + ) -> Result { + if value.is_empty() { + return Ok(value); + } + + if let Some(tag_value_processor) = &self.tag_value_processor { + let jpath: String = path.iter().join_to_string(".", |(k, _)| k); + if let Some(new_value) = + tag_value_processor.call((key, value.clone(), jpath, has_attributes))? + { + return Ok(new_value); + } + } + Ok::<_, Error>(value) + } +} + +#[derive(Debug, Clone)] +#[rquickjs::class] +struct XmlText { + value: String, +} + +impl<'js> Trace<'js> for XmlText { + fn trace<'a>(&self, _tracer: Tracer<'a, 'js>) {} +} + +#[rquickjs::methods(rename_all = "camelCase")] +impl XmlText { + #[qjs(constructor)] + fn new(value: String) -> Self { + let mut escaped = String::with_capacity(value.len()); + escape_element(&mut escaped, &value); + XmlText { value: escaped } + } + + fn to_string(&self) -> String { + self.value.clone() + } +} + +#[derive(Debug, Clone)] +#[rquickjs::class] +#[derive(rquickjs::class::Trace)] +struct XmlNode<'js> { + #[qjs(skip_trace)] + name: String, + //child and attributes are always set to avoid branch checks when adding/removing values + children: Vec>, + #[qjs(skip_trace)] + //vec iteration is faster since we rarely have more than 10 attrs and we want to retain insertion order + attributes: Vec<(String, String)>, +} + +enum NodeStackEntry<'js> { + Node(Class<'js, XmlNode<'js>>), + End(String), +} + +#[rquickjs::methods(rename_all = "camelCase")] +impl<'js> XmlNode<'js> { + #[qjs(constructor)] + fn new(name: String, children: Opt>>) -> Result { + let node = XmlNode { + name, + attributes: Vec::new(), + children: children.0.unwrap_or_default(), + }; + + Ok(node) + } + + #[qjs(static)] + fn of( + ctx: Ctx<'js>, + name: String, + child_text: Opt, + with_name: Opt, + ) -> Result> { + let mut node = XmlNode { + name, + children: Vec::new(), + attributes: Vec::new(), + }; + + if let Some(text) = child_text.0 { + let xml_text = Class::instance(ctx.clone(), XmlText::new(text))?; + node.children.push(xml_text.into_value()); + } + + if let Some(new_name) = with_name.0 { + node.name = new_name; + } + + node.into_js(&ctx) + } + + fn with_name(this: This>, name: String) -> Class<'js, Self> { + this.borrow_mut().name = name; + this.0 + } + + fn add_attribute( + this: This>, + name: String, + value: String, + ) -> Class<'js, Self> { + let this2 = this.clone(); + let mut borrow = this2.borrow_mut(); + if let Some(pos) = borrow.attributes.iter().position(|(a, _)| a == &name) { + borrow.attributes[pos] = (name, value); + } else { + borrow.attributes.push((name, value)); + } + this.0 + } + + fn add_child_node(this: This>, value: Value<'js>) -> Result> { + let this2 = this.clone(); + this2.borrow_mut().children.push(value); + Ok(this.0) + } + + fn remove_attribute(this: This>, name: String) -> Class<'js, Self> { + let this2 = this.clone(); + let mut borrow = this2.borrow_mut(); + if let Some(pos) = borrow.attributes.iter().position(|(a, _)| a == &name) { + borrow.attributes.remove(pos); + } + this.0 + } + + fn to_string(this: This>, ctx: Ctx<'js>) -> Result { + let class = this.0; + let mut xml_text = String::with_capacity(8); + + let mut stack = vec![NodeStackEntry::Node(class)]; + + while let Some(node) = stack.pop() { + match node { + NodeStackEntry::Node(node) => { + let borrow = node.borrow(); + xml_text.push('<'); + xml_text.push_str(&borrow.name); + + for (attribute_name, attribute) in &borrow.attributes { + xml_text.push(' '); + xml_text.push_str(attribute_name); + xml_text.push_str("=\""); + escape_attribute(&mut xml_text, attribute); + xml_text.push('"'); + } + + let has_children = !borrow.children.is_empty(); + if has_children { + stack.push(NodeStackEntry::End(borrow.name.clone())); + xml_text.push('>'); + + // Add children to the stack in reverse order (to maintain original order) + for child in borrow.children.iter().rev() { + if let Some(obj) = child.as_object() { + if let Some(node) = Class::::from_object(&obj.clone()) { + stack.push(NodeStackEntry::Node(node)) + } else if let Some(text) = + Class::::from_object(&obj.clone()) + { + xml_text.push_str(&text.borrow().value); + } else { + let to_string_fn = obj.get::<_, Function>("toString")?; + let string_value: String = to_string_fn.call(())?; + xml_text.push_str(&string_value); + } + } else { + let string_value: String = child + .clone() + .try_into_string() + .map_err(|err| format!("Unable to convert {:?} to string", err)) + .or_throw(&ctx)? + .to_string()?; + xml_text.push_str(&string_value); + } + } + } else { + xml_text.push_str("/>"); + } + drop(borrow); + } + NodeStackEntry::End(name) => { + xml_text.push_str("'); + } + } + } + + Ok(xml_text) + } +} + +fn escape_attribute(text: &mut String, value: &str) { + for c in value.chars() { + match c { + '&' => text.push_str(AMP), + '<' => text.push_str(LT), + '>' => text.push_str(GT), + '"' => text.push_str(QUOT), + _ => text.push(c), + } + } +} + +fn escape_element(text: &mut String, value: &str) { + for c in value.chars() { + match c { + '&' => text.push_str(AMP), + '<' => text.push_str(LT), + '>' => text.push_str(GT), + '\'' => text.push_str(APOS), + '"' => text.push_str(QUOT), + '\r' => text.push_str(CR), + '\n' => text.push_str(LF), + '\u{0085}' => text.push_str(NEL), + '\u{2028}' => text.push_str(LS), + _ => text.push(c), + } + } +} + +pub struct XmlModule; + +impl ModuleDef for XmlModule { + fn declare(declare: &Declarations<'_>) -> Result<()> { + declare.declare(stringify!(XMLParser))?; + declare.declare(stringify!(XmlText))?; + declare.declare(stringify!(XmlNode))?; + + declare.declare("default")?; + + Ok(()) + } + + fn evaluate<'js>(ctx: &Ctx<'js>, exports: &Exports<'js>) -> Result<()> { + export_default(ctx, exports, |default| { + Class::::define(default)?; + Class::::define(default)?; + Class::::define(default)?; + Ok(()) + })?; + + Ok(()) + } +} + +// impl From for ModuleInfo { +// fn from(val: XmlModule) -> Self { +// ModuleInfo { +// name: "xml", +// module: val, +// } +// } +// } diff --git a/rqjs-ext/src/number.rs b/rqjs-ext/src/number.rs new file mode 100644 index 0000000..ebb670b --- /dev/null +++ b/rqjs-ext/src/number.rs @@ -0,0 +1,315 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +use rquickjs::{ + function::{Opt, This}, + Ctx, Exception, Result, Value, +}; +use std::result::Result as StdResult; + +const DIGITS: &[u8] = b"0123456789abcdefghijklmnopqrstuvwxyz"; +const BUF_SIZE: usize = 80; +const BIN_MAX_DIGITS: usize = 64; +const OCT_MAX_DIGITS: usize = 21; + +#[inline(always)] +pub fn to_dec(number: i64) -> String { + itoa::Buffer::new().format(number).into() +} + +#[inline(always)] +pub fn to_base_less_than_10(buf: &mut [u8], num: i64, base: i64) -> String { + let max = buf.len(); + + if num == 0 { + return "0".into(); + } + let mut index = max; + let mut n = num; + + let mut string = String::with_capacity(max + 1); + + if n < 0 { + n = !n + 1; + string.push('-'); + } + + while n > 0 { + index -= 1; + buf[index] = (n % base) as u8 + b'0'; + n /= base; + } + + string.push_str(unsafe { std::str::from_utf8_unchecked(&buf[index..max]) }); + string +} + +pub fn i64_to_base_n(number: i64, radix: u8) -> String { + match radix { + 10 => { + return to_dec(number); + } + 2 => { + let mut buf = [0u8; BIN_MAX_DIGITS]; + return to_base_less_than_10(&mut buf, number, 2); + } + 8 => { + let mut buf = [0u8; OCT_MAX_DIGITS]; + return to_base_less_than_10(&mut buf, number, 8); + } + _ => {} + } + + let mut abs_number = number; + + let mut buf = [0u8; BUF_SIZE]; + let mut string = String::with_capacity(BUF_SIZE); + if number < 0 { + abs_number = -number; + string.push('-'); + } + + let index = internal_i64_to_base_n(&mut buf, abs_number, radix); + + string.push_str(unsafe { std::str::from_utf8_unchecked(&buf[index..BUF_SIZE]) }); + string +} + +#[inline(always)] +fn internal_i64_to_base_n(buf: &mut [u8], number: i64, radix: u8) -> usize { + let mut n = number; + let mut index = BUF_SIZE; + + while n > 0 { + index -= 1; + let digit = n % radix as i64; + buf[index] = DIGITS[digit as usize]; + n /= radix as i64; + } + + index +} + +#[inline(always)] +fn next_up(num: f64) -> f64 { + const TINY_BITS: u64 = 0x1; + const CLEAR_SIGN_MASK: u64 = 0x7fff_ffff_ffff_ffff; + + let bits = num.to_bits(); + if num.is_nan() || bits == f64::INFINITY.to_bits() { + return num; + } + + let abs = bits & CLEAR_SIGN_MASK; + let next_bits = if abs == 0 { + TINY_BITS + } else if bits == abs { + bits + 1 + } else { + bits - 1 + }; + f64::from_bits(next_bits) +} + +#[inline(always)] +fn fractional_to_base(buf: &mut [u8], mut index: usize, mut number: f64, radix: u8) -> usize { + let mut is_odd = number <= 0x1fffffffffffffi64 as f64 && (number as i64) & 1 != 0; + let mut digit; + + //let mut needs_rounding_up = false; + + let next_number = next_up(number); + let mut delta_next_double = next_number - number; + + loop { + let ntmp = number * radix as f64; + let rtmp = delta_next_double * radix as f64; + digit = ntmp as usize; + let ritmp = rtmp as usize; + + if digit & 1 != 0 { + is_odd = !is_odd; + } + + number = ntmp - digit as f64; + delta_next_double = rtmp - ritmp as f64; + + if number > 0.5f64 || number == 0.5f64 && if radix & 1 > 0 { is_odd } else { digit & 1 > 0 } + { + if number + delta_next_double > 1.0 { + //TODO impl round up + break; + } + } else if number < delta_next_double * 2.0 { + break; + } + buf[index] = DIGITS[digit]; + + index += 1; + } + + // let last_index = index; + // while number > 0.0 { + // let tmp = number * radix as f64; + // let itmp = tmp as usize; + // buf[index] = DIGITS[itmp]; + // number = tmp - itmp as f64; + // index += 1; + // if index - last_index > BUF_SIZE - last_index - 1 { + // break; + // } + // } + index +} + +#[inline(always)] +fn f64_to_base_n(number: f64, radix: u8) -> String { + let mut abs_num = number; + let mut string = String::with_capacity(BUF_SIZE); + let mut buf = [0u8; BUF_SIZE]; + + if number < 0.0 { + abs_num = -number; + string.push('-'); + } + + let integer_part = abs_num.trunc(); + let fractional_part = abs_num - integer_part; + let integer_part = abs_num as i64; + + let mut index = internal_i64_to_base_n(&mut buf, integer_part, radix); + string.push_str(unsafe { std::str::from_utf8_unchecked(&buf[index..BUF_SIZE]) }); + + index = BUF_SIZE - index; + + let dot_index = index; + index = fractional_to_base(&mut buf, index + 1, fractional_part, radix); + if index - 1 > dot_index { + buf[dot_index] = b'.'; + } + + string.push_str(unsafe { std::str::from_utf8_unchecked(&buf[..index]) }); + string +} + +pub fn float_to_string(buffer: &mut ryu::Buffer, float: f64) -> &str { + let str = match float_to_str(buffer, float) { + Ok(value) => value, + Err(value) => return value, + }; + let len = str.len(); + if unsafe { str.get_unchecked(len - 2..) } == ".0" { + return unsafe { std::str::from_utf8_unchecked(&str.as_bytes()[..len - 2]) }; + } + str +} + +/// Returns a string representation of the float value. +/// +/// Returns error with a `str` if value is non-finite +#[inline(always)] +pub fn float_to_str(buf: &mut ryu::Buffer, float: f64) -> StdResult<&str, &str> { + const EXP_MASK: u64 = 0x7ff0000000000000; + let bits = float.to_bits(); + if bits & EXP_MASK == EXP_MASK { + return Err(get_nonfinite(bits)); + } + + let str = buf.format_finite(float); + Ok(str) +} + +#[inline(always)] +#[cold] +fn get_nonfinite<'a>(bits: u64) -> &'a str { + const MANTISSA_MASK: u64 = 0x000fffffffffffff; + const SIGN_MASK: u64 = 0x8000000000000000; + if bits & MANTISSA_MASK != 0 { + "NaN" + } else if bits & SIGN_MASK != 0 { + "-Infinity" + } else { + "Infinity" + } +} + +#[inline(always)] +#[cold] +fn check_radix(ctx: &Ctx, radix: u8) -> Result<()> { + if !(2..=36).contains(&radix) { + return Err(Exception::throw_type(ctx, "radix must be between 2 and 36")); + } + Ok(()) +} + +pub fn number_to_string(ctx: Ctx, this: This, radix: Opt) -> Result { + if let Some(int) = this.as_int() { + if let Some(radix) = radix.0 { + check_radix(&ctx, radix)?; + return Ok(i64_to_base_n(int as i64, radix)); + } + let mut buffer = itoa::Buffer::new(); + return Ok(buffer.format(int).into()); + } + if let Some(float) = this.as_float() { + if let Some(radix) = radix.0 { + check_radix(&ctx, radix)?; + return Ok(f64_to_base_n(float, radix)); + } + + let mut buffer = ryu::Buffer::new(); + return Ok(float_to_string(&mut buffer, float).into()); + } + Ok("".into()) +} + +#[cfg(test)] +mod test { + use rand::{thread_rng, Rng}; + + use crate::number::{float_to_string, i64_to_base_n}; + + #[test] + fn test_base_conversions() { + let mut rng = thread_rng(); + + for _ in 0..1_000_000 { + // Generate random i64 and radix values + let num: i64 = rng.gen_range(i64::MIN + 1..i64::MAX - 1); + + let minus_str = if num < 0 { "-" } else { "" }; + + //test bin + let expected_bin = format!("{}{:b}", minus_str, num.abs()); + let actual_bin = i64_to_base_n(num, 2); + assert_eq!(expected_bin, actual_bin); + + //test octal + let expected_octal = format!("{}{:o}", minus_str, num.abs()); + let actual_octal = i64_to_base_n(num, 8); + assert_eq!(expected_octal, actual_octal); + + //test hex + let expected_hex = format!("{}{:x}", minus_str, num.abs()); + let actual_hex = i64_to_base_n(num, 16); + assert_eq!(expected_hex, actual_hex); + } + + // Test i64_to_base_n + let base_36 = i64_to_base_n(123456789, 36); + assert_eq!("21i3v9", base_36); + + let base_36 = i64_to_base_n(-123456789, 36); + assert_eq!("-21i3v9", base_36); + + let mut buf = ryu::Buffer::new(); + + let float = float_to_string(&mut buf, 123.456); + assert_eq!("123.456", float); + + let float = float_to_string(&mut buf, 123.); + assert_eq!("123", float); + + let float = float_to_string(&mut buf, 0.0); + assert_eq!("0", float); + } +} diff --git a/rqjs-ext/src/stream/mod.rs b/rqjs-ext/src/stream/mod.rs new file mode 100644 index 0000000..e49e30e --- /dev/null +++ b/rqjs-ext/src/stream/mod.rs @@ -0,0 +1,46 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +use rquickjs::{prelude::This, Class, Ctx, IntoJs, Result, Value}; +use std::result::Result as StdResult; +use tokio::sync::broadcast::error::RecvError; + +use crate::modules::events::Emitter; + +use self::{readable::DefaultReadableStream, writable::DefaultWritableStream}; + +pub mod readable; +pub mod writable; + +pub fn set_destroyed_and_error<'js>( + is_destroyed: &mut bool, + error_value: &mut Option>, + error: StdResult>, RecvError>, +) { + *is_destroyed = true; + if let Ok(error) = error { + *error_value = error + } +} +const DEFAULT_BUFFER_SIZE: usize = 1024 * 16; + +pub trait SteamEvents<'js> +where + Self: Emitter<'js>, +{ + fn emit_close(this: Class<'js, Self>, ctx: &Ctx<'js>, had_error: bool) -> Result<()> { + Self::emit_str( + This(this), + ctx, + "close", + vec![had_error.into_js(ctx)?], + false, + ) + } + + #[allow(dead_code)] + fn emit_end(this: Class<'js, Self>, ctx: &Ctx<'js>) -> Result<()> { + Self::emit_str(This(this), ctx, "end", vec![], false) + } +} + +impl_stream_events!(DefaultReadableStream, DefaultWritableStream); diff --git a/rqjs-ext/src/stream/readable.rs b/rqjs-ext/src/stream/readable.rs new file mode 100644 index 0000000..10e6873 --- /dev/null +++ b/rqjs-ext/src/stream/readable.rs @@ -0,0 +1,380 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +use std::sync::{atomic::AtomicUsize, Arc, RwLock}; + +use rquickjs::{ + class::{Trace, Tracer}, + prelude::{Func, Opt, This}, + Class, Ctx, IntoJs, Null, Result, Value, +}; + +use tokio::{ + io::{AsyncRead, AsyncReadExt}, + sync::{ + broadcast::{self, Sender}, + oneshot::Receiver, + }, +}; + +use crate::{ + bytearray_buffer::BytearrayBuffer, + modules::{ + buffer::Buffer, + events::{Emitter, EventEmitter, EventKey, EventList}, + }, + utils::result::ResultExt, + // vm::CtxExtension, +}; + +use super::{SteamEvents, DEFAULT_BUFFER_SIZE}; + +#[derive(PartialEq, Clone, Debug)] +pub enum ReadableState { + Init, + Flowing, + Paused, +} + +#[allow(dead_code)] +pub struct ReadableStreamInner<'js> { + emitter: EventEmitter<'js>, + destroy_tx: Sender>>, + is_ended: bool, + is_destroyed: bool, + errored: bool, + buffer: BytearrayBuffer, + emit_close: bool, + state: ReadableState, + high_water_mark: AtomicUsize, + listener: Option<&'static str>, + data_listener_attached_tx: Sender<()>, +} + +impl<'js> Trace<'js> for ReadableStreamInner<'js> { + fn trace<'a>(&self, tracer: Tracer<'a, 'js>) { + self.emitter.trace(tracer); + } +} + +impl<'js> ReadableStreamInner<'js> { + pub fn on_event_changed(&mut self, event: EventKey<'js>, added: bool) -> Result<()> { + if let EventKey::String(event) = event { + let event = event.as_str(); + match event { + "data" => { + if added { + if self.state == ReadableState::Paused { + let _ = self.data_listener_attached_tx.send(()); + } + self.state = ReadableState::Flowing; + self.listener = Some("data"); + } else { + self.listener = None; + } + } + "readable" => { + if added { + self.state = ReadableState::Paused; + self.listener = Some("readable"); + } else { + self.listener = None; + } + } + _ => {} + } + } + Ok(()) + } + + pub fn new(emitter: EventEmitter<'js>, emit_close: bool) -> Self { + let (destroy_tx, _) = broadcast::channel::>>(1); + let (listener_attached_tx, _) = broadcast::channel::<()>(1); + Self { + emitter, + destroy_tx, + is_ended: false, + data_listener_attached_tx: listener_attached_tx, + buffer: BytearrayBuffer::new(DEFAULT_BUFFER_SIZE), + state: ReadableState::Init, + high_water_mark: DEFAULT_BUFFER_SIZE.into(), + listener: None, + is_destroyed: false, + emit_close, + errored: false, + } + } +} + +#[rquickjs::class] +#[derive(rquickjs::class::Trace)] +pub struct DefaultReadableStream<'js> { + inner: ReadableStreamInner<'js>, +} + +impl<'js> DefaultReadableStream<'js> { + fn with_emitter(ctx: Ctx<'js>, emitter: EventEmitter<'js>) -> Result> { + Class::instance( + ctx, + Self { + inner: ReadableStreamInner::new(emitter, true), + }, + ) + } + + pub fn new(ctx: Ctx<'js>) -> Result> { + Self::with_emitter(ctx, EventEmitter::new()) + } +} + +impl<'js> Emitter<'js> for DefaultReadableStream<'js> { + fn get_event_list(&self) -> Arc>> { + self.inner.emitter.get_event_list() + } + + fn on_event_changed(&mut self, event: EventKey<'js>, added: bool) -> Result<()> { + self.inner.on_event_changed(event, added) + } +} +impl<'js> ReadableStream<'js> for DefaultReadableStream<'js> { + fn inner_mut(&mut self) -> &mut ReadableStreamInner<'js> { + &mut self.inner + } + + fn inner(&self) -> &ReadableStreamInner<'js> { + &self.inner + } +} + +pub trait ReadableStream<'js> +where + Self: Emitter<'js> + SteamEvents<'js>, +{ + fn inner_mut(&mut self) -> &mut ReadableStreamInner<'js>; + + fn inner(&self) -> &ReadableStreamInner<'js>; + + fn add_readable_stream_prototype(ctx: &Ctx<'js>) -> Result<()> { + let proto = Class::::prototype(ctx.clone()) + .or_throw_msg(ctx, &format!("Prototype for {} not found", Self::NAME))?; + + proto.set("read", Func::from(Self::read))?; + + proto.set("destroy", Func::from(Self::destroy))?; + + Ok(()) + } + + fn destroy( + this: This>, + _ctx: Ctx<'js>, + error: Opt>, + ) -> Class<'js, Self> { + let mut borrow = this.borrow_mut(); + let inner = borrow.inner_mut(); + inner.is_destroyed = true; + let _ = inner.destroy_tx.send(error.0); + drop(borrow); + this.0 + } + + fn read(this: This>, ctx: Ctx<'js>, size: Opt) -> Result> { + if let Some(data) = this.borrow().inner().buffer.read(size.0) { + return Buffer(data).into_js(&ctx); + } + + Ok(Null.into_value(ctx)) + } + + fn drain(this: Class<'js, Self>, ctx: &Ctx<'js>) -> Result<()> { + let this2 = this.clone(); + let borrow = this2.borrow(); + let inner = borrow.inner(); + let listener = inner.listener; + + if let Some(listener) = listener { + let ba_buffer = inner.buffer.clone(); + if ba_buffer.len() > 0 { + drop(borrow); + let args = match listener { + "data" => { + let buffer = ba_buffer.read(None).unwrap_or_default(); + if buffer.is_empty() { + return Ok(()); + } + vec![Buffer(buffer).into_js(ctx)?] + } + "readable" => { + vec![] + } + _ => { + vec![] + } + }; + Self::emit_str(This(this), ctx, listener, args, false)?; + } + } + Ok(()) + } + + fn process( + this: Class<'js, Self>, + ctx: &Ctx<'js>, + readable: T, + ) -> Result> { + Self::do_process(this, ctx, readable, || {}) + } + + fn process_callback( + this: Class<'js, Self>, + ctx: &Ctx<'js>, + readable: T, + on_end: C, + ) -> Result> { + Self::do_process(this, ctx, readable, on_end) + } + + fn do_process( + this: Class<'js, Self>, + ctx: &Ctx<'js>, + readable: T, + on_end: C, + ) -> Result> { + let ctx2 = ctx.clone(); + todo!() + // ctx.spawn_exit(async move { + // let this2 = this.clone(); + // let ctx3 = ctx2.clone(); + + // let borrow = this2.borrow(); + // let inner = borrow.inner(); + // let mut destroy_rx = inner.destroy_tx.subscribe(); + // let is_ended = inner.is_ended; + // let mut is_destroyed = inner.is_destroyed; + // let emit_close = inner.emit_close; + + // let mut listener_attached_tx = inner.data_listener_attached_tx.subscribe(); + // let ba_buffer = inner.buffer.clone(); + // let mut has_data = false; + // drop(borrow); + + // let read_function = async move { + // let mut reader: BufReader = BufReader::new(readable); + // let mut buffer = Vec::::with_capacity(DEFAULT_BUFFER_SIZE); + // let mut last_state = ReadableState::Init; + // let mut error_value = None; + + // if !is_ended && !is_destroyed { + // loop { + // tokio::select! { + // result = reader.read_buf(&mut buffer) => { + // let bytes_read = result.or_throw(&ctx3)?; + + // let mut state = this2.borrow().inner().state.clone(); + // if !has_data && state == ReadableState::Init { + // this2.borrow_mut().inner_mut().state = ReadableState::Paused; + // state = ReadableState::Paused; + // has_data = true; + // } + + // match state { + // ReadableState::Flowing => { + // if last_state == ReadableState::Paused { + // if let Some(empty_buffer) = ba_buffer.read(None) { + // buffer.extend(empty_buffer); + // } + // } + + // if buffer.is_empty() { + // break; + // } + + // Self::emit_str( + // This(this2.clone()), + // &ctx3, + // "data", + // vec![Buffer(buffer.clone()).into_js(&ctx3)?], + // false + // )?; + // buffer.clear(); + // }, + // ReadableState::Paused => { + + // if bytes_read == 0 { + // break; + // } + + // let write_buffer_future = ba_buffer.write(&mut buffer); + // Self::emit_str( + // This(this2.clone()), + // &ctx3, + // "readable", + // vec![], + // false + // )?; + // tokio::select!{ + // capacity = write_buffer_future => { + // buffer.clear(); + // //increase buffer capacity if bytearray buffer has more capacity to reduce read syscalls + // buffer.reserve(buffer.capacity()-capacity); + // } + // error = destroy_rx.recv() => { + // set_destroyed_and_error(&mut is_destroyed, &mut error_value, error); + // break; + // } + // _ = listener_attached_tx.recv() => { + // ba_buffer.clear().await + // //don't clear buffer + // } + // } + // }, + // _ => { + // //should not happen + // } + // } + + // last_state = state; + + // } + // error = destroy_rx.recv() => { + // set_destroyed_and_error(&mut is_destroyed, &mut error_value, error); + // break; + // }, + // } + // } + // } + + // let mut borrow = this2.borrow_mut(); + // let inner = borrow.inner_mut(); + // inner.buffer.close().await; + // if is_destroyed { + // inner.is_destroyed = true; + // } else { + // inner.is_ended = true; + // } + + // drop(borrow); + // drop(reader); + + // if !is_destroyed { + // on_end(); + // Self::emit_str(This(this2), &ctx3, "end", vec![], false)?; + // } + + // if let Some(error_value) = error_value{ + // return Err(ctx3.throw(error_value)); + // } + + // Ok::<_, Error>(()) + // } + // .await; + + // // let had_error = read_function.emit_error(&ctx2, this.clone())?; + + // if emit_close { + // Self::emit_close(this,&ctx2,had_error)?; + // } + + // Ok::<_, Error>(had_error) + // }) + } +} diff --git a/rqjs-ext/src/stream/writable.rs b/rqjs-ext/src/stream/writable.rs new file mode 100644 index 0000000..e07963e --- /dev/null +++ b/rqjs-ext/src/stream/writable.rs @@ -0,0 +1,299 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +use std::sync::{Arc, RwLock}; + +use rquickjs::{ + class::{Trace, Tracer}, + prelude::{Func, Opt, This}, + Class, Ctx, Function, Result, Value, +}; + +use tokio::{ + io::{AsyncWrite, AsyncWriteExt}, + sync::{ + broadcast::{self, Sender}, + mpsc::{self, UnboundedReceiver, UnboundedSender}, + oneshot::Receiver, + }, +}; + +use crate::{ + modules::events::{Emitter, EventEmitter, EventList}, + utils::result::ResultExt, + // vm::{CtxExtension, ErrorExtensions}, +}; + +use super::SteamEvents; + +pub struct WritableStreamInner<'js> { + emitter: EventEmitter<'js>, + command_tx: UnboundedSender>, + command_rx: Option>>, + is_finished: bool, + #[allow(dead_code)] + errored: bool, + emit_close: bool, + is_destroyed: bool, + destroy_tx: Sender>>, +} + +impl<'js> WritableStreamInner<'js> { + pub fn new(emitter: EventEmitter<'js>, emit_close: bool) -> Self { + let (tx, rx) = mpsc::unbounded_channel(); + + let (destroy_tx, _) = broadcast::channel::>>(1); + + Self { + command_tx: tx, + command_rx: Some(rx), + emitter, + is_finished: false, + is_destroyed: false, + destroy_tx, + emit_close, + errored: false, + } + } +} + +#[derive(Debug)] +#[allow(dead_code)] +pub enum WriteCommand<'js> { + End, + Write(Vec, Option>, bool), + Flush, +} + +#[rquickjs::class] +#[derive(rquickjs::class::Trace)] +pub struct DefaultWritableStream<'js> { + inner: WritableStreamInner<'js>, +} + +impl<'js> Trace<'js> for WritableStreamInner<'js> { + fn trace<'a>(&self, tracer: Tracer<'a, 'js>) { + self.emitter.trace(tracer); + } +} + +impl<'js> Emitter<'js> for DefaultWritableStream<'js> { + fn get_event_list(&self) -> Arc>> { + self.inner.emitter.get_event_list() + } +} + +impl<'js> DefaultWritableStream<'js> { + fn with_emitter(ctx: Ctx<'js>, emitter: EventEmitter<'js>) -> Result> { + Class::instance( + ctx, + Self { + inner: WritableStreamInner::new(emitter, true), + }, + ) + } + + pub fn new(ctx: Ctx<'js>) -> Result> { + Self::with_emitter(ctx, EventEmitter::new()) + } +} + +impl<'js> WritableStream<'js> for DefaultWritableStream<'js> { + fn inner_mut(&mut self) -> &mut WritableStreamInner<'js> { + &mut self.inner + } + + fn inner(&self) -> &WritableStreamInner<'js> { + &self.inner + } +} + +pub trait WritableStream<'js> +where + Self: Emitter<'js> + SteamEvents<'js>, +{ + fn inner_mut(&mut self) -> &mut WritableStreamInner<'js>; + + fn inner(&self) -> &WritableStreamInner<'js>; + + fn add_writable_stream_prototype(ctx: &Ctx<'js>) -> Result<()> { + let proto = Class::::prototype(ctx.clone()) + .or_throw_msg(ctx, &format!("Prototype for {} not found", Self::NAME))?; + + proto.set("write", Func::from(Self::write))?; + + proto.set("end", Func::from(Self::end))?; + + Ok(()) + } + + fn destroy( + this: This>, + _ctx: Ctx<'js>, + error: Opt>, + ) -> Class<'js, Self> { + if !this.borrow().inner().is_finished { + let mut borrow = this.borrow_mut(); + let inner = borrow.inner_mut(); + inner.is_finished = true; + inner.is_destroyed = true; + let tx = inner.destroy_tx.clone(); + drop(borrow); + //it doesn't matter if channel is closed because then writable is already closed + let _ = tx.send(error.0); + } + this.0 + } + + fn end(this: This>) -> Class<'js, Self> { + if !this.borrow().inner().is_finished { + let mut borrow = this.borrow_mut(); + let inner = borrow.inner_mut(); + inner.is_finished = true; + let tx = inner.command_tx.clone(); + drop(borrow); + //it doesn't matter if channel is closed because then writable is already closed + let _ = tx.send(WriteCommand::End); + } + this.0 + } + + #[allow(dead_code)] + fn flush(this: Class<'js, Self>, ctx: &Ctx<'js>) -> Result<()> { + let _ = this + .borrow() + .inner() + .command_tx + .send(WriteCommand::Flush) + .or_throw(ctx); + Ok(()) + } + + fn write_flushed( + this: This>, + ctx: Ctx<'js>, + value: Value<'js>, + cb: Opt>, + ) -> Result<()> { + Self::do_write(this, ctx, value, cb, true) + } + + fn write( + this: This>, + ctx: Ctx<'js>, + value: Value<'js>, + cb: Opt>, + ) -> Result<()> { + Self::do_write(this, ctx, value, cb, false) + } + + fn do_write( + this: This>, + ctx: Ctx<'js>, + value: Value<'js>, + cb: Opt>, + flush: bool, + ) -> Result<()> { + // let bytes = get_bytes(&ctx, value)?; + + // let callback = cb.0; + + // if this + // .borrow() + // .inner() + // .command_tx + // .send(WriteCommand::Write(bytes, callback.clone(), flush)) + // .is_err() + // { + // if let Some(cb) = callback { + // let err = + // Exception::throw_message(&ctx, "This socket has been ended by the other party") + // .into_value(&ctx)?; + + // () = cb.call((err,))?; + // } + // } + + Ok(()) + } + + fn process( + this: Class<'js, Self>, + ctx: &Ctx<'js>, + writable: T, + ) -> Result> { + let mut borrow = this.borrow_mut(); + let inner = borrow.inner_mut(); + let is_ended = inner.is_finished; + let is_destroyed = inner.is_destroyed; + let emit_close = inner.emit_close; + let command_rx = inner + .command_rx + .take() + .expect("rx from writable process already taken!"); + let destroy_rx = inner.destroy_tx.subscribe(); + todo!(); + // let mut error_value = None; + + // drop(borrow); + // let ctx2 = ctx.clone(); + // ctx.spawn_exit(async move { + // let ctx3 = ctx2.clone(); + // let this2 = this.clone(); + // let write_function = async move { + // let mut writer = BufWriter::new(writable); + + // if !is_ended && !is_destroyed { + // loop { + // tokio::select! { + // command = command_rx.recv() => { + // match command { + // Some(WriteCommand::Write(data, cb, flush)) => { + // writer.write_all(&data).await.or_throw(&ctx3)?; + // if flush { + // writer.flush().await.or_throw(&ctx3)?; + // } + + // if let Some(cb) = cb { + // () = cb.call(())?; + // } + // }, + // Some(WriteCommand::End) => { + // writer.shutdown().await.or_throw(&ctx3)?; + // break; + // }, + // Some(WriteCommand::Flush) => writer.flush().await.or_throw(&ctx3)?, + // None => break, + // } + // }, + // error = destroy_rx.recv() => { + // set_destroyed_and_error(&mut is_destroyed, &mut error_value, error); + // break; + // } + // } + // } + // } + + // drop(writer); + + // if !is_destroyed { + // Self::emit_str(This(this2), &ctx3, "finish", vec![], false)?; + // } + + // if let Some(error_value) = error_value{ + // return Err(ctx3.throw(error_value)); + // } + + // Ok::<_, Error>(()) + // } + // .await; + + // let had_error = write_function.emit_error(&ctx2, this.clone())?; + + // if emit_close { + // Self::emit_close(this,&ctx2,had_error)?; + // } + + // Ok::<_, Error>(had_error) + // }) + } +} diff --git a/rqjs-ext/src/utils/class.rs b/rqjs-ext/src/utils/class.rs new file mode 100644 index 0000000..554772f --- /dev/null +++ b/rqjs-ext/src/utils/class.rs @@ -0,0 +1,74 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +use rquickjs::{ + atom::PredefinedAtom, class::JsClass, prelude::This, Array, Class, Ctx, Function, Object, + Result, Value, +}; + +// use crate::modules::console::CUSTOM_INSPECT_SYMBOL_DESCRIPTION; + +use super::{object::ObjectExt, result::OptionExt}; + +pub trait IteratorDef<'js> +where + Self: 'js + JsClass<'js> + Sized, +{ + fn js_entries(&self, ctx: Ctx<'js>) -> Result>; + + fn js_iterator(&self, ctx: Ctx<'js>) -> Result> { + let value = self.js_entries(ctx)?; + let obj = value.as_object(); + let values_fn: Function = obj.get(PredefinedAtom::Values)?; + values_fn.call((This(value),)) + } +} + +pub fn get_class_name(value: &Value) -> Result> { + value + .get_optional::<_, Object>(PredefinedAtom::Constructor)? + .and_then_ok(|ctor| ctor.get_optional::<_, String>(PredefinedAtom::Name)) +} + +#[inline(always)] +pub fn get_class<'js, C>(provided: &Value<'js>) -> Result>> +where + C: JsClass<'js>, +{ + if provided + .as_object() + .map(|p| p.instance_of::()) + .unwrap_or_default() + { + return Ok(Some(Class::::from_value(&provided.clone())?)); + } + Ok(None) +} + +pub trait CustomInspectExtension<'js> { + fn define_with_custom_inspect(globals: &Object<'js>) -> Result<()>; +} + +pub trait CustomInspect<'js> +where + Self: JsClass<'js>, +{ + fn custom_inspect(&self, ctx: Ctx<'js>) -> Result>; +} + +// impl<'js, C> CustomInspectExtension<'js> for Class<'js, C> +// where +// C: JsClass<'js> + CustomInspect<'js> + 'js, +// { +// fn define_with_custom_inspect(globals: &Object<'js>) -> Result<()> { +// Self::define(globals)?; +// let custom_inspect_symbol = +// Symbol::for_description(globals, CUSTOM_INSPECT_SYMBOL_DESCRIPTION)?; +// if let Some(proto) = Class::::prototype(globals.ctx().clone()) { +// proto.prop( +// custom_inspect_symbol, +// Accessor::from(|this: This>, ctx| this.borrow().custom_inspect(ctx)), +// )?; +// } +// Ok(()) +// } +// } diff --git a/rqjs-ext/src/utils/clone.rs b/rqjs-ext/src/utils/clone.rs new file mode 100644 index 0000000..86d65a3 --- /dev/null +++ b/rqjs-ext/src/utils/clone.rs @@ -0,0 +1,474 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +use fxhash::{FxBuildHasher, FxHashSet}; + +use rquickjs::function::This; + +use rquickjs::{ + atom::PredefinedAtom, + function::{Constructor, Opt}, + Array, Ctx, Function, IntoJs, Null, Object, Result, Type, Value, +}; + +use super::object::ObjectExt; + +#[derive(Debug)] +enum StackItem<'js> { + Value(usize, Value<'js>, Option, Option), + ObjectEnd, +} + +#[derive(Debug)] +enum ObjectType { + Set, + Map, +} + +#[derive(Debug)] +enum TapeValue<'js> { + Array(Array<'js>), + Object(Object<'js>), + Value(Value<'js>), + Collection(Option>, ObjectType), +} + +#[derive(Debug)] +struct TapeItem<'js> { + parent: usize, + object_key: Option, + array_index: Option, + value: TapeValue<'js>, +} + +pub fn structured_clone<'js>( + ctx: &Ctx<'js>, + value: Value<'js>, + options: Opt>, +) -> Result> { + let globals = ctx.globals(); + let date_ctor: Constructor = globals.get(PredefinedAtom::Date)?; + let map_ctor: Constructor = globals.get(PredefinedAtom::Map)?; + let set_ctor: Constructor = globals.get(PredefinedAtom::Set)?; + let reg_exp_ctor: Constructor = globals.get(PredefinedAtom::RegExp)?; + let error_ctor: Constructor = globals.get(PredefinedAtom::Error)?; + let array_ctor: Constructor = globals.get(PredefinedAtom::Array)?; + let array_from: Function = array_ctor.get(PredefinedAtom::From)?; + let array_buffer: Constructor = globals.get(PredefinedAtom::ArrayBuffer)?; + let is_view_fn: Function = array_buffer.get("isView")?; + + let mut transfer_set = None; + + if let Some(options) = options.0 { + if let Some(transfer_array) = options.get_optional::<_, Array>("transfer")? { + let mut set = + FxHashSet::with_capacity_and_hasher(transfer_array.len(), FxBuildHasher::default()); + + for item in transfer_array.iter::() { + set.insert(item?); + } + transfer_set = Some(set); + } + } + + let mut tape = Vec::::with_capacity(10); + let mut stack = Vec::with_capacity(10); + let mut visited = Vec::<(usize, usize)>::with_capacity(10); + let mut index = 0usize; + + stack.push(StackItem::Value(0, value, None, None)); + + while let Some(item) = stack.pop() { + match item { + StackItem::Value(parent, value, mut object_key, array_index) => { + if let Some(set) = &transfer_set { + if let Some(value) = set.get(&value) { + append_transfer_value(&mut tape, value, parent, object_key, array_index)?; + index += 1; + continue; + } + } + match value.type_of() { + Type::Object => { + if check_circular( + &mut tape, + &mut visited, + &value, + parent, + &mut object_key, + array_index, + index, + ) { + index += 1; + continue; + } + + let object = value.as_object().unwrap(); + + if object.is_instance_of(&date_ctor) { + append_ctor_value( + &mut tape, + object, + &date_ctor, + parent, + object_key, + array_index, + )?; + index += 1; + continue; + } + + if object.is_instance_of(®_exp_ctor) { + append_ctor_value( + &mut tape, + object, + ®_exp_ctor, + parent, + object_key, + array_index, + )?; + index += 1; + continue; + } + + let is_collection = if object.is_instance_of(&set_ctor) { + Some(ObjectType::Set) + } else if object.is_instance_of(&map_ctor) { + Some(ObjectType::Map) + } else { + None + }; + + if let Some(collection_type) = is_collection { + append_collection( + &mut tape, + &array_from, + object, + parent, + object_key, + array_index, + collection_type, + &mut stack, + index, + )?; + + index += 1; + continue; + } + + if is_view_fn.call::<_, bool>((value.clone(),))? { + append_buffer(&mut tape, object, parent, object_key, array_index)?; + index += 1; + continue; + } + + let new: Object<'_> = if object.is_instance_of(&error_ctor) { + error_ctor.construct(("",)) + } else { + Object::new(ctx.clone()) + }?; + + tape.push(TapeItem { + parent, + object_key, + array_index, + value: TapeValue::Object(new), + }); + stack.push(StackItem::ObjectEnd); + + for key in object.keys::() { + let key = key?; + let value = object.get(&key)?; + stack.push(StackItem::Value(index, value, Some(key), None)); + } + } + Type::Array => { + if check_circular( + &mut tape, + &mut visited, + &value, + parent, + &mut object_key, + array_index, + index, + ) { + index += 1; + continue; + } + let new = Array::new(ctx.clone())?; + tape.push(TapeItem { + parent, + object_key, + array_index, + value: TapeValue::Array(new), + }); + stack.push(StackItem::ObjectEnd); + let array = value.as_array().unwrap(); + + //reverse for loop of items in array + for array_index in (0usize..array.len()).rev() { + stack.push(StackItem::Value( + index, + array.get(array_index)?, + None, + Some(array_index), + )); + } + } + _ => { + tape.push(TapeItem { + parent, + object_key, + array_index, + value: TapeValue::Value(value), + }); + } + } + index += 1; + } + StackItem::ObjectEnd => { + visited.pop(); + } + } + } + + while let Some(item) = tape.pop() { + let value = match item.value { + TapeValue::Array(array) => array.into_value(), + TapeValue::Object(object) => object.into_value(), + TapeValue::Value(value) => value, + TapeValue::Collection(mut value, _) => value.take().unwrap(), + }; + if tape.is_empty() { + return Ok(value); + } + let parent = &mut tape[item.parent]; + let array_index = item.array_index; + let object_key = item.object_key; + match &mut parent.value { + TapeValue::Array(array) => { + array.set(array_index.unwrap(), value)?; + } + TapeValue::Object(object) => { + let string = object_key.unwrap(); + object.set(string, value)?; + } + TapeValue::Collection(collection_value, collection_type) => { + match collection_type { + ObjectType::Set => { + collection_value.replace(set_ctor.construct((value,))?); + } + ObjectType::Map => { + collection_value.replace(map_ctor.construct((value,))?); + } + }; + } + _ => {} + }; + } + + Null.into_js(ctx) +} + +#[inline(always)] +#[cold] +fn append_buffer<'js>( + tape: &mut Vec>, + object: &Object<'js>, + parent: usize, + object_key: Option, + array_index: Option, +) -> Result<()> { + let ctor: Constructor = object.get(PredefinedAtom::Constructor)?; + let slice: Function = object.get("slice")?; + let clone: Value = slice.call((This(object.clone()),))?; + let new = ctor.construct((clone,))?; + tape.push(TapeItem { + parent, + object_key, + array_index, + value: TapeValue::Value(new), + }); + Ok(()) +} + +#[inline(always)] +#[cold] +#[allow(clippy::too_many_arguments)] +fn append_collection<'js>( + tape: &mut Vec>, + array_from: &Function<'js>, + object: &Object<'js>, + parent: usize, + object_key: Option, + array_index: Option, + collection_type: ObjectType, + stack: &mut Vec>, + index: usize, +) -> Result<()> { + let array: Array = array_from.call((object.clone(),))?; + tape.push(TapeItem { + parent, + object_key, + array_index, + value: TapeValue::Collection(None, collection_type), + }); + stack.push(StackItem::ObjectEnd); + stack.push(StackItem::Value(index, array.into(), None, None)); + Ok(()) +} + +#[inline(always)] +fn check_circular( + tape: &mut Vec, + visited: &mut Vec<(usize, usize)>, + value: &Value<'_>, + parent: usize, + object_key: &mut Option, + array_index: Option, + index: usize, +) -> bool { + let hash = fxhash::hash(value); + if let Some(visited) = visited.iter().find(|v| v.0 == hash) { + append_circular(tape, visited, object_key, parent, array_index); + return true; + } + visited.push((hash, index)); + false +} + +#[inline(always)] +#[cold] +fn append_transfer_value<'js>( + tape: &mut Vec>, + value: &Value<'js>, + parent: usize, + object_key: Option, + array_index: Option, +) -> Result<()> { + tape.push(TapeItem { + parent, + object_key, + array_index, + value: TapeValue::Value(value.clone()), + }); + Ok(()) +} + +#[inline(always)] +#[cold] +fn append_circular( + tape: &mut Vec>, + visited: &(usize, usize), + object_key: &mut Option, + parent: usize, + array_index: Option, +) { + let value = match &tape[visited.1].value { + TapeValue::Array(array) => array.clone().into_value(), + TapeValue::Object(object) => object.clone().into_value(), + TapeValue::Value(value) => value.clone(), + TapeValue::Collection(value, _) => value.clone().unwrap(), + }; + + let object_key = object_key.take(); + + tape.push(TapeItem { + parent, + object_key, + array_index, + value: TapeValue::Value(value), + }); +} + +#[inline(always)] +#[cold] +fn append_ctor_value<'js>( + tape: &mut Vec>, + object: &Object<'js>, + ctor: &Constructor<'js>, + parent: usize, + object_key: Option, + array_index: Option, +) -> Result<()> { + let clone: Value = ctor.construct((object.clone(),))?; + tape.push(TapeItem { + parent, + object_key, + array_index, + value: TapeValue::Value(clone), + }); + Ok(()) +} + +// #[cfg(test)] +// mod tests { + +// use rquickjs::{function::Opt, Object, Value}; + +// use crate::{test_utils::utils::with_js_runtime, utils::clone::structured_clone}; + +// #[tokio::test] +// async fn clone() { +// with_js_runtime(|ctx| { +// crate::modules::buffer::init(&ctx)?; +// let value: Object = ctx.eval( +// r#" +// const a = { +// "foo":{ +// "bar":"baz" +// }, +// "foo1":{ +// "bar1":"baz1", +// "bar11":"baz11" +// } +// }; +// a +// "#, +// )?; + +// let cloned = structured_clone(&ctx, value.clone().into_value(), Opt(None))? +// .into_object() +// .unwrap(); + +// let json = ctx +// .json_stringify(value.clone())? +// .unwrap() +// .to_string()? +// .to_string(); + +// let clone_json = ctx +// .json_stringify(cloned.clone())? +// .unwrap() +// .to_string()? +// .to_string(); + +// assert_eq!(json, clone_json); + +// assert_ne!( +// value.get::<_, Value>("foo")?, +// cloned.get::<_, Value>("foo")? +// ); + +// Ok(()) +// }) +// .await +// } + +// #[tokio::test] +// async fn clone_circular() { +// with_js_runtime(|ctx| { +// let _value: Object = ctx.eval( +// r#" +// const originalObject = { foo: { bar: "baz",arr: [1,2,3] } }; +// originalObject.foo.circularRef = originalObject; +// originalObject.foo.circularRef2 = originalObject; +// originalObject.foo.circularRef3 = originalObject.foo; +// originalObject.ref2 = originalObject; +// "#, +// )?; + +// Ok(()) +// }) +// .await +// } +// } diff --git a/rqjs-ext/src/utils/io.rs b/rqjs-ext/src/utils/io.rs new file mode 100644 index 0000000..02f3911 --- /dev/null +++ b/rqjs-ext/src/utils/io.rs @@ -0,0 +1,142 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +use std::{ + fs::Metadata, + io, + path::{Path, PathBuf}, +}; + +use tokio::fs::{self}; + +pub fn get_basename_ext_name(path: &str) -> (String, String) { + let path = path.strip_prefix("./").unwrap_or(path); + let (basename, ext) = path.split_at(path.rfind('.').unwrap_or(path.len())); + (basename.to_string(), ext.to_string()) +} + +pub static JS_EXTENSIONS: &[&str] = &[".js", ".mjs", ".cjs"]; + +pub fn get_js_path(path: &str) -> Option { + let (mut basename, ext) = get_basename_ext_name(path); + + let filepath = Path::new(path); + + let exists = filepath.exists(); + + if !ext.is_empty() && exists { + return Some(filepath.to_owned()); + } + + if filepath.is_dir() && exists { + basename = format!("{}/index", &basename); + } + + for ext in JS_EXTENSIONS { + let path = &format!("{}{}", &basename, ext); + + let path = Path::new(path); + if path.exists() { + return Some(path.to_owned()); + } + } + + None +} + +pub struct DirectoryWalker +where + T: Fn(&str) -> bool, +{ + stack: Vec<(PathBuf, Option)>, + filter: T, + recursive: bool, + eat_root: bool, +} + +impl DirectoryWalker +where + T: Fn(&str) -> bool, +{ + pub fn new(root: PathBuf, filter: T) -> Self { + Self { + stack: vec![(root, None)], + filter, + recursive: false, + eat_root: true, + } + } + + pub fn set_recursive(&mut self, recursive: bool) { + self.recursive = recursive; + } + + pub async fn walk(&mut self) -> io::Result> { + if self.eat_root { + self.eat_root = false; + let (dir, _) = self.stack.pop().unwrap(); + self.append_stack(&dir).await?; + } + if let Some((dir, metadata)) = self.stack.pop() { + let metadata = metadata.unwrap(); + if self.recursive && metadata.is_dir() { + self.append_stack(&dir).await?; + } + + Ok(Some((dir, metadata))) + } else { + Ok(None) + } + } + + pub fn walk_sync(&mut self) -> io::Result> { + if self.eat_root { + self.eat_root = false; + let (dir, _) = self.stack.pop().unwrap(); + self.append_stack_sync(&dir)?; + } + if let Some((dir, metadata)) = self.stack.pop() { + let metadata = metadata.unwrap(); + if self.recursive && metadata.is_dir() { + self.append_stack_sync(&dir)?; + } + + Ok(Some((dir, metadata))) + } else { + Ok(None) + } + } + + async fn append_stack(&mut self, dir: &PathBuf) -> io::Result<()> { + let mut stream = fs::read_dir(dir).await?; + + while let Some(entry) = stream.next_entry().await? { + let entry_path = entry.path(); + + let name = entry.file_name().to_string_lossy().to_string(); + if !(self.filter)(&name) { + continue; + } + + let metadata = fs::symlink_metadata(&entry_path).await?; + + self.stack.push((entry_path, Some(metadata))); + } + Ok(()) + } + + fn append_stack_sync(&mut self, dir: &PathBuf) -> io::Result<()> { + let dir = std::fs::read_dir(dir)?; + + for entry in dir.flatten() { + let name = entry.file_name().to_string_lossy().to_string(); + if !(self.filter)(&name) { + continue; + } + let entry_path = entry.path(); + let metadata = entry_path.symlink_metadata()?; + self.stack.push((entry_path, Some(metadata))) + } + + Ok(()) + } +} diff --git a/rqjs-ext/src/utils/mc_oneshot.rs b/rqjs-ext/src/utils/mc_oneshot.rs new file mode 100644 index 0000000..972a16c --- /dev/null +++ b/rqjs-ext/src/utils/mc_oneshot.rs @@ -0,0 +1,119 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +use std::{ + future::Future, + pin::Pin, + sync::{ + atomic::{AtomicBool, Ordering}, + Arc, RwLock, + }, + task::{Context, Poll}, +}; + +#[derive(Clone, Debug)] +pub struct Sender { + is_sent: Arc, + value: Arc>>, +} + +impl Sender { + pub fn send(&self, value: T) { + if !self.is_sent.load(Ordering::Relaxed) { + self.value.write().unwrap().replace(value); + self.is_sent.store(true, Ordering::Relaxed); + } + } + + pub fn subscribe(&self) -> Receiver { + Receiver { + is_sent: self.is_sent.clone(), + value: self.value.clone(), + } + } +} + +#[derive(Clone, Debug)] +pub struct Receiver { + is_sent: Arc, + value: Arc>>, +} + +impl Receiver { + pub fn recv(&self) -> ReceiverWaiter { + ReceiverWaiter { + is_sent: self.is_sent.clone(), + value: self.value.clone(), + } + } +} + +pub struct ReceiverWaiter { + is_sent: Arc, + value: Arc>>, +} + +impl Future for ReceiverWaiter { + type Output = T; + + fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + if self.is_sent.load(Ordering::Relaxed) { + let a = self.get_mut().value.read().unwrap().clone().unwrap(); + return Poll::Ready(a); + } + + cx.waker().wake_by_ref(); + + Poll::Pending + } +} + +pub fn channel() -> (Sender, Receiver) { + let is_sent = Arc::new(AtomicBool::new(false)); + let value = Arc::new(RwLock::new(None)); + + ( + Sender { + is_sent: is_sent.clone(), + value: value.clone(), + }, + Receiver { + is_sent: is_sent.clone(), + value: value.clone(), + }, + ) +} + +#[cfg(test)] +mod tests { + use tokio::join; + + #[tokio::test] + async fn test() { + let (tx, rx1) = super::channel::(); + + let rx2 = tx.subscribe(); + let rx3 = tx.subscribe(); + + let a = tokio::spawn(async move { + let val = rx1.recv().await; //wait for value to become false + assert!(val) + }); + + let b = tokio::spawn(async move { + let val = rx2.recv().await; //wait for value to become false + assert!(val) + }); + + tokio::time::sleep(std::time::Duration::from_millis(10)).await; + + tx.send(true); + + let val = rx3.recv().await; + assert!(val); + + let (a, b) = join!(a, b); + a.unwrap(); + b.unwrap(); + } +} diff --git a/rqjs-ext/src/utils/mod.rs b/rqjs-ext/src/utils/mod.rs new file mode 100644 index 0000000..00348ff --- /dev/null +++ b/rqjs-ext/src/utils/mod.rs @@ -0,0 +1,9 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +pub mod class; +pub mod clone; +pub mod io; +pub mod mc_oneshot; +pub mod object; +pub mod result; +pub mod string; diff --git a/rqjs-ext/src/utils/object.rs b/rqjs-ext/src/utils/object.rs new file mode 100644 index 0000000..f27034c --- /dev/null +++ b/rqjs-ext/src/utils/object.rs @@ -0,0 +1,289 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +use std::collections::{BTreeMap, HashMap}; + +use rquickjs::{ + atom::PredefinedAtom, Array, ArrayBuffer, Coerced, Ctx, Exception, FromJs, Function, IntoAtom, + IntoJs, Object, Result, Symbol, TypedArray, Value, +}; + +use super::result::ResultExt; + +#[allow(dead_code)] +pub fn array_to_hash_map<'js>( + ctx: &Ctx<'js>, + array: Array<'js>, +) -> Result> { + let value = object_from_entries(ctx, array)?; + let value = value.into_value(); + HashMap::from_js(ctx, value) +} + +pub fn array_to_btree_map<'js>( + ctx: &Ctx<'js>, + array: Array<'js>, +) -> Result>> { + let value = object_from_entries(ctx, array)?; + let value = value.into_value(); + BTreeMap::from_js(ctx, value) +} + +pub fn object_from_entries<'js>(ctx: &Ctx<'js>, array: Array<'js>) -> Result> { + let obj = Object::new(ctx.clone())?; + for value in array.into_iter().flatten() { + if let Some(entry) = value.as_array() { + if let Ok(key) = entry.get::(0) { + if let Ok(value) = entry.get::(1) { + let _ = obj.set(key, value); //ignore result of failed + } + } + } + } + Ok(obj) +} + +pub fn map_to_entries<'js, K, V, M>(ctx: &Ctx<'js>, map: M) -> Result> +where + M: IntoIterator, + K: IntoJs<'js>, + V: IntoJs<'js>, +{ + let array = Array::new(ctx.clone())?; + for (idx, (key, value)) in map.into_iter().enumerate() { + let entry = Array::new(ctx.clone())?; + entry.set(0, key)?; + entry.set(1, value)?; + array.set(idx, entry)?; + } + + Ok(array) +} + +pub fn get_start_end_indexes( + source_len: usize, + target_len: Option, + offset: usize, +) -> (usize, usize) { + if offset > source_len { + return (0, 0); + } + + let target_len = target_len.unwrap_or(source_len - offset); + + if offset + target_len > source_len { + return (offset, source_len); + } + + (offset, target_len + offset) +} + +pub fn get_bytes_offset_length<'js>( + ctx: &Ctx<'js>, + value: Value<'js>, + offset: usize, + length: Option, +) -> Result> { + if let Some(bytes) = get_string_bytes(&value, offset, length)? { + return Ok(bytes); + } + if let Some(bytes) = get_array_bytes(ctx, &value, offset, length)? { + return Ok(bytes); + } + + if let Some(obj) = value.as_object() { + if let Some((array_buffer, source_length, source_offset)) = obj_to_array_buffer(obj)? { + let (start, end) = get_start_end_indexes(source_length, length, offset); + let bytes: &[u8] = array_buffer.as_ref(); + return Ok(bytes[start + source_offset..end - source_offset].to_vec()); + } + } + + if let Some(bytes) = get_coerced_string_bytes(&value, offset, length) { + return Ok(bytes); + } + + Err(Exception::throw_message( + ctx, + "value must be typed DataView, Buffer, ArrayBuffer, Uint8Array or interpretable as string", + )) +} + +pub fn get_array_bytes<'js>( + ctx: &Ctx<'js>, + value: &Value<'js>, + offset: usize, + length: Option, +) -> Result>> { + if value.is_array() { + let array = value.as_array().unwrap(); + let (start, end) = get_start_end_indexes(array.len(), length, offset); + let size = end - start; + let mut bytes: Vec = Vec::with_capacity(size); + + for val in array.iter::().skip(start).take(size) { + let val: u8 = val.or_throw_msg(ctx, "array value is not u8")?; + bytes.push(val); + } + + return Ok(Some(bytes)); + } + Ok(None) +} + +pub fn get_coerced_string_bytes( + value: &Value<'_>, + offset: usize, + length: Option, +) -> Option> { + if let Ok(val) = value.get::>() { + let string = val.to_string(); + return Some(bytes_from_js_string(string, offset, length)); + }; + None +} + +#[inline] +pub fn get_string_bytes( + value: &Value<'_>, + offset: usize, + length: Option, +) -> Result>> { + if let Some(val) = value.as_string() { + let string = val.to_string()?; + return Ok(Some(bytes_from_js_string(string, offset, length))); + } + Ok(None) +} + +fn bytes_from_js_string(string: String, offset: usize, length: Option) -> Vec { + let (start, end) = get_start_end_indexes(string.len(), length, offset); + string.as_bytes()[start..end].to_vec() +} + +pub fn obj_to_array_buffer<'js>( + obj: &Object<'js>, +) -> Result, usize, usize)>> { + //most common + if let Ok(typed_array) = TypedArray::::from_object(obj.clone()) { + let byte_length = typed_array.len(); + let offset: usize = typed_array.get("byteOffset")?; + return Ok(Some((typed_array.arraybuffer()?, byte_length, offset))); + } + //second most common + if let Some(array_buffer) = ArrayBuffer::from_object(obj.clone()) { + let byte_length = array_buffer.len(); + return Ok(Some((array_buffer, byte_length, 0))); + } + + if let Ok(typed_array) = TypedArray::::from_object(obj.clone()) { + let byte_length = typed_array.len(); + let offset: usize = typed_array.get("byteOffset")?; + return Ok(Some((typed_array.arraybuffer()?, byte_length, offset))); + } + + if let Ok(typed_array) = TypedArray::::from_object(obj.clone()) { + let byte_length = typed_array.len() * 2; + let offset: usize = typed_array.get("byteOffset")?; + return Ok(Some((typed_array.arraybuffer()?, byte_length, offset))); + } + + if let Ok(typed_array) = TypedArray::::from_object(obj.clone()) { + let byte_length = typed_array.len() * 2; + let offset: usize = typed_array.get("byteOffset")?; + return Ok(Some((typed_array.arraybuffer()?, byte_length, offset))); + } + + if let Ok(typed_array) = TypedArray::::from_object(obj.clone()) { + let byte_length = typed_array.len() * 4; + let offset: usize = typed_array.get("byteOffset")?; + return Ok(Some((typed_array.arraybuffer()?, byte_length, offset))); + } + + if let Ok(typed_array) = TypedArray::::from_object(obj.clone()) { + let byte_length = typed_array.len() * 4; + let offset: usize = typed_array.get("byteOffset")?; + return Ok(Some((typed_array.arraybuffer()?, byte_length, offset))); + } + + if let Ok(typed_array) = TypedArray::::from_object(obj.clone()) { + let byte_length = typed_array.len() * 8; + let offset: usize = typed_array.get("byteOffset")?; + return Ok(Some((typed_array.arraybuffer()?, byte_length, offset))); + } + + if let Ok(typed_array) = TypedArray::::from_object(obj.clone()) { + let byte_length = typed_array.len() * 8; + let offset: usize = typed_array.get("byteOffset")?; + return Ok(Some((typed_array.arraybuffer()?, byte_length, offset))); + } + + if let Ok(typed_array) = TypedArray::::from_object(obj.clone()) { + let byte_length = typed_array.len() * 4; + let offset: usize = typed_array.get("byteOffset")?; + return Ok(Some((typed_array.arraybuffer()?, byte_length, offset))); + } + + if let Ok(typed_array) = TypedArray::::from_object(obj.clone()) { + let byte_length = typed_array.len() * 8; + let offset: usize = typed_array.get("byteOffset")?; + return Ok(Some((typed_array.arraybuffer()?, byte_length, offset))); + } + + if let Ok(array_buffer) = obj.get::<_, ArrayBuffer>("buffer") { + let length = array_buffer.len(); + return Ok(Some((array_buffer, length, 0))); + } + + Ok(None) +} + +pub fn get_array_buffer_bytes( + array_buffer: ArrayBuffer<'_>, + start: usize, + end_end: usize, +) -> Vec { + let bytes: &[u8] = array_buffer.as_ref(); + bytes[start..end_end].to_vec() +} + +pub fn get_bytes<'js>(ctx: &Ctx<'js>, value: Value<'js>) -> Result> { + get_bytes_offset_length(ctx, value, 0, None) +} + +pub fn bytes_to_typed_array<'js>(ctx: Ctx<'js>, bytes: &[u8]) -> Result> { + TypedArray::::new(ctx.clone(), bytes).into_js(&ctx) +} + +pub trait ObjectExt<'js> { + fn get_optional + Clone, V: FromJs<'js>>(&self, k: K) -> Result>; +} + +impl<'js> ObjectExt<'js> for Object<'js> { + fn get_optional + Clone, V: FromJs<'js> + Sized>( + &self, + k: K, + ) -> Result> { + self.get::>(k) + } +} + +impl<'js> ObjectExt<'js> for Value<'js> { + fn get_optional + Clone, V: FromJs<'js>>(&self, k: K) -> Result> { + if let Some(obj) = self.as_object() { + return obj.get_optional(k); + } + Ok(None) + } +} + +pub trait CreateSymbol<'js> { + fn for_description(globals: &Object<'js>, description: &'static str) -> Result>; +} + +impl<'js> CreateSymbol<'js> for Symbol<'js> { + fn for_description(globals: &Object<'js>, description: &'static str) -> Result> { + let symbol_function: Function = globals.get(PredefinedAtom::Symbol)?; + let for_function: Function = symbol_function.get(PredefinedAtom::For)?; + for_function.call((description,)) + } +} diff --git a/rqjs-ext/src/utils/result.rs b/rqjs-ext/src/utils/result.rs new file mode 100644 index 0000000..372e3de --- /dev/null +++ b/rqjs-ext/src/utils/result.rs @@ -0,0 +1,48 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +use std::result::Result as StdResult; + +use rquickjs::{Ctx, Exception, Result}; + +pub trait ResultExt { + fn or_throw_msg(self, ctx: &Ctx, msg: &str) -> Result; + fn or_throw(self, ctx: &Ctx) -> Result; +} + +pub trait OptionExt { + fn and_then_ok(self, f: F) -> StdResult, E> + where + F: FnOnce(T) -> StdResult, E>; +} + +impl ResultExt for StdResult { + fn or_throw_msg(self, ctx: &Ctx, msg: &str) -> Result { + self.map_err(|e| Exception::throw_message(ctx, &format!("{}. {}", msg, &e.to_string()))) + } + + fn or_throw(self, ctx: &Ctx) -> Result { + self.map_err(|err| Exception::throw_message(ctx, &err.to_string())) + } +} + +impl ResultExt for Option { + fn or_throw_msg(self, ctx: &Ctx, msg: &str) -> Result { + self.ok_or(Exception::throw_message(ctx, msg)) + } + + fn or_throw(self, ctx: &Ctx) -> Result { + self.ok_or(Exception::throw_message(ctx, "Value is not present")) + } +} + +impl OptionExt for Option { + fn and_then_ok(self, f: F) -> StdResult, E> + where + F: FnOnce(T) -> StdResult, E>, + { + match self { + Some(v) => f(v), + None => Ok(None), + } + } +} diff --git a/rqjs-ext/src/utils/string.rs b/rqjs-ext/src/utils/string.rs new file mode 100644 index 0000000..dfab361 --- /dev/null +++ b/rqjs-ext/src/utils/string.rs @@ -0,0 +1,30 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +pub trait JoinToString { + fn join_to_string(&mut self, separator: &str, f: F) -> String + where + F: FnMut(&T) -> &str; +} + +impl JoinToString for I +where + I: Iterator, +{ + fn join_to_string(&mut self, separator: &str, mut f: F) -> String + where + F: FnMut(&T) -> &str, + { + let mut result = String::new(); + + if let Some(first_item) = self.next() { + result.push_str(f(&first_item)); + + for item in self { + result.push_str(separator); + result.push_str(f(&item)); + } + } + + result + } +} diff --git a/rqjs-ext/src/vm.rs b/rqjs-ext/src/vm.rs new file mode 100644 index 0000000..4b70143 --- /dev/null +++ b/rqjs-ext/src/vm.rs @@ -0,0 +1,758 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +use std::{ + cmp::min, + collections::{HashMap, HashSet}, + ffi::CStr, + future::Future, + str::FromStr, + sync::{Arc, Mutex}, +}; + +// use once_cell::sync::Lazy; + +// use chrono::Utc; +// use ring::rand::SecureRandom; +use rquickjs::{ + atom::PredefinedAtom, context::EvalOptions, function::Opt, prelude::Func, qjs, CatchResultExt, + CaughtError, Ctx, Error, Function, IntoJs, Module, Object, Promise, Result, String as JsString, + Value, +}; +// use tokio::sync::oneshot::{self, Receiver}; +// use tracing::trace; +// use zstd::{bulk::Decompressor, dict::DecoderDictionary}; + +// use crate::modules::{ +// console, +// crypto::SYSTEM_RANDOM, +// path::{dirname, join_path, resolve_path}, +// }; + +// use crate::{ +// bytecode::{BYTECODE_COMPRESSED, BYTECODE_UNCOMPRESSED, BYTECODE_VERSION, SIGNATURE_LENGTH}, +// environment, +// json::{parse::json_parse, stringify::json_stringify_replacer_space}, +// number::number_to_string, +// utils::{ +// clone::structured_clone, +// io::get_js_path, +// object::{get_bytes, ObjectExt}, +// }, +// }; + +// pub static TIME_ORIGIN: AtomicUsize = AtomicUsize::new(0); + +// #[inline] +// pub fn uncompressed_size(input: &[u8]) -> StdResult<(usize, &[u8]), io::Error> { +// let size = input.get(..4).ok_or(io::ErrorKind::InvalidInput)?; +// let size: &[u8; 4] = size.try_into().map_err(|_| io::ErrorKind::InvalidInput)?; +// let uncompressed_size = u32::from_le_bytes(*size) as usize; +// let rest = &input[4..]; +// Ok((uncompressed_size, rest)) +// } + +// pub(crate) static COMPRESSION_DICT: &[u8] = include_bytes!("../../bundle/lrt/compression.dict"); + +// static DECOMPRESSOR_DICT: Lazy = +// Lazy::new(|| DecoderDictionary::copy(COMPRESSION_DICT)); + +fn print(value: String, stdout: Opt) { + if stdout.0.unwrap_or_default() { + println!("{value}"); + } else { + eprintln!("{value}") + } +} + +// #[derive(Debug)] +// pub struct BinaryResolver { +// paths: Vec, +// cwd: PathBuf, +// } +// impl BinaryResolver { +// pub fn add_path>(&mut self, path: P) -> &mut Self { +// self.paths.push(path.into()); +// self +// } + +// pub fn get_bin_path(path: &Path) -> PathBuf { +// path.with_extension("lrt") +// } + +// pub fn normalize>(path: P) -> PathBuf { +// let ends_with_slash = path.as_ref().to_str().map_or(false, |s| s.ends_with('/')); +// let mut normalized = PathBuf::new(); +// for component in path.as_ref().components() { +// match &component { +// Component::ParentDir => { +// if !normalized.pop() { +// normalized.push(component); +// } +// }, +// _ => { +// normalized.push(component); +// }, +// } +// } +// if ends_with_slash { +// normalized.push(""); +// } +// normalized +// } +// } + +// impl Default for BinaryResolver { +// fn default() -> Self { +// let cwd = env::current_dir().unwrap(); +// Self { +// cwd, +// paths: Vec::with_capacity(10), +// } +// } +// } + +// #[allow(clippy::manual_strip)] +// impl Resolver for BinaryResolver { +// fn resolve(&mut self, _ctx: &Ctx, base: &str, name: &str) -> Result { +// trace!("Try resolve \"{}\" from \"{}\"", name, base); + +// if BYTECODE_CACHE.contains_key(name) { +// return Ok(name.to_string()); +// } + +// let base_path = Path::new(base); +// let base_path = if base_path.is_dir() { +// if base_path == self.cwd { +// Path::new(".") +// } else { +// base_path +// } +// } else { +// base_path.parent().unwrap_or(base_path) +// }; + +// let normalized_path = base_path.join(name); + +// let normalized_path = BinaryResolver::normalize(normalized_path); +// let mut normalized_path = normalized_path.to_str().unwrap(); +// let cache_path = if normalized_path.starts_with("./") { +// &normalized_path[2..] +// } else { +// normalized_path +// }; + +// let cache_key = Path::new(cache_path).with_extension("js"); +// let cache_key = cache_key.to_str().unwrap(); + +// trace!("Normalized path: {}, key: {}", normalized_path, cache_key); + +// if BYTECODE_CACHE.contains_key(cache_key) { +// return Ok(cache_key.to_string()); +// } + +// if BYTECODE_CACHE.contains_key(base) { +// normalized_path = name; +// if Path::new(normalized_path).exists() { +// return Ok(normalized_path.to_string()); +// } +// } + +// if Path::new(normalized_path).exists() { +// return Ok(normalized_path.to_string()); +// } + +// let path = self +// .paths +// .iter() +// .find_map(|path| { +// let path = path.join(normalized_path); +// let bin_path = BinaryResolver::get_bin_path(&path); +// if bin_path.exists() { +// return Some(bin_path); +// } +// get_js_path(path.to_str().unwrap()) +// }) +// .ok_or_else(|| Error::new_resolving(base, name))?; + +// Ok(path.into_os_string().into_string().unwrap()) +// } +// } + +// #[derive(Debug)] +// pub struct BinaryLoader; + +// impl Default for BinaryLoader { +// fn default() -> Self { +// Self +// } +// } + +// struct RawLoaderContainer +// where +// T: RawLoader + 'static, +// { +// loader: T, +// cwd: String, +// } +// impl RawLoaderContainer +// where +// T: RawLoader + 'static, +// { +// fn new(loader: T) -> Self { +// Self { +// loader, +// cwd: std::env::current_dir() +// .unwrap() +// .to_string_lossy() +// .to_string(), +// } +// } +// } + +// unsafe impl RawLoader for RawLoaderContainer +// where +// T: RawLoader + 'static, +// { +// #[allow(clippy::manual_strip)] +// unsafe fn raw_load<'js>(&mut self, ctx: &Ctx<'js>, name: &str) -> Result> { +// let res = self.loader.raw_load(ctx, name)?; + +// let name = if name.starts_with("./") { +// &name[2..] +// } else { +// name +// }; + +// if name.starts_with('/') { +// set_import_meta(&res, name)?; +// } else { +// set_import_meta(&res, &format!("{}/{}", &self.cwd, name))?; +// }; + +// Ok(res) +// } +// } + +// impl Loader for BinaryLoader { +// fn load(&mut self, _ctx: &Ctx<'_>, name: &str) -> Result { +// trace!("Loading module: {}", name); +// if let Some(bytes) = BYTECODE_CACHE.get(name) { +// trace!("Loading embedded module: {}", name); + +// return load_bytecode_module(name, bytes); +// } +// let path = PathBuf::from(name); +// let mut bytes: &[u8] = &std::fs::read(path)?; + +// if name.ends_with(".lrt") { +// trace!("Loading binary module: {}", name); +// return load_bytecode_module(name, bytes); +// } +// if bytes.starts_with(b"#!") { +// bytes = bytes.splitn(2, |&c| c == b'\n').nth(1).unwrap_or(bytes); +// } +// Ok(ModuleData::source(name, bytes)) +// } +// } + +// pub fn load_bytecode_module(name: &str, buf: &[u8]) -> Result { +// let bytes = load_module(buf)?; +// Ok(unsafe { ModuleData::bytecode(name, bytes) }) +// } + +// fn load_module(input: &[u8]) -> Result> { +// let (_, compressed, input) = get_bytecode_signature(input)?; + +// if compressed { +// let (size, input) = uncompressed_size(input)?; +// let mut buf = Vec::with_capacity(size); +// let mut decompressor = Decompressor::with_prepared_dictionary(&DECOMPRESSOR_DICT)?; +// decompressor.decompress_to_buffer(input, &mut buf)?; +// return Ok(buf); +// } + +// Ok(input.to_vec()) +// } + +// fn get_bytecode_signature(input: &[u8]) -> StdResult<(&[u8], bool, &[u8]), io::Error> { +// let raw_signature = input +// .get(..SIGNATURE_LENGTH) +// .ok_or(io::Error::new::( +// io::ErrorKind::InvalidInput, +// "Invalid bytecode signature length".into(), +// ))?; + +// let (last, signature) = raw_signature.split_last().unwrap(); + +// if signature != BYTECODE_VERSION.as_bytes() { +// return Err(io::Error::new::( +// io::ErrorKind::InvalidInput, +// "Invalid bytecode version".into(), +// )); +// } + +// let mut compressed = None; +// if *last == BYTECODE_COMPRESSED { +// compressed = Some(true) +// } else if *last == BYTECODE_UNCOMPRESSED { +// compressed = Some(false) +// } + +// let rest = &input[SIGNATURE_LENGTH..]; +// Ok(( +// signature, +// compressed.ok_or(io::Error::new::( +// io::ErrorKind::InvalidInput, +// "Invalid bytecode signature".into(), +// ))?, +// rest, +// )) +// } + +// pub struct Vm { +// pub runtime: AsyncRuntime, +// pub ctx: AsyncContext, +// } + +struct LifetimeArgs<'js>(Ctx<'js>); + +#[allow(dead_code)] +struct ExportArgs<'js>(Ctx<'js>, Object<'js>, Value<'js>, Value<'js>); + +// pub struct VmOptions { +// pub module_builder: crate::module_builder::ModuleBuilder, +// pub max_stack_size: usize, +// pub gc_threshold_mb: usize, +// } + +// impl Default for VmOptions { +// fn default() -> Self { +// Self { +// module_builder: crate::module_builder::ModuleBuilder::with_default(), +// max_stack_size: 512 * 1024, +// gc_threshold_mb: { +// const DEFAULT_GC_THRESHOLD_MB: usize = 20; + +// let gc_threshold_mb: usize = env::var(environment::ENV_LLRT_GC_THRESHOLD_MB) +// .map(|threshold| threshold.parse().unwrap_or(DEFAULT_GC_THRESHOLD_MB)) +// .unwrap_or(DEFAULT_GC_THRESHOLD_MB); + +// gc_threshold_mb * 1024 * 1024 +// }, +// } +// } +// } + +// impl Vm { +// pub const ENV_LAMBDA_TASK_ROOT: &'static str = "LAMBDA_TASK_ROOT"; + +// pub async fn from_options( +// vm_options: VmOptions, +// ) -> StdResult> { +// if TIME_ORIGIN.load(Ordering::Relaxed) == 0 { +// let time_origin = Utc::now().timestamp_nanos_opt().unwrap_or_default() as usize; +// TIME_ORIGIN.store(time_origin, Ordering::Relaxed) +// } + +// SYSTEM_RANDOM +// .fill(&mut [0; 8]) +// .expect("Failed to initialize SystemRandom"); + +// let mut file_resolver = FileResolver::default(); +// let mut binary_resolver = BinaryResolver::default(); +// let mut paths: Vec<&str> = Vec::with_capacity(10); + +// paths.push("."); + +// let task_root = env::var(Self::ENV_LAMBDA_TASK_ROOT).unwrap_or_else(|_| String::from("")); +// let task_root = task_root.as_str(); +// if cfg!(debug_assertions) { +// paths.push("bundle"); +// } else { +// paths.push("/opt"); +// } + +// if !task_root.is_empty() { +// paths.push(task_root); +// } + +// for path in paths.iter() { +// file_resolver.add_path(*path); +// binary_resolver.add_path(*path); +// } + +// let (builtin_resolver, module_loader, module_names, init_globals) = +// vm_options.module_builder.build(); + +// let resolver = (builtin_resolver, binary_resolver, file_resolver); + +// let loader = RawLoaderContainer::new(( +// module_loader, +// BinaryLoader, +// BuiltinLoader::default(), +// ScriptLoader::default() +// .with_extension("mjs") +// .with_extension("cjs"), +// )); + +// let runtime = AsyncRuntime::new()?; +// runtime.set_max_stack_size(vm_options.max_stack_size).await; +// runtime.set_gc_threshold(vm_options.gc_threshold_mb).await; +// runtime.set_loader(resolver, loader).await; +// let ctx = AsyncContext::full(&runtime).await?; +// ctx.with(|ctx| { +// for init_global in init_globals { +// init_global(&ctx)?; +// } +// init(&ctx, module_names)?; +// Ok::<_, Error>(()) +// }) +// .await?; + +// Ok(Vm { runtime, ctx }) +// } + +// pub async fn new() -> StdResult> { +// let vm = Self::from_options(VmOptions::default()).await?; +// Ok(vm) +// } + +// pub fn load_module<'js>(ctx: &Ctx<'js>, filename: PathBuf) -> Result> { +// Module::import(ctx, filename.to_string_lossy().to_string()) +// } + +// pub async fn run_module(ctx: &AsyncContext, filename: &Path) { +// Self::run_and_handle_exceptions(ctx, |ctx| { +// let _res = Vm::load_module(&ctx, filename.to_path_buf())?; +// Ok(()) +// }) +// .await +// } + +// pub async fn run_and_handle_exceptions<'js, F>(ctx: &AsyncContext, f: F) +// where +// F: FnOnce(Ctx) -> rquickjs::Result<()> + Send, +// { +// ctx.with(|ctx| { +// f(ctx.clone()) +// .catch(&ctx) +// .unwrap_or_else(|err| Self::print_error_and_exit(&ctx, err)); +// }) +// .await; +// } + +// pub fn print_error_and_exit<'js>(ctx: &Ctx<'js>, err: CaughtError<'js>) -> ! { +// let mut error_str = String::new(); +// write!(error_str, "Error: {:?}", err).unwrap(); +// if let Ok(error) = err.into_value(ctx) { +// if console::log_std_err(ctx, Rest(vec![error.clone()]), console::LogLevel::Fatal) +// .is_err() +// { +// eprintln!("{}", error_str); +// }; +// exit(1) +// } else { +// eprintln!("{}", error_str); +// exit(1) +// }; +// } + +// pub async fn idle(self) -> StdResult<(), Box> { +// self.runtime.idle().await; + +// drop(self.ctx); +// drop(self.runtime); +// Ok(()) +// } +// } + +use tokio::sync::oneshot::Receiver; + +use crate::{ + json::{parse::json_parse, stringify::json_stringify_replacer_space}, + modules::path::{dirname, join_path, resolve_path}, + number::number_to_string, + utils::object::{get_bytes, ObjectExt}, +}; + +fn json_parse_string<'js>(ctx: Ctx<'js>, value: Value<'js>) -> Result> { + let bytes = get_bytes(&ctx, value)?; + json_parse(&ctx, bytes) +} + +fn run_gc(ctx: Ctx<'_>) { + // trace!("Running GC"); + + unsafe { + let rt = qjs::JS_GetRuntime(ctx.as_raw().as_ptr()); + qjs::JS_RunGC(rt); + }; +} + +use crate::utils::clone::structured_clone; +fn init(ctx: &Ctx<'_>, module_names: HashSet<&'static str>) -> Result<()> { + let globals = ctx.globals(); + + globals.set("__gc", Func::from(run_gc))?; + + let number: Function = globals.get(PredefinedAtom::Number)?; + let number_proto: Object = number.get(PredefinedAtom::Prototype)?; + number_proto.set(PredefinedAtom::ToString, Func::from(number_to_string))?; + + globals.set("global", ctx.globals())?; + globals.set("self", ctx.globals())?; + globals.set("load", Func::from(load))?; + globals.set("print", Func::from(print))?; + globals.set( + "structuredClone", + Func::from(|ctx, value, options| structured_clone(&ctx, value, options)), + )?; + + let json_module: Object = globals.get(PredefinedAtom::JSON)?; + json_module.set("parse", Func::from(json_parse_string))?; + json_module.set( + "stringify", + Func::from(|ctx, value, replacer, space| { + struct StringifyArgs<'js>(Ctx<'js>, Value<'js>, Opt>, Opt>); + let StringifyArgs(ctx, value, replacer, space) = + StringifyArgs(ctx, value, replacer, space); + + let mut space_value = None; + let mut replacer_value = None; + + if let Some(replacer) = replacer.0 { + if let Some(space) = space.0 { + if let Some(space) = space.as_string() { + let mut space = space.clone().to_string()?; + space.truncate(20); + space_value = Some(space); + } + if let Some(number) = space.as_int() { + if number > 0 { + space_value = Some(" ".repeat(min(10, number as usize))); + } + } + } + replacer_value = Some(replacer); + } + + json_stringify_replacer_space(&ctx, value, replacer_value, space_value) + .map(|v| v.into_js(&ctx))? + }), + )?; + + #[allow(clippy::arc_with_non_send_sync)] + let require_in_progress: Arc>> = + Arc::new(Mutex::new(HashMap::new())); + + #[allow(clippy::arc_with_non_send_sync)] + let require_exports: Arc>> = Arc::new(Mutex::new(None)); + let require_exports_ref = require_exports.clone(); + let require_exports_ref_2 = require_exports.clone(); + + let js_bootstrap = Object::new(ctx.clone())?; + js_bootstrap.set( + "moduleExport", + Func::from(move |ctx, obj, prop, value| { + let ExportArgs(_ctx, _, _, value) = ExportArgs(ctx, obj, prop, value); + let mut exports = require_exports.lock().unwrap(); + exports.replace(value); + Result::Ok(true) + }), + )?; + js_bootstrap.set( + "exports", + Func::from(move |ctx, obj, prop, value| { + let ExportArgs(ctx, _, prop, value) = ExportArgs(ctx, obj, prop, value); + let mut exports = require_exports_ref.lock().unwrap(); + let exports = if exports.is_some() { + exports.as_ref().unwrap() + } else { + exports.replace(Object::new(ctx.clone())?.into_value()); + exports.as_ref().unwrap() + }; + exports.as_object().unwrap().set(prop, value)?; + Result::Ok(true) + }), + )?; + globals.set("__bootstrap", js_bootstrap)?; + + globals.set( + "require", + Func::from(move |ctx, specifier: String| -> Result { + let LifetimeArgs(ctx) = LifetimeArgs(ctx); + let specifier = if let Some(striped_specifier) = &specifier.strip_prefix("node:") { + striped_specifier.to_string() + } else { + specifier + }; + let import_name = if module_names.contains(specifier.as_str()) + // || BYTECODE_CACHE.contains_key(&specifier) + || specifier.starts_with('/') + { + specifier + } else { + let module_name = get_script_or_module_name(ctx.clone()); + let abs_path = resolve_path([module_name].iter()); + let import_directory = dirname(abs_path); + join_path(vec![import_directory, specifier]) + }; + + let mut map = require_in_progress.lock().unwrap(); + if let Some(obj) = map.get(&import_name) { + return Ok(obj.clone().into_value()); + } + + let obj = Object::new(ctx.clone())?; + map.insert(import_name.clone(), obj.clone()); + drop(map); + + // trace!("Require: {}", import_name); + + let imported_object: Promise = Module::import(&ctx, import_name.clone()).unwrap(); + require_in_progress.lock().unwrap().remove(&import_name); + + if let Some(exports) = require_exports_ref_2.lock().unwrap().take() { + if let Some(exports) = exports.as_object() { + for prop in exports.props::() { + let (key, value) = prop?; + obj.set(key, value)?; + } + } else { + return Ok(exports); + } + } + + for prop in imported_object.props::() { + let (key, value) = prop?; + obj.set(key, value)?; + } + + Ok(obj.into_value()) + }), + )?; + + Module::import(ctx, "@llrt/std")?; + + Ok(()) +} + +fn load<'js>(ctx: Ctx<'js>, filename: String, options: Opt>) -> Result> { + let mut eval_options = EvalOptions::default(); + eval_options.global = true; + eval_options.strict = false; + eval_options.backtrace_barrier = false; + eval_options.promise = true; + + // let mut eval_options = EvalOptions { + // global: true, + // strict: false, + // backtrace_barrier: false, + // promise: false, + // }; + + if let Some(options) = options.0 { + if let Some(global) = options.get_optional("global")? { + eval_options.global = global; + } + + if let Some(strict) = options.get_optional("strict")? { + eval_options.strict = strict; + } + } + + ctx.eval_file_with_options( + std::path::PathBuf::from_str(&filename).unwrap(), + eval_options, + ) +} + +fn get_script_or_module_name(ctx: Ctx<'_>) -> String { + unsafe { + let ctx_ptr = ctx.as_raw().as_ptr(); + let atom = qjs::JS_GetScriptOrModuleName(ctx_ptr, 0); + let c_str = qjs::JS_AtomToCString(ctx_ptr, atom); + if c_str.is_null() { + qjs::JS_FreeCString(ctx_ptr, c_str); + return String::from("."); + } + let bytes = CStr::from_ptr(c_str).to_bytes(); + let res = std::str::from_utf8_unchecked(bytes).to_string(); + qjs::JS_FreeCString(ctx_ptr, c_str); + res + } +} + +fn set_import_meta(module: &Module<'_>, filepath: &str) -> Result<()> { + let meta: Object = module.meta()?; + meta.prop("url", format!("file://{}", filepath))?; + Ok(()) +} + +pub trait ErrorExtensions<'js> { + fn into_value(self, ctx: &Ctx<'js>) -> Result>; +} + +impl<'js> ErrorExtensions<'js> for Error { + fn into_value(self, ctx: &Ctx<'js>) -> Result> { + Err::<(), _>(self).catch(ctx).unwrap_err().into_value(ctx) + } +} + +impl<'js> ErrorExtensions<'js> for CaughtError<'js> { + fn into_value(self, ctx: &Ctx<'js>) -> Result> { + Ok(match self { + CaughtError::Error(err) => { + JsString::from_str(ctx.clone(), &err.to_string())?.into_value() + } + CaughtError::Exception(ex) => ex.into_value(), + CaughtError::Value(val) => val, + }) + } +} + +pub trait CtxExtension<'js> { + fn spawn_exit(&self, future: F) -> Result> + where + F: Future> + 'js, + R: 'js; +} + +impl<'js> CtxExtension<'js> for Ctx<'js> { + fn spawn_exit(&self, future: F) -> Result> + where + F: Future> + 'js, + R: 'js, + { + todo!(); + // let ctx = self.clone(); + + // let type_error_ctor: Constructor = ctx.globals().get(PredefinedAtom::TypeError)?; + // let type_error: Object = type_error_ctor.construct(())?; + // let stack: Option = type_error.get(PredefinedAtom::Stack).ok(); + + // let (join_channel_tx, join_channel_rx) = oneshot::channel(); + + // self.spawn(async move { + // match future.await.catch(&ctx) { + // Ok(res) => { + // //result here dosn't matter if receiver has dropped + // let _ = join_channel_tx.send(res); + // } + // Err(err) => { + // // if let CaughtError::Exception(err) = err { + // // if err.stack().is_none() { + // // if let Some(stack) = stack { + // // err.set(PredefinedAtom::Stack, stack).unwrap(); + // // } + // // } + // // Vm::print_error_and_exit(&ctx, CaughtError::Exception(err)); + // // } else { + // // Vm::print_error_and_exit(&ctx, err); + // // } + // } + // } + // }); + // Ok(join_channel_rx) + } +} diff --git a/src/main.rs b/src/main.rs deleted file mode 100644 index e7a11a9..0000000 --- a/src/main.rs +++ /dev/null @@ -1,3 +0,0 @@ -fn main() { - println!("Hello, world!"); -}