diff --git a/.gitignore b/.gitignore index dd8d39e43..850157278 100644 --- a/.gitignore +++ b/.gitignore @@ -33,4 +33,11 @@ build/ .vscode/ ### Node Modules ### -node_modules \ No newline at end of file +node_modules + +### rust ### +/target/ +index.wasm +index.wit + +.DS_Store diff --git a/JS/wasm/Cargo.lock b/JS/wasm/Cargo.lock new file mode 100644 index 000000000..606b8ad96 --- /dev/null +++ b/JS/wasm/Cargo.lock @@ -0,0 +1,4186 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "Inflector" +version = "0.11.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe438c63458706e03479442743baae6c88256498e6431708f6dfc520a26515d3" +dependencies = [ + "lazy_static", + "regex", +] + +[[package]] +name = "addr2line" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +dependencies = [ + "gimli 0.28.1", +] + +[[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.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77c3a9648d43b9cd48db467b3f87fdd6e146bcc88ab0180006cef2179fe11d01" +dependencies = [ + "cfg-if", + "once_cell", + "version_check", + "zerocopy", +] + +[[package]] +name = "aho-corasick" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" +dependencies = [ + "memchr", +] + +[[package]] +name = "alloc-no-stdlib" +version = "2.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc7bb162ec39d46ab1ca8c77bf72e890535becd1751bb45f64c597edb4c8c6b3" + +[[package]] +name = "alloc-stdlib" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94fb8275041c72129eb51b7d0322c29b8387a0386127718b096429201a5d6ece" +dependencies = [ + "alloc-no-stdlib", +] + +[[package]] +name = "ambient-authority" +version = "0.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e9d4ee0d472d1cd2e28c97dfa124b3d8d992e10eb0a035f33f5d12e3a177ba3b" + +[[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 = "anes" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299" + +[[package]] +name = "ansi_term" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2" +dependencies = [ + "winapi", +] + +[[package]] +name = "anstyle" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2faccea4cc4ab4a667ce676a30e8ec13922a692c99bb8f5b11f1502c72e04220" + +[[package]] +name = "anyhow" +version = "1.0.79" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "080e9890a082662b09c1ad45f567faeeb47f22b5fb23895fbe1e651e718e25ca" + +[[package]] +name = "apis" +version = "0.0.1" +dependencies = [ + "anyhow", + "fastrand", + "javy", +] + +[[package]] +name = "arakoo-core" +version = "0.0.1" +dependencies = [ + "anyhow", + "apis", + "javy", + "once_cell", +] + +[[package]] +name = "arbitrary" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d5a26814d8dcb93b0e5a0ff3c6d80a8843bafb21b39e8e18a6f05471870e110" + +[[package]] +name = "arrayvec" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" + +[[package]] +name = "ast_node" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3e3e06ec6ac7d893a0db7127d91063ad7d9da8988f8a1a256f03729e6eec026" +dependencies = [ + "proc-macro2", + "quote", + "swc_macros_common", + "syn 2.0.48", +] + +[[package]] +name = "async-trait" +version = "0.1.77" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c980ee35e870bd1a4d2c8294d4c04d0499e67bca1e4b5cefcc693c2fa00caea9" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.48", +] + +[[package]] +name = "atty" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +dependencies = [ + "hermit-abi 0.1.19", + "libc", + "winapi", +] + +[[package]] +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + +[[package]] +name = "backtrace" +version = "0.3.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", +] + +[[package]] +name = "base64" +version = "0.21.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" + +[[package]] +name = "better_scoped_tls" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "794edcc9b3fb07bb4aecaa11f093fd45663b4feadb782d68303a2268bc2701de" +dependencies = [ + "scoped-tls", +] + +[[package]] +name = "binaryen" +version = "0.12.1" +source = "git+https://github.com/pepyakin/binaryen-rs?rev=00c98174843f957681ba0bc5cdcc9d15f5d0cb23#00c98174843f957681ba0bc5cdcc9d15f5d0cb23" +dependencies = [ + "binaryen-sys", +] + +[[package]] +name = "binaryen-sys" +version = "0.12.1" +source = "git+https://github.com/pepyakin/binaryen-rs?rev=00c98174843f957681ba0bc5cdcc9d15f5d0cb23#00c98174843f957681ba0bc5cdcc9d15f5d0cb23" +dependencies = [ + "cc", + "cmake", + "heck 0.3.3", + "regex", +] + +[[package]] +name = "bincode" +version = "1.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" +dependencies = [ + "serde", +] + +[[package]] +name = "bindgen" +version = "0.69.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a00dc851838a2120612785d195287475a3ac45514741da670b735818822129a0" +dependencies = [ + "bitflags 2.4.2", + "cexpr", + "clang-sys", + "itertools 0.12.1", + "lazy_static", + "lazycell", + "log", + "prettyplease", + "proc-macro2", + "quote", + "regex", + "rustc-hash", + "shlex", + "syn 2.0.48", + "which", +] + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitflags" +version = "2.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf" + +[[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 = "brotli" +version = "3.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "516074a47ef4bce09577a3b379392300159ce5b1ba2e501ff1c819950066100f" +dependencies = [ + "alloc-no-stdlib", + "alloc-stdlib", + "brotli-decompressor", +] + +[[package]] +name = "brotli-decompressor" +version = "2.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e2e4afe60d7dd600fdd3de8d0f08c2b7ec039712e3b6137ff98b7004e82de4f" +dependencies = [ + "alloc-no-stdlib", + "alloc-stdlib", +] + +[[package]] +name = "bumpalo" +version = "3.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "bytes" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" + +[[package]] +name = "camino" +version = "1.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c59e92b5a388f549b863a7bea62612c09f24c8393560709a54558a9abdfb3b9c" +dependencies = [ + "serde", +] + +[[package]] +name = "cap-fs-ext" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88e341d15ac1029aadce600be764a1a1edafe40e03cde23285bc1d261b3a4866" +dependencies = [ + "cap-primitives", + "cap-std", + "io-lifetimes", + "windows-sys 0.52.0", +] + +[[package]] +name = "cap-net-ext" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "434168fe6533055f0f4204039abe3ff6d7db338ef46872a5fa39e9d5ad5ab7a9" +dependencies = [ + "cap-primitives", + "cap-std", + "rustix", + "smallvec", +] + +[[package]] +name = "cap-primitives" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe16767ed8eee6d3f1f00d6a7576b81c226ab917eb54b96e5f77a5216ef67abb" +dependencies = [ + "ambient-authority", + "fs-set-times", + "io-extras", + "io-lifetimes", + "ipnet", + "maybe-owned", + "rustix", + "windows-sys 0.52.0", + "winx", +] + +[[package]] +name = "cap-rand" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20e5695565f0cd7106bc3c7170323597540e772bb73e0be2cd2c662a0f8fa4ca" +dependencies = [ + "ambient-authority", + "rand", +] + +[[package]] +name = "cap-std" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "593db20e4c51f62d3284bae7ee718849c3214f93a3b94ea1899ad85ba119d330" +dependencies = [ + "cap-primitives", + "io-extras", + "io-lifetimes", + "rustix", +] + +[[package]] +name = "cap-time-ext" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03261630f291f425430a36f38c847828265bc928f517cdd2004c56f4b02f002b" +dependencies = [ + "ambient-authority", + "cap-primitives", + "iana-time-zone", + "once_cell", + "rustix", + "winx", +] + +[[package]] +name = "cargo-platform" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ceed8ef69d8518a5dda55c07425450b58a4e1946f4951eab6d7191ee86c2443d" +dependencies = [ + "serde", +] + +[[package]] +name = "cargo_metadata" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d886547e41f740c616ae73108f6eb70afe6d940c7bc697cb30f13daec073037" +dependencies = [ + "camino", + "cargo-platform", + "semver 1.0.21", + "serde", + "serde_json", + "thiserror", +] + +[[package]] +name = "cast" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" + +[[package]] +name = "cc" +version = "1.0.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" +dependencies = [ + "jobserver", + "libc", +] + +[[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 = "ciborium" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42e69ffd6f0917f5c029256a24d0161db17cea3997d185db0d35926308770f0e" +dependencies = [ + "ciborium-io", + "ciborium-ll", + "serde", +] + +[[package]] +name = "ciborium-io" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05afea1e0a06c9be33d539b876f1ce3692f4afea2cb41f740e7743225ed1c757" + +[[package]] +name = "ciborium-ll" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57663b653d948a338bfb3eeba9bb2fd5fcfaecb9e199e87e1eda4d9e8b240fd9" +dependencies = [ + "ciborium-io", + "half", +] + +[[package]] +name = "clang-sys" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67523a3b4be3ce1989d607a828d036249522dd9c1c8de7f4dd2dae43a37369d1" +dependencies = [ + "glob", + "libc", + "libloading", +] + +[[package]] +name = "clap" +version = "2.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c" +dependencies = [ + "ansi_term", + "atty", + "bitflags 1.3.2", + "strsim", + "textwrap", + "unicode-width", + "vec_map", +] + +[[package]] +name = "clap" +version = "4.4.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e578d6ec4194633722ccf9544794b71b1385c3c027efe0c55db226fc880865c" +dependencies = [ + "clap_builder", +] + +[[package]] +name = "clap_builder" +version = "4.4.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4df4df40ec50c46000231c914968278b1eb05098cf8f1b3a518a95030e71d1c7" +dependencies = [ + "anstyle", + "clap_lex", +] + +[[package]] +name = "clap_lex" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1" + +[[package]] +name = "cli" +version = "0.0.1" +dependencies = [ + "anyhow", + "binaryen", + "brotli", + "convert_case", + "criterion", + "lazy_static", + "num-format", + "serde", + "serde_json", + "serve", + "structopt", + "swc_core", + "tempfile", + "tokio", + "uuid", + "walrus", + "wasi-common", + "wasmparser 0.118.1", + "wasmprinter", + "wasmtime", + "wasmtime-wasi", + "wat", + "wit-parser", + "wizer", +] + +[[package]] +name = "cmake" +version = "0.1.50" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a31c789563b815f77f4250caee12365734369f942439b7defd71e18a48197130" +dependencies = [ + "cc", +] + +[[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" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" + +[[package]] +name = "cpp_demangle" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eeaa953eaad386a53111e47172c2fedba671e5684c8dd601a5f474f4f118710f" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "cpufeatures" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" +dependencies = [ + "libc", +] + +[[package]] +name = "cranelift-bforest" +version = "0.103.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c22542c0b95bd3302f7ed6839869c561f2324bac2fd5e7e99f5cfa65fdc8b92" +dependencies = [ + "cranelift-entity", +] + +[[package]] +name = "cranelift-codegen" +version = "0.103.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b3db903ef2e9c8a4de2ea6db5db052c7857282952f9df604aa55d169e6000d8" +dependencies = [ + "bumpalo", + "cranelift-bforest", + "cranelift-codegen-meta", + "cranelift-codegen-shared", + "cranelift-control", + "cranelift-entity", + "cranelift-isle", + "gimli 0.28.1", + "hashbrown 0.14.3", + "log", + "regalloc2", + "smallvec", + "target-lexicon", +] + +[[package]] +name = "cranelift-codegen-meta" +version = "0.103.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6590feb5a1d6438f974bf6a5ac4dddf69fca14e1f07f3265d880f69e61a94463" +dependencies = [ + "cranelift-codegen-shared", +] + +[[package]] +name = "cranelift-codegen-shared" +version = "0.103.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7239038c56fafe77fddc8788fc8533dd6c474dc5bdc5637216404f41ba807330" + +[[package]] +name = "cranelift-control" +version = "0.103.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7dc9c595341404d381d27a3d950160856b35b402275f0c3990cd1ad683c8053" +dependencies = [ + "arbitrary", +] + +[[package]] +name = "cranelift-entity" +version = "0.103.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44e3ee532fc4776c69bcedf7e62f9632cbb3f35776fa9a525cdade3195baa3f7" +dependencies = [ + "serde", + "serde_derive", +] + +[[package]] +name = "cranelift-frontend" +version = "0.103.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a612c94d09e653662ec37681dc2d6fd2b9856e6df7147be0afc9aabb0abf19df" +dependencies = [ + "cranelift-codegen", + "log", + "smallvec", + "target-lexicon", +] + +[[package]] +name = "cranelift-isle" +version = "0.103.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85db9830abeb1170b7d29b536ffd55af1d4d26ac8a77570b5d1aca003bf225cc" + +[[package]] +name = "cranelift-native" +version = "0.103.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "301ef0edafeaeda5771a5d2db64ac53e1818ae3111220a185677025fe91db4a1" +dependencies = [ + "cranelift-codegen", + "libc", + "target-lexicon", +] + +[[package]] +name = "cranelift-wasm" +version = "0.103.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "380f0abe8264e4570ac615fc31cef32a3b90a77f7eb97b08331f9dd357b1f500" +dependencies = [ + "cranelift-codegen", + "cranelift-entity", + "cranelift-frontend", + "itertools 0.10.5", + "log", + "smallvec", + "wasmparser 0.118.1", + "wasmtime-types", +] + +[[package]] +name = "crc32fast" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "criterion" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2b12d017a929603d80db1831cd3a24082f8137ce19c69e6447f54f5fc8d692f" +dependencies = [ + "anes", + "cast", + "ciborium", + "clap 4.4.18", + "criterion-plot", + "is-terminal", + "itertools 0.10.5", + "num-traits", + "once_cell", + "oorandom", + "plotters", + "rayon", + "regex", + "serde", + "serde_derive", + "serde_json", + "tinytemplate", + "walkdir", +] + +[[package]] +name = "criterion-plot" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b50826342786a51a89e2da3a28f1c32b06e387201bc2d19791f622c673706b1" +dependencies = [ + "cast", + "itertools 0.10.5", +] + +[[package]] +name = "crossbeam-deque" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345" + +[[package]] +name = "crunchy" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" + +[[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 = "data-encoding" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e962a19be5cfc3f3bf6dd8f61eb50107f356ad6270fbb3ed41476571db78be5" + +[[package]] +name = "debugid" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef552e6f588e446098f6ba40d89ac146c8c7b64aade83c051ee00bb5d2bc18d" +dependencies = [ + "serde", + "uuid", +] + +[[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 = "directories-next" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "339ee130d97a610ea5a5872d2bbb130fdf68884ff09d3028b81bec8a1ac23bbc" +dependencies = [ + "cfg-if", + "dirs-sys-next", +] + +[[package]] +name = "dirs" +version = "4.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca3aa72a6f96ea37bbc5aa912f6788242832f75369bdfdadcb0e38423f100059" +dependencies = [ + "dirs-sys", +] + +[[package]] +name = "dirs-sys" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b1d1d91c932ef41c0f2663aa8b0ca0342d444d842c06914aa0a7e352d0bada6" +dependencies = [ + "libc", + "redox_users", + "winapi", +] + +[[package]] +name = "dirs-sys-next" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d" +dependencies = [ + "libc", + "redox_users", + "winapi", +] + +[[package]] +name = "either" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" + +[[package]] +name = "encoding_rs" +version = "0.8.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7268b386296a025e474d5140678f75d6de9493ae55a5d709eeb9dd08149945e1" +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.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "fallible-iterator" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7" + +[[package]] +name = "fallible-iterator" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2acce4a10f12dc2fb14a218589d4f1f62ef011b2d0cc4b3cb1bba8e94da14649" + +[[package]] +name = "fastrand" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" + +[[package]] +name = "fd-lock" +version = "4.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e5768da2206272c81ef0b5e951a41862938a6070da63bcea197899942d3b947" +dependencies = [ + "cfg-if", + "rustix", + "windows-sys 0.52.0", +] + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "foreign-types" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" +dependencies = [ + "foreign-types-shared", +] + +[[package]] +name = "foreign-types-shared" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" + +[[package]] +name = "form_urlencoded" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" +dependencies = [ + "percent-encoding", +] + +[[package]] +name = "from_variant" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a0b11eeb173ce52f84ebd943d42e58813a2ebb78a6a3ff0a243b71c5199cd7b" +dependencies = [ + "proc-macro2", + "swc_macros_common", + "syn 2.0.48", +] + +[[package]] +name = "fs-set-times" +version = "0.20.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "033b337d725b97690d86893f9de22b67b80dcc4e9ad815f348254c38119db8fb" +dependencies = [ + "io-lifetimes", + "rustix", + "windows-sys 0.52.0", +] + +[[package]] +name = "futures" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" + +[[package]] +name = "futures-executor" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-io" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" + +[[package]] +name = "futures-macro" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.48", +] + +[[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-channel", + "futures-core", + "futures-io", + "futures-macro", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite", + "pin-utils", + "slab", +] + +[[package]] +name = "fxhash" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c" +dependencies = [ + "byteorder", +] + +[[package]] +name = "fxprof-processed-profile" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27d12c0aed7f1e24276a241aadc4cb8ea9f83000f34bc062b7cc2d51e3b0fabd" +dependencies = [ + "bitflags 2.4.2", + "debugid", + "fxhash", + "serde", + "serde_json", +] + +[[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.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "gimli" +version = "0.26.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22030e2c5a68ec659fde1e949a745124b48e6fa8b045b7ed5bd1fe4ccc5c4e5d" +dependencies = [ + "fallible-iterator 0.2.0", + "indexmap 1.9.3", + "stable_deref_trait", +] + +[[package]] +name = "gimli" +version = "0.28.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" +dependencies = [ + "fallible-iterator 0.3.0", + "indexmap 2.2.2", + "stable_deref_trait", +] + +[[package]] +name = "glob" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" + +[[package]] +name = "h2" +version = "0.3.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb2c4422095b67ee78da96fbb51a4cc413b3b25883c7717ff7ca1ab31022c9c9" +dependencies = [ + "bytes", + "fnv", + "futures-core", + "futures-sink", + "futures-util", + "http 0.2.11", + "indexmap 2.2.2", + "slab", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "half" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc52e53916c08643f1b56ec082790d1e86a32e58dc5268f897f313fbae7b4872" +dependencies = [ + "cfg-if", + "crunchy", +] + +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" + +[[package]] +name = "hashbrown" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e" +dependencies = [ + "ahash", +] + +[[package]] +name = "hashbrown" +version = "0.14.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" +dependencies = [ + "ahash", +] + +[[package]] +name = "heck" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c" +dependencies = [ + "unicode-segmentation", +] + +[[package]] +name = "heck" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" + +[[package]] +name = "hermit-abi" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" +dependencies = [ + "libc", +] + +[[package]] +name = "hermit-abi" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d3d0e0f38255e7fa3cf31335b3a56f05febd18025f4db5ef7a0cfb4f8da651f" + +[[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 = "hstr" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17fafeca18cf0927e23ea44d7a5189c10536279dfe9094e0dfa953053fbb5377" +dependencies = [ + "new_debug_unreachable", + "once_cell", + "phf", + "rustc-hash", + "smallvec", +] + +[[package]] +name = "http" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8947b1a6fad4393052c7ba1f4cd97bed3e953a95c79c92ad9b051a04611d9fbb" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "http" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b32afd38673a8016f7c9ae69e5af41a58f81b1d31689040f2f1959594ce194ea" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "http-body" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" +dependencies = [ + "bytes", + "http 0.2.11", + "pin-project-lite", +] + +[[package]] +name = "http-body" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cac85db508abc24a2e48553ba12a996e87244a0395ce011e62b37158745d643" +dependencies = [ + "bytes", + "http 1.0.0", +] + +[[package]] +name = "http-body-util" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41cb79eb393015dadd30fc252023adb0b2400a0caee0fa2a077e6e21a551e840" +dependencies = [ + "bytes", + "futures-util", + "http 1.0.0", + "http-body 1.0.0", + "pin-project-lite", +] + +[[package]] +name = "httparse" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" + +[[package]] +name = "httpdate" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" + +[[package]] +name = "hyper" +version = "0.14.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf96e135eb83a2a8ddf766e426a841d8ddd7449d5f00d34ea02b41d2f19eef80" +dependencies = [ + "bytes", + "futures-channel", + "futures-core", + "futures-util", + "h2", + "http 0.2.11", + "http-body 0.4.6", + "httparse", + "httpdate", + "itoa", + "pin-project-lite", + "socket2", + "tokio", + "tower-service", + "tracing", + "want", +] + +[[package]] +name = "hyper" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb5aa53871fc917b1a9ed87b683a5d86db645e23acb32c2e0785a353e522fb75" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "http 1.0.0", + "http-body 1.0.0", + "httparse", + "itoa", + "pin-project-lite", + "tokio", + "want", +] + +[[package]] +name = "hyper-tls" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" +dependencies = [ + "bytes", + "http-body-util", + "hyper 1.1.0", + "hyper-util", + "native-tls", + "tokio", + "tokio-native-tls", + "tower-service", +] + +[[package]] +name = "hyper-util" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca38ef113da30126bbff9cd1705f9273e15d45498615d138b0c20279ac7a76aa" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "http 1.0.0", + "http-body 1.0.0", + "hyper 1.1.0", + "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 = "id-arena" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25a2bc672d1148e28034f176e01fffebb08b35768468cc954630da77a1449005" + +[[package]] +name = "idna" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" +dependencies = [ + "unicode-bidi", + "unicode-normalization", +] + +[[package]] +name = "if_chain" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb56e1aa765b4b4f3aadfab769793b7087bb03a4ea4920644a6d238e2df5b9ed" + +[[package]] +name = "indexmap" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" +dependencies = [ + "autocfg", + "hashbrown 0.12.3", +] + +[[package]] +name = "indexmap" +version = "2.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "824b2ae422412366ba479e8111fd301f7b5faece8149317bb81925979a53f520" +dependencies = [ + "equivalent", + "hashbrown 0.14.3", + "serde", +] + +[[package]] +name = "io-extras" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c301e73fb90e8a29e600a9f402d095765f74310d582916a952f618836a1bd1ed" +dependencies = [ + "io-lifetimes", + "windows-sys 0.52.0", +] + +[[package]] +name = "io-lifetimes" +version = "2.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a611371471e98973dbcab4e0ec66c31a10bc356eeb4d54a0e05eac8158fe38c" + +[[package]] +name = "ipnet" +version = "2.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" + +[[package]] +name = "is-macro" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59a85abdc13717906baccb5a1e435556ce0df215f242892f721dff62bf25288f" +dependencies = [ + "Inflector", + "proc-macro2", + "quote", + "syn 2.0.48", +] + +[[package]] +name = "is-terminal" +version = "0.4.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bad00257d07be169d870ab665980b06cdb366d792ad690bf2e76876dc503455" +dependencies = [ + "hermit-abi 0.3.4", + "rustix", + "windows-sys 0.52.0", +] + +[[package]] +name = "itertools" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +dependencies = [ + "either", +] + +[[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.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" + +[[package]] +name = "ittapi" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b996fe614c41395cdaedf3cf408a9534851090959d90d54a535f675550b64b1" +dependencies = [ + "anyhow", + "ittapi-sys", + "log", +] + +[[package]] +name = "ittapi-sys" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52f5385394064fa2c886205dba02598013ce83d3e92d33dbdc0c52fe0e7bf4fc" +dependencies = [ + "cc", +] + +[[package]] +name = "javy" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a19c120cb4edb704e21f55d5b10b9ea3fe38c51741f2bc10403d02add8d34921" +dependencies = [ + "anyhow", + "quickjs-wasm-rs", + "serde-transcode", + "serde_json", +] + +[[package]] +name = "jobserver" +version = "0.1.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c37f63953c4c63420ed5fd3d6d398c719489b9f872b9fa683262f8edd363c7d" +dependencies = [ + "libc", +] + +[[package]] +name = "js-sys" +version = "0.3.67" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a1d36f1235bc969acba30b7f5990b864423a6068a10f7c90ae8f0112e3a59d1" +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 = "leb128" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "884e2677b40cc8c339eaefcb701c32ef1fd2493d71118dc0ca4b6a736c93bd67" + +[[package]] +name = "libc" +version = "0.2.153" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" + +[[package]] +name = "libloading" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c571b676ddfc9a8c12f1f3d3085a7b163966a8fd8098a90640953ce5f6170161" +dependencies = [ + "cfg-if", + "windows-sys 0.48.0", +] + +[[package]] +name = "libredox" +version = "0.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85c833ca1e66078851dba29046874e38f08b2c883700aa29a03ddd3b23814ee8" +dependencies = [ + "bitflags 2.4.2", + "libc", + "redox_syscall", +] + +[[package]] +name = "linux-raw-sys" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c" + +[[package]] +name = "lock_api" +version = "0.4.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45" +dependencies = [ + "autocfg", + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" + +[[package]] +name = "mach" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b823e83b2affd8f40a9ee8c29dbc56404c1e34cd2710921f2801e2cf29527afa" +dependencies = [ + "libc", +] + +[[package]] +name = "matchers" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" +dependencies = [ + "regex-automata 0.1.10", +] + +[[package]] +name = "maybe-owned" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4facc753ae494aeb6e3c22f839b158aebd4f9270f55cd3c79906c45476c47ab4" + +[[package]] +name = "memchr" +version = "2.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" + +[[package]] +name = "memfd" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2cffa4ad52c6f791f4f8b15f0c05f9824b2ced1160e88cc393d64fff9a8ac64" +dependencies = [ + "rustix", +] + +[[package]] +name = "memoffset" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a634b1c61a95585bd15607c6ab0c4e5b226e695ff2800ba0cdccddf208c406c" +dependencies = [ + "autocfg", +] + +[[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.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" +dependencies = [ + "adler", +] + +[[package]] +name = "mio" +version = "0.8.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f3d0b296e374a4e6f3c7b0a1f5a51d748a0d34c85e7dc48fc3fa9a87657fe09" +dependencies = [ + "libc", + "wasi", + "windows-sys 0.48.0", +] + +[[package]] +name = "native-tls" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07226173c32f2926027b63cce4bcd8076c3552846cbe7925f3aaffeac0a3b92e" +dependencies = [ + "lazy_static", + "libc", + "log", + "openssl", + "openssl-probe", + "openssl-sys", + "schannel", + "security-framework", + "security-framework-sys", + "tempfile", +] + +[[package]] +name = "new_debug_unreachable" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4a24736216ec316047a1fc4252e27dabb04218aa4a3f37c6e7ddbf1f9782b54" + +[[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 = "nu-ansi-term" +version = "0.46.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" +dependencies = [ + "overload", + "winapi", +] + +[[package]] +name = "num-bigint" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "608e7659b5c3d7cba262d894801b9ec9d00de989e8a82bd4bef91d08da45cdc0" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", + "serde", +] + +[[package]] +name = "num-format" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a652d9771a63711fd3c3deb670acfbe5c30a4072e664d7a3bf5a9e1056ac72c3" +dependencies = [ + "arrayvec", + "itoa", +] + +[[package]] +name = "num-integer" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" +dependencies = [ + "autocfg", + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c" +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 0.3.4", + "libc", +] + +[[package]] +name = "object" +version = "0.32.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" +dependencies = [ + "crc32fast", + "hashbrown 0.14.3", + "indexmap 2.2.2", + "memchr", +] + +[[package]] +name = "once_cell" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" + +[[package]] +name = "oorandom" +version = "11.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575" + +[[package]] +name = "openssl" +version = "0.10.63" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15c9d69dd87a29568d4d017cfe8ec518706046a05184e5aea92d0af890b803c8" +dependencies = [ + "bitflags 2.4.2", + "cfg-if", + "foreign-types", + "libc", + "once_cell", + "openssl-macros", + "openssl-sys", +] + +[[package]] +name = "openssl-macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.48", +] + +[[package]] +name = "openssl-probe" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" + +[[package]] +name = "openssl-sys" +version = "0.9.99" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22e1bf214306098e4832460f797824c05d25aacdf896f64a985fb0fd992454ae" +dependencies = [ + "cc", + "libc", + "pkg-config", + "vcpkg", +] + +[[package]] +name = "overload" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" + +[[package]] +name = "parking_lot" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-targets 0.48.5", +] + +[[package]] +name = "paste" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" + +[[package]] +name = "percent-encoding" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" + +[[package]] +name = "phf" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc" +dependencies = [ + "phf_macros", + "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_macros" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3444646e286606587e49f3bcf1679b8cef1dc2c5ecc29ddacaffc305180d464b" +dependencies = [ + "phf_generator", + "phf_shared", + "proc-macro2", + "quote", + "syn 2.0.48", +] + +[[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.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0302c4a0442c456bd56f841aee5c3bfd17967563f6fadc9ceb9f9c23cf3807e0" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "266c042b60c9c76b8d53061e52b2e0d1116abc57cefc8c5cd671619a56ac3690" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.48", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "pkg-config" +version = "0.3.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2900ede94e305130c13ddd391e0ab7cbaeb783945ae07a279c268cb05109c6cb" + +[[package]] +name = "plotters" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2c224ba00d7cadd4d5c660deaf2098e5e80e07846537c51f9cfa4be50c1fd45" +dependencies = [ + "num-traits", + "plotters-backend", + "plotters-svg", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "plotters-backend" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e76628b4d3a7581389a35d5b6e2139607ad7c75b17aed325f210aa91f4a9609" + +[[package]] +name = "plotters-svg" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38f6d39893cca0701371e3c27294f09797214b86f1fb951b89ade8ec04e2abab" +dependencies = [ + "plotters-backend", +] + +[[package]] +name = "pmutil" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52a40bc70c2c58040d2d8b167ba9a5ff59fc9dab7ad44771cfde3dcfde7a09c6" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.48", +] + +[[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.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a41cf62165e97c7f814d2221421dbb9afcbcdb0a88068e5ea206e19951c2cbb5" +dependencies = [ + "proc-macro2", + "syn 2.0.48", +] + +[[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", + "quote", + "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", + "quote", + "version_check", +] + +[[package]] +name = "proc-macro2" +version = "1.0.78" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "psm" +version = "0.1.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5787f7cda34e3033a72192c018bc5883100330f362ef279a8cbccfce8bb4e874" +dependencies = [ + "cc", +] + +[[package]] +name = "quickjs-wasm-rs" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2ac26c035fca8cb3fbbe2aae881f5630b1570aebb8fe19d30a320320913d00d" +dependencies = [ + "anyhow", + "once_cell", + "quickjs-wasm-sys", + "serde", +] + +[[package]] +name = "quickjs-wasm-sys" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d96c8767ef96ee1a3166330bec6ffc7670a6cf8abe9d0a4f7974906db16f9cc" +dependencies = [ + "anyhow", + "bindgen", + "cc", + "http-body-util", + "hyper 1.1.0", + "hyper-tls", + "hyper-util", + "tokio", + "walkdir", +] + +[[package]] +name = "quote" +version = "1.0.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" +dependencies = [ + "proc-macro2", +] + +[[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 = "rayon" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa7237101a77a10773db45d62004a272517633fbcc3df19d96455ede1122e051" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" +dependencies = [ + "crossbeam-deque", + "crossbeam-utils", +] + +[[package]] +name = "redox_syscall" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" +dependencies = [ + "bitflags 1.3.2", +] + +[[package]] +name = "redox_users" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a18479200779601e498ada4e8c1e1f50e3ee19deb0259c25825a98b5603b2cb4" +dependencies = [ + "getrandom", + "libredox", + "thiserror", +] + +[[package]] +name = "regalloc2" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad156d539c879b7a24a363a2016d77961786e71f48f2e2fc8302a92abd2429a6" +dependencies = [ + "hashbrown 0.13.2", + "log", + "rustc-hash", + "slice-group-by", + "smallvec", +] + +[[package]] +name = "regex" +version = "1.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b62dbe01f0b06f9d8dc7d49e05a0785f153b00b2c227856282f671e0318c9b15" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata 0.4.5", + "regex-syntax 0.8.2", +] + +[[package]] +name = "regex-automata" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" +dependencies = [ + "regex-syntax 0.6.29", +] + +[[package]] +name = "regex-automata" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5bb987efffd3c6d0d8f5f89510bb458559eab11e4f869acb20bf845e016259cd" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax 0.8.2", +] + +[[package]] +name = "regex-syntax" +version = "0.6.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" + +[[package]] +name = "regex-syntax" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" + +[[package]] +name = "rustc-demangle" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" + +[[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.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" +dependencies = [ + "semver 0.9.0", +] + +[[package]] +name = "rustix" +version = "0.38.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ea3e1a662af26cd7a3ba09c0297a31af215563ecf42817c98df621387f4e949" +dependencies = [ + "bitflags 2.4.2", + "errno", + "itoa", + "libc", + "linux-raw-sys", + "once_cell", + "windows-sys 0.52.0", +] + +[[package]] +name = "rustversion" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" + +[[package]] +name = "ryu" +version = "1.0.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f98d2aa92eebf49b69786be48e4477826b256916e84a57ff2a4f21923b48eb4c" + +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "schannel" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fbc91545643bcf3a0bbb6569265615222618bdf33ce4ffbbd13c4bbd4c093534" +dependencies = [ + "windows-sys 0.52.0", +] + +[[package]] +name = "scoped-tls" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "security-framework" +version = "2.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05b64fb303737d99b81884b2c63433e9ae28abebe5eb5045dcdd175dc2ecf4de" +dependencies = [ + "bitflags 1.3.2", + "core-foundation", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework-sys" +version = "2.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e932934257d3b408ed8f30db49d85ea163bfe74961f017f405b025af298f0c7a" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "semver" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" +dependencies = [ + "semver-parser", +] + +[[package]] +name = "semver" +version = "1.0.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b97ed7a9823b74f99c7742f5336af7be5ecd3eeafcb1507d1fa93347b1d589b0" +dependencies = [ + "serde", +] + +[[package]] +name = "semver-parser" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" + +[[package]] +name = "serde" +version = "1.0.196" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "870026e60fa08c69f064aa766c10f10b1d62db9ccd4d0abb206472bee0ce3b32" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde-transcode" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "590c0e25c2a5bb6e85bf5c1bce768ceb86b316e7a01bdf07d2cb4ec2271990e2" +dependencies = [ + "serde", +] + +[[package]] +name = "serde_derive" +version = "1.0.196" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33c85360c95e7d137454dc81d9a4ed2b8efd8fbe19cee57357b32b9771fccb67" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.48", +] + +[[package]] +name = "serde_json" +version = "1.0.113" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69801b70b1c3dac963ecb03a364ba0ceda9cf60c71cfe475e99864759c8b8a79" +dependencies = [ + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "serve" +version = "0.0.1" +dependencies = [ + "anyhow", + "futures", + "hyper 0.14.28", + "serde", + "serde_json", + "tokio", + "tracing", + "tracing-subscriber", + "wasi-common", + "wasmtime", + "wasmtime-wasi", +] + +[[package]] +name = "sha2" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "sharded-slab" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" +dependencies = [ + "lazy_static", +] + +[[package]] +name = "shellexpand" +version = "2.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ccc8076840c4da029af4f87e4e8daeb0fca6b87bbb02e10cb60b791450e11e4" +dependencies = [ + "dirs", +] + +[[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.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1" +dependencies = [ + "libc", +] + +[[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 = "slice-group-by" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "826167069c09b99d56f31e9ae5c99049e932a98c9dc2dac47645b08dbbf76ba7" + +[[package]] +name = "smallvec" +version = "1.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6ecd384b10a64542d77071bd64bd7b231f4ed5940fba55e98c3de13824cf3d7" + +[[package]] +name = "smartstring" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fb72c633efbaa2dd666986505016c32c3044395ceaf881518399d2f4127ee29" +dependencies = [ + "autocfg", + "static_assertions", + "version_check", +] + +[[package]] +name = "socket2" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b5fac59a5cb5dd637972e5fca70daf0523c9067fcdc4842f053dae04a18f8e9" +dependencies = [ + "libc", + "windows-sys 0.48.0", +] + +[[package]] +name = "sourcemap" +version = "6.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4cbf65ca7dc576cf50e21f8d0712d96d4fcfd797389744b7b222a85cdf5bd90" +dependencies = [ + "data-encoding", + "debugid", + "if_chain", + "rustc_version", + "serde", + "serde_json", + "unicode-id", + "url", +] + +[[package]] +name = "sptr" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b9b39299b249ad65f3b7e96443bad61c02ca5cd3589f46cb6d610a0fd6c0d6a" + +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + +[[package]] +name = "stacker" +version = "0.1.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c886bd4480155fd3ef527d45e9ac8dd7118a898a46530b7b94c3e21866259fce" +dependencies = [ + "cc", + "cfg-if", + "libc", + "psm", + "winapi", +] + +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + +[[package]] +name = "string_enum" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b650ea2087d32854a0f20b837fc56ec987a1cb4f758c9757e1171ee9812da63" +dependencies = [ + "proc-macro2", + "quote", + "swc_macros_common", + "syn 2.0.48", +] + +[[package]] +name = "strsim" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" + +[[package]] +name = "structopt" +version = "0.3.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c6b5c64445ba8094a6ab0c3cd2ad323e07171012d9c98b0b15651daf1787a10" +dependencies = [ + "clap 2.34.0", + "lazy_static", + "structopt-derive", +] + +[[package]] +name = "structopt-derive" +version = "0.4.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcb5ae327f9cc13b68763b5749770cb9e048a99bd9dfdfa58d0cf05d5f64afe0" +dependencies = [ + "heck 0.3.3", + "proc-macro-error", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "swc_atoms" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d538eaaa6f085161d088a04cf0a3a5a52c5a7f2b3bd9b83f73f058b0ed357c0" +dependencies = [ + "hstr", + "once_cell", + "rustc-hash", + "serde", +] + +[[package]] +name = "swc_common" +version = "0.33.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3792c10fa5d3e93a705b31f13fdea4a6e68c3c20d4351e84ed1741b7864399cd" +dependencies = [ + "ast_node", + "better_scoped_tls", + "cfg-if", + "either", + "from_variant", + "new_debug_unreachable", + "num-bigint", + "once_cell", + "rustc-hash", + "serde", + "siphasher", + "sourcemap", + "swc_atoms", + "swc_eq_ignore_macros", + "swc_visit", + "tracing", + "unicode-width", + "url", +] + +[[package]] +name = "swc_core" +version = "0.87.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b3e389aed344d9d738f7e0901a1778a8402f10e459556c6d3a7a5b4501bf4cf" +dependencies = [ + "swc_atoms", + "swc_common", + "swc_ecma_ast", + "swc_ecma_parser", + "swc_ecma_transforms_base", + "vergen", +] + +[[package]] +name = "swc_ecma_ast" +version = "0.110.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79401a45da704f4fb2552c5bf86ee2198e8636b121cb81f8036848a300edd53b" +dependencies = [ + "bitflags 2.4.2", + "is-macro", + "num-bigint", + "phf", + "scoped-tls", + "string_enum", + "swc_atoms", + "swc_common", + "unicode-id", +] + +[[package]] +name = "swc_ecma_parser" +version = "0.141.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4d17401dd95048a6a62b777d533c0999dabdd531ef9d667e22f8ae2a2a0d294" +dependencies = [ + "either", + "new_debug_unreachable", + "num-bigint", + "num-traits", + "phf", + "serde", + "smallvec", + "smartstring", + "stacker", + "swc_atoms", + "swc_common", + "swc_ecma_ast", + "tracing", + "typed-arena", +] + +[[package]] +name = "swc_ecma_transforms_base" +version = "0.135.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6f0efec63cc56f3f2b93d1367d16e684d1c6f4a6cb85436db2c91448867df2b" +dependencies = [ + "better_scoped_tls", + "bitflags 2.4.2", + "indexmap 2.2.2", + "once_cell", + "phf", + "rustc-hash", + "serde", + "smallvec", + "swc_atoms", + "swc_common", + "swc_ecma_ast", + "swc_ecma_parser", + "swc_ecma_utils", + "swc_ecma_visit", + "tracing", +] + +[[package]] +name = "swc_ecma_utils" +version = "0.125.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7cead1083e46b0f072a82938f16d366014468f7510350957765bb4d013496890" +dependencies = [ + "indexmap 2.2.2", + "num_cpus", + "once_cell", + "rustc-hash", + "swc_atoms", + "swc_common", + "swc_ecma_ast", + "swc_ecma_visit", + "tracing", + "unicode-id", +] + +[[package]] +name = "swc_ecma_visit" +version = "0.96.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1d0100c383fb08b6f34911ab6f925950416a5d14404c1cd520d59fb8dfbb3bf" +dependencies = [ + "num-bigint", + "swc_atoms", + "swc_common", + "swc_ecma_ast", + "swc_visit", + "tracing", +] + +[[package]] +name = "swc_eq_ignore_macros" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "695a1d8b461033d32429b5befbf0ad4d7a2c4d6ba9cd5ba4e0645c615839e8e4" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.48", +] + +[[package]] +name = "swc_macros_common" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50176cfc1cbc8bb22f41c6fe9d1ec53fbe057001219b5954961b8ad0f336fce9" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.48", +] + +[[package]] +name = "swc_visit" +version = "0.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b27078d8571abe23aa52ef608dd1df89096a37d867cf691cbb4f4c392322b7c9" +dependencies = [ + "either", + "swc_visit_macros", +] + +[[package]] +name = "swc_visit_macros" +version = "0.5.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa8bb05975506741555ea4d10c3a3bdb0e2357cd58e1a4a4332b8ebb4b44c34d" +dependencies = [ + "Inflector", + "pmutil", + "proc-macro2", + "quote", + "swc_macros_common", + "syn 2.0.48", +] + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.48" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f3531638e407dfc0814761abb7c00a5b54992b849452a0646b7f65c9f770f3f" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "system-interface" +version = "0.26.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0682e006dd35771e392a6623ac180999a9a854b1d4a6c12fb2e804941c2b1f58" +dependencies = [ + "bitflags 2.4.2", + "cap-fs-ext", + "cap-std", + "fd-lock", + "io-lifetimes", + "rustix", + "windows-sys 0.52.0", + "winx", +] + +[[package]] +name = "target-lexicon" +version = "0.12.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69758bda2e78f098e4ccb393021a0963bb3442eac05f135c30f61b7370bbafae" + +[[package]] +name = "tempfile" +version = "3.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01ce4141aa927a6d1bd34a041795abd0db1cccba5d5f24b009f694bdf3a1f3fa" +dependencies = [ + "cfg-if", + "fastrand", + "redox_syscall", + "rustix", + "windows-sys 0.52.0", +] + +[[package]] +name = "textwrap" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" +dependencies = [ + "unicode-width", +] + +[[package]] +name = "thiserror" +version = "1.0.56" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d54378c645627613241d077a3a79db965db602882668f9136ac42af9ecb730ad" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.56" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa0faa943b50f3db30a20aa7e265dbc66076993efed8463e8de414e5d06d3471" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.48", +] + +[[package]] +name = "thread_local" +version = "1.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fdd6f064ccff2d6567adcb3873ca630700f00b5ad3f060c25b5dcfd9a4ce152" +dependencies = [ + "cfg-if", + "once_cell", +] + +[[package]] +name = "tinytemplate" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be4d6b5f19ff7664e8c98d03e2139cb510db9b0a60b55f8e8709b689d939b6bc" +dependencies = [ + "serde", + "serde_json", +] + +[[package]] +name = "tinyvec" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + +[[package]] +name = "tokio" +version = "1.36.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61285f6515fa018fb2d1e46eb21223fff441ee8db5d0f1435e8ab4f5cdb80931" +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.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.48", +] + +[[package]] +name = "tokio-native-tls" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" +dependencies = [ + "native-tls", + "tokio", +] + +[[package]] +name = "tokio-util" +version = "0.7.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5419f34732d9eb6ee4c3578b7989078579b7f039cbbb9ca2c4da015749371e15" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "pin-project-lite", + "tokio", + "tracing", +] + +[[package]] +name = "toml" +version = "0.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234" +dependencies = [ + "serde", +] + +[[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", + "tracing", +] + +[[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 = [ + "log", + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.48", +] + +[[package]] +name = "tracing-core" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" +dependencies = [ + "once_cell", + "valuable", +] + +[[package]] +name = "tracing-log" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" +dependencies = [ + "log", + "once_cell", + "tracing-core", +] + +[[package]] +name = "tracing-subscriber" +version = "0.3.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b" +dependencies = [ + "matchers", + "nu-ansi-term", + "once_cell", + "regex", + "sharded-slab", + "smallvec", + "thread_local", + "tracing", + "tracing-core", + "tracing-log", +] + +[[package]] +name = "try-lock" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" + +[[package]] +name = "typed-arena" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6af6ae20167a9ece4bcb41af5b80f8a1f1df981f6391189ce00fd257af04126a" + +[[package]] +name = "typenum" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" + +[[package]] +name = "unicode-bidi" +version = "0.3.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" + +[[package]] +name = "unicode-id" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1b6def86329695390197b82c1e244a54a131ceb66c996f2088a3876e2ae083f" + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + +[[package]] +name = "unicode-normalization" +version = "0.1.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" +dependencies = [ + "tinyvec", +] + +[[package]] +name = "unicode-segmentation" +version = "1.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36" + +[[package]] +name = "unicode-width" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" + +[[package]] +name = "unicode-xid" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" + +[[package]] +name = "url" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", +] + +[[package]] +name = "uuid" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f00cc9702ca12d3c81455259621e676d0f7251cec66a21e98fe2e9a37db93b2a" +dependencies = [ + "getrandom", +] + +[[package]] +name = "valuable" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" + +[[package]] +name = "vcpkg" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" + +[[package]] +name = "vec_map" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" + +[[package]] +name = "vergen" +version = "8.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e27d6bdd219887a9eadd19e1c34f32e47fa332301184935c6d9bca26f3cca525" +dependencies = [ + "anyhow", + "cargo_metadata", + "regex", + "rustversion", +] + +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + +[[package]] +name = "walkdir" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d71d857dc86794ca4c280d616f7da00d2dbfd8cd788846559a6813e6aa4b54ee" +dependencies = [ + "same-file", + "winapi-util", +] + +[[package]] +name = "walrus" +version = "0.20.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c03529cd0c4400a2449f640d2f27cd1b48c3065226d15e26d98e4429ab0adb7" +dependencies = [ + "anyhow", + "gimli 0.26.2", + "id-arena", + "leb128", + "log", + "walrus-macro", + "wasm-encoder 0.29.0", + "wasmparser 0.80.2", +] + +[[package]] +name = "walrus-macro" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a6e5bd22c71e77d60140b0bd5be56155a37e5bd14e24f5f87298040d0cc40d7" +dependencies = [ + "heck 0.3.3", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[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 = "wasi-cap-std-sync" +version = "16.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "154528979a211aa28d969846e883df75705809ed9bcc70aba61460683ea7355b" +dependencies = [ + "anyhow", + "async-trait", + "cap-fs-ext", + "cap-rand", + "cap-std", + "cap-time-ext", + "fs-set-times", + "io-extras", + "io-lifetimes", + "once_cell", + "rustix", + "system-interface", + "tracing", + "wasi-common", + "windows-sys 0.48.0", +] + +[[package]] +name = "wasi-common" +version = "16.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d888b611fee7d273dd057dc009d2dd3132736f36710ffd65657ac83628d1e3b" +dependencies = [ + "anyhow", + "bitflags 2.4.2", + "cap-rand", + "cap-std", + "io-extras", + "log", + "rustix", + "thiserror", + "tracing", + "wasmtime", + "wiggle", + "windows-sys 0.48.0", +] + +[[package]] +name = "wasm-bindgen" +version = "0.2.90" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1223296a201415c7fad14792dbefaace9bd52b62d33453ade1c5b5f07555406" +dependencies = [ + "cfg-if", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.90" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcdc935b63408d58a32f8cc9738a0bffd8f05cc7c002086c6ef20b7312ad9dcd" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn 2.0.48", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.90" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e4c238561b2d428924c49815533a8b9121c664599558a5d9ec51f8a1740a999" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.90" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bae1abb6806dc1ad9e560ed242107c0f6c84335f1749dd4e8ddb012ebd5e25a7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.48", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.90" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d91413b1c31d7539ba5ef2451af3f0b833a005eb27a631cec32bc0635a8602b" + +[[package]] +name = "wasm-encoder" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18c41dbd92eaebf3612a39be316540b8377c871cb9bde6b064af962984912881" +dependencies = [ + "leb128", +] + +[[package]] +name = "wasm-encoder" +version = "0.30.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2f8e9778e04cbf44f58acc301372577375a666b966c50b03ef46144f80436a8" +dependencies = [ + "leb128", +] + +[[package]] +name = "wasm-encoder" +version = "0.38.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ad2b51884de9c7f4fe2fd1043fccb8dcad4b1e29558146ee57a144d15779f3f" +dependencies = [ + "leb128", +] + +[[package]] +name = "wasm-encoder" +version = "0.41.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e09bca7d6388637d27fb5edbeab11f56bfabcef8743c55ae34370e1e5030a071" +dependencies = [ + "leb128", +] + +[[package]] +name = "wasmparser" +version = "0.80.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "449167e2832691a1bff24cde28d2804e90e09586a448c8e76984792c44334a6b" + +[[package]] +name = "wasmparser" +version = "0.106.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d014e33793cab91655fa6349b0bc974984de106b2e0f6b0dfe6f6594b260624d" +dependencies = [ + "indexmap 1.9.3", + "url", +] + +[[package]] +name = "wasmparser" +version = "0.118.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95ee9723b928e735d53000dec9eae7b07a60e490c85ab54abb66659fc61bfcd9" +dependencies = [ + "indexmap 2.2.2", + "semver 1.0.21", +] + +[[package]] +name = "wasmparser" +version = "0.121.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "953cf6a7606ab31382cb1caa5ae403e77ba70c7f8e12eeda167e7040d42bfda8" +dependencies = [ + "bitflags 2.4.2", + "indexmap 2.2.2", + "semver 1.0.21", +] + +[[package]] +name = "wasmprinter" +version = "0.2.78" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05e32c13c59fdc64d3f6998a1d52eb1d362b6904a88b754190ccb85661ad577a" +dependencies = [ + "anyhow", + "wasmparser 0.121.0", +] + +[[package]] +name = "wasmtime" +version = "16.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8e539fded2495422ea3c4dfa7beeddba45904eece182cf315294009e1a323bf" +dependencies = [ + "anyhow", + "async-trait", + "bincode", + "bumpalo", + "cfg-if", + "encoding_rs", + "fxprof-processed-profile", + "indexmap 2.2.2", + "libc", + "log", + "object", + "once_cell", + "paste", + "rayon", + "serde", + "serde_derive", + "serde_json", + "target-lexicon", + "wasm-encoder 0.38.1", + "wasmparser 0.118.1", + "wasmtime-cache", + "wasmtime-component-macro", + "wasmtime-component-util", + "wasmtime-cranelift", + "wasmtime-environ", + "wasmtime-fiber", + "wasmtime-jit", + "wasmtime-runtime", + "wasmtime-winch", + "wat", + "windows-sys 0.48.0", +] + +[[package]] +name = "wasmtime-asm-macros" +version = "16.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "660ba9143e15a2acd921820df221b73aee256bd3ca2d208d73d8adc9587ccbb9" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "wasmtime-cache" +version = "16.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3ce373743892002f9391c6741ef0cb0335b55ec899d874f311222b7e36f4594" +dependencies = [ + "anyhow", + "base64", + "bincode", + "directories-next", + "log", + "rustix", + "serde", + "serde_derive", + "sha2", + "toml", + "windows-sys 0.48.0", + "zstd", +] + +[[package]] +name = "wasmtime-component-macro" +version = "16.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12ef32643324e564e1c359e9044daa06cbf90d7e2d6c99a738d17a12959f01a5" +dependencies = [ + "anyhow", + "proc-macro2", + "quote", + "syn 2.0.48", + "wasmtime-component-util", + "wasmtime-wit-bindgen", + "wit-parser", +] + +[[package]] +name = "wasmtime-component-util" +version = "16.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c87d06c18d21a4818f354c00a85f4ebc62b2270961cd022968452b0e4dbed9d" + +[[package]] +name = "wasmtime-cranelift" +version = "16.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d648c8b4064a7911093b02237cd5569f71ca171d3a0a486bf80600b19e1cba2" +dependencies = [ + "anyhow", + "cfg-if", + "cranelift-codegen", + "cranelift-control", + "cranelift-entity", + "cranelift-frontend", + "cranelift-native", + "cranelift-wasm", + "gimli 0.28.1", + "log", + "object", + "target-lexicon", + "thiserror", + "wasmparser 0.118.1", + "wasmtime-cranelift-shared", + "wasmtime-environ", + "wasmtime-versioned-export-macros", +] + +[[package]] +name = "wasmtime-cranelift-shared" +version = "16.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "290a89027688782da8ff60b12bb95695494b1874e0d0ba2ba387d23dace6d70c" +dependencies = [ + "anyhow", + "cranelift-codegen", + "cranelift-control", + "cranelift-native", + "gimli 0.28.1", + "object", + "target-lexicon", + "wasmtime-environ", +] + +[[package]] +name = "wasmtime-environ" +version = "16.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61eb64fb3e0da883e2df4a13a81d6282e072336e6cb6295021d0f7ab2e352754" +dependencies = [ + "anyhow", + "cranelift-entity", + "gimli 0.28.1", + "indexmap 2.2.2", + "log", + "object", + "serde", + "serde_derive", + "target-lexicon", + "thiserror", + "wasm-encoder 0.38.1", + "wasmparser 0.118.1", + "wasmprinter", + "wasmtime-component-util", + "wasmtime-types", +] + +[[package]] +name = "wasmtime-fiber" +version = "16.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40ecf1d3a838b0956b71ad3f8cb80069a228339775bf02dd35d86a5a68bbe443" +dependencies = [ + "anyhow", + "cc", + "cfg-if", + "rustix", + "wasmtime-asm-macros", + "wasmtime-versioned-export-macros", + "windows-sys 0.48.0", +] + +[[package]] +name = "wasmtime-jit" +version = "16.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f485336add49267d8859e8f8084d2d4b9a4b1564496b6f30ba5b168d50c10ceb" +dependencies = [ + "addr2line", + "anyhow", + "bincode", + "cfg-if", + "cpp_demangle", + "gimli 0.28.1", + "ittapi", + "log", + "object", + "rustc-demangle", + "rustix", + "serde", + "serde_derive", + "target-lexicon", + "wasmtime-environ", + "wasmtime-jit-debug", + "wasmtime-jit-icache-coherence", + "wasmtime-runtime", + "windows-sys 0.48.0", +] + +[[package]] +name = "wasmtime-jit-debug" +version = "16.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "65e119affec40edb2fab9044f188759a00c2df9c3017278d047012a2de1efb4f" +dependencies = [ + "object", + "once_cell", + "rustix", + "wasmtime-versioned-export-macros", +] + +[[package]] +name = "wasmtime-jit-icache-coherence" +version = "16.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b6d197fcc34ad32ed440e1f9552fd57d1f377d9699d31dee1b5b457322c1f8a" +dependencies = [ + "cfg-if", + "libc", + "windows-sys 0.48.0", +] + +[[package]] +name = "wasmtime-runtime" +version = "16.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "794b2bb19b99ef8322ff0dd9fe1ba7e19c41036dfb260b3f99ecce128c42ff92" +dependencies = [ + "anyhow", + "cc", + "cfg-if", + "encoding_rs", + "indexmap 2.2.2", + "libc", + "log", + "mach", + "memfd", + "memoffset", + "paste", + "psm", + "rustix", + "sptr", + "wasm-encoder 0.38.1", + "wasmtime-asm-macros", + "wasmtime-environ", + "wasmtime-fiber", + "wasmtime-jit-debug", + "wasmtime-versioned-export-macros", + "wasmtime-wmemcheck", + "windows-sys 0.48.0", +] + +[[package]] +name = "wasmtime-types" +version = "16.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d995db8bb56f2cd8d2dc0ed5ffab94ffb435283b0fe6747f80f7aab40b2d06a1" +dependencies = [ + "cranelift-entity", + "serde", + "serde_derive", + "thiserror", + "wasmparser 0.118.1", +] + +[[package]] +name = "wasmtime-versioned-export-macros" +version = "16.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f55c5565959287c21dd0f4277ae3518dd2ae62679f655ee2dbc4396e19d210db" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.48", +] + +[[package]] +name = "wasmtime-wasi" +version = "16.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccd8370078149d49a3a47e93741553fd79b700421464b6a27ca32718192ab130" +dependencies = [ + "anyhow", + "async-trait", + "bitflags 2.4.2", + "bytes", + "cap-fs-ext", + "cap-net-ext", + "cap-rand", + "cap-std", + "cap-time-ext", + "fs-set-times", + "futures", + "io-extras", + "io-lifetimes", + "libc", + "log", + "once_cell", + "rustix", + "system-interface", + "thiserror", + "tokio", + "tracing", + "url", + "wasi-cap-std-sync", + "wasi-common", + "wasmtime", + "wiggle", + "windows-sys 0.48.0", +] + +[[package]] +name = "wasmtime-winch" +version = "16.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c6f945ff9bad96e0a69973d74f193c19f627c8adbf250e7cb73ae7564b6cc8a" +dependencies = [ + "anyhow", + "cranelift-codegen", + "gimli 0.28.1", + "object", + "target-lexicon", + "wasmparser 0.118.1", + "wasmtime-cranelift-shared", + "wasmtime-environ", + "winch-codegen", +] + +[[package]] +name = "wasmtime-wit-bindgen" +version = "16.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f328b2d4a690270324756e886ed5be3a4da4c00be0eea48253f4595ad068062b" +dependencies = [ + "anyhow", + "heck 0.4.1", + "indexmap 2.2.2", + "wit-parser", +] + +[[package]] +name = "wasmtime-wmemcheck" +version = "16.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67761d8f8c0b3c13a5d34356274b10a40baba67fe9cfabbfc379a8b414e45de2" + +[[package]] +name = "wast" +version = "35.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ef140f1b49946586078353a453a1d28ba90adfc54dde75710bc1931de204d68" +dependencies = [ + "leb128", +] + +[[package]] +name = "wast" +version = "70.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3d5061300042ff5065123dae1e27d00c03f567d34a2937c8472255148a216dc" +dependencies = [ + "bumpalo", + "leb128", + "memchr", + "unicode-width", + "wasm-encoder 0.41.0", +] + +[[package]] +name = "wat" +version = "1.0.85" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "afd7357b6cc46d46a2509c43dcb1dd4131dafbf4e75562d87017b5a05ffad2d6" +dependencies = [ + "wast 70.0.2", +] + +[[package]] +name = "web-sys" +version = "0.3.67" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58cd2333b6e0be7a39605f0e255892fd7418a682d8da8fe042fe25128794d2ed" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[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 = "wiggle" +version = "16.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0afb26cd3269289bb314a361ff0a6685e5ce793b62181a9fe3f81ace15051697" +dependencies = [ + "anyhow", + "async-trait", + "bitflags 2.4.2", + "thiserror", + "tracing", + "wasmtime", + "wiggle-macro", +] + +[[package]] +name = "wiggle-generate" +version = "16.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cef2868fed7584d2b552fa317104858ded80021d23b073b2d682d3c932a027bd" +dependencies = [ + "anyhow", + "heck 0.4.1", + "proc-macro2", + "quote", + "shellexpand", + "syn 2.0.48", + "witx", +] + +[[package]] +name = "wiggle-macro" +version = "16.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31ae1ec11a17ea481539ee9a5719a278c9790d974060fbf71db4b2c05378780b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.48", + "wiggle-generate", +] + +[[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-util" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596" +dependencies = [ + "winapi", +] + +[[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 = "winch-codegen" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58e58c236a6abdd9ab454552b4f29e16cfa837a86897c1503313b2e62e7609ec" +dependencies = [ + "anyhow", + "cranelift-codegen", + "gimli 0.28.1", + "regalloc2", + "smallvec", + "target-lexicon", + "wasmparser 0.118.1", + "wasmtime-environ", +] + +[[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.0", +] + +[[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.0", +] + +[[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.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd" +dependencies = [ + "windows_aarch64_gnullvm 0.52.0", + "windows_aarch64_msvc 0.52.0", + "windows_i686_gnu 0.52.0", + "windows_i686_msvc 0.52.0", + "windows_x86_64_gnu 0.52.0", + "windows_x86_64_gnullvm 0.52.0", + "windows_x86_64_msvc 0.52.0", +] + +[[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.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" + +[[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.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" + +[[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.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" + +[[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.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" + +[[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.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd" + +[[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.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" + +[[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.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" + +[[package]] +name = "winx" +version = "0.36.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9643b83820c0cd246ecabe5fa454dd04ba4fa67996369466d0747472d337346" +dependencies = [ + "bitflags 2.4.2", + "windows-sys 0.52.0", +] + +[[package]] +name = "wit-parser" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df4913a2219096373fd6512adead1fb77ecdaa59d7fc517972a7d30b12f625be" +dependencies = [ + "anyhow", + "id-arena", + "indexmap 2.2.2", + "log", + "semver 1.0.21", + "serde", + "serde_derive", + "serde_json", + "unicode-xid", +] + +[[package]] +name = "witx" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e366f27a5cabcddb2706a78296a40b8fcc451e1a6aba2fc1d94b4a01bdaaef4b" +dependencies = [ + "anyhow", + "log", + "thiserror", + "wast 35.0.2", +] + +[[package]] +name = "wizer" +version = "4.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31f1f0143257faa028962616998d9bcf456f2b92b41d923fb630d0c62250f1fc" +dependencies = [ + "anyhow", + "cap-std", + "log", + "rayon", + "wasi-cap-std-sync", + "wasm-encoder 0.30.0", + "wasmparser 0.106.0", + "wasmtime", + "wasmtime-wasi", +] + +[[package]] +name = "zerocopy" +version = "0.7.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74d4d3961e53fa4c9a25a8637fc2bfaf2595b3d3ae34875568a5cf64787716be" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.48", +] + +[[package]] +name = "zstd" +version = "0.11.2+zstd.1.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20cc960326ece64f010d2d2107537f26dc589a6573a316bd5b1dba685fa5fde4" +dependencies = [ + "zstd-safe", +] + +[[package]] +name = "zstd-safe" +version = "5.0.2+zstd.1.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d2a5585e04f9eea4b2a3d1eca508c4dee9592a89ef6f450c11719da0726f4db" +dependencies = [ + "libc", + "zstd-sys", +] + +[[package]] +name = "zstd-sys" +version = "2.0.9+zstd.1.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e16efa8a874a0481a574084d34cc26fdb3b99627480f785888deb6386506656" +dependencies = [ + "cc", + "pkg-config", +] diff --git a/JS/wasm/Cargo.toml b/JS/wasm/Cargo.toml new file mode 100644 index 000000000..b0b56e72d --- /dev/null +++ b/JS/wasm/Cargo.toml @@ -0,0 +1,20 @@ +[workspace] +members = [ "crates/apis", "crates/arakoo-core", "crates/cli","crates/serve"] +resolver = "2" + +[workspace.package] +edition = "2021" +version = "0.0.1" + +[workspace.dependencies] +wizer = "4.0.0" +wasmtime = "16" +wasmtime-wasi = "16" +wasi-common = "16" +javy = { version = "2.2.0-alpha.1" } +anyhow = "1.0.79" +once_cell = "1.19.0" + +[profile.release] +lto = true +opt-level = 3 diff --git a/JS/wasm/crates/apis/Cargo.toml b/JS/wasm/crates/apis/Cargo.toml new file mode 100644 index 000000000..b31e6a2e6 --- /dev/null +++ b/JS/wasm/crates/apis/Cargo.toml @@ -0,0 +1,17 @@ +[package] +name = "apis" +edition.workspace = true +version.workspace = true + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[features] +console = [] +random = ["dep:fastrand"] +stream_io = [] +text_encoding = [] + +[dependencies] +anyhow = { workspace = true } +fastrand = { version = "2.0.1", optional = true } +javy = {workspace = true} \ No newline at end of file diff --git a/JS/wasm/crates/apis/src/api_config.rs b/JS/wasm/crates/apis/src/api_config.rs new file mode 100644 index 000000000..0b0955adc --- /dev/null +++ b/JS/wasm/crates/apis/src/api_config.rs @@ -0,0 +1,12 @@ +/// A configuration for APIs added in this crate. +/// +/// Example usage: +/// ``` +/// # use javy_apis::APIConfig; +/// let api_config = APIConfig::default(); +/// ``` +#[derive(Debug, Default)] +pub struct APIConfig { + #[cfg(feature = "console")] + pub(crate) console: crate::console::ConsoleConfig, +} diff --git a/JS/wasm/crates/apis/src/console/config.rs b/JS/wasm/crates/apis/src/console/config.rs new file mode 100644 index 000000000..3eb2152fb --- /dev/null +++ b/JS/wasm/crates/apis/src/console/config.rs @@ -0,0 +1,51 @@ +use std::io::{self, Write}; + +use crate::APIConfig; + +/// A selection of possible destination streams for `console.log` and +/// `console.error`. +#[derive(Debug)] +pub enum LogStream { + /// The standard output stream. + StdOut, + /// The standard error stream. + StdErr, +} + +impl LogStream { + pub(super) fn to_stream(&self) -> Box { + match self { + Self::StdErr => Box::new(io::stderr()), + Self::StdOut => Box::new(io::stdout()), + } + } +} + +#[derive(Debug)] +pub(crate) struct ConsoleConfig { + pub(super) log_stream: LogStream, + pub(super) error_stream: LogStream, +} + +impl Default for ConsoleConfig { + fn default() -> Self { + Self { + log_stream: LogStream::StdOut, + error_stream: LogStream::StdErr, + } + } +} + +impl APIConfig { + /// Sets the destination stream for `console.log`. + pub fn log_stream(&mut self, stream: LogStream) -> &mut Self { + self.console.log_stream = stream; + self + } + + /// Sets the destination stream for `console.error`. + pub fn error_stream(&mut self, stream: LogStream) -> &mut Self { + self.console.error_stream = stream; + self + } +} diff --git a/JS/wasm/crates/apis/src/console/mod.rs b/JS/wasm/crates/apis/src/console/mod.rs new file mode 100644 index 000000000..eb75d3427 --- /dev/null +++ b/JS/wasm/crates/apis/src/console/mod.rs @@ -0,0 +1,187 @@ +use std::io::Write; + +use anyhow::Result; +use javy::{ + quickjs::{JSContextRef, JSValue, JSValueRef}, + Runtime, +}; + +use crate::{APIConfig, JSApiSet}; + +pub(super) use config::ConsoleConfig; +pub use config::LogStream; + +mod config; + +pub(super) struct Console {} + +impl Console { + pub(super) fn new() -> Self { + Console {} + } +} + +impl JSApiSet for Console { + fn register(&self, runtime: &Runtime, config: &APIConfig) -> Result<()> { + register_console( + runtime.context(), + config.console.log_stream.to_stream(), + config.console.error_stream.to_stream(), + ) + } +} + +fn register_console(context: &JSContextRef, log_stream: T, error_stream: U) -> Result<()> +where + T: Write + 'static, + U: Write + 'static, +{ + let console_log_callback = context.wrap_callback(console_log_to(log_stream))?; + let console_error_callback = context.wrap_callback(console_log_to(error_stream))?; + let console_object = context.object_value()?; + console_object.set_property("log", console_log_callback)?; + console_object.set_property("error", console_error_callback)?; + context + .global_object()? + .set_property("console", console_object)?; + Ok(()) +} + +fn console_log_to( + mut stream: T, +) -> impl FnMut(&JSContextRef, JSValueRef, &[JSValueRef]) -> Result +where + T: Write + 'static, +{ + move |_ctx: &JSContextRef, _this: JSValueRef, args: &[JSValueRef]| { + // Write full string to in-memory destination before writing to stream since each write call to the stream + // will invoke a hostcall. + let mut log_line = String::new(); + for (i, arg) in args.iter().enumerate() { + if i != 0 { + log_line.push(' '); + } + let line = arg.to_string(); + log_line.push_str(&line); + } + + writeln!(stream, "{log_line}")?; + + Ok(JSValue::Undefined) + } +} + +#[cfg(test)] +mod tests { + use anyhow::Result; + use javy::Runtime; + use std::cell::RefCell; + use std::rc::Rc; + use std::{cmp, io}; + + use crate::console::register_console; + use crate::{APIConfig, JSApiSet}; + + use super::Console; + + #[test] + fn test_register() -> Result<()> { + let runtime = Runtime::default(); + Console::new().register(&runtime, &APIConfig::default())?; + let console = runtime.context().global_object()?.get_property("console")?; + assert!(console.get_property("log").is_ok()); + assert!(console.get_property("error").is_ok()); + Ok(()) + } + + #[test] + fn test_console_log() -> Result<()> { + let mut stream = SharedStream::default(); + + let runtime = Runtime::default(); + let ctx = runtime.context(); + register_console(ctx, stream.clone(), stream.clone())?; + + ctx.eval_global("main", "console.log(\"hello world\");")?; + assert_eq!(b"hello world\n", stream.buffer.borrow().as_slice()); + + stream.clear(); + + ctx.eval_global("main", "console.log(\"bonjour\", \"le\", \"monde\")")?; + assert_eq!(b"bonjour le monde\n", stream.buffer.borrow().as_slice()); + + stream.clear(); + + ctx.eval_global( + "main", + "console.log(2.3, true, { foo: 'bar' }, null, undefined)", + )?; + assert_eq!( + b"2.3 true [object Object] null undefined\n", + stream.buffer.borrow().as_slice() + ); + Ok(()) + } + + #[test] + fn test_console_error() -> Result<()> { + let mut stream = SharedStream::default(); + + let runtime = Runtime::default(); + let ctx = runtime.context(); + register_console(ctx, stream.clone(), stream.clone())?; + + ctx.eval_global("main", "console.error(\"hello world\");")?; + assert_eq!(b"hello world\n", stream.buffer.borrow().as_slice()); + + stream.clear(); + + ctx.eval_global("main", "console.error(\"bonjour\", \"le\", \"monde\")")?; + assert_eq!(b"bonjour le monde\n", stream.buffer.borrow().as_slice()); + + stream.clear(); + + ctx.eval_global( + "main", + "console.error(2.3, true, { foo: 'bar' }, null, undefined)", + )?; + assert_eq!( + b"2.3 true [object Object] null undefined\n", + stream.buffer.borrow().as_slice() + ); + Ok(()) + } + + #[derive(Clone)] + struct SharedStream { + buffer: Rc>>, + capacity: usize, + } + + impl Default for SharedStream { + fn default() -> Self { + Self { + buffer: Default::default(), + capacity: usize::MAX, + } + } + } + + impl SharedStream { + fn clear(&mut self) { + (*self.buffer).borrow_mut().clear(); + } + } + + impl io::Write for SharedStream { + fn write(&mut self, buf: &[u8]) -> io::Result { + let available_capacity = self.capacity - (*self.buffer).borrow().len(); + let leftover = cmp::min(available_capacity, buf.len()); + (*self.buffer).borrow_mut().write(&buf[..leftover]) + } + + fn flush(&mut self) -> io::Result<()> { + (*self.buffer).borrow_mut().flush() + } + } +} diff --git a/JS/wasm/crates/apis/src/http/mod.rs b/JS/wasm/crates/apis/src/http/mod.rs new file mode 100644 index 000000000..37a0b2e47 --- /dev/null +++ b/JS/wasm/crates/apis/src/http/mod.rs @@ -0,0 +1,13 @@ +use anyhow::Result; + +use crate::JSApiSet; + +pub(super) struct Http; + +impl JSApiSet for Http { + fn register(&self, runtime: &javy::Runtime, _config: &crate::APIConfig) -> Result<()> { + let context = runtime.context(); + context.eval_global("http.js", include_str!("shims/dist/index.js"))?; + Ok(()) + } +} diff --git a/JS/wasm/crates/apis/src/http/shims/.gitignore b/JS/wasm/crates/apis/src/http/shims/.gitignore new file mode 100644 index 000000000..1eae0cf67 --- /dev/null +++ b/JS/wasm/crates/apis/src/http/shims/.gitignore @@ -0,0 +1,2 @@ +dist/ +node_modules/ diff --git a/JS/wasm/crates/apis/src/http/shims/build.js b/JS/wasm/crates/apis/src/http/shims/build.js new file mode 100644 index 000000000..6e463e218 --- /dev/null +++ b/JS/wasm/crates/apis/src/http/shims/build.js @@ -0,0 +1,15 @@ +import { build } from "esbuild"; + +// Build for index.js +build({ + entryPoints: ["index.js"], + bundle: true, + outfile: "dist/index.js", + format: "esm", + target: "esnext", + platform: "node", + treeShaking: false, +}).catch((error) => { + console.error(error); + process.exit(1); +}); diff --git a/JS/wasm/crates/apis/src/http/shims/index.js b/JS/wasm/crates/apis/src/http/shims/index.js new file mode 100644 index 000000000..c0e54bd58 --- /dev/null +++ b/JS/wasm/crates/apis/src/http/shims/index.js @@ -0,0 +1,301 @@ +import { TextEncoder, TextDecoder } from "@sinonjs/text-encoding"; +import httpStatus from "http-status"; +import Url from "url-parse"; +import _queryString from "query-string"; + +class URL { + constructor(urlStr, base = undefined) { + let url = Url(urlStr, base); + this.url = url; + this.protocol = url.protocol; + this.slashes = url.slashes; + this.auth = url.auth; + this.username = url.username; + this.password = url.password; + this.host = url.host; + this.port = url.port; + this.pathname = url.pathname; + this.search = url.query; + this.searchParams = new URLSearchParams(this.search); + this.hash = url.hash; + this.href = url.origin; + this.origin = url.origin; + } + + set(key, value) { + this.url.set(key, value); + } + + toString() { + return this.url.toString(); + } + + toJson() { + return this.url.toString(); + } +} + +class URLSearchParams { + queryParams = {}; + + constructor(val) { + this.queryParams = { + ..._queryString.parse(val), + }; + } + append(key, val) { + this.queryParams[key] = val; + } + delete(key) { + delete this.queryParams[key]; + } + entries() { + let arr = []; + Object.entries(this.queryParams).map((o) => { + if (Array.isArray(o[1])) { + o[1].map((k) => { + arr.push([o[0], k]); + }); + } else { + arr.push([o[0], o[1]]); + } + }); + let iterLength = arr.length; + let iterIndex = 0; + return { + next: function () { + return iterIndex < iterLength + ? { value: arr[iterIndex++], done: false } + : { done: true }; + }, + }; + } + get(key) { + let val = this.queryParams[key]; + if (val) { + if (typeof val == "object") { + return val[0]; + } + return val; + } + return null; + } + getAll(key) { + let val = this.queryParams[key]; + if (val) { + return val; + } + return null; + } + has(key) { + return this.queryParams[key] != undefined ? true : false; + } + keys() { + return Object.keys(this.queryParams); + } + set(key, val) { + this.queryParams[key] = val; + } + toString() { + return _queryString.stringify(this.queryParams); + } + values() { + return Object.keys(this.queryParams).map((k) => this.queryParams[k]); + } + [Symbol.iterator]() { + return this.entries(); + } +} + +globalThis.URL = URL; +globalThis.URLSearchParams = URLSearchParams; + +function atob(b64) { + return Buffer.from(b64, "base64").toString(); +} + +function btoa(data) { + return Buffer.from(data).toString("base64"); +} + +globalThis.btoa = btoa; +globalThis.atob = atob; + +class Headers { + constructor(initialHeaders) { + let headers = {}; + + for (const key in initialHeaders) { + let value = initialHeaders[key]; + + if (typeof value === "string") { + headers[key] = value; + } + } + + this.headers = headers; + } + + append(key, value) { + this.headers[key] = value; + return value; + } + + set(key, value) { + this.append(key, value); + return value; + } + + delete(key) { + let dropValue = delete this.headers[key]; + return dropValue; + } + + get(key) { + return this.headers[key]; + } + + toJSON() { + return this.headers; + } +} + +class Request { + constructor(input) { + this.url = input.url; + this.method = input.method; + this.headers = new Headers(input.headers || {}); + this.body = input.body; + this.params = input.params || {}; + this.geo = input.geo || {}; + } + + text() { + return this.body; + } +} + +class Response { + constructor(body, options = {}) { + if (body instanceof String) { + this.body = body.toString(); + } else { + this.body = body; + } + + if (options.headers instanceof Headers) { + this.headers = options.headers; + } else if (options.headers instanceof Object) { + this.headers = new Headers(options.headers); + } else { + this.headers = new Headers({}); + } + + this.status = options.status || 200; + this.statusText = options.statusText || httpStatus[this.status]; + } + + static redirect(url, status = 307) { + return new Response(`Redirecting to ${url}`, { + status, + headers: { + Location: url, + }, + }); + } + + get ok() { + return this.status >= 200 && this.status < 300; + } + + defaultEncoding() { + return "utf-8"; + } + + arrayBuffer() { + let parsedBody = this.body; + + if (typeof this.body === "string") { + try { + parsedBody = new TextEncoder().encode(this.body); + } catch (e) { + return Promise.reject(`err: ${e}`); + } + } + + return parsedBody; + } + + json() { + let parsedBody = this.body; + + if (typeof this.body !== "string") { + try { + parsedBody = new TextDecoder(this.defaultEncoding()).decode(this.body); + } catch (e) { + return Promise.reject(`err: ${e}`); + } + } + + try { + return Promise.resolve(JSON.parse(parsedBody)); + } catch (e) { + return Promise.reject(`err: ${e}`); + } + } + + text() { + let parsedBody = this.body; + + if (typeof this.body !== "string") { + try { + parsedBody = new TextDecoder(this.defaultEncoding()).decode(this.body); + } catch (e) { + return Promise.reject(`err: ${e}`); + } + } + + return parsedBody; + } + + toString() { + return this.body; + } +} +let handlerFunction; +globalThis.addEventListener = (_eventName, handler) => { + handlerFunction = handler; +}; + +const requestToHandler = (input) => { + const request = new Request(input); + const event = { + request, + response: {}, + respondWith(res) { + this.response = res; + }, + }; + + try { + handlerFunction(event); + + Promise.resolve(event.response) + .then((res) => { + result = { + data: res.body, + headers: res.headers.headers, + status: res.status, + }; + }) + .catch((err) => { + error = `err: \n${err}`; + }); + } catch (err) { + error = `err: ${err}\n${err.stack}`; + } +}; + +globalThis.entrypoint = requestToHandler; +globalThis.result = {}; +globalThis.error = null; diff --git a/JS/wasm/crates/apis/src/http/shims/package.json b/JS/wasm/crates/apis/src/http/shims/package.json new file mode 100644 index 000000000..afb62cc72 --- /dev/null +++ b/JS/wasm/crates/apis/src/http/shims/package.json @@ -0,0 +1,18 @@ +{ + "name": "shims", + "version": "1.0.0", + "description": "Shims for http", + "main": "index.js", + "type": "module", + "license": "MIT", + "scripts": { + "build": "node build.js" + }, + "dependencies": { + "@sinonjs/text-encoding": "^0.7.2", + "esbuild": "^0.20.0", + "http-status": "^1.7.3", + "query-string": "^8.1.0", + "url-parse": "^1.5.10" + } +} diff --git a/JS/wasm/crates/apis/src/http/shims/yarn.lock b/JS/wasm/crates/apis/src/http/shims/yarn.lock new file mode 100644 index 000000000..f70d7a66a --- /dev/null +++ b/JS/wasm/crates/apis/src/http/shims/yarn.lock @@ -0,0 +1,199 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@esbuild/aix-ppc64@0.20.0": + version "0.20.0" + resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.20.0.tgz#509621cca4e67caf0d18561a0c56f8b70237472f" + integrity sha512-fGFDEctNh0CcSwsiRPxiaqX0P5rq+AqE0SRhYGZ4PX46Lg1FNR6oCxJghf8YgY0WQEgQuh3lErUFE4KxLeRmmw== + +"@esbuild/android-arm64@0.20.0": + version "0.20.0" + resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.20.0.tgz#109a6fdc4a2783fc26193d2687827045d8fef5ab" + integrity sha512-aVpnM4lURNkp0D3qPoAzSG92VXStYmoVPOgXveAUoQBWRSuQzt51yvSju29J6AHPmwY1BjH49uR29oyfH1ra8Q== + +"@esbuild/android-arm@0.20.0": + version "0.20.0" + resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.20.0.tgz#1397a2c54c476c4799f9b9073550ede496c94ba5" + integrity sha512-3bMAfInvByLHfJwYPJRlpTeaQA75n8C/QKpEaiS4HrFWFiJlNI0vzq/zCjBrhAYcPyVPG7Eo9dMrcQXuqmNk5g== + +"@esbuild/android-x64@0.20.0": + version "0.20.0" + resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.20.0.tgz#2b615abefb50dc0a70ac313971102f4ce2fdb3ca" + integrity sha512-uK7wAnlRvjkCPzh8jJ+QejFyrP8ObKuR5cBIsQZ+qbMunwR8sbd8krmMbxTLSrDhiPZaJYKQAU5Y3iMDcZPhyQ== + +"@esbuild/darwin-arm64@0.20.0": + version "0.20.0" + resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.20.0.tgz#5c122ed799eb0c35b9d571097f77254964c276a2" + integrity sha512-AjEcivGAlPs3UAcJedMa9qYg9eSfU6FnGHJjT8s346HSKkrcWlYezGE8VaO2xKfvvlZkgAhyvl06OJOxiMgOYQ== + +"@esbuild/darwin-x64@0.20.0": + version "0.20.0" + resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.20.0.tgz#9561d277002ba8caf1524f209de2b22e93d170c1" + integrity sha512-bsgTPoyYDnPv8ER0HqnJggXK6RyFy4PH4rtsId0V7Efa90u2+EifxytE9pZnsDgExgkARy24WUQGv9irVbTvIw== + +"@esbuild/freebsd-arm64@0.20.0": + version "0.20.0" + resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.20.0.tgz#84178986a3138e8500d17cc380044868176dd821" + integrity sha512-kQ7jYdlKS335mpGbMW5tEe3IrQFIok9r84EM3PXB8qBFJPSc6dpWfrtsC/y1pyrz82xfUIn5ZrnSHQQsd6jebQ== + +"@esbuild/freebsd-x64@0.20.0": + version "0.20.0" + resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.20.0.tgz#3f9ce53344af2f08d178551cd475629147324a83" + integrity sha512-uG8B0WSepMRsBNVXAQcHf9+Ko/Tr+XqmK7Ptel9HVmnykupXdS4J7ovSQUIi0tQGIndhbqWLaIL/qO/cWhXKyQ== + +"@esbuild/linux-arm64@0.20.0": + version "0.20.0" + resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.20.0.tgz#24efa685515689df4ecbc13031fa0a9dda910a11" + integrity sha512-uTtyYAP5veqi2z9b6Gr0NUoNv9F/rOzI8tOD5jKcCvRUn7T60Bb+42NDBCWNhMjkQzI0qqwXkQGo1SY41G52nw== + +"@esbuild/linux-arm@0.20.0": + version "0.20.0" + resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.20.0.tgz#6b586a488e02e9b073a75a957f2952b3b6e87b4c" + integrity sha512-2ezuhdiZw8vuHf1HKSf4TIk80naTbP9At7sOqZmdVwvvMyuoDiZB49YZKLsLOfKIr77+I40dWpHVeY5JHpIEIg== + +"@esbuild/linux-ia32@0.20.0": + version "0.20.0" + resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.20.0.tgz#84ce7864f762708dcebc1b123898a397dea13624" + integrity sha512-c88wwtfs8tTffPaoJ+SQn3y+lKtgTzyjkD8NgsyCtCmtoIC8RDL7PrJU05an/e9VuAke6eJqGkoMhJK1RY6z4w== + +"@esbuild/linux-loong64@0.20.0": + version "0.20.0" + resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.20.0.tgz#1922f571f4cae1958e3ad29439c563f7d4fd9037" + integrity sha512-lR2rr/128/6svngnVta6JN4gxSXle/yZEZL3o4XZ6esOqhyR4wsKyfu6qXAL04S4S5CgGfG+GYZnjFd4YiG3Aw== + +"@esbuild/linux-mips64el@0.20.0": + version "0.20.0" + resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.20.0.tgz#7ca1bd9df3f874d18dbf46af009aebdb881188fe" + integrity sha512-9Sycc+1uUsDnJCelDf6ZNqgZQoK1mJvFtqf2MUz4ujTxGhvCWw+4chYfDLPepMEvVL9PDwn6HrXad5yOrNzIsQ== + +"@esbuild/linux-ppc64@0.20.0": + version "0.20.0" + resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.20.0.tgz#8f95baf05f9486343bceeb683703875d698708a4" + integrity sha512-CoWSaaAXOZd+CjbUTdXIJE/t7Oz+4g90A3VBCHLbfuc5yUQU/nFDLOzQsN0cdxgXd97lYW/psIIBdjzQIwTBGw== + +"@esbuild/linux-riscv64@0.20.0": + version "0.20.0" + resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.20.0.tgz#ca63b921d5fe315e28610deb0c195e79b1a262ca" + integrity sha512-mlb1hg/eYRJUpv8h/x+4ShgoNLL8wgZ64SUr26KwglTYnwAWjkhR2GpoKftDbPOCnodA9t4Y/b68H4J9XmmPzA== + +"@esbuild/linux-s390x@0.20.0": + version "0.20.0" + resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.20.0.tgz#cb3d069f47dc202f785c997175f2307531371ef8" + integrity sha512-fgf9ubb53xSnOBqyvWEY6ukBNRl1mVX1srPNu06B6mNsNK20JfH6xV6jECzrQ69/VMiTLvHMicQR/PgTOgqJUQ== + +"@esbuild/linux-x64@0.20.0": + version "0.20.0" + resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.20.0.tgz#ac617e0dc14e9758d3d7efd70288c14122557dc7" + integrity sha512-H9Eu6MGse++204XZcYsse1yFHmRXEWgadk2N58O/xd50P9EvFMLJTQLg+lB4E1cF2xhLZU5luSWtGTb0l9UeSg== + +"@esbuild/netbsd-x64@0.20.0": + version "0.20.0" + resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.20.0.tgz#6cc778567f1513da6e08060e0aeb41f82eb0f53c" + integrity sha512-lCT675rTN1v8Fo+RGrE5KjSnfY0x9Og4RN7t7lVrN3vMSjy34/+3na0q7RIfWDAj0e0rCh0OL+P88lu3Rt21MQ== + +"@esbuild/openbsd-x64@0.20.0": + version "0.20.0" + resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.20.0.tgz#76848bcf76b4372574fb4d06cd0ed1fb29ec0fbe" + integrity sha512-HKoUGXz/TOVXKQ+67NhxyHv+aDSZf44QpWLa3I1lLvAwGq8x1k0T+e2HHSRvxWhfJrFxaaqre1+YyzQ99KixoA== + +"@esbuild/sunos-x64@0.20.0": + version "0.20.0" + resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.20.0.tgz#ea4cd0639bf294ad51bc08ffbb2dac297e9b4706" + integrity sha512-GDwAqgHQm1mVoPppGsoq4WJwT3vhnz/2N62CzhvApFD1eJyTroob30FPpOZabN+FgCjhG+AgcZyOPIkR8dfD7g== + +"@esbuild/win32-arm64@0.20.0": + version "0.20.0" + resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.20.0.tgz#a5c171e4a7f7e4e8be0e9947a65812c1535a7cf0" + integrity sha512-0vYsP8aC4TvMlOQYozoksiaxjlvUcQrac+muDqj1Fxy6jh9l9CZJzj7zmh8JGfiV49cYLTorFLxg7593pGldwQ== + +"@esbuild/win32-ia32@0.20.0": + version "0.20.0" + resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.20.0.tgz#f8ac5650c412d33ea62d7551e0caf82da52b7f85" + integrity sha512-p98u4rIgfh4gdpV00IqknBD5pC84LCub+4a3MO+zjqvU5MVXOc3hqR2UgT2jI2nh3h8s9EQxmOsVI3tyzv1iFg== + +"@esbuild/win32-x64@0.20.0": + version "0.20.0" + resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.20.0.tgz#2efddf82828aac85e64cef62482af61c29561bee" + integrity sha512-NgJnesu1RtWihtTtXGFMU5YSE6JyyHPMxCwBZK7a6/8d31GuSo9l0Ss7w1Jw5QnKUawG6UEehs883kcXf5fYwg== + +"@sinonjs/text-encoding@^0.7.2": + version "0.7.2" + resolved "https://registry.yarnpkg.com/@sinonjs/text-encoding/-/text-encoding-0.7.2.tgz#5981a8db18b56ba38ef0efb7d995b12aa7b51918" + integrity sha512-sXXKG+uL9IrKqViTtao2Ws6dy0znu9sOaP1di/jKGW1M6VssO8vlpXCQcpZ+jisQ1tTFAC5Jo/EOzFbggBagFQ== + +decode-uri-component@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.4.1.tgz#2ac4859663c704be22bf7db760a1494a49ab2cc5" + integrity sha512-+8VxcR21HhTy8nOt6jf20w0c9CADrw1O8d+VZ/YzzCt4bJ3uBjw+D1q2osAB8RnpwwaeYBxy0HyKQxD5JBMuuQ== + +esbuild@^0.20.0: + version "0.20.0" + resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.20.0.tgz#a7170b63447286cd2ff1f01579f09970e6965da4" + integrity sha512-6iwE3Y2RVYCME1jLpBqq7LQWK3MW6vjV2bZy6gt/WrqkY+WE74Spyc0ThAOYpMtITvnjX09CrC6ym7A/m9mebA== + optionalDependencies: + "@esbuild/aix-ppc64" "0.20.0" + "@esbuild/android-arm" "0.20.0" + "@esbuild/android-arm64" "0.20.0" + "@esbuild/android-x64" "0.20.0" + "@esbuild/darwin-arm64" "0.20.0" + "@esbuild/darwin-x64" "0.20.0" + "@esbuild/freebsd-arm64" "0.20.0" + "@esbuild/freebsd-x64" "0.20.0" + "@esbuild/linux-arm" "0.20.0" + "@esbuild/linux-arm64" "0.20.0" + "@esbuild/linux-ia32" "0.20.0" + "@esbuild/linux-loong64" "0.20.0" + "@esbuild/linux-mips64el" "0.20.0" + "@esbuild/linux-ppc64" "0.20.0" + "@esbuild/linux-riscv64" "0.20.0" + "@esbuild/linux-s390x" "0.20.0" + "@esbuild/linux-x64" "0.20.0" + "@esbuild/netbsd-x64" "0.20.0" + "@esbuild/openbsd-x64" "0.20.0" + "@esbuild/sunos-x64" "0.20.0" + "@esbuild/win32-arm64" "0.20.0" + "@esbuild/win32-ia32" "0.20.0" + "@esbuild/win32-x64" "0.20.0" + +filter-obj@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/filter-obj/-/filter-obj-5.1.0.tgz#5bd89676000a713d7db2e197f660274428e524ed" + integrity sha512-qWeTREPoT7I0bifpPUXtxkZJ1XJzxWtfoWWkdVGqa+eCr3SHW/Ocp89o8vLvbUuQnadybJpjOKu4V+RwO6sGng== + +http-status@^1.7.3: + version "1.7.3" + resolved "https://registry.yarnpkg.com/http-status/-/http-status-1.7.3.tgz#d6dcc3a5a3fb5b1bfcc6ad2b38af0b7258bc1459" + integrity sha512-GS8tL1qHT2nBCMJDYMHGkkkKQLNkIAHz37vgO68XKvzv+XyqB4oh/DfmMHdtRzfqSJPj1xKG2TaELZtlCz6BEQ== + +query-string@^8.1.0: + version "8.1.0" + resolved "https://registry.yarnpkg.com/query-string/-/query-string-8.1.0.tgz#e7f95367737219544cd360a11a4f4ca03836e115" + integrity sha512-BFQeWxJOZxZGix7y+SByG3F36dA0AbTy9o6pSmKFcFz7DAj0re9Frkty3saBn3nHo3D0oZJ/+rx3r8H8r8Jbpw== + dependencies: + decode-uri-component "^0.4.1" + filter-obj "^5.1.0" + split-on-first "^3.0.0" + +querystringify@^2.1.1: + version "2.2.0" + resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-2.2.0.tgz#3345941b4153cb9d082d8eee4cda2016a9aef7f6" + integrity sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ== + +requires-port@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" + integrity sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ== + +split-on-first@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/split-on-first/-/split-on-first-3.0.0.tgz#f04959c9ea8101b9b0bbf35a61b9ebea784a23e7" + integrity sha512-qxQJTx2ryR0Dw0ITYyekNQWpz6f8dGd7vffGNflQQ3Iqj9NJ6qiZ7ELpZsJ/QBhIVAiDfXdag3+Gp8RvWa62AA== + +url-parse@^1.5.10: + version "1.5.10" + resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.5.10.tgz#9d3c2f736c1d75dd3bd2be507dcc111f1e2ea9c1" + integrity sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ== + dependencies: + querystringify "^2.1.1" + requires-port "^1.0.0" diff --git a/JS/wasm/crates/apis/src/lib.rs b/JS/wasm/crates/apis/src/lib.rs new file mode 100644 index 000000000..739a3b931 --- /dev/null +++ b/JS/wasm/crates/apis/src/lib.rs @@ -0,0 +1,92 @@ +//! JS APIs for Javy. +//! +//! This crate provides JS APIs you can add to Javy. +//! +//! Example usage: +//! ``` +//! # use anyhow::{anyhow, Error, Result}; +//! use javy::{quickjs::JSValue, Runtime}; +//! use javy_apis::RuntimeExt; +//! +//! let runtime = Runtime::new_with_defaults()?; +//! let context = runtime.context(); +//! context.global_object()?.set_property( +//! "print", +//! context.wrap_callback(move |_ctx, _this, args| { +//! let str = args +//! .first() +//! .ok_or(anyhow!("Need to pass an argument"))? +//! .to_string(); +//! println!("{str}"); +//! Ok(JSValue::Undefined) +//! })?, +//! )?; +//! context.eval_global("hello.js", "print('hello!');")?; +//! # Ok::<(), Error>(()) +//! ``` +//! +//! If you want to customize the runtime or the APIs, you can use the +//! [`Runtime::new_with_apis`] method instead to provide a [`javy::Config`] +//! for the underlying [`Runtime`] or an [`APIConfig`] for the APIs. +//! +//! ## Features +//! * `console` - Registers an implementation of the `console` API. +//! * `text_encoding` - Registers implementations of `TextEncoder` and `TextDecoder`. +//! * `random` - Overrides the implementation of `Math.random` to one that +//! seeds the RNG on first call to `Math.random`. This is helpful to enable +//! when using Wizer to snapshot a [`javy::Runtime`] so that the output of +//! `Math.random` relies on the WASI context used at runtime and not the +//! WASI context used when Wizening. Enabling this feature will increase the +//! size of the Wasm module that includes the Javy Runtime and will +//! introduce an additional hostcall invocation when `Math.random` is +//! invoked for the first time. +//! * `stream_io` - Registers implementations of `Javy.IO.readSync` and `Javy.IO.writeSync`. + +use anyhow::Result; +use javy::Runtime; + +pub use api_config::APIConfig; +#[cfg(feature = "console")] +pub use console::LogStream; +pub use runtime_ext::RuntimeExt; + +mod api_config; +#[cfg(feature = "console")] +mod console; +#[cfg(feature = "random")] +mod random; +mod runtime_ext; +#[cfg(feature = "stream_io")] +mod stream_io; +#[cfg(feature = "text_encoding")] +mod text_encoding; + +mod http; + +pub(crate) trait JSApiSet { + fn register(&self, runtime: &Runtime, config: &APIConfig) -> Result<()>; +} + +/// Adds enabled JS APIs to the provided [`Runtime`]. +/// +/// ## Example +/// ``` +/// # use anyhow::Error; +/// # use javy::Runtime; +/// # use javy_apis::APIConfig; +/// let runtime = Runtime::default(); +/// javy_apis::add_to_runtime(&runtime, APIConfig::default())?; +/// # Ok::<(), Error>(()) +/// ``` +pub fn add_to_runtime(runtime: &Runtime, config: APIConfig) -> Result<()> { + #[cfg(feature = "console")] + console::Console::new().register(runtime, &config)?; + #[cfg(feature = "random")] + random::Random.register(runtime, &config)?; + #[cfg(feature = "stream_io")] + stream_io::StreamIO.register(runtime, &config)?; + #[cfg(feature = "text_encoding")] + text_encoding::TextEncoding.register(runtime, &config)?; + http::Http.register(runtime, &config)?; + Ok(()) +} diff --git a/JS/wasm/crates/apis/src/random/mod.rs b/JS/wasm/crates/apis/src/random/mod.rs new file mode 100644 index 000000000..e7bbb5708 --- /dev/null +++ b/JS/wasm/crates/apis/src/random/mod.rs @@ -0,0 +1,37 @@ +use anyhow::Result; +use javy::{quickjs::JSValue, Runtime}; + +use crate::{APIConfig, JSApiSet}; + +pub struct Random; + +impl JSApiSet for Random { + fn register(&self, runtime: &Runtime, _config: &APIConfig) -> Result<()> { + let ctx = runtime.context(); + ctx.global_object()?.get_property("Math")?.set_property( + "random", + // TODO figure out if we can lazily initialize the PRNG + ctx.wrap_callback(|_ctx, _this, _args| Ok(JSValue::Float(fastrand::f64())))?, + )?; + Ok(()) + } +} + +#[cfg(test)] +mod tests { + use crate::{random::Random, APIConfig, JSApiSet}; + use anyhow::Result; + use javy::Runtime; + + #[test] + fn test_random() -> Result<()> { + let runtime = Runtime::default(); + Random.register(&runtime, &APIConfig::default())?; + let ctx = runtime.context(); + ctx.eval_global("test.js", "result = Math.random()")?; + let result = ctx.global_object()?.get_property("result")?.as_f64()?; + assert!(result >= 0.0); + assert!(result < 1.0); + Ok(()) + } +} diff --git a/JS/wasm/crates/apis/src/runtime_ext.rs b/JS/wasm/crates/apis/src/runtime_ext.rs new file mode 100644 index 000000000..d64915741 --- /dev/null +++ b/JS/wasm/crates/apis/src/runtime_ext.rs @@ -0,0 +1,35 @@ +use anyhow::Result; +use javy::{Config, Runtime}; + +use crate::APIConfig; + +/// A extension trait for [`Runtime`] that creates a [`Runtime`] with APIs +/// provided in this crate. +/// +/// ## Example +/// ``` +/// # use anyhow::Error; +/// use javy::Runtime; +/// use javy_apis::RuntimeExt; +/// let runtime = Runtime::new_with_defaults()?; +/// # Ok::<(), Error>(()) +/// ``` +pub trait RuntimeExt { + /// Creates a [`Runtime`] configured by the provided [`Config`] with JS + /// APIs added configured according to the [`APIConfig`]. + fn new_with_apis(config: Config, api_config: APIConfig) -> Result; + /// Creates a [`Runtime`] with JS APIs added with a default configuration. + fn new_with_defaults() -> Result; +} + +impl RuntimeExt for Runtime { + fn new_with_apis(config: Config, api_config: APIConfig) -> Result { + let runtime = Runtime::new(config)?; + crate::add_to_runtime(&runtime, api_config)?; + Ok(runtime) + } + + fn new_with_defaults() -> Result { + Self::new_with_apis(Config::default(), APIConfig::default()) + } +} diff --git a/JS/wasm/crates/apis/src/stream_io/io.js b/JS/wasm/crates/apis/src/stream_io/io.js new file mode 100644 index 000000000..8777c80a4 --- /dev/null +++ b/JS/wasm/crates/apis/src/stream_io/io.js @@ -0,0 +1,31 @@ +(function () { + const __javy_io_readSync = globalThis.__javy_io_readSync; + const __javy_io_writeSync = globalThis.__javy_io_writeSync; + globalThis.Javy.IO = { + readSync(fd, data) { + if (!(data instanceof Uint8Array)) { + throw TypeError("Data needs to be an Uint8Array"); + } + return __javy_io_readSync( + fd, + data.buffer, + data.byteOffset, + data.byteLength + ); + }, + writeSync(fd, data) { + if (!(data instanceof Uint8Array)) { + throw TypeError("Data needs to be an Uint8Array"); + } + return __javy_io_writeSync( + fd, + data.buffer, + data.byteOffset, + data.byteLength + ); + }, + }; + + Reflect.deleteProperty(globalThis, "__javy_io_readSync"); + Reflect.deleteProperty(globalThis, "__javy_io_writeSync"); +})(); diff --git a/JS/wasm/crates/apis/src/stream_io/mod.rs b/JS/wasm/crates/apis/src/stream_io/mod.rs new file mode 100644 index 000000000..abdf12176 --- /dev/null +++ b/JS/wasm/crates/apis/src/stream_io/mod.rs @@ -0,0 +1,68 @@ +use anyhow::Result; +use std::io::{Read, Write}; + +use javy::Runtime; + +use crate::{APIConfig, JSApiSet}; + +pub(super) struct StreamIO; + +impl JSApiSet for StreamIO { + fn register(&self, runtime: &Runtime, _config: &APIConfig) -> Result<()> { + let context = runtime.context(); + let global = context.global_object()?; + + let mut javy_object = global.get_property("Javy")?; + if javy_object.is_undefined() { + javy_object = context.object_value()?; + global.set_property("Javy", javy_object)?; + } + + global.set_property( + "__javy_io_writeSync", + context.wrap_callback(|_, _this_arg, args| { + let [fd, data, offset, length, ..] = args else { + anyhow::bail!("Invalid number of parameters"); + }; + + let mut fd: Box = match fd.try_into()? { + 1 => Box::new(std::io::stdout()), + 2 => Box::new(std::io::stderr()), + _ => anyhow::bail!("Only stdout and stderr are supported"), + }; + let data: Vec = data.try_into()?; + let offset: usize = offset.try_into()?; + let length: usize = length.try_into()?; + let data = &data[offset..(offset + length)]; + let n = fd.write(data)?; + fd.flush()?; + Ok(n.into()) + })?, + )?; + + global.set_property( + "__javy_io_readSync", + context.wrap_callback(|_, _this_arg, args| { + let [fd, data, offset, length, ..] = args else { + anyhow::bail!("Invalid number of parameters"); + }; + let mut fd: Box = match fd.try_into()? { + 0 => Box::new(std::io::stdin()), + _ => anyhow::bail!("Only stdin is supported"), + }; + let offset: usize = offset.try_into()?; + let length: usize = length.try_into()?; + if !data.is_array_buffer() { + anyhow::bail!("Data needs to be an ArrayBuffer"); + } + let data = data.as_bytes_mut()?; + let data = &mut data[offset..(offset + length)]; + let n = fd.read(data)?; + Ok(n.into()) + })?, + )?; + + context.eval_global("io.js", include_str!("io.js"))?; + Ok(()) + } +} diff --git a/JS/wasm/crates/apis/src/text_encoding/mod.rs b/JS/wasm/crates/apis/src/text_encoding/mod.rs new file mode 100644 index 000000000..7d8007647 --- /dev/null +++ b/JS/wasm/crates/apis/src/text_encoding/mod.rs @@ -0,0 +1,102 @@ +use std::{borrow::Cow, str}; + +use anyhow::{anyhow, Result}; +use javy::{ + quickjs::{JSContextRef, JSError, JSValue, JSValueRef}, + Runtime, +}; + +use crate::{APIConfig, JSApiSet}; + +pub(super) struct TextEncoding; + +impl JSApiSet for TextEncoding { + fn register(&self, runtime: &Runtime, _config: &APIConfig) -> Result<()> { + let context = runtime.context(); + let global = context.global_object()?; + global.set_property( + "__javy_decodeUtf8BufferToString", + context.wrap_callback(decode_utf8_buffer_to_js_string())?, + )?; + global.set_property( + "__javy_encodeStringToUtf8Buffer", + context.wrap_callback(encode_js_string_to_utf8_buffer())?, + )?; + + context.eval_global("text-encoding.js", include_str!("./text-encoding.js"))?; + Ok(()) + } +} + +fn decode_utf8_buffer_to_js_string( +) -> impl FnMut(&JSContextRef, JSValueRef, &[JSValueRef]) -> anyhow::Result { + move |_ctx: &JSContextRef, _this: JSValueRef, args: &[JSValueRef]| { + if args.len() != 5 { + return Err(anyhow!("Expecting 5 arguments, received {}", args.len())); + } + + let buffer: Vec = args[0].try_into()?; + let byte_offset: usize = args[1].try_into()?; + let byte_length: usize = args[2].try_into()?; + let fatal: bool = args[3].try_into()?; + let ignore_bom: bool = args[4].try_into()?; + + let mut view = buffer + .get(byte_offset..(byte_offset + byte_length)) + .ok_or_else(|| { + anyhow!("Provided offset and length is not valid for provided buffer") + })?; + + if !ignore_bom { + view = match view { + // [0xEF, 0xBB, 0xBF] is the UTF-8 BOM which we want to strip + [0xEF, 0xBB, 0xBF, rest @ ..] => rest, + _ => view, + }; + } + + let str = + if fatal { + Cow::from(str::from_utf8(view).map_err(|_| { + JSError::Type("The encoded data was not valid utf-8".to_string()) + })?) + } else { + String::from_utf8_lossy(view) + }; + Ok(str.to_string().into()) + } +} + +fn encode_js_string_to_utf8_buffer( +) -> impl FnMut(&JSContextRef, JSValueRef, &[JSValueRef]) -> anyhow::Result { + move |_ctx: &JSContextRef, _this: JSValueRef, args: &[JSValueRef]| { + if args.len() != 1 { + return Err(anyhow!("Expecting 1 argument, got {}", args.len())); + } + + let js_string: String = args[0].try_into()?; + Ok(js_string.into_bytes().into()) + } +} + +#[cfg(test)] +mod tests { + use crate::{APIConfig, JSApiSet}; + use anyhow::Result; + use javy::Runtime; + + use super::TextEncoding; + + #[test] + fn test_text_encoder_decoder() -> Result<()> { + let runtime = Runtime::default(); + let context = runtime.context(); + TextEncoding.register(&runtime, &APIConfig::default())?; + let result = context.eval_global( + "main", + "let encoder = new TextEncoder(); let buffer = encoder.encode('hello'); let decoder = new TextDecoder(); decoder.decode(buffer) == 'hello';" + )?; + assert!(result.as_bool()?); + Ok(()) + } +} diff --git a/JS/wasm/crates/apis/src/text_encoding/text-encoding.js b/JS/wasm/crates/apis/src/text_encoding/text-encoding.js new file mode 100644 index 000000000..f8c834d92 --- /dev/null +++ b/JS/wasm/crates/apis/src/text_encoding/text-encoding.js @@ -0,0 +1,66 @@ +(function () { + const __javy_decodeUtf8BufferToString = globalThis.__javy_decodeUtf8BufferToString; + const __javy_encodeStringToUtf8Buffer = globalThis.__javy_encodeStringToUtf8Buffer; + + class TextDecoder { + constructor(label = "utf-8", options = {}) { + label = label.trim().toLowerCase(); + const acceptedLabels = ["utf-8", "utf8", "unicode-1-1-utf-8", "unicode11utf8", "unicode20utf8", "x-unicode20utf8"]; + if (!acceptedLabels.includes(label)) { + // Not spec-compliant behaviour + throw new RangeError("The encoding label provided must be utf-8"); + } + Object.defineProperties(this, { + encoding: { value: "utf-8", enumerable: true, writable: false }, + fatal: { value: !!options.fatal, enumerable: true, writable: false }, + ignoreBOM: { value: !!options.ignoreBOM, enumerable: true, writable: false }, + }) + } + + decode(input, options = {}) { + if (input === undefined) { + return ""; + } + + if (options.stream) { + throw new Error("Streaming decode is not supported"); + } + + // backing buffer would not have byteOffset and may have different byteLength + let byteOffset = input.byteOffset || 0; + let byteLength = input.byteLength; + if (ArrayBuffer.isView(input)) { + input = input.buffer; + } + + if (!(input instanceof ArrayBuffer)) { + throw new TypeError("The provided value is not of type '(ArrayBuffer or ArrayBufferView)'"); + } + + return __javy_decodeUtf8BufferToString(input, byteOffset, byteLength, this.fatal, this.ignoreBOM); + } + } + + class TextEncoder { + constructor() { + Object.defineProperties(this, { + encoding: { value: "utf-8", enumerable: true, writable: false }, + }); + } + + encode(input = "") { + input = input.toString(); // non-string inputs are converted to strings + return new Uint8Array(__javy_encodeStringToUtf8Buffer(input)); + } + + encodeInto(source, destination) { + throw new Error("encodeInto is not supported"); + } + } + + globalThis.TextDecoder = TextDecoder; + globalThis.TextEncoder = TextEncoder; + + Reflect.deleteProperty(globalThis, "__javy_decodeUtf8BufferToString"); + Reflect.deleteProperty(globalThis, "__javy_encodeStringToUtf8Buffer"); +})(); diff --git a/JS/wasm/crates/arakoo-core/Cargo.toml b/JS/wasm/crates/arakoo-core/Cargo.toml new file mode 100644 index 000000000..2c4b24772 --- /dev/null +++ b/JS/wasm/crates/arakoo-core/Cargo.toml @@ -0,0 +1,20 @@ +[package] +name = "arakoo-core" +edition.workspace = true +version.workspace = true + +[[bin]] +name = "arakoo-core" +path = "src/main.rs" +[lib] +name = "javy_quickjs_provider" +crate-type = ["cdylib"] + +[dependencies] +anyhow = { workspace = true } +javy = { workspace=true, features = ["export_alloc_fns","json"] } +once_cell = {workspace = true} +apis = { path = "../apis", features = ["console", "text_encoding", "random", "stream_io"] } + +[features] +experimental_event_loop = [] \ No newline at end of file diff --git a/JS/wasm/crates/arakoo-core/src/execution.rs b/JS/wasm/crates/arakoo-core/src/execution.rs new file mode 100644 index 000000000..11cd32473 --- /dev/null +++ b/JS/wasm/crates/arakoo-core/src/execution.rs @@ -0,0 +1,75 @@ +use std::process; + +use anyhow::{bail, Error, Result}; +use javy::{json, quickjs::JSContextRef, Runtime}; + +pub fn run_bytecode(runtime: &Runtime, bytecode: &[u8]) { + let context = runtime.context(); + + context + .eval_binary(bytecode) + .and_then(|_| process_event_loop(context)) + .unwrap_or_else(handle_error); +} + +pub fn invoke_entrypoint( + runtime: &Runtime, + bytecode: &[u8], + input: String, +) -> anyhow::Result> { + let context = runtime.context(); + context.eval_binary(bytecode).unwrap(); + + let global = context.global_object().unwrap(); + let entry_point = global.get_property("entrypoint").unwrap(); + + let request = input; + let input_bytes = request.as_bytes(); + let input_value = json::transcode_input(context, input_bytes).unwrap_or_else(|e| { + eprintln!("Error when transcoding input: {e}"); + process::abort(); + }); + entry_point + .call(&global, &[input_value]) + .and_then(|_| process_event_loop(context)) + .unwrap_or_else(handle_error); + + let global = context.global_object().unwrap(); + let error = global.get_property("error").unwrap(); + let output = global.get_property("result").unwrap(); + + if !error.is_null_or_undefined() { + let error = error.to_string(); + eprintln!("Error while running JS: {error}"); + process::abort(); + } + let output = json::transcode_output(output).unwrap(); + Ok(output) +} + +pub fn invoke_function(runtime: &Runtime, fn_module: &str, fn_name: &str) { + let context = runtime.context(); + let js = if fn_name == "default" { + format!("import {{ default as defaultFn }} from '{fn_module}'; defaultFn();") + } else { + format!("import {{ {fn_name} }} from '{fn_module}'; {fn_name}();") + }; + context + .eval_module("runtime.mjs", &js) + .and_then(|_| process_event_loop(context)) + .unwrap_or_else(handle_error); +} + +fn process_event_loop(context: &JSContextRef) -> Result<()> { + if cfg!(feature = "experimental_event_loop") { + context.execute_pending()?; + } else if context.is_pending() { + bail!("Adding tasks to the event queue is not supported"); + } + Ok(()) +} + +fn handle_error(e: Error) { + eprintln!("Error while running JS: {e}"); + process::abort(); +} diff --git a/JS/wasm/crates/arakoo-core/src/lib.rs b/JS/wasm/crates/arakoo-core/src/lib.rs new file mode 100644 index 000000000..5a56a9400 --- /dev/null +++ b/JS/wasm/crates/arakoo-core/src/lib.rs @@ -0,0 +1,84 @@ +use javy::Runtime; +use once_cell::sync::OnceCell; +use std::slice; +use std::str; + +mod execution; +mod runtime; + +const FUNCTION_MODULE_NAME: &str = "function.mjs"; + +static mut COMPILE_SRC_RET_AREA: [u32; 2] = [0; 2]; + +static mut RUNTIME: OnceCell = OnceCell::new(); + +/// Used by Wizer to preinitialize the module +#[export_name = "wizer.initialize"] +pub extern "C" fn init() { + let runtime = runtime::new_runtime().unwrap(); + unsafe { RUNTIME.set(runtime).unwrap() }; +} + +/// Compiles JS source code to QuickJS bytecode. +/// +/// Returns a pointer to a buffer containing a 32-bit pointer to the bytecode byte array and the +/// u32 length of the bytecode byte array. +/// +/// # Arguments +/// +/// * `js_src_ptr` - A pointer to the start of a byte array containing UTF-8 JS source code +/// * `js_src_len` - The length of the byte array containing JS source code +/// +/// # Safety +/// +/// * `js_src_ptr` must reference a valid array of unsigned bytes of `js_src_len` length +#[export_name = "compile_src"] +pub unsafe extern "C" fn compile_src(js_src_ptr: *const u8, js_src_len: usize) -> *const u32 { + // Use fresh runtime to avoid depending on Wizened runtime + let runtime = runtime::new_runtime().unwrap(); + let js_src = str::from_utf8(slice::from_raw_parts(js_src_ptr, js_src_len)).unwrap(); + let bytecode = runtime + .context() + .compile_module(FUNCTION_MODULE_NAME, js_src) + .unwrap(); + let bytecode_len = bytecode.len(); + // We need the bytecode buffer to live longer than this function so it can be read from memory + let bytecode_ptr = Box::leak(bytecode.into_boxed_slice()).as_ptr(); + COMPILE_SRC_RET_AREA[0] = bytecode_ptr as u32; + COMPILE_SRC_RET_AREA[1] = bytecode_len.try_into().unwrap(); + COMPILE_SRC_RET_AREA.as_ptr() +} + +/// Evaluates QuickJS bytecode +/// +/// # Safety +/// +/// * `bytecode_ptr` must reference a valid array of unsigned bytes of `bytecode_len` length +#[export_name = "eval_bytecode"] +pub unsafe extern "C" fn eval_bytecode(bytecode_ptr: *const u8, bytecode_len: usize) { + let runtime = RUNTIME.get().unwrap(); + let bytecode = slice::from_raw_parts(bytecode_ptr, bytecode_len); + execution::run_bytecode(runtime, bytecode); +} + +/// Evaluates QuickJS bytecode and invokes the exported JS function name. +/// +/// # Safety +/// +/// * `bytecode_ptr` must reference a valid array of bytes of `bytecode_len` +/// length. +/// * `fn_name_ptr` must reference a UTF-8 string with `fn_name_len` byte +/// length. +#[export_name = "invoke"] +pub unsafe extern "C" fn invoke( + bytecode_ptr: *const u8, + bytecode_len: usize, + fn_name_ptr: *const u8, + fn_name_len: usize, +) { + let runtime = RUNTIME.get().unwrap(); + let bytecode = slice::from_raw_parts(bytecode_ptr, bytecode_len); + let fn_name = str::from_utf8_unchecked(slice::from_raw_parts(fn_name_ptr, fn_name_len)); + execution::run_bytecode(runtime, bytecode); + execution::invoke_function(runtime, FUNCTION_MODULE_NAME, fn_name); +} diff --git a/JS/wasm/crates/arakoo-core/src/main.rs b/JS/wasm/crates/arakoo-core/src/main.rs new file mode 100644 index 000000000..8d15716e7 --- /dev/null +++ b/JS/wasm/crates/arakoo-core/src/main.rs @@ -0,0 +1,103 @@ +use javy::Runtime; +use once_cell::sync::OnceCell; +use std::io::{self, Read}; +use std::slice; +use std::str; +use std::string::String; + +mod execution; +mod runtime; + +const FUNCTION_MODULE_NAME: &str = "function.mjs"; + +static mut COMPILE_SRC_RET_AREA: [u32; 2] = [0; 2]; + +static mut RUNTIME: OnceCell = OnceCell::new(); +static mut BYTECODE: OnceCell> = OnceCell::new(); + +#[export_name = "wizer.initialize"] +pub extern "C" fn init() { + let _wasm_ctx = WasmCtx::new(); + + let runtime = runtime::new_runtime().unwrap(); + + let mut contents = String::new(); + io::stdin().read_to_string(&mut contents).unwrap(); + let bytecode = runtime + .context() + .compile_module("function.mjs", &contents) + .unwrap(); + + unsafe { + RUNTIME.set(runtime).unwrap(); + BYTECODE.set(bytecode).unwrap(); + } +} + +fn main() { + let bytecode = unsafe { BYTECODE.take().unwrap() }; + let runtime = unsafe { RUNTIME.take().unwrap() }; + execution::run_bytecode(&runtime, &bytecode); +} + +#[export_name = "run_entrypoint"] +pub unsafe fn run_entrypoint(input_ptr: *mut u8, input_len: usize) -> *const u32 { + let runtime = unsafe { RUNTIME.take().unwrap() }; + let bytecode = unsafe { BYTECODE.take().unwrap() }; + let input = str::from_utf8(unsafe { slice::from_raw_parts(input_ptr, input_len) }).unwrap(); + let result = execution::invoke_entrypoint(&runtime, &bytecode, input.to_string()).unwrap(); + let result_len = result.len(); + let result_ptr = Box::leak(result.into_boxed_slice()).as_ptr(); + COMPILE_SRC_RET_AREA[0] = result_ptr as u32; + COMPILE_SRC_RET_AREA[1] = result_len.try_into().unwrap(); + COMPILE_SRC_RET_AREA.as_ptr() +} + +// Removed in post-processing. +/// Evaluates QuickJS bytecode and invokes the exported JS function name. +/// +/// # Safety +/// +/// * `fn_name_ptr` must reference a UTF-8 string with `fn_name_size` byte +/// length. +#[export_name = "javy.invoke"] +pub unsafe extern "C" fn invoke(fn_name_ptr: *mut u8, fn_name_size: usize) { + let _wasm_ctx = WasmCtx::new(); + + let js_fn_name = str::from_utf8_unchecked(slice::from_raw_parts(fn_name_ptr, fn_name_size)); + let runtime = unsafe { RUNTIME.take().unwrap() }; + execution::invoke_function(&runtime, FUNCTION_MODULE_NAME, js_fn_name); +} + +// RAII abstraction for calling Wasm ctors and dtors for exported non-main functions. +struct WasmCtx; + +impl WasmCtx { + #[must_use = "Failing to assign the return value will result in the wasm dtors being run immediately"] + fn new() -> Self { + unsafe { __wasm_call_ctors() }; + Self + } +} + +impl Drop for WasmCtx { + fn drop(&mut self) { + unsafe { __wasm_call_dtors() }; + } +} + +extern "C" { + // `__wasm_call_ctors` is generated by `wasm-ld` and invokes all of the global constructors. + // In a Rust bin crate, the `_start` function will invoke this implicitly but no other exported + // Wasm functions will invoke this. + // If this is not invoked, access to environment variables and directory preopens will not be + // available. + // This should only be invoked at the start of exported Wasm functions that are not the `main` + // function. + // References: + // - [Rust 1.67.0 stopped initializing the WASI environment for exported functions](https://github.com/rust-lang/rust/issues/107635) + // - [Wizer header in Fastly's JS compute runtime](https://github.com/fastly/js-compute-runtime/blob/main/runtime/js-compute-runtime/third_party/wizer.h#L92) + fn __wasm_call_ctors(); + + fn __wasm_call_dtors(); +} diff --git a/JS/wasm/crates/arakoo-core/src/runtime.rs b/JS/wasm/crates/arakoo-core/src/runtime.rs new file mode 100644 index 000000000..51c7591c0 --- /dev/null +++ b/JS/wasm/crates/arakoo-core/src/runtime.rs @@ -0,0 +1,9 @@ +use anyhow::Result; +use apis::{APIConfig, LogStream, RuntimeExt}; +use javy::{Config, Runtime}; + +pub fn new_runtime() -> Result { + let mut api_config = APIConfig::default(); + api_config.log_stream(LogStream::StdErr); + Runtime::new_with_apis(Config::default(), api_config) +} diff --git a/JS/wasm/crates/cli/Cargo.toml b/JS/wasm/crates/cli/Cargo.toml new file mode 100644 index 000000000..d0c379b53 --- /dev/null +++ b/JS/wasm/crates/cli/Cargo.toml @@ -0,0 +1,50 @@ +[package] +name = "cli" +edition.workspace = true +version.workspace = true + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[[bin]] +name = "arakoo" +path = "src/main.rs" + +[features] +dump_wat = ["dep:wasmprinter"] +experimental_event_loop = [] + +[dependencies] +wizer = { workspace = true } +structopt = "0.3" +anyhow = { workspace = true } +binaryen = { git = "https://github.com/pepyakin/binaryen-rs", rev = "00c98174843f957681ba0bc5cdcc9d15f5d0cb23" } +brotli = "3.4.0" +wasmprinter = { version = "0.2.75", optional = true } +wasmtime = { workspace = true } +wasmtime-wasi = { workspace = true } +wasi-common = { workspace = true } +walrus = "0.20.3" +swc_core = { version = "0.87.19", features = [ + "common_sourcemap", + "ecma_ast", + "ecma_parser", +] } +wit-parser = "0.13.0" +convert_case = "0.6.0" +wat = "1.0.85" +serve = { path = "../serve" } +tokio = { version = "1.0" } + +[dev-dependencies] +serde_json = "1.0" +uuid = { version = "1.6", features = ["v4"] } +lazy_static = "1.4" +serde = { version = "1.0", default-features = false, features = ["derive"] } +criterion = "0.5" +num-format = "0.4.4" +tempfile = "3.9.0" +wasmparser = "0.118.1" + +[build-dependencies] +anyhow = "1.0.79" +wizer = { workspace = true } \ No newline at end of file diff --git a/JS/wasm/crates/cli/build.rs b/JS/wasm/crates/cli/build.rs new file mode 100644 index 000000000..dfe079d62 --- /dev/null +++ b/JS/wasm/crates/cli/build.rs @@ -0,0 +1,79 @@ +use std::env; +use std::fs; +use std::io::{Read, Write}; + +use std::path::{Path, PathBuf}; + +use anyhow::Result; + +fn main() -> Result<()> { + if let Ok("cargo-clippy") = env::var("CARGO_CFG_FEATURE").as_ref().map(String::as_str) { + stub_javy_core_for_clippy() + } else { + copy_javy_core() + } +} + +// When using clippy, we need to write stubbed engine.wasm and provider.wasm files to ensure +// compilation succeeds. This skips building the actual engine.wasm and provider.wasm that would +// be injected into the CLI binary. +fn stub_javy_core_for_clippy() -> Result<()> { + let out_dir = PathBuf::from(env::var("OUT_DIR")?); + let engine_path = out_dir.join("engine.wasm"); + let provider_path = out_dir.join("provider.wasm"); + + if !engine_path.exists() { + std::fs::write(engine_path, [])?; + println!("cargo:warning=using stubbed engine.wasm for static analysis purposes..."); + } + + if !provider_path.exists() { + std::fs::write(provider_path, [])?; + println!("cargo:warning=using stubbed provider.wasm for static analysis purposes..."); + } + Ok(()) +} + +fn read_file(path: impl AsRef) -> Result> { + let mut buf: Vec = vec![]; + fs::File::open(path.as_ref())?.read_to_end(&mut buf)?; + Ok(buf) +} + +// Copy the engine binary build from the `core` crate +fn copy_javy_core() -> Result<()> { + let cargo_manifest_dir = env::var("CARGO_MANIFEST_DIR")?; + let module_path = PathBuf::from(&cargo_manifest_dir) + .parent() + .unwrap() + .parent() + .unwrap() + .join("target/wasm32-wasi/release"); + let engine_path = module_path.join("arakoo-core.wasm"); + let quickjs_provider_path = module_path.join("javy_quickjs_provider.wasm"); + let quickjs_provider_wizened_path = module_path.join("javy_quickjs_provider_wizened.wasm"); + + let mut wizer = wizer::Wizer::new(); + let wizened = wizer + .allow_wasi(true)? + .wasm_bulk_memory(true) + .run(read_file(&quickjs_provider_path)?.as_slice())?; + fs::File::create(&quickjs_provider_wizened_path)?.write_all(&wizened)?; + + println!("cargo:rerun-if-changed={}", engine_path.to_str().unwrap()); + println!( + "cargo:rerun-if-changed={}", + quickjs_provider_path.to_str().unwrap() + ); + println!("cargo:rerun-if-changed=build.rs"); + + if engine_path.exists() { + let out_dir = env::var("OUT_DIR")?; + let copied_engine_path = Path::new(&out_dir).join("engine.wasm"); + let copied_provider_path = Path::new(&out_dir).join("provider.wasm"); + + fs::copy(&engine_path, copied_engine_path)?; + fs::copy(&quickjs_provider_wizened_path, copied_provider_path)?; + } + Ok(()) +} diff --git a/JS/wasm/crates/cli/src/bytecode.rs b/JS/wasm/crates/cli/src/bytecode.rs new file mode 100644 index 000000000..abe4ec4ee --- /dev/null +++ b/JS/wasm/crates/cli/src/bytecode.rs @@ -0,0 +1,79 @@ +use anyhow::{anyhow, Result}; +use wasmtime::{Engine, Instance, Linker, Memory, Module, Store}; +use wasmtime_wasi::{WasiCtx, WasiCtxBuilder}; + +pub const QUICKJS_PROVIDER_MODULE: &[u8] = + include_bytes!(concat!(env!("OUT_DIR"), "/provider.wasm")); + +pub fn compile_source(js_source_code: &[u8]) -> Result> { + let (mut store, instance, memory) = create_wasm_env()?; + let (js_src_ptr, js_src_len) = + copy_source_code_into_instance(js_source_code, &mut store, &instance, &memory)?; + let ret_ptr = call_compile(js_src_ptr, js_src_len, &mut store, &instance)?; + let bytecode = copy_bytecode_from_instance(ret_ptr, &mut store, &memory)?; + Ok(bytecode) +} + +fn create_wasm_env() -> Result<(Store, Instance, Memory)> { + let engine = Engine::default(); + let module = Module::new(&engine, QUICKJS_PROVIDER_MODULE)?; + let mut linker = Linker::new(&engine); + wasmtime_wasi::snapshots::preview_1::add_wasi_snapshot_preview1_to_linker(&mut linker, |s| s)?; + let wasi = WasiCtxBuilder::new().inherit_stderr().build(); + let mut store = Store::new(&engine, wasi); + let instance = linker.instantiate(&mut store, &module)?; + let memory = instance.get_memory(&mut store, "memory").unwrap(); + Ok((store, instance, memory)) +} + +fn copy_source_code_into_instance( + js_source_code: &[u8], + mut store: &mut Store, + instance: &Instance, + memory: &Memory, +) -> Result<(u32, u32)> { + let realloc_fn = instance + .get_typed_func::<(u32, u32, u32, u32), u32>(&mut store, "canonical_abi_realloc")?; + let js_src_len = js_source_code.len().try_into()?; + + let original_ptr = 0; + let original_size = 0; + let alignment = 1; + let size = js_src_len; + let js_source_ptr = + realloc_fn.call(&mut store, (original_ptr, original_size, alignment, size))?; + + memory.write(&mut store, js_source_ptr.try_into()?, js_source_code)?; + + Ok((js_source_ptr, js_src_len)) +} + +fn call_compile( + js_src_ptr: u32, + js_src_len: u32, + mut store: &mut Store, + instance: &Instance, +) -> Result { + let compile_src_fn = instance.get_typed_func::<(u32, u32), u32>(&mut store, "compile_src")?; + let ret_ptr = compile_src_fn + .call(&mut store, (js_src_ptr, js_src_len)) + .map_err(|_| anyhow!("JS compilation failed"))?; + Ok(ret_ptr) +} + +fn copy_bytecode_from_instance( + ret_ptr: u32, + mut store: &mut Store, + memory: &Memory, +) -> Result> { + let mut ret_buffer = [0; 8]; + memory.read(&mut store, ret_ptr.try_into()?, &mut ret_buffer)?; + + let bytecode_ptr = u32::from_le_bytes(ret_buffer[0..4].try_into()?); + let bytecode_len = u32::from_le_bytes(ret_buffer[4..8].try_into()?); + + let mut bytecode = vec![0; bytecode_len.try_into()?]; + memory.read(&mut store, bytecode_ptr.try_into()?, &mut bytecode)?; + + Ok(bytecode) +} diff --git a/JS/wasm/crates/cli/src/commands.rs b/JS/wasm/crates/cli/src/commands.rs new file mode 100644 index 000000000..ef7563d8d --- /dev/null +++ b/JS/wasm/crates/cli/src/commands.rs @@ -0,0 +1,72 @@ +use std::path::PathBuf; +use structopt::StructOpt; + +#[derive(Debug, StructOpt)] +#[structopt(name = "javy", about = "JavaScript to WebAssembly toolchain")] +pub enum Command { + /// Compiles JavaScript to WebAssembly. + Compile(CompileCommandOpts), + /// Emits the provider binary that is required to run dynamically + /// linked WebAssembly modules. + EmitProvider(EmitProviderCommandOpts), + Serve(ServeCommandOpts), +} + +#[derive(Debug, StructOpt)] +pub struct CompileCommandOpts { + #[structopt(parse(from_os_str))] + /// Path of the JavaScript input file. + pub input: PathBuf, + + #[structopt(short = "o", parse(from_os_str), default_value = "index.wasm")] + /// Desired path of the WebAssembly output file. + pub output: PathBuf, + + #[structopt(short = "d")] + /// Creates a smaller module that requires a dynamically linked QuickJS provider Wasm + /// module to execute (see `emit-provider` command). + pub dynamic: bool, + + #[structopt(long = "wit")] + /// Optional path to WIT file describing exported functions. + /// Only supports function exports with no arguments and no return values. + pub wit: Option, + + #[structopt(short = "n")] + /// Optional WIT world name for WIT file. Must be specified if WIT is file path is specified. + pub wit_world: Option, + + #[structopt(long = "no-source-compression")] + /// Disable source code compression, which reduces compile time at the expense of generating larger WebAssembly files. + pub no_source_compression: bool, +} + +#[derive(Debug, StructOpt)] +pub struct EmitProviderCommandOpts { + #[structopt(long = "out", short = "o")] + /// Output path for the provider binary (default is stdout). + pub out: Option, +} + +#[derive(Debug, StructOpt)] +pub struct ServeCommandOpts { + input: PathBuf, + #[structopt(short, long, default_value = "0.0.0.0")] + hostname: String, + #[structopt(short, long, default_value = "8080")] + port: u16, +} + +impl ServeCommandOpts { + /// The path to the service's Wasm binary. + pub fn input(&self) -> PathBuf { + PathBuf::from(&self.input) + } + + /// The address to bind the server to. + pub fn addr(&self) -> std::net::SocketAddr { + format!("{}:{}", self.hostname, self.port) + .parse() + .expect("Invalid address") + } +} diff --git a/JS/wasm/crates/cli/src/exports.rs b/JS/wasm/crates/cli/src/exports.rs new file mode 100644 index 000000000..19e5eb52d --- /dev/null +++ b/JS/wasm/crates/cli/src/exports.rs @@ -0,0 +1,48 @@ +use anyhow::{anyhow, Result}; +use convert_case::{Case, Casing}; +use std::{env, path::Path}; + +use crate::{js::JS, wit}; + +pub struct Export { + pub wit: String, + pub js: String, +} + +pub fn process_exports(js: &JS, wit: &Path, wit_world: &str) -> Result> { + let js_exports = js.exports()?; + parse_wit_exports(wit, wit_world)? + .into_iter() + .map(|wit_export| { + let export = wit_export.from_case(Case::Kebab).to_case(Case::Camel); + if !js_exports.contains(&export) { + Err(anyhow!("JS module does not export {export}")) + } else { + Ok(Export { + wit: wit_export, + js: export, + }) + } + }) + .collect::>>() +} + +fn parse_wit_exports(wit: &Path, wit_world: &str) -> Result> { + // Configure wit-parser to not require semicolons but only if the relevant + // environment variable is not already set. + const SEMICOLONS_OPTIONAL_ENV_VAR: &str = "WIT_REQUIRE_SEMICOLONS"; + let semicolons_env_var_already_set = env::var(SEMICOLONS_OPTIONAL_ENV_VAR).is_ok(); + if !semicolons_env_var_already_set { + env::set_var(SEMICOLONS_OPTIONAL_ENV_VAR, "0"); + } + + let exports = wit::parse_exports(wit, wit_world); + + // If we set the environment variable to not require semicolons, remove + // that environment variable now that we no longer need it set. + if !semicolons_env_var_already_set { + env::remove_var(SEMICOLONS_OPTIONAL_ENV_VAR); + } + + exports +} diff --git a/JS/wasm/crates/cli/src/js.rs b/JS/wasm/crates/cli/src/js.rs new file mode 100644 index 000000000..c0f47fbfd --- /dev/null +++ b/JS/wasm/crates/cli/src/js.rs @@ -0,0 +1,317 @@ +/// Higher-level representation of JavaScript. +/// +/// This is intended to be used to derive different representations of source +/// code. For example, as a byte array, a string, QuickJS bytecode, compressed +/// bytes, or attributes of the source code like what it exports. +use std::{ + collections::HashMap, + fs::File, + io::{Cursor, Read}, + path::Path, + rc::Rc, +}; + +use anyhow::{anyhow, bail, Context, Result}; +use brotli::enc::{self, BrotliEncoderParams}; +use swc_core::{ + common::{FileName, SourceMap}, + ecma::{ + ast::{ + Decl, EsVersion, ExportDecl, ExportSpecifier, Module, ModuleDecl, ModuleExportName, + ModuleItem, Stmt, + }, + parser::{self, EsConfig, Syntax}, + }, +}; + +use crate::bytecode; + +#[derive(Clone, Debug)] +pub struct JS { + source_code: Rc, +} + +impl JS { + fn from_string(source_code: String) -> JS { + JS { + source_code: Rc::new(source_code), + } + } + + pub fn from_file(path: &Path) -> Result { + let mut input_file = File::open(path) + .with_context(|| format!("Failed to open input file {}", path.display()))?; + let mut contents: Vec = vec![]; + input_file.read_to_end(&mut contents)?; + Ok(Self::from_string(String::from_utf8(contents)?)) + } + + pub fn as_bytes(&self) -> &[u8] { + self.source_code.as_bytes() + } + + pub fn compile(&self) -> Result> { + bytecode::compile_source(self.source_code.as_bytes()) + } + + pub fn compress(&self) -> Result> { + let mut compressed_source_code: Vec = vec![]; + enc::BrotliCompress( + &mut Cursor::new(&self.source_code.as_bytes()), + &mut compressed_source_code, + &BrotliEncoderParams { + quality: 11, + ..Default::default() + }, + )?; + Ok(compressed_source_code) + } + + pub fn exports(&self) -> Result> { + let module = self.parse_module()?; + + // function foo() ... + let mut functions = HashMap::new(); + // export { foo, bar as baz } + let mut named_exports = vec![]; + // export function foo() ... + let mut exported_functions = vec![]; + for item in module.body { + match item { + ModuleItem::ModuleDecl(ModuleDecl::ExportDecl(ExportDecl { + decl: Decl::Fn(f), + .. + })) => { + if !f.function.params.is_empty() { + bail!("Exported functions with parameters are not supported"); + } + if f.function.is_generator { + bail!("Exported generators are not supported"); + } + exported_functions.push(f.ident.sym); + } + ModuleItem::ModuleDecl(ModuleDecl::ExportNamed(e)) => { + for specifier in e.specifiers { + if let ExportSpecifier::Named(n) = specifier { + let orig = match n.orig { + ModuleExportName::Ident(i) => i.sym, + ModuleExportName::Str(s) => s.value, + }; + let exported_name = n.exported.map(|e| match e { + ModuleExportName::Ident(i) => i.sym, + ModuleExportName::Str(s) => s.value, + }); + named_exports.push((orig, exported_name)); + } + } + } + ModuleItem::ModuleDecl(ModuleDecl::ExportDefaultDecl(e)) if e.decl.is_fn_expr() => { + exported_functions.push("default".into()) + } + ModuleItem::ModuleDecl(ModuleDecl::ExportDefaultExpr(e)) if e.expr.is_arrow() => { + exported_functions.push("default".into()) + } + ModuleItem::Stmt(Stmt::Decl(Decl::Fn(f))) => { + functions.insert( + f.ident.sym, + (f.function.params.is_empty(), f.function.is_generator), + ); + } + _ => continue, + } + } + + let mut named_exported_functions = named_exports + .into_iter() + .filter_map(|(orig, exported)| { + if let Some((no_params, is_generator)) = functions.get(&orig) { + if !no_params { + Some(Err(anyhow!( + "Exported functions with parameters are not supported" + ))) + } else if *is_generator { + Some(Err(anyhow!("Exported generators are not supported"))) + } else { + Some(Ok(exported.unwrap_or(orig))) + } + } else { + None + } + }) + .collect::, _>>()?; + exported_functions.append(&mut named_exported_functions); + Ok(exported_functions + .into_iter() + .map(|f| f.to_string()) + .collect()) + } + + fn parse_module(&self) -> Result { + let source_map: SourceMap = Default::default(); + let file = source_map.new_source_file_from(FileName::Anon, self.source_code.clone()); + let mut errors = vec![]; + parser::parse_file_as_module( + &file, + Syntax::Es(EsConfig::default()), + EsVersion::Es2020, + None, + &mut errors, + ) + .map_err(|e| anyhow!(e.into_kind().msg())) + .with_context(|| "Invalid JavaScript") + } +} + +#[cfg(test)] +mod tests { + use crate::js::JS; + + use anyhow::Result; + + #[test] + fn parse_no_exports() -> Result<()> { + let exports = parse("function foo() {}")?; + assert_eq!(Vec::<&str>::default(), exports); + Ok(()) + } + + #[test] + fn parse_invalid_js() -> Result<()> { + let res = parse("fun foo() {}"); + assert_eq!("Invalid JavaScript", res.err().unwrap().to_string()); + Ok(()) + } + + #[test] + fn parse_one_func_export() -> Result<()> { + let exports = parse("export function foo() {}")?; + assert_eq!(vec!["foo"], exports); + Ok(()) + } + + #[test] + fn parse_func_export_with_parameter() -> Result<()> { + let res = parse("export function foo(bar) {}"); + assert_eq!( + "Exported functions with parameters are not supported", + res.err().unwrap().to_string() + ); + Ok(()) + } + + #[test] + fn parse_generator_export() -> Result<()> { + let res = parse("export function *foo() {}"); + assert_eq!( + "Exported generators are not supported", + res.err().unwrap().to_string() + ); + Ok(()) + } + + #[test] + fn parse_two_func_exports() -> Result<()> { + let exports = parse("export function foo() {}; export function bar() {};")?; + assert_eq!(vec!["foo", "bar"], exports); + Ok(()) + } + + #[test] + fn parse_const_export() -> Result<()> { + let exports = parse("export const x = 1;")?; + let expected_exports: Vec<&str> = vec![]; + assert_eq!(expected_exports, exports); + Ok(()) + } + + #[test] + fn parse_const_export_and_func_export() -> Result<()> { + let exports = parse("export const x = 1; export function foo() {}")?; + assert_eq!(vec!["foo"], exports); + Ok(()) + } + + #[test] + fn parse_named_func_export() -> Result<()> { + let exports = parse("function foo() {}; export { foo };")?; + assert_eq!(vec!["foo"], exports); + Ok(()) + } + + #[test] + fn parse_named_func_export_with_arg() -> Result<()> { + let res = parse("function foo(bar) {}; export { foo };"); + assert_eq!( + "Exported functions with parameters are not supported", + res.err().unwrap().to_string() + ); + Ok(()) + } + + #[test] + fn parse_funcs_with_args() -> Result<()> { + let exports = parse("function foo(bar) {}")?; + assert_eq!(Vec::<&str>::default(), exports); + Ok(()) + } + + #[test] + fn parse_named_func_export_and_const_export() -> Result<()> { + let exports = parse("function foo() {}; const bar = 1; export { foo, bar };")?; + assert_eq!(vec!["foo"], exports); + Ok(()) + } + + #[test] + fn parse_func_export_and_named_func_export() -> Result<()> { + let exports = parse("export function foo() {}; function bar() {}; export { bar };")?; + assert_eq!(vec!["foo", "bar"], exports); + Ok(()) + } + + #[test] + fn parse_renamed_func_export() -> Result<()> { + let exports = parse("function foo() {}; export { foo as bar };")?; + assert_eq!(vec!["bar"], exports); + Ok(()) + } + + #[test] + fn parse_hoisted_func_export() -> Result<()> { + let exports = parse("export { foo }; function foo() {}")?; + assert_eq!(vec!["foo"], exports); + Ok(()) + } + + #[test] + fn parse_renamed_hosted_func_export() -> Result<()> { + let exports = parse("export { foo as bar }; function foo() {}")?; + assert_eq!(vec!["bar"], exports); + Ok(()) + } + + #[test] + fn parse_hoisted_exports_with_func_and_const() -> Result<()> { + let exports = parse("export { foo, bar }; function foo() {}; const bar = 1;")?; + assert_eq!(vec!["foo"], exports); + Ok(()) + } + + #[test] + fn parse_default_arrow_export() -> Result<()> { + let exports = parse("export default () => {}")?; + assert_eq!(vec!["default"], exports); + Ok(()) + } + + #[test] + fn parse_default_function_export() -> Result<()> { + let exports = parse("export default function() {}")?; + assert_eq!(vec!["default"], exports); + Ok(()) + } + + fn parse(js: &str) -> Result> { + JS::from_string(js.to_string()).exports() + } +} diff --git a/JS/wasm/crates/cli/src/main.rs b/JS/wasm/crates/cli/src/main.rs new file mode 100644 index 000000000..d06673fbb --- /dev/null +++ b/JS/wasm/crates/cli/src/main.rs @@ -0,0 +1,56 @@ +mod bytecode; +mod commands; +mod exports; +mod js; +mod wasm_generator; +mod wit; + +use crate::commands::{Command, EmitProviderCommandOpts}; +use crate::wasm_generator::r#static as static_generator; +use anyhow::{bail, Result}; +use js::JS; +use std::fs; +use std::fs::File; +use std::io::Write; +use structopt::StructOpt; +use wasm_generator::dynamic as dynamic_generator; + +#[tokio::main] +async fn main() -> Result<()> { + let cmd = Command::from_args(); + + match &cmd { + Command::EmitProvider(opts) => emit_provider(opts), + Command::Compile(opts) => { + let js = JS::from_file(&opts.input)?; + let exports = match (&opts.wit, &opts.wit_world) { + (None, None) => Ok(vec![]), + (None, Some(_)) => Ok(vec![]), + (Some(_), None) => bail!("Must provide WIT world when providing WIT file"), + (Some(wit), Some(world)) => exports::process_exports(&js, wit, world), + }?; + let wasm = if opts.dynamic { + dynamic_generator::generate(&js, exports, opts.no_source_compression)? + } else { + static_generator::generate(&js, exports, opts.no_source_compression)? + }; + fs::write(&opts.output, wasm)?; + Ok(()) + } + Command::Serve(opts) => { + serve::WorkerCtx::new(opts.input())? + .serve(opts.addr()) + .await?; + Ok(()) + } + } +} + +fn emit_provider(opts: &EmitProviderCommandOpts) -> Result<()> { + let mut file: Box = match opts.out.as_ref() { + Some(path) => Box::new(File::create(path)?), + _ => Box::new(std::io::stdout()), + }; + file.write_all(bytecode::QUICKJS_PROVIDER_MODULE)?; + Ok(()) +} diff --git a/JS/wasm/crates/cli/src/wasm_generator/dynamic.rs b/JS/wasm/crates/cli/src/wasm_generator/dynamic.rs new file mode 100644 index 000000000..a89455a1e --- /dev/null +++ b/JS/wasm/crates/cli/src/wasm_generator/dynamic.rs @@ -0,0 +1,193 @@ +use crate::{exports::Export, js::JS}; + +use super::transform::{self, SourceCodeSection}; +use anyhow::Result; +use walrus::{DataKind, FunctionBuilder, Module, ValType}; + +// Run the calling code with the `dump_wat` feature enabled to print the WAT to stdout +// +// For the example generated WAT, the `bytecode_len` is 137 +// (module +// (type (;0;) (func)) +// (type (;1;) (func (param i32 i32))) +// (type (;2;) (func (param i32 i32 i32 i32))) +// (type (;3;) (func (param i32 i32 i32 i32) (result i32))) +// (import "javy_quickjs_provider_v1" "canonical_abi_realloc" (func (;0;) (type 3))) +// (import "javy_quickjs_provider_v1" "eval_bytecode" (func (;1;) (type 1))) +// (import "javy_quickjs_provider_v1" "memory" (memory (;0;) 0)) +// (import "javy_quickjs_provider_v1" "invoke" (func (;2;) (type 2))) +// (func (;3;) (type 0) +// (local i32 i32) +// i32.const 0 +// i32.const 0 +// i32.const 1 +// i32.const 137 +// call 0 +// local.tee 0 +// i32.const 0 +// i32.const 137 +// memory.init 0 +// data.drop 0 +// i32.const 0 +// i32.const 0 +// i32.const 1 +// i32.const 3 +// call 0 +// local.tee 1 +// i32.const 0 +// i32.const 3 +// memory.init 1 +// data.drop 1 +// local.get 0 +// i32.const 137 +// local.get 1 +// i32.const 3 +// call 2 +// ) +// (func (;4;) (type 0) +// (local i32) +// i32.const 0 +// i32.const 0 +// i32.const 1 +// i32.const 137 +// call 0 +// local.tee 0 +// i32.const 0 +// i32.const 137 +// memory.init 0 +// local.get 0 +// i32.const 137 +// call 1 +// ) +// (export "_start" (func 4)) +// (export "foo" (func 3)) +// (data (;0;) "\02\05\18function.mjs\06foo\0econsole\06log\06bar\0f\bc\03\00\01\00\00\be\03\00\00\0e\00\06\01\a0\01\00\00\00\03\01\01\1a\00\be\03\00\01\08\ea\05\c0\00\e1)8\e0\00\00\00B\e1\00\00\00\04\e2\00\00\00$\01\00)\bc\03\01\04\01\00\07\0a\0eC\06\01\be\03\00\00\00\03\00\00\13\008\e0\00\00\00B\e1\00\00\00\04\df\00\00\00$\01\00)\bc\03\01\02\03]") +// (data (;1;) "foo") +// ) +pub fn generate( + js: &JS, + exported_functions: Vec, + no_source_compression: bool, +) -> Result> { + let mut module = Module::with_config(transform::module_config()); + + const IMPORT_NAMESPACE: &str = "javy_quickjs_provider_v1"; + + let canonical_abi_realloc_type = module.types.add( + &[ValType::I32, ValType::I32, ValType::I32, ValType::I32], + &[ValType::I32], + ); + let (canonical_abi_realloc_fn, _) = module.add_import_func( + IMPORT_NAMESPACE, + "canonical_abi_realloc", + canonical_abi_realloc_type, + ); + + let eval_bytecode_type = module.types.add(&[ValType::I32, ValType::I32], &[]); + let (eval_bytecode_fn, _) = + module.add_import_func(IMPORT_NAMESPACE, "eval_bytecode", eval_bytecode_type); + + let (memory, _) = module.add_import_memory(IMPORT_NAMESPACE, "memory", false, 0, None); + + transform::add_producers_section(&mut module.producers); + if no_source_compression { + module.customs.add(SourceCodeSection::uncompressed(js)?); + } else { + module.customs.add(SourceCodeSection::compressed(js)?); + } + + let bytecode = js.compile()?; + let bytecode_len: i32 = bytecode.len().try_into()?; + let bytecode_data = module.data.add(DataKind::Passive, bytecode); + + let mut main = FunctionBuilder::new(&mut module.types, &[], &[]); + let bytecode_ptr_local = module.locals.add(ValType::I32); + main.func_body() + // Allocate memory in javy_quickjs_provider for bytecode array. + .i32_const(0) // orig ptr + .i32_const(0) // orig size + .i32_const(1) // alignment + .i32_const(bytecode_len) // new size + .call(canonical_abi_realloc_fn) + // Copy bytecode array into allocated memory. + .local_tee(bytecode_ptr_local) // save returned address to local and set as dest addr for mem.init + .i32_const(0) // offset into data segment for mem.init + .i32_const(bytecode_len) // size to copy from data segment + // top-2: dest addr, top-1: offset into source, top-0: size of memory region in bytes. + .memory_init(memory, bytecode_data) + // Evaluate bytecode. + .local_get(bytecode_ptr_local) // ptr to bytecode + .i32_const(bytecode_len) + .call(eval_bytecode_fn); + let main = main.finish(vec![], &mut module.funcs); + + module.exports.add("_start", main); + + if !exported_functions.is_empty() { + let invoke_type = module.types.add( + &[ValType::I32, ValType::I32, ValType::I32, ValType::I32], + &[], + ); + let (invoke_fn, _) = module.add_import_func(IMPORT_NAMESPACE, "invoke", invoke_type); + + let fn_name_ptr_local = module.locals.add(ValType::I32); + for export in exported_functions { + // For each JS function export, add an export that copies the name of the function into memory and invokes it. + let js_export_bytes = export.js.as_bytes(); + let js_export_len: i32 = js_export_bytes.len().try_into().unwrap(); + let fn_name_data = module.data.add(DataKind::Passive, js_export_bytes.to_vec()); + + let mut export_fn = FunctionBuilder::new(&mut module.types, &[], &[]); + export_fn + .func_body() + // Copy bytecode. + .i32_const(0) // orig ptr + .i32_const(0) // orig len + .i32_const(1) // alignment + .i32_const(bytecode_len) // size to copy + .call(canonical_abi_realloc_fn) + .local_tee(bytecode_ptr_local) + .i32_const(0) // offset into data segment + .i32_const(bytecode_len) // size to copy + .memory_init(memory, bytecode_data) // copy bytecode into allocated memory + .data_drop(bytecode_data) + // Copy function name. + .i32_const(0) // orig ptr + .i32_const(0) // orig len + .i32_const(1) // alignment + .i32_const(js_export_len) // new size + .call(canonical_abi_realloc_fn) + .local_tee(fn_name_ptr_local) + .i32_const(0) // offset into data segment + .i32_const(js_export_len) // size to copy + .memory_init(memory, fn_name_data) // copy fn name into allocated memory + .data_drop(fn_name_data) + // Call invoke. + .local_get(bytecode_ptr_local) + .i32_const(bytecode_len) + .local_get(fn_name_ptr_local) + .i32_const(js_export_len) + .call(invoke_fn); + let export_fn = export_fn.finish(vec![], &mut module.funcs); + module.exports.add(&export.wit, export_fn); + } + } + + let wasm = module.emit_wasm(); + print_wat(&wasm)?; + Ok(wasm) +} + +#[cfg(feature = "dump_wat")] +fn print_wat(wasm_binary: &[u8]) -> Result<()> { + println!( + "Generated WAT: \n{}", + wasmprinter::print_bytes(&wasm_binary)? + ); + Ok(()) +} + +#[cfg(not(feature = "dump_wat"))] +fn print_wat(_wasm_binary: &[u8]) -> Result<()> { + Ok(()) +} diff --git a/JS/wasm/crates/cli/src/wasm_generator/mod.rs b/JS/wasm/crates/cli/src/wasm_generator/mod.rs new file mode 100644 index 000000000..186453527 --- /dev/null +++ b/JS/wasm/crates/cli/src/wasm_generator/mod.rs @@ -0,0 +1,3 @@ +pub mod dynamic; +pub mod r#static; +mod transform; diff --git a/JS/wasm/crates/cli/src/wasm_generator/static.rs b/JS/wasm/crates/cli/src/wasm_generator/static.rs new file mode 100644 index 000000000..53a7450f7 --- /dev/null +++ b/JS/wasm/crates/cli/src/wasm_generator/static.rs @@ -0,0 +1,143 @@ +use std::{collections::HashMap, rc::Rc, sync::OnceLock}; + +use anyhow::{anyhow, Result}; +use binaryen::{CodegenConfig, Module}; +use walrus::{DataKind, ExportItem, FunctionBuilder, FunctionId, MemoryId, ValType}; +use wasi_common::{pipe::ReadPipe, WasiCtx}; +use wasmtime::Linker; +use wasmtime_wasi::WasiCtxBuilder; +use wizer::Wizer; + +use crate::{exports::Export, js::JS}; + +use super::transform::{self, SourceCodeSection}; + +static mut WASI: OnceLock = OnceLock::new(); + +pub fn generate(js: &JS, exports: Vec, no_source_compression: bool) -> Result> { + let wasm = include_bytes!(concat!(env!("OUT_DIR"), "/engine.wasm")); + + let wasi = WasiCtxBuilder::new() + .stdin(Box::new(ReadPipe::from(js.as_bytes()))) + .inherit_stdout() + .inherit_stderr() + .build(); + // We can't move the WasiCtx into `make_linker` since WasiCtx doesn't implement the `Copy` trait. + // So we move the WasiCtx into a mutable static OnceLock instead. + // Setting the value in the `OnceLock` and getting the reference back from it should be safe given + // we're never executing this code concurrently. This code will also fail if `generate` is invoked + // more than once per execution. + if unsafe { WASI.set(wasi) }.is_err() { + panic!("Failed to set WASI static variable") + } + + let wasm = Wizer::new() + .make_linker(Some(Rc::new(|engine| { + let mut linker = Linker::new(engine); + wasmtime_wasi::add_to_linker(&mut linker, |_ctx: &mut Option| { + unsafe { WASI.get_mut() }.unwrap() + })?; + Ok(linker) + })))? + .wasm_bulk_memory(true) + .run(wasm) + .map_err(|_| anyhow!("JS compilation failed"))?; + + let mut module = transform::module_config().parse(&wasm)?; + + let (realloc, free, invoke, memory) = { + let mut exports = HashMap::new(); + for export in module.exports.iter() { + exports.insert(export.name.as_str(), export); + } + ( + *exports.get("canonical_abi_realloc").unwrap(), + *exports.get("canonical_abi_free").unwrap(), + *exports.get("javy.invoke").unwrap(), + *exports.get("memory").unwrap(), + ) + }; + + // let realloc_export = realloc.id(); + let free_export = free.id(); + let invoke_export = invoke.id(); + + if !exports.is_empty() { + let ExportItem::Function(realloc_fn) = realloc.item else { + unreachable!() + }; + let ExportItem::Function(invoke_fn) = invoke.item else { + unreachable!() + }; + let ExportItem::Memory(memory) = memory.item else { + unreachable!() + }; + export_exported_js_functions(&mut module, realloc_fn, invoke_fn, memory, exports); + } + + // We no longer need these exports so remove them. + // module.exports.delete(realloc_export); + module.exports.delete(free_export); + module.exports.delete(invoke_export); + + let wasm = module.emit_wasm(); + + let codegen_cfg = CodegenConfig { + optimization_level: 3, // Aggressively optimize for speed. + shrink_level: 0, // Don't optimize for size at the expense of performance. + debug_info: false, + }; + + let mut module = Module::read(&wasm) + .map_err(|_| anyhow!("Unable to read wasm binary for wasm-opt optimizations"))?; + module.optimize(&codegen_cfg); + module + .run_optimization_passes(vec!["strip"], &codegen_cfg) + .map_err(|_| anyhow!("Running wasm-opt optimization passes failed"))?; + let wasm = module.write(); + + let mut module = transform::module_config().parse(&wasm)?; + if no_source_compression { + module.customs.add(SourceCodeSection::uncompressed(js)?); + } else { + module.customs.add(SourceCodeSection::compressed(js)?); + } + transform::add_producers_section(&mut module.producers); + Ok(module.emit_wasm()) +} + +fn export_exported_js_functions( + module: &mut walrus::Module, + realloc_fn: FunctionId, + invoke_fn: FunctionId, + memory: MemoryId, + js_exports: Vec, +) { + let ptr_local = module.locals.add(ValType::I32); + for export in js_exports { + println!("Exporting JS function: {}", export.js); + // For each JS function export, add an export that copies the name of the function into memory and invokes it. + let js_export_bytes = export.js.as_bytes(); + let js_export_len: i32 = js_export_bytes.len().try_into().unwrap(); + let fn_name_data = module.data.add(DataKind::Passive, js_export_bytes.to_vec()); + + let mut export_fn = FunctionBuilder::new(&mut module.types, &[], &[]); + export_fn + .func_body() + .i32_const(0) // orig ptr + .i32_const(0) // orig len + .i32_const(1) // alignment + .i32_const(js_export_len) // new size + .call(realloc_fn) + .local_tee(ptr_local) + .i32_const(0) // offset into data segment + .i32_const(js_export_len) // size to copy + .memory_init(memory, fn_name_data) // copy fn name into allocated memory + .data_drop(fn_name_data) + .local_get(ptr_local) + .i32_const(js_export_len) + .call(invoke_fn); + let export_fn = export_fn.finish(vec![], &mut module.funcs); + module.exports.add(&export.wit, export_fn); + } +} diff --git a/JS/wasm/crates/cli/src/wasm_generator/transform.rs b/JS/wasm/crates/cli/src/wasm_generator/transform.rs new file mode 100644 index 000000000..68023dcbd --- /dev/null +++ b/JS/wasm/crates/cli/src/wasm_generator/transform.rs @@ -0,0 +1,47 @@ +use std::borrow::Cow; + +use anyhow::Result; +use walrus::{CustomSection, IdsToIndices, ModuleConfig, ModuleProducers}; + +use crate::js::JS; + +#[derive(Debug)] +pub struct SourceCodeSection { + source_code: Vec, +} + +impl SourceCodeSection { + pub fn compressed(js: &JS) -> Result { + Ok(SourceCodeSection { + source_code: js.compress()?, + }) + } + + pub fn uncompressed(js: &JS) -> Result { + Ok(SourceCodeSection { + source_code: js.as_bytes().to_vec(), + }) + } +} + +impl CustomSection for SourceCodeSection { + fn name(&self) -> &str { + "javy_source" + } + + fn data(&self, _ids_to_indices: &IdsToIndices) -> Cow<[u8]> { + (&self.source_code).into() + } +} + +pub fn module_config() -> ModuleConfig { + let mut config = ModuleConfig::new(); + config.generate_name_section(false); + config +} + +pub fn add_producers_section(producers: &mut ModuleProducers) { + producers.clear(); // removes Walrus and Rust + producers.add_language("JavaScript", "ES2020"); + producers.add_processed_by("Javy", env!("CARGO_PKG_VERSION")); +} diff --git a/JS/wasm/crates/cli/src/wit.rs b/JS/wasm/crates/cli/src/wit.rs new file mode 100644 index 000000000..027dc22da --- /dev/null +++ b/JS/wasm/crates/cli/src/wit.rs @@ -0,0 +1,35 @@ +use std::path::Path; + +use anyhow::{bail, Result}; + +use wit_parser::{Resolve, UnresolvedPackage, WorldItem}; + +pub fn parse_exports(wit: impl AsRef, world: &str) -> Result> { + let mut resolve = Resolve::default(); + let package = UnresolvedPackage::parse_path(wit.as_ref())?; + resolve.push(package)?; + let (_, package_id) = resolve.package_names.first().unwrap(); + let world_id = resolve.select_world(*package_id, Some(world))?; + let world = resolve.worlds.get(world_id).unwrap(); + + if !world.imports.is_empty() { + bail!("Imports in WIT file are not supported"); + } + let mut exported_functions = vec![]; + for (_, export) in &world.exports { + match export { + WorldItem::Interface(_) => bail!("Exported interfaces are not supported"), + WorldItem::Function(f) => { + if !f.params.is_empty() { + bail!("Exported functions with parameters are not supported") + } else if f.results.len() != 0 { + bail!("Exported functions with return values are not supported") + } else { + exported_functions.push(f.name.clone()) + } + } + WorldItem::Type(_) => bail!("Exported types are not supported"), + } + } + Ok(exported_functions) +} diff --git a/JS/wasm/crates/serve/Cargo.toml b/JS/wasm/crates/serve/Cargo.toml new file mode 100644 index 000000000..0d0c111aa --- /dev/null +++ b/JS/wasm/crates/serve/Cargo.toml @@ -0,0 +1,18 @@ +[package] +name = "serve" +edition.workspace = true +version.workspace = true + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html +[dependencies] +wasi-common = { workspace = true } +wasmtime = { workspace = true } +wasmtime-wasi = { workspace = true } +anyhow = {workspace = true} +serde = { version = "1", features = ["derive"] } +serde_json = "1" +tokio = { version = "1.21.2", features = ["full"] } +tracing = "0.1.37" +hyper = {version="0.14.26", features=["full"]} +futures = "0.3.24" +tracing-subscriber = { version = "^0.3.18", features = ["env-filter", "fmt"] } \ No newline at end of file diff --git a/JS/wasm/crates/serve/src/io.rs b/JS/wasm/crates/serve/src/io.rs new file mode 100644 index 000000000..ee0ea26ba --- /dev/null +++ b/JS/wasm/crates/serve/src/io.rs @@ -0,0 +1,61 @@ +use std::collections::HashMap; + +use hyper::{header::HOST, http::request::Parts, HeaderMap, Uri}; +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Debug)] +pub struct WasmInput<'a> { + url: String, + method: &'a str, + headers: HashMap, + body: &'a str, + params: HashMap, +} + +impl<'a> WasmInput<'a> { + pub fn new(request: &'a Parts, body: &'a str) -> Self { + let mut params = HashMap::new(); + + if let Some(query) = request.uri.query() { + for pair in query.split('&') { + let mut parts = pair.split('='); + let key = parts.next().unwrap(); + let value = parts.next().unwrap(); + params.insert(key.to_string(), value.to_string()); + } + } + + let url = Self::build_url(request); + + Self { + url, + method: request.method.as_str(), + headers: Self::build_headers_hash(&request.headers), + body, + params, + } + } + + fn build_url(request: &Parts) -> String { + Uri::builder() + .scheme("http") + .authority(request.headers.get(HOST).unwrap().to_str().unwrap()) + .path_and_query(request.uri.path_and_query().unwrap().clone()) + .build() + .unwrap() + .to_string() + } + + fn build_headers_hash(headers: &HeaderMap) -> HashMap { + let mut parsed_headers = HashMap::new(); + + for (key, value) in headers.iter() { + parsed_headers.insert( + String::from(key.as_str()), + String::from(value.to_str().unwrap()), + ); + } + + parsed_headers + } +} diff --git a/JS/wasm/crates/serve/src/lib.rs b/JS/wasm/crates/serve/src/lib.rs new file mode 100644 index 000000000..1b108342c --- /dev/null +++ b/JS/wasm/crates/serve/src/lib.rs @@ -0,0 +1,245 @@ +mod io; +use std::{ + convert::Infallible, + env, + future::Future, + net::SocketAddr, + path::Path, + pin::Pin, + task::{self, Poll}, +}; + +use futures::future::{self, Ready}; +use hyper::{ + http::request::Parts, server::conn::AddrStream, service::Service, Body, Request, Response, +}; + +use tracing::{error, event, info, Level}; +use tracing_subscriber::{filter::EnvFilter, FmtSubscriber}; +use wasi_common::WasiCtx; +use wasmtime_wasi::WasiCtxBuilder; + +use wasmtime::{Config, Engine, Instance, Linker, Memory, Module, Store}; + +use crate::io::WasmInput; + +#[derive(Clone)] +pub struct RequestService { + worker_ctx: WorkerCtx, +} + +impl RequestService { + /// Create a new request service. + fn new(ctx: WorkerCtx) -> Self { + Self { worker_ctx: ctx } + } +} + +#[derive(Clone)] +pub struct WorkerCtx { + engine: Engine, + module: Module, +} + +impl WorkerCtx { + pub fn new(module_path: impl AsRef) -> anyhow::Result { + tracing_subscriber(); + info!("Loading module from {:?}", module_path.as_ref()); + // let config = configure_wasmtime(profiling_strategy); + let engine = Engine::new(Config::default().async_support(true)).unwrap(); //Engine::new(&config)?; + + let module = Module::from_file(&engine, module_path)?; + Ok(Self { engine, module }) + } + + pub fn module(&self) -> &Module { + &self.module + } + + pub fn engine(&self) -> &Engine { + &self.engine + } + pub async fn serve(self, addr: SocketAddr) -> Result<(), hyper::Error> { + info!("Starting server ..."); + let server = hyper::Server::bind(&addr).serve(self); + event!(Level::INFO, "Listening on http://{}", server.local_addr()); + server.await?; + Ok(()) + } + + pub async fn handle_request( + &self, + request: hyper::Request, + ) -> anyhow::Result<(Response, Option)> { + let (parts, body) = request.into_parts(); + info!("Handling request: {:?} {:?}", parts.method, parts.uri); + let body = hyper::body::to_bytes(body).await.unwrap(); + let body_str = String::from_utf8_lossy(&body).to_string(); + let result = self.run(&parts, &body_str).await; + + match result { + Ok(output) => { + let response = Response::new(Body::from(output)); + Ok((response, None)) + } + Err(e) => { + error!("Error: {}", e); + let response = Response::builder() + .status(500) + .body(Body::from("Internal Server Error")) + .unwrap(); + Ok((response, Some(e))) + } + } + } + + fn make_service(&self) -> RequestService { + RequestService::new(self.clone()) + } + + async fn run(&self, parts: &Parts, body: &str) -> anyhow::Result> { + let input = serde_json::to_string(&WasmInput::new(parts, body)).unwrap(); + + let mut linker: Linker = Linker::new(self.engine()); + + wasmtime_wasi::add_to_linker(&mut linker, |ctx| ctx)?; + + let mut wasi_ctx = WasiCtxBuilder::new(); + wasi_ctx.inherit_stdout().inherit_stderr(); + let wasi_builder = wasi_ctx.build(); + let mut store = Store::new(self.engine(), wasi_builder); + + let instance = linker + .instantiate_async(&mut store, self.module()) + .await + .map_err(anyhow::Error::msg)?; + + let memory = &instance.get_memory(&mut store, "memory").unwrap(); + + let (result_ptr, result_len) = + copy_request_into_instance(input.as_bytes(), &mut store, &instance, memory).await?; + + let run_entrypoint_fn = + instance.get_typed_func::<(u32, u32), u32>(&mut store, "run_entrypoint")?; + + let output_ptr = run_entrypoint_fn + .call_async(&mut store, (result_ptr, result_len)) + .await + .map_err(anyhow::Error::msg)?; + + let output = copy_bytecode_from_instance(output_ptr, &mut store, memory)?; + + drop(store); + + Ok(output) + } +} + +impl<'addr> Service<&'addr AddrStream> for WorkerCtx { + type Response = RequestService; + type Error = Infallible; + type Future = Ready>; + + fn poll_ready(&mut self, _cx: &mut task::Context<'_>) -> Poll> { + Poll::Ready(Ok(())) + } + + fn call(&mut self, _addr: &'addr AddrStream) -> Self::Future { + future::ok(self.make_service()) + } +} + +impl Service> for RequestService { + type Response = Response; + type Error = anyhow::Error; + #[allow(clippy::type_complexity)] + type Future = Pin> + Send>>; + + fn poll_ready(&mut self, _cx: &mut task::Context<'_>) -> Poll> { + Poll::Ready(Ok(())) + } + + fn call(&mut self, req: Request) -> Self::Future { + let ctx = self.worker_ctx.clone(); + + Box::pin(async move { ctx.handle_request(req).await.map(|result| result.0) }) + } +} + +fn tracing_subscriber() { + let verbosity = match env::var("RUST_LOG_VERBOSITY") { + Ok(s) => s.parse().unwrap_or(0), + Err(_) => 0, + }; + + if env::var("RUST_LOG").ok().is_none() { + match verbosity { + 0 => env::set_var("RUST_LOG", "info"), + 1 => env::set_var("RUST_LOG", "debug"), + _ => env::set_var("RUST_LOG", "trace"), + } + } + + // Build a subscriber, using the default `RUST_LOG` environment variable for our filter. + let builder = FmtSubscriber::builder() + .with_writer(std::io::stderr) + .with_env_filter(EnvFilter::from_default_env()) + .with_target(false); + + match env::var("RUST_LOG_PRETTY") { + // If the `RUST_LOG_PRETTY` environment variable is set to "true", we should emit logs in a + // pretty, human-readable output format. + Ok(s) if s == "true" => builder + .pretty() + // Show levels, because ANSI escape sequences are normally used to indicate this. + .with_level(true) + .init(), + // Otherwise, we should install the subscriber without any further additions. + _ => builder.with_ansi(false).init(), + } + event!( + Level::DEBUG, + "RUST_LOG set to '{}'", + env::var("RUST_LOG").unwrap_or_else(|_| String::from("")) + ); +} + +async fn copy_request_into_instance( + request: &[u8], + mut store: &mut Store, + instance: &Instance, + memory: &Memory, +) -> anyhow::Result<(u32, u32)> { + let realloc_fn = instance + .get_typed_func::<(u32, u32, u32, u32), u32>(&mut store, "canonical_abi_realloc")?; + let request_len = request.len().try_into()?; + + let original_ptr = 0; + let original_size = 0; + let alignment = 1; + let size = request_len; + let request_ptr = realloc_fn + .call_async(&mut store, (original_ptr, original_size, alignment, size)) + .await?; + + memory.write(&mut store, request_ptr.try_into()?, request)?; + + Ok((request_ptr, request_len)) +} + +fn copy_bytecode_from_instance( + ret_ptr: u32, + mut store: &mut Store, + memory: &Memory, +) -> anyhow::Result> { + let mut ret_buffer = [0; 8]; + memory.read(&mut store, ret_ptr.try_into()?, &mut ret_buffer)?; + + let bytecode_ptr = u32::from_le_bytes(ret_buffer[0..4].try_into()?); + let bytecode_len = u32::from_le_bytes(ret_buffer[4..8].try_into()?); + + let mut bytecode = vec![0; bytecode_len.try_into()?]; + memory.read(&mut store, bytecode_ptr.try_into()?, &mut bytecode)?; + + Ok(bytecode) +} diff --git a/JS/wasm/examples/ec-wasmjs-hono/src/index.js b/JS/wasm/examples/ec-wasmjs-hono/src/index.js index 65c3be440..716c17c9a 100644 --- a/JS/wasm/examples/ec-wasmjs-hono/src/index.js +++ b/JS/wasm/examples/ec-wasmjs-hono/src/index.js @@ -1,14 +1,13 @@ import { Hono } from "hono"; import { connect } from "@planetscale/database"; -import Jsonnet from "arakoo-jsonnet"; const app = new Hono(); - +const env = {}; app.get("/", (c) => { - const geo = c.req.raw.geo; - return c.text(`Your from ${geo.city}, ${geo.country_name}!`); + return c.text("Hello World!"); }); + app.get("/vars", async (c) => { try { const extVars = JSON.stringify({ @@ -49,4 +48,4 @@ app.notFound((c) => { return c.text("404 not found", 404); }); -export default app; +app.fire(); diff --git a/JS/wasm/rust-toolchain.toml b/JS/wasm/rust-toolchain.toml new file mode 100644 index 000000000..92e761c7f --- /dev/null +++ b/JS/wasm/rust-toolchain.toml @@ -0,0 +1,5 @@ +[toolchain] +channel = "nightly" +components = ["clippy", "rustfmt"] +targets = ["wasm32-wasi"] +profile = "default"