diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index adb54015a..d20ed3c23 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -23,8 +23,8 @@ jobs: run: rustup update stable --no-self-update && rustup default stable - name: Install wasm32-unknown-unknown target run: rustup target add wasm32-unknown-unknown - - name: Install wasm32-wasi target - run: rustup target add wasm32-wasi + - name: Install wasm32-wasip1 target + run: rustup target add wasm32-wasip1 - name: Install NPM packages run: npm install - name: Build @@ -51,7 +51,7 @@ jobs: - os: macos-latest node: 18.x - os: windows-latest - node: 20.x + node: latest - os: windows-latest node: 18.x runs-on: ${{ matrix.os }} @@ -96,15 +96,15 @@ jobs: - name: Install wasm32-unknown-unknown target if: steps.cache-wasi-tests.outputs.cache-hit != 'true' run: rustup target add wasm32-unknown-unknown - - name: Install wasm32-wasi target + - name: Install wasm32-wasip1 target if: steps.cache-wasi-tests.outputs.cache-hit != 'true' - run: rustup target add wasm32-wasi + run: rustup target add wasm32-wasip1 - name: Install wasm-tools if: steps.cache-wasi-tests.outputs.cache-hit != 'true' run: cargo install wasm-tools - name: Generate WASI Tests if: steps.cache-wasi-tests.outputs.cache-hit != 'true' - run: cargo xtask generate tests + run: cargo xtask generate preview2-tests - name: Upload Generated WASI Tests uses: actions/upload-artifact@v4 with: diff --git a/Cargo.lock b/Cargo.lock index 5d482918c..0471073fd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -25,9 +25,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.83" +version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25bdb32cbbdce2b519a9cd7df3a678443100e265d5e25ca763b7572a5104f5f3" +checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" [[package]] name = "atty" @@ -46,15 +46,6 @@ version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" -[[package]] -name = "bincode" -version = "1.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" -dependencies = [ - "serde", -] - [[package]] name = "bitflags" version = "1.3.2" @@ -63,9 +54,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.5.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" [[package]] name = "bumpalo" @@ -94,36 +85,65 @@ dependencies = [ "vec_map", ] +[[package]] +name = "cobs" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67ba02a97a2bd10f4b59b25c7973101c79642302776489e030cd13cdab09ed15" + +[[package]] +name = "cranelift-bitset" +version = "0.110.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38a1dfc50dca188a15d938867c4400589530bcb0138f7022aae6d059d1d8c309" +dependencies = [ + "serde", + "serde_derive", +] + [[package]] name = "cranelift-entity" -version = "0.107.1" +version = "0.110.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78689d6588f53981bf005b82d94125cc40cf9856b667bc276d1acdede400b633" +checksum = "ea62eb109baec2247e1a6fa7b74c0f584b1e76e289cfd7017385b4b031fc8450" dependencies = [ + "cranelift-bitset", "serde", "serde_derive", ] [[package]] name = "crc32fast" -version = "1.4.0" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3855a8a784b474f333699ef2bbca9db2c4a1f6d9088a90a2d25b1eb53111eaa" +checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" dependencies = [ "cfg-if", ] [[package]] -name = "equivalent" -version = "1.0.1" +name = "diff" +version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" +checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8" + +[[package]] +name = "either" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" [[package]] -name = "fallible-iterator" -version = "0.3.0" +name = "embedded-io" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2acce4a10f12dc2fb14a218589d4f1f62ef011b2d0cc4b3cb1bba8e94da14649" +checksum = "ef1a6892d9eef45c8fa6b9e0086428a2cca8491aca8f787c534a3d6d0bcb3ced" + +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "gimli" @@ -131,9 +151,7 @@ version = "0.28.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" dependencies = [ - "fallible-iterator", "indexmap", - "stable_deref_trait", ] [[package]] @@ -143,6 +161,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" dependencies = [ "ahash", + "serde", ] [[package]] @@ -154,15 +173,6 @@ dependencies = [ "unicode-segmentation", ] -[[package]] -name = "heck" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" -dependencies = [ - "unicode-segmentation", -] - [[package]] name = "heck" version = "0.5.0" @@ -195,6 +205,15 @@ dependencies = [ "serde", ] +[[package]] +name = "itertools" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" +dependencies = [ + "either", +] + [[package]] name = "itoa" version = "1.0.11" @@ -203,7 +222,7 @@ checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" [[package]] name = "jco" -version = "1.2.4" +version = "1.4.0" dependencies = [ "anyhow", "xshell", @@ -211,13 +230,14 @@ dependencies = [ [[package]] name = "js-component-bindgen" -version = "1.2.4" +version = "1.4.0" dependencies = [ "anyhow", "base64", "heck 0.5.0", "indexmap", - "wasm-encoder 0.202.0", + "wasm-encoder 0.212.0", + "wasmparser", "wasmtime-environ", "wit-bindgen-core", "wit-component", @@ -226,7 +246,7 @@ dependencies = [ [[package]] name = "js-component-bindgen-component" -version = "1.2.4" +version = "1.4.0" dependencies = [ "anyhow", "js-component-bindgen", @@ -237,9 +257,9 @@ dependencies = [ [[package]] name = "lazy_static" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "leb128" @@ -249,27 +269,37 @@ checksum = "884e2677b40cc8c339eaefcb701c32ef1fd2493d71118dc0ca4b6a736c93bd67" [[package]] name = "libc" -version = "0.2.154" +version = "0.2.155" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae743338b92ff9146ce83992f766a31066a91a8c84a45e0e9f21e7cf6de6d346" +checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" [[package]] name = "log" -version = "0.4.21" +version = "0.4.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" [[package]] name = "memchr" -version = "2.7.2" +version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" + +[[package]] +name = "nom" +version = "5.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08959a387a676302eebf4ddbcbc611da04285579f76f88ee0506c63b1a61dd4b" +dependencies = [ + "memchr", + "version_check", +] [[package]] name = "object" -version = "0.33.0" +version = "0.36.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8dd6c0cdf9429bce006e1362bfce61fa1bfd8c898a643ed8d2b471934701d3d" +checksum = "3f203fa8daa7bb185f760ae12bd8e097f63d17041dcdcaf675ac54cdf863170e" dependencies = [ "crc32fast", "hashbrown", @@ -283,6 +313,37 @@ version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" +[[package]] +name = "postcard" +version = "1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a55c51ee6c0db07e68448e336cf8ea4131a620edefebf9893e759b2d793420f8" +dependencies = [ + "cobs", + "embedded-io", + "serde", +] + +[[package]] +name = "pretty_assertions" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af7cee1a6c8a5b9208b3cb1061f10c0cb689087b3d8ce85fb9d2dd7a29b6ba66" +dependencies = [ + "diff", + "yansi", +] + +[[package]] +name = "prettyplease" +version = "0.2.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f12335488a2f3b0a83b14edad48dca9879ce89b2edd10e80237e4e852dd645e" +dependencies = [ + "proc-macro2", + "syn 2.0.72", +] + [[package]] name = "proc-macro-error" version = "1.0.4" @@ -309,9 +370,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.81" +version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d1597b0c024618f09a9c3b8655b7e430397a36d23fdafec26d6965e9eec3eba" +checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" dependencies = [ "unicode-ident", ] @@ -327,41 +388,44 @@ dependencies = [ [[package]] name = "ryu" -version = "1.0.17" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" [[package]] name = "semver" -version = "1.0.22" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92d43fe69e652f3df9bdc2b85b2854a0825b86e4fb76bc44d945137d053639ca" +checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" +dependencies = [ + "serde", +] [[package]] name = "serde" -version = "1.0.200" +version = "1.0.204" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ddc6f9cc94d67c0e21aaf7eda3a010fd3af78ebf6e096aa6e2e13c79749cce4f" +checksum = "bc76f558e0cbb2a839d37354c575f1dc3fdc6546b5be373ba43d95f231bf7c12" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.200" +version = "1.0.204" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "856f046b9400cee3c8c94ed572ecdb752444c24528c035cd35882aad6f492bcb" +checksum = "e0cd7e117be63d3c3678776753929474f3b04a43a080c744d6b0ae2a8c28e222" dependencies = [ "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.72", ] [[package]] name = "serde_json" -version = "1.0.116" +version = "1.0.120" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e17db7126d17feb94eb3fad46bf1a96b034e8aacbc2e775fe81505f8b0b2813" +checksum = "4e0d21c9a8cae1235ad58a00c11cb40d4b1e5c784f1ef2c537876ed6ffd8b7c5" dependencies = [ "itoa", "ryu", @@ -373,22 +437,19 @@ name = "smallvec" version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" +dependencies = [ + "serde", +] [[package]] name = "spdx" -version = "0.10.4" +version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29ef1a0fa1e39ac22972c8db23ff89aea700ab96aa87114e1fb55937a631a0c9" +checksum = "47317bbaf63785b53861e1ae2d11b80d6b624211d42cb20efcd210ee6f8a14bc" dependencies = [ "smallvec", ] -[[package]] -name = "stable_deref_trait" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" - [[package]] name = "strsim" version = "0.8.0" @@ -432,9 +493,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.60" +version = "2.0.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "909518bc7b1c9b779f1bbf07f2929d35af9f0f37e47c6e9ef7f9dddc1e1821f3" +checksum = "dc4b9b9bf2add8093d3f2c0204471e951b2285580335de42f9d2534f3ae7a8af" dependencies = [ "proc-macro2", "quote", @@ -443,37 +504,26 @@ dependencies = [ [[package]] name = "target-lexicon" -version = "0.12.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1fc403891a21bcfb7c37834ba66a547a8f402146eba7265b5a6d88059c9ff2f" - -[[package]] -name = "textwrap" -version = "0.11.0" +version = "0.12.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" -dependencies = [ - "unicode-width", -] +checksum = "4873307b7c257eddcb50c9bedf158eb669578359fb28428bef438fec8e6ba7c2" [[package]] -name = "thiserror" -version = "1.0.59" +name = "termcolor" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0126ad08bff79f29fc3ae6a55cc72352056dfff61e3ff8bb7129476d44b23aa" +checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" dependencies = [ - "thiserror-impl", + "winapi-util", ] [[package]] -name = "thiserror-impl" -version = "1.0.59" +name = "textwrap" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1cd413b5d558b4c5bf3680e324a6fa5014e7b7c067a51e69dbdf47eb7148b66" +checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.60", + "unicode-width", ] [[package]] @@ -490,9 +540,9 @@ checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202" [[package]] name = "unicode-width" -version = "0.1.12" +version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68f5e5f3158ecfd4b8ff6fe086db7c8467a2dfdac97fe420f2b7c4aa97af66d6" +checksum = "0336d538f7abc86d282a4189614dfaa90810dfc2c6f6427eaf88e16311dd225d" [[package]] name = "unicode-xid" @@ -508,33 +558,34 @@ checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" [[package]] name = "version_check" -version = "0.9.4" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" [[package]] name = "wasm-encoder" -version = "0.202.0" +version = "0.212.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfd106365a7f5f7aa3c1916a98cbb3ad477f5ff96ddb130285a91c6e7429e67a" +checksum = "501940df4418b8929eb6d52f1aade1fdd15a5b86c92453cb696e3c906bd3fc33" dependencies = [ "leb128", + "wasmparser", ] [[package]] name = "wasm-encoder" -version = "0.206.0" +version = "0.214.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d759312e1137f199096d80a70be685899cd7d3d09c572836bb2e9b69b4dc3b1e" +checksum = "ff694f02a8d7a50b6922b197ae03883fbf18cdb2ae9fbee7b6148456f5f44041" dependencies = [ "leb128", ] [[package]] name = "wasm-metadata" -version = "0.202.0" +version = "0.212.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "094aea3cb90e09f16ee25a4c0e324b3e8c934e7fd838bfa039aef5352f44a917" +checksum = "8a1849fac257fd76c43268555e73d74848c8dff23975c238c2cbad61cffe5045" dependencies = [ "anyhow", "indexmap", @@ -542,7 +593,7 @@ dependencies = [ "serde_derive", "serde_json", "spdx", - "wasm-encoder 0.202.0", + "wasm-encoder 0.212.0", "wasmparser", ] @@ -551,7 +602,7 @@ name = "wasm-tools-js" version = "0.1.0" dependencies = [ "anyhow", - "wasm-encoder 0.202.0", + "wasm-encoder 0.212.0", "wasm-metadata", "wasmparser", "wasmprinter", @@ -563,49 +614,54 @@ dependencies = [ [[package]] name = "wasmparser" -version = "0.202.0" +version = "0.212.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6998515d3cf3f8b980ef7c11b29a9b1017d4cf86b99ae93b546992df9931413" +checksum = "8d28bc49ba1e5c5b61ffa7a2eace10820443c4b7d1c0b144109261d14570fdf8" dependencies = [ - "bitflags 2.5.0", + "ahash", + "bitflags 2.6.0", + "hashbrown", "indexmap", "semver", + "serde", ] [[package]] name = "wasmprinter" -version = "0.202.0" +version = "0.212.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab1cc9508685eef9502e787f4d4123745f5651a1e29aec047645d3cac1e2da7a" +checksum = "dfac65326cc561112af88c3028f6dfdb140acff67ede33a8e86be2dc6b8956f7" dependencies = [ "anyhow", + "termcolor", "wasmparser", ] [[package]] name = "wasmtime-component-util" -version = "20.0.1" +version = "23.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44d65e6a21c3e3482240ff03cc26f5c7ae7ee5df524c2283f39cf492ab711a15" +checksum = "2bd9555175ad59d13fd353c2a6d9bc92f47f3496fc2b92e84eaa9e6edf048f3c" [[package]] name = "wasmtime-environ" -version = "20.0.1" +version = "23.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90f7b5dbae8c3c6586e22f063ddb9e5cbf02c09629df75e5d8710f7bf880b117" +checksum = "9e52faba13550fed76d5ffe75ec7cada73109b9324c4dabcaf18b3165107010d" dependencies = [ "anyhow", - "bincode", + "cranelift-bitset", "cranelift-entity", "gimli", "indexmap", "log", "object", + "postcard", + "semver", "serde", "serde_derive", "target-lexicon", - "thiserror", - "wasm-encoder 0.202.0", + "wasm-encoder 0.212.0", "wasmparser", "wasmprinter", "wasmtime-component-util", @@ -614,39 +670,61 @@ dependencies = [ [[package]] name = "wasmtime-types" -version = "20.0.1" +version = "23.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fa3a1f3c0deb3034d76e7dcf340c5df670a6603019ee5b58adb70870649c769" +checksum = "44a0fba5f60b030c635abafdcaf2e9ad883163676bd02a0f0ebaed9393453f28" dependencies = [ + "anyhow", "cranelift-entity", "serde", "serde_derive", - "thiserror", + "smallvec", "wasmparser", ] [[package]] name = "wast" -version = "206.0.0" +version = "214.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68586953ee4960b1f5d84ebf26df3b628b17e6173bc088e0acfbce431469795a" +checksum = "694bcdb24c49c8709bd8713768b71301a11e823923eee355d530f1d8d0a7f8e9" dependencies = [ "bumpalo", "leb128", "memchr", "unicode-width", - "wasm-encoder 0.206.0", + "wasm-encoder 0.214.0", ] [[package]] name = "wat" -version = "1.206.0" +version = "1.214.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da4c6f2606276c6e991aebf441b2fc92c517807393f039992a3e0ad873efe4ad" +checksum = "347249eb56773fa728df2656cfe3a8c19437ded61a922a0b5e0839d9790e278e" dependencies = [ "wast", ] +[[package]] +name = "webidl2wit" +version = "0.1.0" +source = "git+https://github.com/wasi-gfx/webidl2wit?rev=9cf1e53c5393e02e4b5ecc437012caf23ef1002f#9cf1e53c5393e02e4b5ecc437012caf23ef1002f" +dependencies = [ + "anyhow", + "heck 0.5.0", + "itertools", + "weedle", + "wit-encoder", +] + +[[package]] +name = "weedle" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfde6c0c0dc6d6c8b4f13afc35b46793e5a62890bcafa1a9d4c2c2301fa2f829" +dependencies = [ + "nom", +] + [[package]] name = "winapi" version = "0.3.9" @@ -663,17 +741,99 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" +[[package]] +name = "winapi-util" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d4cc384e1e73b93bafa6fb4f1df8c41695c8a91cf9c4c64358067d15a7b6c6b" +dependencies = [ + "windows-sys", +] + [[package]] name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + [[package]] name = "wit-bindgen" -version = "0.24.0" +version = "0.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fb4e7653763780be47e38f479e9aa83c768aa6a3b2ed086dc2826fdbbb7e7f5" +checksum = "fabce76bbb8938536c437da0c3e1d4dda9065453f72a68f797c0cb3d67356a28" dependencies = [ "wit-bindgen-rt", "wit-bindgen-rust-macro", @@ -681,32 +841,35 @@ dependencies = [ [[package]] name = "wit-bindgen-core" -version = "0.24.0" +version = "0.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b67e11c950041849a10828c7600ea62a4077c01e8af72e8593253575428f91b" +checksum = "1b43fbdd3497c471bbfb6973b1fb9ffe6949f158248cb43171d6f1cf3de7eaa3" dependencies = [ "anyhow", + "heck 0.5.0", "wit-parser", ] [[package]] name = "wit-bindgen-rt" -version = "0.24.0" +version = "0.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b0780cf7046630ed70f689a098cd8d56c5c3b22f2a7379bbdb088879963ff96" +checksum = "75956ff0a04a87ca0526b07199ce3b9baee899f2e4723b5b63aa296ab172ec52" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", ] [[package]] name = "wit-bindgen-rust" -version = "0.24.0" +version = "0.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30acbe8fb708c3a830a33c4cb705df82659bf831b492ec6ca1a17a369cfeeafb" +checksum = "bf509c4ef97b18ec0218741c8318706ac30ff16bc1731f990319a42bbbcfe8e3" dependencies = [ "anyhow", - "heck 0.4.1", + "heck 0.5.0", "indexmap", + "prettyplease", + "syn 2.0.72", "wasm-metadata", "wit-bindgen-core", "wit-component", @@ -714,43 +877,55 @@ dependencies = [ [[package]] name = "wit-bindgen-rust-macro" -version = "0.24.0" +version = "0.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b1b06eae85feaecdf9f2854f7cac124e00d5a6e5014bfb02eb1ecdeb5f265b9" +checksum = "88d6f2e025e38395d71fc1bf064e581b2ad275ce322d6f8d87ddc5e76a7b8c42" dependencies = [ "anyhow", + "prettyplease", "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.72", "wit-bindgen-core", "wit-bindgen-rust", ] [[package]] name = "wit-component" -version = "0.202.0" +version = "0.212.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c836b1fd9932de0431c1758d8be08212071b6bba0151f7bac826dbc4312a2a9" +checksum = "8ed5b0f9fc3d6424787d2a49e1142bf954ae4f26ee891992c144f0cfd68c4b7f" dependencies = [ "anyhow", - "bitflags 2.5.0", + "bitflags 2.6.0", "indexmap", "log", "serde", "serde_derive", "serde_json", - "wasm-encoder 0.202.0", + "wasm-encoder 0.212.0", "wasm-metadata", "wasmparser", "wat", "wit-parser", ] +[[package]] +name = "wit-encoder" +version = "0.214.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56024e6c0235a742909f0aff7bb0a4c6524d33a3aca59129a7db0f3320f975a1" +dependencies = [ + "pretty_assertions", + "semver", + "serde", +] + [[package]] name = "wit-parser" -version = "0.202.0" +version = "0.212.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "744237b488352f4f27bca05a10acb79474415951c450e52ebd0da784c1df2bcc" +checksum = "ceeb0424aa8679f3fcf2d6e3cfa381f3d6fa6179976a2c05a6249dd2bb426716" dependencies = [ "anyhow", "id-arena", @@ -785,27 +960,37 @@ version = "0.0.0" dependencies = [ "anyhow", "js-component-bindgen", + "semver", "structopt", + "webidl2wit", + "weedle", "wit-component", + "wit-encoder", "xshell", ] +[[package]] +name = "yansi" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09041cd90cf85f7f8b2df60c646f853b7f535ce68f85244eb6731cf89fa498ec" + [[package]] name = "zerocopy" -version = "0.7.33" +version = "0.7.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "087eca3c1eaf8c47b94d02790dd086cd594b912d2043d4de4bfdd466b3befb7c" +checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.7.33" +version = "0.7.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f4b6c273f496d8fd4eaf18853e6b448760225dc030ff2c485a786859aea6393" +checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.72", ] diff --git a/Cargo.toml b/Cargo.toml index 51d0c5950..b4578b678 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,7 +19,7 @@ resolver = "2" [workspace.package] edition = "2021" -version = "1.2.4" +version = "1.4.0" [profile.release] codegen-units = 1 @@ -34,23 +34,26 @@ rpath = false strip = true [workspace.dependencies] -anyhow = "1.0.82" -base64 = "0.22.0" -heck = "0.5.0" +anyhow = "1.0.86" +base64 = "0.22.1" +heck = "0.5.0" indexmap = "2.2" js-component-bindgen = { path = "./crates/js-component-bindgen" } structopt = "0.3.26" -wasm-encoder = "0.202.0" -wasm-metadata = "0.202.0" -wasmparser = "0.202.0" -wasmprinter = "0.202.0" -wasmtime-environ = { version = "20.0.1", features = ["component-model", "compile"] } -wat = "1.202.0" -wit-bindgen = "0.24.0" -wit-bindgen-core = "0.24.0" -wit-component = { version = "0.202.0", features = ["dummy-module"] } -wit-parser = "0.202.0" -xshell = "0.2.5" +wasm-encoder = "0.212.0" +wasm-metadata = "0.212.0" +wasmparser = "0.212.0" +wasmprinter = "0.212.0" +wasmtime-environ = { version = "23.0.1", features = [ + "component-model", + "compile", +] } +wat = "1.212.0" +wit-bindgen = "0.27.0" +wit-bindgen-core = "0.27.0" +wit-component = { version = "0.212.0", features = ["dummy-module"] } +wit-parser = "0.212.0" +xshell = "0.2.6" [dev-dependencies] anyhow = { workspace = true } diff --git a/README.md b/README.md index 1727d7ff4..b6d53c8a4 100644 --- a/README.md +++ b/README.md @@ -25,15 +25,13 @@ Jco provides a fully native JS toolchain for working with [WebAssembly Component Features include: * "Transpiling" Wasm Component binaries into ES modules that can run in any JS environment. -* WASI Preview2 support in Node.js ([undergoing stabilization](https://github.com/bytecodealliance/jco/milestone/1)) & browsers (experimental). +* WASI Preview2 support in Node.js & browsers (experimental). * Component builds of [Wasm Tools](https://github.com/bytecodealliance/wasm-tools) helpers, available for use as a library or CLI commands for use in native JS environments, as well as optimization helper for Components via Binaryen. * Run and serve commands like Wasmtime, as JS implementations of the Command and HTTP Proxy worlds. * "Componentize" command to easily create components written in JavaScript (wrapper of [ComponentizeJS](https://github.com/bytecodealliance/ComponentizeJS)). For creating components in other languages, see the [Cargo Component](https://github.com/bytecodealliance/cargo-Component) project for Rust and [Wit Bindgen](https://github.com/bytecodealliance/wit-bindgen) for various guest bindgen helpers. -> **Note**: This is an experimental project, no guarantees are provided for stability, security or support and breaking changes may be made without notice. - ## Installation ```shell @@ -44,7 +42,7 @@ Jco can be used as either a library import or as a CLI via the `jco` command. ## Example -See the [example workflow](docs/src/example.md) page for a full usage example. +See the [Example Workflow](https://bytecodealliance.github.io/jco/example.html) page for a full usage example. ## CLI @@ -79,45 +77,11 @@ For help with individual command options, use `jco --help`. ### Transpile -To transpile a component into JS: - -``` -jco transpile component.wasm -o out-dir -``` - -The resultant file can be imported providing the bindings of the component as if it were imported directly: - -app.js -``` -import { fn } from './out-dir/component.js'; - -fn(); -``` - -Imports can be remapped using the `--map` flag, or to provide imports as an argument use the `--instantiation` option. - -Components relying on WASI bindings will contain external WASI imports, which are automatically updated -to the `@bytecodealliance/preview2-shim` package. This package can be installed from npm separately for -runtime usage. This shim layer supports both Node.js and browsers. - -Options include: -* `--name`: Give a custom name for the component JS file in `out-dir/[name].js` -* `--minify`: Minify the component JS -* `--optimize`: Runs the internal core Wasm files through Binaryen for optimization. Optimization options can be passed with a `-- ` flag separator. -* `--tla-compat`: Instead of relying on top-level-await, requires an `$init` promise to be imported and awaited first. -* `--js`: Converts core Wasm files to JavaScript for environments that don't even support core Wasm. -* `--base64-cutoff=`: Sets the maximum number of bytes for inlining Wasm files into the JS using base64 encoding. Set to zero to disable base64 inlining entirely. -* `--no-wasi-shim`: Disable the WASI shim mapping to `@bytecodealliance/preview2-shim`. -* `--map`: Provide custom mappings for world imports. Supports both wildcard mappings (`*` similarly as in the package.json "exports" field) as well as `#` mappings for targetting exported interfaces. For example, the WASI mappings are internally defined with mappings like `--map wasi:filesystem/*=@bytecodealliance/preview2-shim/filesystem#*` to map `import as * filesystem from 'wasi:filesystem/types'` to `import { types } from '@bytecodealliance/preview2-shim/filesystem`. -* `--no-nodejs-compat`: Disables Node.js compat in the output to load core Wasm with FS methods. -* `--instantiation [mode]`: Instead of a direct ES module, export an `instantiate` function which can take the imports as an argument instead of implicit imports. The `instantiate` function can be async (with `--instantiation` or `--instantiation async`), or sync (with `--instantiation sync`). -* `--valid-lifting-optimization`: Internal validations are removed assuming that core Wasm binaries are valid components, providing a minor output size saving. -* `--tracing`: Emit tracing calls for all function entry and exits. -* `--no-namespaced-exports`: Removes exports of the type `test as "test:flavorful/test"` which are not compatible with typescript +See the [Transpiling Docs](https://bytecodealliance.github.io/jco/transpiling.html) for more background and info. #### Bindgen Crate -To directly call into the transpilation in Rust, the bindgen used in jco is also available on crates.io as [js-component-bindgen](https://crates.io/crates/js-component-bindgen). +To directly call into the transpilation in Rust, the bindgen used in Jco is also available on crates.io as [js-component-bindgen](https://crates.io/crates/js-component-bindgen). ### Run & Serve @@ -139,6 +103,8 @@ jco serve --port 8080 server.wasm ### Componentize +> **Note**: `jco componentize` is considered experimental, and breaking changes may be made without notice. + To componentize a JS file run: ``` @@ -191,7 +157,7 @@ Add new producer metadata to a component or core Wasm binary. ## Contributing -See the [Contributing](docs/src/contributing.md) chapter of the jco book. +See the [Contributing](https://bytecodealliance.github.io/jco/contributing.html) chapter of the Jco book. # License diff --git a/crates/js-component-bindgen-component/src/lib.rs b/crates/js-component-bindgen-component/src/lib.rs index ff50bc1b5..c231d7716 100644 --- a/crates/js-component-bindgen-component/src/lib.rs +++ b/crates/js-component-bindgen-component/src/lib.rs @@ -1,9 +1,9 @@ use std::path::PathBuf; -use anyhow::{Context, Result}; +use anyhow::Result; use js_component_bindgen::{ generate_types, generate_typescript_stubs, - source::wit_parser::{PackageId, Resolve, UnresolvedPackage}, + source::wit_parser::{PackageId, Resolve}, transpile, }; @@ -116,11 +116,10 @@ impl Guest for JsComponentBindgenComponent { name: String, opts: TypeGenerationOptions, ) -> Result)>, String> { - let (resolve, id) = - resolve_package(opts.wit, Some(name.as_str())).map_err(|e| e.to_string())?; + let (resolve, ids) = resolve_package(opts.wit, Some(&name))?; let world_string = opts.world.map(|world| world.to_string()); let world = resolve - .select_world(id, world_string.as_deref()) + .select_world(&ids, world_string.as_deref()) .map_err(|e| e.to_string())?; let opts = js_component_bindgen::TranspileOpts { @@ -144,10 +143,10 @@ impl Guest for JsComponentBindgenComponent { } fn generate_typescript_stubs(opts: TypescriptStubOptions) -> Result { - let (resolve, id) = resolve_package(opts.wit, None).map_err(|e| e.to_string())?; + let (resolve, ids) = resolve_package(opts.wit, None).map_err(|e| e.to_string())?; let world_string = opts.world.map(|world| world.to_string()); let world = resolve - .select_world(id, world_string.as_deref()) + .select_world(&ids, world_string.as_deref()) .map_err(|e| e.to_string())?; let files = generate_typescript_stubs(resolve, world).map_err(|e| e.to_string())?; @@ -156,31 +155,23 @@ impl Guest for JsComponentBindgenComponent { } } -fn resolve_package(wit_opt: Wit, name: Option<&str>) -> Result<(Resolve, PackageId)> { +fn resolve_package(wit_opt: Wit, name: Option<&str>) -> Result<(Resolve, Vec), String> { + let name = name.unwrap_or("world"); let mut resolve = Resolve::default(); - let id = match wit_opt { - Wit::Source(source) => { - let name = name.unwrap_or("world"); - let pkg = UnresolvedPackage::parse(&PathBuf::from(format!("{name}.wit")), &source)?; - resolve.push(pkg)? - } + let ids = match wit_opt { + Wit::Source(source) => resolve + .push_str(format!("{name}.wit"), &source) + .map_err(|e| e.to_string())?, Wit::Path(path) => { let path = PathBuf::from(path); if path.is_dir() { - resolve.push_dir(&path)?.0 + resolve.push_dir(&path).map_err(|e| e.to_string())?.0 } else { - let contents = std::fs::read(&path) - .with_context(|| format!("failed to read file {path:?}"))?; - let text = match std::str::from_utf8(&contents) { - Ok(s) => s, - Err(_) => anyhow::bail!("input file is not valid utf-8"), - }; - let pkg = UnresolvedPackage::parse(&path, text)?; - resolve.push(pkg)? + resolve.push_file(&path).map_err(|e| e.to_string())? } } Wit::Binary(_) => todo!(), }; - Ok((resolve, id)) + Ok((resolve, ids)) } diff --git a/crates/js-component-bindgen/Cargo.toml b/crates/js-component-bindgen/Cargo.toml index a94cca8d6..1858876b1 100644 --- a/crates/js-component-bindgen/Cargo.toml +++ b/crates/js-component-bindgen/Cargo.toml @@ -23,6 +23,7 @@ transpile-bindgen = [] [dependencies] anyhow = { workspace = true } heck = { workspace = true } +wasmparser = { workspace = true } wasmtime-environ = { workspace = true, features = ['component-model'] } wit-bindgen-core = { workspace = true } wit-component = { workspace = true } diff --git a/crates/js-component-bindgen/src/core.rs b/crates/js-component-bindgen/src/core.rs index a16f5ed39..e02949a0b 100644 --- a/crates/js-component-bindgen/src/core.rs +++ b/crates/js-component-bindgen/src/core.rs @@ -37,9 +37,9 @@ //! supported because, again, Wasmtime doesn't use it at this time. use anyhow::{bail, Result}; -use indexmap::IndexMap; use std::collections::{HashMap, HashSet}; use wasm_encoder::*; +use wasmparser::collections::IndexMap; use wasmparser::*; use wasmtime_environ::component::CoreDef; use wasmtime_environ::{wasmparser, ModuleTranslation}; @@ -79,7 +79,6 @@ pub enum AugmentedOp { I64Store, F32Store, F64Store, - MemorySize, } @@ -88,16 +87,14 @@ impl<'a> Translation<'a> { if multi_memory { return Ok(Translation::Normal(translation)); } - let mut features = WasmFeatures { - multi_memory: false, - ..Default::default() - }; + let mut features = WasmFeatures::default(); + features.set(WasmFeatures::MULTI_MEMORY, false); match Validator::new_with_features(features).validate_all(translation.wasm) { // This module validates without multi-memory, no need to augment // it Ok(_) => return Ok(Translation::Normal(translation)), Err(e) => { - features.multi_memory = true; + features.set(WasmFeatures::MULTI_MEMORY, true); match Validator::new_with_features(features).validate_all(translation.wasm) { // This module validates with multi-memory, so fall through // to augmentation. @@ -364,12 +361,14 @@ impl Augmenter<'_> { TypeRef::Global(g) => EntityType::Global(wasm_encoder::GlobalType { mutable: g.mutable, val_type: valtype(g.content_type), + shared: g.shared, }), TypeRef::Memory(m) => EntityType::Memory(wasm_encoder::MemoryType { maximum: m.maximum, minimum: m.initial, memory64: m.memory64, shared: m.shared, + page_size_log2: m.page_size_log2, }), TypeRef::Table(_) => unimplemented!(), TypeRef::Tag(_) => unimplemented!(), @@ -533,7 +532,7 @@ macro_rules! define_visit { (augment $self:ident I32Store16 $memarg:ident) => { $self.0.augment_op($memarg.memory, AugmentedOp::I32Store16); }; - (augment $self:ident MemorySize $mem:ident $byte:ident) => { + (augment $self:ident MemorySize $mem:ident) => { $self.0.augment_op($mem, AugmentedOp::MemorySize); }; @@ -672,7 +671,7 @@ macro_rules! define_translate { (translate $self:ident F64Store $memarg:ident) => {{ $self.augment(AugmentedOp::F64Store, F64Store, $memarg) }}; - (translate $self:ident MemorySize $mem:ident $byte:ident) => {{ + (translate $self:ident MemorySize $mem:ident) => {{ if $mem < 1 { $self.func.instruction(&MemorySize($mem)); } else { @@ -707,7 +706,7 @@ macro_rules! define_translate { CallIndirect { ty: $ty, table: $table } }); (mk ReturnCallIndirect $ty:ident $table:ident) => ( - ReturnCallIndirect { ty: $ty, table: $table } + ReturnCallIndirect { type_index: $ty, table_index: $table } ); (mk I32Const $v:ident) => (I32Const($v)); (mk I64Const $v:ident) => (I64Const($v)); @@ -730,6 +729,7 @@ macro_rules! define_translate { // Individual cases of mapping one argument type to another, similar to the // `define_visit` macro above. (map $self:ident $arg:ident memarg) => {$self.memarg($arg)}; + (map $self:ident $arg:ident ordering) => {$self.ordering($arg)}; (map $self:ident $arg:ident blockty) => {$self.blockty($arg)}; (map $self:ident $arg:ident hty) => {$self.heapty($arg)}; (map $self:ident $arg:ident tag_index) => {$arg}; @@ -815,6 +815,13 @@ impl Translator<'_, '_> { } } + fn ordering(&self, ty: wasmparser::Ordering) -> wasm_encoder::Ordering { + match ty { + wasmparser::Ordering::AcqRel => wasm_encoder::Ordering::AcqRel, + wasmparser::Ordering::SeqCst => wasm_encoder::Ordering::SeqCst, + } + } + fn augment( &mut self, op: AugmentedOp, diff --git a/crates/js-component-bindgen/src/esm_bindgen.rs b/crates/js-component-bindgen/src/esm_bindgen.rs index 671224092..f4f0bef78 100644 --- a/crates/js-component-bindgen/src/esm_bindgen.rs +++ b/crates/js-component-bindgen/src/esm_bindgen.rs @@ -1,5 +1,6 @@ use heck::ToLowerCamelCase; +use crate::intrinsics::Intrinsic; use crate::names::{maybe_quote_id, maybe_quote_member, LocalNames}; use crate::source::Source; use crate::{uwrite, uwriteln, TranspileOpts}; @@ -208,14 +209,29 @@ impl EsmBindgen { ) { let mut iface_imports = Vec::new(); for (specifier, binding) in &self.imports { - if imports_object.is_some() { + let idl_binding = if specifier.starts_with("webidl:") { + let iface_idx = specifier.find('/').unwrap() + 1; + let iface_name = if let Some(version_idx) = specifier.find('@') { + &specifier[iface_idx..version_idx] + } else { + &specifier[iface_idx..] + }; + Some(if iface_name.starts_with("global-") { + &iface_name[7..] + } else { + "" + }) + } else { + None + }; + if imports_object.is_some() || idl_binding.is_some() { uwrite!(output, "const "); } else { uwrite!(output, "import "); } match binding { Binding::Interface(bindings) => { - if imports_object.is_none() && bindings.len() == 1 { + if imports_object.is_none() && idl_binding.is_none() && bindings.len() == 1 { let (import_name, import) = bindings.iter().next().unwrap(); if import_name == "default" { let local_name = match import { @@ -252,7 +268,7 @@ impl EsmBindgen { }; if external_name == local_name { uwrite!(output, "{external_name}"); - } else if imports_object.is_some() { + } else if imports_object.is_some() || idl_binding.is_some() { uwrite!(output, "{external_name}: {local_name}"); } else { uwrite!(output, "{external_name} as {local_name}"); @@ -267,6 +283,14 @@ impl EsmBindgen { "}} = {imports_object}{};", maybe_quote_member(specifier) ); + } else if let Some(idl_binding) = idl_binding { + uwrite!(output, "}} = {}()", Intrinsic::GlobalThisIdlProxy.name()); + if idl_binding != "" { + for segment in idl_binding.split('-') { + uwrite!(output, ".{}()", segment.to_lowercase()); + } + } + uwrite!(output, ";\n"); } else { uwriteln!(output, "}} from '{specifier}';"); } diff --git a/crates/js-component-bindgen/src/files.rs b/crates/js-component-bindgen/src/files.rs index 5ef436521..d75502efa 100644 --- a/crates/js-component-bindgen/src/files.rs +++ b/crates/js-component-bindgen/src/files.rs @@ -25,7 +25,7 @@ impl Files { self.files.remove(name) } - pub fn iter(&self) -> impl Iterator { + pub fn iter(&self) -> impl Iterator { self.files.iter().map(|p| (p.0.as_str(), p.1.as_slice())) } } diff --git a/crates/js-component-bindgen/src/function_bindgen.rs b/crates/js-component-bindgen/src/function_bindgen.rs index 597632e8c..c75edc4ab 100644 --- a/crates/js-component-bindgen/src/function_bindgen.rs +++ b/crates/js-component-bindgen/src/function_bindgen.rs @@ -1142,7 +1142,6 @@ impl Bindgen for FunctionBindgen<'_> { drop(rsc[{symbol_resource_handle}]); delete rsc[{symbol_resource_handle}]; }} - {cur_resource_borrows}[i][{symbol_resource_handle}] = null; }} {cur_resource_borrows} = [];" ); diff --git a/crates/js-component-bindgen/src/intrinsics.rs b/crates/js-component-bindgen/src/intrinsics.rs index 2f2460207..5899bd739 100644 --- a/crates/js-component-bindgen/src/intrinsics.rs +++ b/crates/js-component-bindgen/src/intrinsics.rs @@ -18,6 +18,7 @@ pub enum Intrinsic { FinalizationRegistryCreate, GetErrorPayload, GetErrorPayloadString, + GlobalThisIdlProxy, HandleTables, HasOwnProperty, I32ToF32, @@ -209,6 +210,63 @@ pub fn render_intrinsics( ") }, + Intrinsic::GlobalThisIdlProxy => output.push_str(r#" + var idlProxy; + function globalThisIdlProxy () { + if (idlProxy) return idlProxy; + const innerSymbol = Symbol('inner'); + const isProxySymbol = Symbol('isProxy'); + const uppercaseRegex = /html|Html|dom|Dom/g; + const globalNames = ['Window', 'WorkerGlobalScope']; + function proxy(target, fake = {}) { + const origTarget = target; + return new Proxy(fake, { + get: (_, prop, receiver) => { + if (prop === innerSymbol) return origTarget; + if (prop === isProxySymbol) return true; + if (typeof prop !== 'string') return maybeProxy(Reflect.get(origTarget, prop)); + if (origTarget === globalThis && prop.startsWith('get') && globalNames.includes(prop.slice(3))) { + return () => receiver; + } + prop = prop.replaceAll(uppercaseRegex, x => x.toUpperCase()); + if (prop.startsWith('set')) return val => Reflect.set(origTarget, `${prop[3].toLowerCase()}${prop.slice(4)}`, val); + if (prop.startsWith('as')) return () => receiver; + const res = Reflect.get(origTarget, prop); + if (res === undefined && prop[0].toUpperCase() === prop[0]) { + return Object.getPrototypeOf(globalThis[`${prop[0].toLowerCase()}${prop.slice(1)}`]).constructor; + } + return maybeProxy(res); + }, + apply: (_, thisArg, args) => { + if (args.length === 1 && Array.isArray(args[0]) && origTarget.length === 0) args = args[0]; + const res = Reflect.apply(origTarget, proxyInner(thisArg), args.map(a => a[isProxySymbol] ? proxyInner(a) : a)); + return typeof res === 'object' ? proxy(res) : res; + }, + getPrototypeOf: _ => Reflect.getPrototypeOf(origTarget), + construct: (_, argArray, newTarget) => maybeProxy(Reflect.construct(origTarget, argArray, newTarget)), + defineProperty: (_, property, attributes) => maybeProxy(Reflect.defineProperty(origTarget, property, attributes)), + deleteProperty: (_, p) => maybeProxy(Reflect.deleteProperty(origTarget, p)), + getOwnPropertyDescriptor: (_, p) => Reflect.getOwnPropertyDescriptor(origTarget, p), + has: (_, p) => maybeProxy(Reflect.has(origTarget, p)), + isExtensible: (_) => maybeProxy(Reflect.isExtensible(origTarget)), + ownKeys: _ => maybeProxy(Reflect.ownKeys(origTarget)), + preventExtensions: _ => maybeProxy(Reflect.preventExtensions(origTarget)), + set: (_, p, newValue, receiver) => maybeProxy(Reflect.set(origTarget, p, newValue, receiver)), + setPrototypeOf: (_, v) => maybeProxy(Reflect.setPrototypeOf(origTarget, v)), + }); + } + function maybeProxy(res) { + if (typeof res === 'function') + return proxy(res, () => {}); + if (typeof res === 'object' && res !== null) + return () => proxy(res); + return res; + } + const proxyInner = proxy => proxy ? proxy[innerSymbol] : proxy; + return (idlProxy = proxy(globalThis)); + }; + "#), + Intrinsic::HandleTables => output.push_str(" const handleTables = []; "), @@ -608,6 +666,7 @@ impl Intrinsic { "fetchCompile", "finalizationRegistryCreate", "getErrorPayload", + "globalThisIdlProxy", "handleTables", "hasOwnProperty", "i32ToF32", @@ -687,6 +746,7 @@ impl Intrinsic { Intrinsic::FinalizationRegistryCreate => "finalizationRegistryCreate", Intrinsic::GetErrorPayload => "getErrorPayload", Intrinsic::GetErrorPayloadString => "getErrorPayloadString", + Intrinsic::GlobalThisIdlProxy => "globalThisIdlProxy", Intrinsic::HandleTables => "handleTables", Intrinsic::HasOwnProperty => "hasOwnProperty", Intrinsic::I32ToF32 => "i32ToF32", diff --git a/crates/js-component-bindgen/src/lib.rs b/crates/js-component-bindgen/src/lib.rs index 7bad41c73..a95a243bc 100644 --- a/crates/js-component-bindgen/src/lib.rs +++ b/crates/js-component-bindgen/src/lib.rs @@ -15,9 +15,8 @@ use anyhow::Result; use transpile_bindgen::transpile_bindgen; use anyhow::{bail, Context}; -use wasmtime_environ::component::Export; -use wasmtime_environ::component::{ComponentTypesBuilder, StaticModuleIndex}; -use wasmtime_environ::wasmparser::{Validator, WasmFeatures}; +use wasmtime_environ::component::{ComponentTypesBuilder, Export, StaticModuleIndex}; +use wasmtime_environ::wasmparser::Validator; use wasmtime_environ::{PrimaryMap, ScopeVec, Tunables}; use wit_component::DecodedWasm; @@ -89,7 +88,7 @@ pub fn generate_typescript_stubs( /// Outputs the file map and import and export metadata for the Transpilation #[cfg(feature = "transpile-bindgen")] pub fn transpile(component: &[u8], opts: TranspileOpts) -> Result { - use wasmtime_environ::component::Translator; + use wasmtime_environ::component::{Component, Translator}; let name = opts.name.clone(); let mut files = files::Files::default(); @@ -104,7 +103,7 @@ pub fn transpile(component: &[u8], opts: TranspileOpts) -> Result bail!("unexpected wit package as input"), + DecodedWasm::WitPackages(_, _) => bail!("unexpected wit package as input"), DecodedWasm::Component(resolve, world_id) => (resolve, world_id), }; @@ -124,11 +123,8 @@ pub fn transpile(component: &[u8], opts: TranspileOpts) -> Result Result>()?; - let types = types.finish(&PrimaryMap::new(), Vec::new(), Vec::new()); + let mut wasmtime_component = Component::default(); + let types = types.finish(&mut wasmtime_component); // Insert all core wasm modules into the generated `Files` which will // end up getting used in the `generate_instantiate` method. diff --git a/crates/js-component-bindgen/src/transpile_bindgen.rs b/crates/js-component-bindgen/src/transpile_bindgen.rs index 272b144ea..2e01fca9e 100644 --- a/crates/js-component-bindgen/src/transpile_bindgen.rs +++ b/crates/js-component-bindgen/src/transpile_bindgen.rs @@ -10,12 +10,11 @@ use crate::source; use crate::{uwrite, uwriteln}; use base64::{engine::general_purpose, Engine as _}; use heck::*; -use indexmap::IndexMap; use std::cell::RefCell; use std::collections::{BTreeMap, BTreeSet, HashMap}; use std::fmt::Write; use std::mem; -use wasmtime_environ::component::Transcode; +use wasmtime_environ::component::{ExportIndex, NameMap, NameMapNoIntern, Transcode}; use wasmtime_environ::{ component, component::{ @@ -192,11 +191,22 @@ pub fn transpile_bindgen( .iter() .map(|(export_name, canon_export_name)| { let export = if canon_export_name.contains(':') { - &instantiator.component.exports[*canon_export_name] + instantiator + .component + .exports + .get(canon_export_name, &NameMapNoIntern) + .unwrap() } else { - &instantiator.component.exports[&canon_export_name.to_kebab_case()] + instantiator + .component + .exports + .get(&canon_export_name.to_kebab_case(), &NameMapNoIntern) + .unwrap() }; - (export_name.to_string(), export.clone()) + ( + export_name.to_string(), + instantiator.component.export_items[*export].clone(), + ) }) .collect(); @@ -256,38 +266,24 @@ impl<'a> JsBindgen<'a> { self.opts.instantiation.is_some(), ); - match self.opts.instantiation { - Some(InstantiationMode::Async) => { - uwrite!( - output, - "\ - export async function instantiate(getCoreModule, imports, instantiateCore = WebAssembly.instantiate) {{ - {} - {} - {} - ", - &js_intrinsics as &str, - &intrinsic_definitions as &str, - &compilation_promises as &str, - ) - } - - Some(InstantiationMode::Sync) => { - uwrite!( - output, - "\ - export function instantiate(getCoreModule, imports, instantiateCore = (module, importObject) => new WebAssembly.Instance(module, importObject)) {{ - {} - {} - {} - ", - &js_intrinsics as &str, - &intrinsic_definitions as &str, - &compilation_promises as &str, - ) - } - - None => {} + if let Some(instantiation) = &self.opts.instantiation { + uwrite!( + output, + "\ + export function instantiate(getCoreModule, imports, instantiateCore = {}) {{ + {} + {} + {} + ", + match instantiation { + InstantiationMode::Async => "WebAssembly.instantiate", + InstantiationMode::Sync => + "(module, importObject) => new WebAssembly.Instance(module, importObject)", + }, + &js_intrinsics as &str, + &intrinsic_definitions as &str, + &compilation_promises as &str, + ); } let imports_object = if self.opts.instantiation.is_some() { @@ -308,8 +304,31 @@ impl<'a> JsBindgen<'a> { uwrite!( output, "\ - {}\ - {}; + let gen = (function* init () {{ + {}\ + {}; + }})(); + let promise, resolve, reject; + function runNext (value) {{ + try {{ + let done; + do {{ + ({{ value, done }} = gen.next(value)); + }} while (!(value instanceof Promise) && !done); + if (done) {{ + if (resolve) resolve(value); + else return value; + }} + if (!promise) promise = new Promise((_resolve, _reject) => (resolve = _resolve, reject = _reject)); + value.then(nextVal => done ? resolve() : runNext(nextVal), reject); + }} + catch (e) {{ + if (reject) reject(e); + else throw e; + }} + }} + const maybeSyncReturn = runNext(null); + return promise || maybeSyncReturn; }} ", &self.src.js_init as &str, @@ -340,9 +359,32 @@ impl<'a> JsBindgen<'a> { {} {} {} - {maybe_init_export}const $init = (async() => {{ - {}\ - {}\ + {maybe_init_export}const $init = (() => {{ + let gen = (function* init () {{ + {}\ + {}\ + }})(); + let promise, resolve, reject; + function runNext (value) {{ + try {{ + let done; + do {{ + ({{ value, done }} = gen.next(value)); + }} while (!(value instanceof Promise) && !done); + if (done) {{ + if (resolve) resolve(value); + else return value; + }} + if (!promise) promise = new Promise((_resolve, _reject) => (resolve = _resolve, reject = _reject)); + value.then(runNext, reject); + }} + catch (e) {{ + if (reject) reject(e); + else throw e; + }} + }} + const maybeSyncReturn = runNext(null); + return promise || maybeSyncReturn; }})(); {maybe_init}\ ", @@ -425,7 +467,7 @@ impl<'a> Instantiator<'a, '_> { .find(|(_, (impt_name, _))| impt_name == name) else { match item { - WorldItem::Interface(_) => unreachable!(), + WorldItem::Interface { .. } => unreachable!(), WorldItem::Function(_) => unreachable!(), WorldItem::Type(ty) => { assert!(!matches!( @@ -437,12 +479,12 @@ impl<'a> Instantiator<'a, '_> { continue; }; match item { - WorldItem::Interface(iface) => { + WorldItem::Interface { id, stability: _ } => { let TypeDef::ComponentInstance(instance) = import else { unreachable!() }; let import_ty = &self.types[*instance]; - let iface = &self.resolve.interfaces[*iface]; + let iface = &self.resolve.interfaces[*id]; for (ty_name, ty) in &iface.types { match &import_ty.exports.get(ty_name) { Some(TypeDef::Resource(resource)) => { @@ -470,23 +512,26 @@ impl<'a> Instantiator<'a, '_> { self.exports_resource_types = self.imports_resource_types.clone(); for (key, item) in &self.resolve.worlds[self.world].exports { let name = &self.resolve.name_world_key(key); - let (_, export) = self + let (_, export_idx) = self .component .exports - .iter() + .raw_iter() .find(|(expt_name, _)| *expt_name == name) .unwrap(); + let export = &self.component.export_items[*export_idx]; match item { - WorldItem::Interface(iface) => { - let iface = &self.resolve.interfaces[*iface]; + WorldItem::Interface { id, stability: _ } => { + let iface = &self.resolve.interfaces[*id]; let Export::Instance { exports, .. } = &export else { unreachable!() }; for (ty_name, ty) in &iface.types { - match exports.get(ty_name).unwrap() { + match self.component.export_items + [*exports.get(ty_name, &NameMapNoIntern).unwrap()] + { Export::Type(TypeDef::Resource(resource)) => { let ty = crate::dealias(self.resolve, *ty); - let resource_idx = self.types[*resource].ty; + let resource_idx = self.types[resource].ty; self.exports_resource_types.insert(ty, resource_idx); } Export::Type(_) => {} @@ -968,7 +1013,7 @@ impl<'a> Instantiator<'a, '_> { Some(InstantiationMode::Async) | None => { uwriteln!( self.src.js_init, - "({{ exports: exports{iu32} }} = await {instantiate}(await module{}{imports}));", + "({{ exports: exports{iu32} }} = yield {instantiate}(yield module{}{imports}));", idx.as_u32() ) } @@ -1038,9 +1083,9 @@ impl<'a> Instantiator<'a, '_> { assert_eq!(path.len(), 0); (func, import_name, None) } - WorldItem::Interface(i) => { + WorldItem::Interface { id, stability: _ } => { assert_eq!(path.len(), 1); - let iface = &self.resolve.interfaces[*i]; + let iface = &self.resolve.interfaces[*id]; let func = &iface.functions[&path[0]]; ( func, @@ -1254,6 +1299,9 @@ impl<'a> Instantiator<'a, '_> { import_binding: Option, local_name: String, ) { + if import_specifier.starts_with("webidl:") { + self.gen.intrinsic(Intrinsic::GlobalThisIdlProxy); + } // add the function import to the ESM bindgen if let Some(_iface_name) = iface_name { // mapping can be used to construct virtual nested namespaces @@ -1339,7 +1387,10 @@ impl<'a> Instantiator<'a, '_> { self.resolve.worlds[self.world] .imports .iter() - .find(|&(_, item)| *item == WorldItem::Interface(iface)) + .find(|&(_, item)| match item { + WorldItem::Interface { id, .. } => *id == iface, + _ => false, + }) .unwrap() .0 .clone(), @@ -1702,8 +1753,9 @@ impl<'a> Instantiator<'a, '_> { format!("exports{i}{}", maybe_quote_member(name)) } - fn exports(&mut self, exports: &IndexMap) { - for (export_name, export) in exports.iter() { + fn exports(&mut self, exports: &NameMap) { + for (export_name, export_idx) in exports.raw_iter() { + let export = &self.component.export_items[*export_idx]; let world_key = &self.exports[export_name]; let item = &self.resolve.worlds[self.world].exports[world_key]; let mut resource_map = ResourceMap::new(); @@ -1715,7 +1767,7 @@ impl<'a> Instantiator<'a, '_> { } => { let func = match item { WorldItem::Function(f) => f, - WorldItem::Interface(_) | WorldItem::Type(_) => unreachable!(), + WorldItem::Interface { .. } | WorldItem::Type(_) => unreachable!(), }; self.create_resource_fn_map(func, *func_ty, &mut resource_map); @@ -1735,8 +1787,8 @@ impl<'a> Instantiator<'a, '_> { .to_string(); self.export_bindgen( &local_name, - def, - options, + &def, + &options, func, export_name, &resource_map, @@ -1761,10 +1813,11 @@ impl<'a> Instantiator<'a, '_> { } Export::Instance { exports, .. } => { let id = match item { - WorldItem::Interface(id) => *id, + WorldItem::Interface { id, stability: _ } => *id, WorldItem::Function(_) | WorldItem::Type(_) => unreachable!(), }; - for (func_name, export) in exports { + for (func_name, export_idx) in exports.raw_iter() { + let export = &self.component.export_items[*export_idx]; let (def, options, func_ty) = match export { Export::LiftedFunction { func, options, ty } => (func, options, ty), Export::Type(_) => continue, // ignored @@ -1786,7 +1839,7 @@ impl<'a> Instantiator<'a, '_> { &self.exports_resource_types, ) } else { - self.gen.local_names.create_once(func_name) + self.gen.local_names.create_once(&func_name) } .to_string(); @@ -1824,8 +1877,7 @@ impl<'a> Instantiator<'a, '_> { Export::Type(_) => {} // This can't be tested at this time so leave it unimplemented - Export::ModuleStatic(_) => unimplemented!(), - Export::ModuleImport { .. } => unimplemented!(), + Export::ModuleStatic { .. } | Export::ModuleImport { .. } => unimplemented!(), } } self.gen.esm_bindgen.populate_export_aliases(); diff --git a/crates/js-component-bindgen/src/ts_bindgen.rs b/crates/js-component-bindgen/src/ts_bindgen.rs index 2bb7ee570..4333f6be3 100644 --- a/crates/js-component-bindgen/src/ts_bindgen.rs +++ b/crates/js-component-bindgen/src/ts_bindgen.rs @@ -67,7 +67,7 @@ pub fn ts_bindgen( WorldKey::Name(name) => funcs.push((name.to_string(), f)), WorldKey::Interface(id) => funcs.push((resolve.id_of(*id).unwrap(), f)), }, - WorldItem::Interface(id) => match name { + WorldItem::Interface { id, stability: _ } => match name { WorldKey::Name(name) => { // kebab name -> direct ns namespace import bindgen.import_interface(resolve, name, *id, files); @@ -144,7 +144,7 @@ pub fn ts_bindgen( seen_names.insert(export_name.to_string()); funcs.push((export_name.to_lower_camel_case(), f)); } - WorldItem::Interface(id) => { + WorldItem::Interface { id, stability: _ } => { let iface_id: String; let (export_name, iface_name): (&str, &str) = match name { WorldKey::Name(export_name) => (export_name, export_name), @@ -249,10 +249,15 @@ pub fn ts_bindgen( * on the web, for example. */ export function instantiate( - getCoreModule: (path: string) => Promise, + getCoreModule: (path: string) => WebAssembly.Module, + imports: ImportObject, + instantiateCore?: (module: WebAssembly.Module, imports: Record) => WebAssembly.Instance + ): {camel}; + export function instantiate( + getCoreModule: (path: string) => WebAssembly.Module | Promise, imports: ImportObject, - instantiateCore?: (module: WebAssembly.Module, imports: Record) => Promise - ): Promise<{camel}>; + instantiateCore?: (module: WebAssembly.Module, imports: Record) => WebAssembly.Instance | Promise + ): {camel} | Promise<{camel}>; ", ) } @@ -421,16 +426,27 @@ impl TsBindgen { let local_name = local_name.to_upper_camel_case(); if !local_exists { - uwriteln!( - self.src, - "import {{ {} }} from './{}.js';", - if camel == local_name { - camel.to_string() - } else { - format!("{camel} as {local_name}") - }, - &file_name[0..file_name.len() - 5] - ); + // TypeScript doesn't work with empty namespaces, so we don't import in this case, + // just define them as empty. + let is_empty_interface = resolve.interfaces[id].functions.len() == 0 + && resolve.interfaces[id] + .types + .iter() + .all(|(_, ty)| !matches!(resolve.types[*ty].kind, TypeDefKind::Resource)); + if is_empty_interface { + uwriteln!(self.src, "declare const {local_name}: {{}};"); + } else { + uwriteln!( + self.src, + "import {{ {} }} from './{}.js';", + if camel == local_name { + camel.to_string() + } else { + format!("{camel} as {local_name}") + }, + &file_name[0..file_name.len() - 5] + ); + } } if iface_exists { @@ -440,6 +456,7 @@ impl TsBindgen { let mut gen = self.ts_interface(resolve, false); uwriteln!(gen.src, "export namespace {camel} {{"); + for (_, func) in resolve.interfaces[id].functions.iter() { gen.ts_func(func, false, true); } @@ -454,6 +471,7 @@ impl TsBindgen { } } } + uwriteln!(gen.src, "}}"); gen.types(id); diff --git a/crates/js-component-bindgen/src/ts_stubgen.rs b/crates/js-component-bindgen/src/ts_stubgen.rs index dc0bd51b3..388d4cc34 100644 --- a/crates/js-component-bindgen/src/ts_stubgen.rs +++ b/crates/js-component-bindgen/src/ts_stubgen.rs @@ -51,7 +51,7 @@ pub fn ts_stubgen(resolve: &Resolve, id: WorldId, files: &mut Files) -> anyhow:: } } }, - WorldItem::Interface(_) => match name { + WorldItem::Interface { .. } => match name { // TODO: Is this even possible? WorldKey::Name(name) => { bail!("Interface imported by name not implemented {name}"); @@ -102,7 +102,7 @@ pub fn ts_stubgen(resolve: &Resolve, id: WorldId, files: &mut Files) -> anyhow:: func: f, }); } - WorldItem::Interface(id) => { + WorldItem::Interface { id, .. } => { let id = *id; if let WorldKey::Name(name) = name { export_interfaces.push(ExportInterface { diff --git a/crates/wasm-tools-component/src/lib.rs b/crates/wasm-tools-component/src/lib.rs index ca4878f2b..b8ca53521 100644 --- a/crates/wasm-tools-component/src/lib.rs +++ b/crates/wasm-tools-component/src/lib.rs @@ -4,7 +4,7 @@ use std::path::PathBuf; use wasm_encoder::{Encode, Section}; use wasm_metadata::Producers; use wit_component::{ComponentEncoder, DecodedWasm, WitPrinter}; -use wit_parser::{Resolve, UnresolvedPackage}; +use wit_parser::Resolve; use exports::local::wasm_tools::tools::{ EmbedOpts, Guest, ModuleMetaType, ModuleMetadata, ProducersFields, StringEncoding, @@ -58,12 +58,12 @@ impl Guest for WasmToolsJs { // let world = decode_world("component", &binary); let doc = match &decoded { - DecodedWasm::WitPackage(_resolve, _pkg) => panic!("Unexpected wit package"), + DecodedWasm::WitPackages(_resolve, _pkg) => panic!("Unexpected wit package"), DecodedWasm::Component(resolve, world) => resolve.worlds[*world].package.unwrap(), }; let output = WitPrinter::default() - .print(decoded.resolve(), doc) + .print(decoded.resolve(), &[doc]) .map_err(|e| format!("Unable to print wit\n${:?}", e))?; Ok(output) @@ -74,15 +74,15 @@ impl Guest for WasmToolsJs { let mut resolve = Resolve::default(); - let id = if let Some(wit_source) = &embed_opts.wit_source { + let ids = if let Some(wit_source) = &embed_opts.wit_source { let path = PathBuf::from("component.wit"); - let pkg = UnresolvedPackage::parse(&path, wit_source).map_err(|e| e.to_string())?; - resolve.push(pkg).map_err(|e| e.to_string())? + resolve + .push_str(&path, wit_source) + .map_err(|e| e.to_string())? } else { let wit_path = &PathBuf::from(embed_opts.wit_path.as_ref().unwrap()); if metadata(wit_path).unwrap().is_file() { - let pkg = UnresolvedPackage::parse_file(wit_path).map_err(|e| e.to_string())?; - resolve.push(pkg).map_err(|e| e.to_string())? + resolve.push_file(wit_path).map_err(|e| e.to_string())? } else { resolve.push_dir(wit_path).map_err(|e| e.to_string())?.0 } @@ -90,7 +90,7 @@ impl Guest for WasmToolsJs { let world_string = embed_opts.world.as_ref().map(|world| world.to_string()); let world = resolve - .select_world(id, world_string.as_deref()) + .select_world(&ids, world_string.as_deref()) .map_err(|e| e.to_string())?; let string_encoding = match &embed_opts.string_encoding { diff --git a/create-idl-component.sh b/create-idl-component.sh new file mode 100755 index 000000000..ce00510ae --- /dev/null +++ b/create-idl-component.sh @@ -0,0 +1,12 @@ +# Generate IDL from test/fixtures/idl/*.webidl to test/fixtures/idl/*.wit +cargo xtask generate idl +# Componentize the IDL test case at test/fixtures/*.test.js + +./src/jco.js componentize test/fixtures/idl/dom.test.js --wit test/fixtures/idl/dom.wit -o dom.component.wasm --disable stdio --disable random --disable clocks --disable http --world-name window-test +./src/jco.js transpile dom.component.wasm -o dom-test + +./src/jco.js componentize test/fixtures/idl/console.test.js --wit test/fixtures/idl/console.wit -o console.component.wasm --disable stdio --disable random --disable clocks --disable http --world-name console-test +./src/jco.js transpile console.component.wasm -o console-test + +# Test it +# node --input-type=module -e "import { test } from './dom-test/dom.component.js'; test();" diff --git a/docs/src/example.md b/docs/src/example.md index 0115575cc..9bb1a83b6 100644 --- a/docs/src/example.md +++ b/docs/src/example.md @@ -96,8 +96,6 @@ $ jco componentize cowsay.js --wit cowsay.wit -o cowsay.wasm OK Successfully written cowsay.wasm with imports (). ``` -> Note: For debugging, it is useful to pass `--enable-stdout` to ComponentizeJS to get error messages and enable `console.log`. - ### Inspecting Component WIT As a first step, we might like to look instead this binary black box of a Component and see what it actually does. diff --git a/docs/src/transpiling.md b/docs/src/transpiling.md index 436c98baa..fd88b0b26 100644 --- a/docs/src/transpiling.md +++ b/docs/src/transpiling.md @@ -12,7 +12,85 @@ and exports the component exports. For the default output, you will likely want to ensure there is a package.json file with a `{ "type": "module" }` set for Node.js ES module support (although this is not needed for browser module loading or JS build tooling). -## Export Conventions +## Usage + +To transpile a component into JS: + +``` +jco transpile component.wasm -o out-dir +``` + +The resultant file can be imported providing the bindings of the component as if it were imported directly: + +app.js +``` +import { fn } from './out-dir/component.js'; + +fn(); +``` + +Imports can be remapped using the `--map` flag, or to provide imports as an argument use the `--instantiation` option. + +Components relying on WASI bindings will contain external WASI imports, which are automatically updated +to the `@bytecodealliance/preview2-shim` package. This package can be installed from npm separately for +runtime usage. This shim layer supports both Node.js and browsers. + +## Options + +Options include: + +* `--name`: Give a custom name for the component JS file in `out-dir/[name].js` +* `--minify`: Minify the component JS +* `--optimize`: Runs the internal core Wasm files through Binaryen for optimization. Optimization options can be passed with a `-- ` flag separator. +* `--tla-compat`: Instead of relying on top-level-await, requires an `$init` promise to be imported and awaited first. +* `--js`: Converts core Wasm files to JavaScript for environments that don't even support core Wasm. +* `--base64-cutoff=`: Sets the maximum number of bytes for inlining Wasm files into the JS using base64 encoding. Set to zero to disable base64 inlining entirely. +* `--no-wasi-shim`: Disable the WASI shim mapping to `@bytecodealliance/preview2-shim`. +* `--map`: Provide custom mappings for world imports. Supports both wildcard mappings (`*` similarly as in the package.json "exports" field) as well as `#` mappings for targetting exported interfaces. For example, the WASI mappings are internally defined with mappings like `--map wasi:filesystem/*=@bytecodealliance/preview2-shim/filesystem#*` to map `import as * filesystem from 'wasi:filesystem/types'` to `import { types } from '@bytecodealliance/preview2-shim/filesystem`. +* `--no-nodejs-compat`: Disables Node.js compat in the output to load core Wasm with FS methods. +* `--instantiation [mode]`: Instead of a direct ES module, export an `instantiate` function which can take the imports as an argument instead of implicit imports. The `instantiate` function can be async (with `--instantiation` or `--instantiation async`), or sync (with `--instantiation sync`). +* `--valid-lifting-optimization`: Internal validations are removed assuming that core Wasm binaries are valid components, providing a minor output size saving. +* `--tracing`: Emit tracing calls for all function entry and exits. +* `--no-namespaced-exports`: Removes exports of the type `test as "test:flavorful/test"` which are not compatible with typescript + +## Browser Support + +Jco itself can be used in the browser, which provides the simpler Jco API that is just exactly the same +as the internal [Jco component](https://github.com/bytecodealliance/jco/blob/main/crates/js-component-bindgen-component/wit/js-component-bindgen.wit) Jco uses to self-host. + +To use this browser-supported internal component build, import the `/component` subpath directly: + +```js +import { transpile } from '@bytecodealliance/jco/component'; +``` + +Most JS build tools should then correctly work with such code bundled for the browser. + +### Experimental WebIDL Imports + +Jco has experimental support for zero-runtime and zero-configuration WEbIDL bindings, when using the +`webidl:` interface. + +A canonical WebIDL resource is not yet available, but some examples of these IDLs and WITs can be found +in the [IDL fixtures directory](https://github.com/bytecodealliance/jco/tree/main/test/fixtures/idl/). + +Whenever the `webidl:` namespace is used, Jco will automatically bind such imports to the global object. + +Two top-level conventions are then provided for global access: + +1. A top-level `getWindow` function can be used (or for any singleton global name) to obtain the global object. +2. If the imported interface name starts with `global-` such as `global-console`, then the interface is bound + to that object name on the global object, with dashes replaced with `.` access, ie `globalThis.console`. + +Under these conventions, many WebIDL files can be directly supported for components without any additional +runtime configuration needed. A WebIDL to WIT converter is in development at https://github.com/wasi-gfx/webidl2wit. + +This work is highly experimental, and contributors and improvements would be welcome to help steer this +feature to stability. + +## Transpilation Semantics + +### Export Conventions Components can represent both bundles of modules and individual modules. Compponents export the direct export interface as well as the canonical named interface for the implementation to represent both of these cases. @@ -30,7 +108,7 @@ If not needing this disambiguation feature, and since support for string exports export { interface } ``` -## Import Conventions +### Import Conventions When using the ESM integration default transpilation output bindings are output directly in the `registry:name/interface` form, but with versions removed. @@ -92,6 +170,8 @@ For all subsystems - `cli`, `clocks`, `filesystem`, `http`, `io`, `random` and ` To disable this automatic WASI handling the `--no-wasi-shim` flag can be provided and WASI will be treated like any other import without special handling. +Note that browser support for WASI is currently experimental. + ### Interface Implementation Example Here's an example of implementing a custom WIT interface in JavaScript: @@ -151,7 +231,7 @@ export const iface = { > Note: Top-level results are turned into JS exceptions, all other results are treated as tagged objects `{ tag: 'ok' | 'err', val }`. -### WASI Proposals +## WASI Proposals **Jco will always take PRs to support all open WASI proposals.** diff --git a/lib/wasi_snapshot_preview1.command.wasm b/lib/wasi_snapshot_preview1.command.wasm index bd2fc9f3b..725429c23 100644 Binary files a/lib/wasi_snapshot_preview1.command.wasm and b/lib/wasi_snapshot_preview1.command.wasm differ diff --git a/lib/wasi_snapshot_preview1.reactor.wasm b/lib/wasi_snapshot_preview1.reactor.wasm index e35bc198d..61be7cfce 100644 Binary files a/lib/wasi_snapshot_preview1.reactor.wasm and b/lib/wasi_snapshot_preview1.reactor.wasm differ diff --git a/package-lock.json b/package-lock.json index 6a9ff1f2b..9f218ab36 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,19 +1,19 @@ { "name": "@golemcloud/jco", - "version": "1.2.4-golem.4", + "version": "1.4.0-golem.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@golemcloud/jco", - "version": "1.2.4-golem.4", + "version": "1.4.0-golem.1", "license": "(Apache-2.0 WITH LLVM-exception)", "workspaces": [ "packages/preview2-shim" ], "dependencies": { - "@bytecodealliance/preview2-shim": "^0.16.2", - "binaryen": "^116.0.0", + "@bytecodealliance/preview2-shim": "^0.16.4", + "binaryen": "^118.0.0", "chalk-template": "^1", "commander": "^12", "mkdirp": "^3", @@ -24,14 +24,16 @@ "jco": "src/jco.js" }, "devDependencies": { - "@golemcloud/componentize-js": "0.8.3-golem.2", - "@types/node": "^18.11.17", - "@typescript-eslint/eslint-plugin": "^5.41.0", - "@typescript-eslint/parser": "^5.41.0", - "eslint": "^8.30.0", - "mocha": "^10.2.0", + "@golemcloud/componentize-js": "0.10.2-golem.1", + "@types/node": "^20.14.12", + "@typescript-eslint/eslint-plugin": "^7.17.0", + "@typescript-eslint/parser": "^7.17.0", + "eslint": "^8.56.0", + "mime": "^4.0.4", + "mocha": "^10.7.0", + "puppeteer": "^22.14.0", "terser": "^5.16.1", - "typescript": "^5.3.3" + "typescript": "^5.5.4" } }, "node_modules/@aashutoshrathi/word-wrap": { @@ -43,6 +45,124 @@ "node": ">=0.10.0" } }, + "node_modules/@babel/code-frame": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.7.tgz", + "integrity": "sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/highlight": "^7.24.7", + "picocolors": "^1.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz", + "integrity": "sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.7.tgz", + "integrity": "sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-validator-identifier": "^7.24.7", + "chalk": "^2.4.2", + "js-tokens": "^4.0.0", + "picocolors": "^1.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/@babel/highlight/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@babel/highlight/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/@babel/highlight/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/@bytecodealliance/preview2-shim": { "resolved": "packages/preview2-shim", "link": true @@ -220,9 +340,9 @@ } }, "node_modules/@golemcloud/componentize-js": { - "version": "0.8.3-golem.2", - "resolved": "https://registry.npmjs.org/@golemcloud/componentize-js/-/componentize-js-0.8.3-golem.2.tgz", - "integrity": "sha512-+d35/6/hve4ZIhPZxIHKM0zJ0l5BopBobw+wkO/Y1tvL2n++Mtm6v3FUSQEELuWRcaM1v541L6lgOCMhVpopUQ==", + "version": "0.10.2-golem.1", + "resolved": "https://registry.npmjs.org/@golemcloud/componentize-js/-/componentize-js-0.10.2-golem.1.tgz", + "integrity": "sha512-jVzAY2JpOdicqKls2cUpDQLAZgXvArbGIGxBpVMsfPAJ4tVSjvMS6PSKO6Yan9/tZ+sNFiXNF4nNdd/qhXvL5A==", "dev": true, "workspaces": [ "." @@ -230,7 +350,7 @@ "dependencies": { "@bytecodealliance/wizer": "^3.0.1", "@golemcloud/jco": "1.2.4-golem.2", - "es-module-lexer": "^1.4.1" + "es-module-lexer": "^1.5.4" } }, "node_modules/@golemcloud/jco": { @@ -238,6 +358,7 @@ "resolved": "https://registry.npmjs.org/@golemcloud/jco/-/jco-1.2.4-golem.2.tgz", "integrity": "sha512-Q49XQLNlqF6ei+I3hJZQDIt14ulvrIqbzcO40LpwusSqwMNd0t+oLOXKWO9NIt22LtapGRZ69IyVodjaKzPUrQ==", "dev": true, + "license": "(Apache-2.0 WITH LLVM-exception)", "workspaces": [ "packages/preview2-shim" ], @@ -254,6 +375,17 @@ "jco": "src/jco.js" } }, + "node_modules/@golemcloud/jco/node_modules/binaryen": { + "version": "116.0.0", + "resolved": "https://registry.npmjs.org/binaryen/-/binaryen-116.0.0.tgz", + "integrity": "sha512-Hp0dXC6Cb/rTwWEoUS2BRghObE7g/S9umKtxuTDt3f61G6fNTE/YVew/ezyy3IdHcLx3f17qfh6LwETgCfvWkQ==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "wasm-opt": "bin/wasm-opt", + "wasm2js": "bin/wasm2js" + } + }, "node_modules/@humanwhocodes/config-array": { "version": "0.11.14", "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", @@ -380,54 +512,150 @@ "node": ">= 8" } }, - "node_modules/@types/json-schema": { - "version": "7.0.15", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", - "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", - "dev": true + "node_modules/@puppeteer/browsers": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@puppeteer/browsers/-/browsers-2.3.0.tgz", + "integrity": "sha512-ioXoq9gPxkss4MYhD+SFaU9p1IHFUX0ILAWFPyjGaBdjLsYAlZw6j1iLA0N/m12uVHLFDfSYNF7EQccjinIMDA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "debug": "^4.3.5", + "extract-zip": "^2.0.1", + "progress": "^2.0.3", + "proxy-agent": "^6.4.0", + "semver": "^7.6.3", + "tar-fs": "^3.0.6", + "unbzip2-stream": "^1.4.3", + "yargs": "^17.7.2" + }, + "bin": { + "browsers": "lib/cjs/main-cli.js" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@puppeteer/browsers/node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@puppeteer/browsers/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/@puppeteer/browsers/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@puppeteer/browsers/node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@puppeteer/browsers/node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/@tootallnate/quickjs-emscripten": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@tootallnate/quickjs-emscripten/-/quickjs-emscripten-0.23.0.tgz", + "integrity": "sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA==", + "dev": true, + "license": "MIT" }, "node_modules/@types/node": { - "version": "18.19.31", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.31.tgz", - "integrity": "sha512-ArgCD39YpyyrtFKIqMDvjz79jto5fcI/SVUs2HwB+f0dAzq68yqOdyaSivLiLugSziTpNXLQrVb7RZFmdZzbhA==", + "version": "20.14.13", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.13.tgz", + "integrity": "sha512-+bHoGiZb8UiQ0+WEtmph2IWQCjIqg8MDZMAV+ppRRhUZnquF5mQkP/9vpSwJClEiSM/C7fZZExPzfU0vJTyp8w==", "dev": true, + "license": "MIT", "dependencies": { "undici-types": "~5.26.4" } }, - "node_modules/@types/semver": { - "version": "7.5.8", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.8.tgz", - "integrity": "sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==", - "dev": true + "node_modules/@types/yauzl": { + "version": "2.10.3", + "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.3.tgz", + "integrity": "sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@types/node": "*" + } }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.62.0.tgz", - "integrity": "sha512-TiZzBSJja/LbhNPvk6yc0JrX9XqhQ0hdh6M2svYfsHGejaKFIAGd9MQ+ERIMzLGlN/kZoYIgdxFV0PuljTKXag==", + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.18.0.tgz", + "integrity": "sha512-94EQTWZ40mzBc42ATNIBimBEDltSJ9RQHCC8vc/PDbxi4k8dVwUAv4o98dk50M1zB+JGFxp43FP7f8+FP8R6Sw==", "dev": true, + "license": "MIT", "dependencies": { - "@eslint-community/regexpp": "^4.4.0", - "@typescript-eslint/scope-manager": "5.62.0", - "@typescript-eslint/type-utils": "5.62.0", - "@typescript-eslint/utils": "5.62.0", - "debug": "^4.3.4", + "@eslint-community/regexpp": "^4.10.0", + "@typescript-eslint/scope-manager": "7.18.0", + "@typescript-eslint/type-utils": "7.18.0", + "@typescript-eslint/utils": "7.18.0", + "@typescript-eslint/visitor-keys": "7.18.0", "graphemer": "^1.4.0", - "ignore": "^5.2.0", - "natural-compare-lite": "^1.4.0", - "semver": "^7.3.7", - "tsutils": "^3.21.0" + "ignore": "^5.3.1", + "natural-compare": "^1.4.0", + "ts-api-utils": "^1.3.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || >=20.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@typescript-eslint/parser": "^5.0.0", - "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + "@typescript-eslint/parser": "^7.0.0", + "eslint": "^8.56.0" }, "peerDependenciesMeta": { "typescript": { @@ -436,25 +664,27 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.62.0.tgz", - "integrity": "sha512-VlJEV0fOQ7BExOsHYAGrgbEiZoi8D+Bl2+f6V2RrXerRSylnp+ZBHmPvaIa8cz0Ajx7WO7Z5RqfgYg7ED1nRhA==", + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.18.0.tgz", + "integrity": "sha512-4Z+L8I2OqhZV8qA132M4wNL30ypZGYOQVBfMgxDH/K5UX0PNqTu1c6za9ST5r9+tavvHiTWmBnKzpCJ/GlVFtg==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { - "@typescript-eslint/scope-manager": "5.62.0", - "@typescript-eslint/types": "5.62.0", - "@typescript-eslint/typescript-estree": "5.62.0", + "@typescript-eslint/scope-manager": "7.18.0", + "@typescript-eslint/types": "7.18.0", + "@typescript-eslint/typescript-estree": "7.18.0", + "@typescript-eslint/visitor-keys": "7.18.0", "debug": "^4.3.4" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || >=20.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + "eslint": "^8.56.0" }, "peerDependenciesMeta": { "typescript": { @@ -463,16 +693,17 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.62.0.tgz", - "integrity": "sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==", + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.18.0.tgz", + "integrity": "sha512-jjhdIE/FPF2B7Z1uzc6i3oWKbGcHb87Qw7AWj6jmEqNOfDFbJWtjt/XfwCpvNkpGWlcJaog5vTR+VV8+w9JflA==", "dev": true, + "license": "MIT", "dependencies": { - "@typescript-eslint/types": "5.62.0", - "@typescript-eslint/visitor-keys": "5.62.0" + "@typescript-eslint/types": "7.18.0", + "@typescript-eslint/visitor-keys": "7.18.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || >=20.0.0" }, "funding": { "type": "opencollective", @@ -480,25 +711,26 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.62.0.tgz", - "integrity": "sha512-xsSQreu+VnfbqQpW5vnCJdq1Z3Q0U31qiWmRhr98ONQmcp/yhiPJFPq8MXiJVLiksmOKSjIldZzkebzHuCGzew==", + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.18.0.tgz", + "integrity": "sha512-XL0FJXuCLaDuX2sYqZUUSOJ2sG5/i1AAze+axqmLnSkNEVMVYLF+cbwlB2w8D1tinFuSikHmFta+P+HOofrLeA==", "dev": true, + "license": "MIT", "dependencies": { - "@typescript-eslint/typescript-estree": "5.62.0", - "@typescript-eslint/utils": "5.62.0", + "@typescript-eslint/typescript-estree": "7.18.0", + "@typescript-eslint/utils": "7.18.0", "debug": "^4.3.4", - "tsutils": "^3.21.0" + "ts-api-utils": "^1.3.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || >=20.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "*" + "eslint": "^8.56.0" }, "peerDependenciesMeta": { "typescript": { @@ -507,12 +739,13 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.62.0.tgz", - "integrity": "sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==", + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.18.0.tgz", + "integrity": "sha512-iZqi+Ds1y4EDYUtlOOC+aUmxnE9xS/yCigkjA7XpTKV6nCBd3Hp/PRGGmdwnfkV2ThMyYldP1wRpm/id99spTQ==", "dev": true, + "license": "MIT", "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || >=20.0.0" }, "funding": { "type": "opencollective", @@ -520,21 +753,23 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.62.0.tgz", - "integrity": "sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==", + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.18.0.tgz", + "integrity": "sha512-aP1v/BSPnnyhMHts8cf1qQ6Q1IFwwRvAQGRvBFkWlo3/lH29OXA3Pts+c10nxRxIBrDnoMqzhgdwVe5f2D6OzA==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { - "@typescript-eslint/types": "5.62.0", - "@typescript-eslint/visitor-keys": "5.62.0", + "@typescript-eslint/types": "7.18.0", + "@typescript-eslint/visitor-keys": "7.18.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", - "semver": "^7.3.7", - "tsutils": "^3.21.0" + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^1.3.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || >=20.0.0" }, "funding": { "type": "opencollective", @@ -546,43 +781,67 @@ } } }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/@typescript-eslint/utils": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.62.0.tgz", - "integrity": "sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==", + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.18.0.tgz", + "integrity": "sha512-kK0/rNa2j74XuHVcoCZxdFBMF+aq/vH83CXAOHieC+2Gis4mF8jJXT5eAfyD3K0sAxtPuwxaIOIOvhwzVDt/kw==", "dev": true, + "license": "MIT", "dependencies": { - "@eslint-community/eslint-utils": "^4.2.0", - "@types/json-schema": "^7.0.9", - "@types/semver": "^7.3.12", - "@typescript-eslint/scope-manager": "5.62.0", - "@typescript-eslint/types": "5.62.0", - "@typescript-eslint/typescript-estree": "5.62.0", - "eslint-scope": "^5.1.1", - "semver": "^7.3.7" + "@eslint-community/eslint-utils": "^4.4.0", + "@typescript-eslint/scope-manager": "7.18.0", + "@typescript-eslint/types": "7.18.0", + "@typescript-eslint/typescript-estree": "7.18.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || >=20.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + "eslint": "^8.56.0" } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.62.0.tgz", - "integrity": "sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==", + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.18.0.tgz", + "integrity": "sha512-cDF0/Gf81QpY3xYyJKDV14Zwdmid5+uuENhjH2EqFaF0ni+yAyq/LzMaIJdhNJXZI7uLzwIlA+V7oWoyn6Curg==", "dev": true, + "license": "MIT", "dependencies": { - "@typescript-eslint/types": "5.62.0", - "eslint-visitor-keys": "^3.3.0" + "@typescript-eslint/types": "7.18.0", + "eslint-visitor-keys": "^3.4.3" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || >=20.0.0" }, "funding": { "type": "opencollective", @@ -616,6 +875,19 @@ "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, + "node_modules/agent-base": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", + "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, "node_modules/ajv": { "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", @@ -633,10 +905,11 @@ } }, "node_modules/ansi-colors": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", - "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", + "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } @@ -689,16 +962,119 @@ "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, + "node_modules/ast-types": { + "version": "0.13.4", + "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.13.4.tgz", + "integrity": "sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w==", + "dev": true, + "license": "MIT", + "dependencies": { + "tslib": "^2.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/b4a": { + "version": "1.6.6", + "resolved": "https://registry.npmjs.org/b4a/-/b4a-1.6.6.tgz", + "integrity": "sha512-5Tk1HLk6b6ctmjIkAcU/Ujv/1WqiDl0F0JdRCR80VsOcUlHcu7pWeWRlOqQLHfDEsVx9YH/aif5AG4ehoCtTmg==", + "dev": true, + "license": "Apache-2.0" + }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "dev": true }, + "node_modules/bare-events": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/bare-events/-/bare-events-2.4.2.tgz", + "integrity": "sha512-qMKFd2qG/36aA4GwvKq8MxnPgCQAmBWmSyLWsJcbn8v03wvIPQ/hG1Ms8bPzndZxMDoHpxez5VOS+gC9Yi24/Q==", + "dev": true, + "license": "Apache-2.0", + "optional": true + }, + "node_modules/bare-fs": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/bare-fs/-/bare-fs-2.3.1.tgz", + "integrity": "sha512-W/Hfxc/6VehXlsgFtbB5B4xFcsCl+pAh30cYhoFyXErf6oGrwjh8SwiPAdHgpmWonKuYpZgGywN0SXt7dgsADA==", + "dev": true, + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "bare-events": "^2.0.0", + "bare-path": "^2.0.0", + "bare-stream": "^2.0.0" + } + }, + "node_modules/bare-os": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/bare-os/-/bare-os-2.4.0.tgz", + "integrity": "sha512-v8DTT08AS/G0F9xrhyLtepoo9EJBJ85FRSMbu1pQUlAf6A8T0tEEQGMVObWeqpjhSPXsE0VGlluFBJu2fdoTNg==", + "dev": true, + "license": "Apache-2.0", + "optional": true + }, + "node_modules/bare-path": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/bare-path/-/bare-path-2.1.3.tgz", + "integrity": "sha512-lh/eITfU8hrj9Ru5quUp0Io1kJWIk1bTjzo7JH1P5dWmQ2EL4hFUlfI8FonAhSlgIfhn63p84CDY/x+PisgcXA==", + "dev": true, + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "bare-os": "^2.1.0" + } + }, + "node_modules/bare-stream": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/bare-stream/-/bare-stream-2.1.3.tgz", + "integrity": "sha512-tiDAH9H/kP+tvNO5sczyn9ZAA7utrSMobyDchsnyyXBuUe2FSQWbxhtuHB8jwpHYYevVo2UJpcmvvjrbHboUUQ==", + "dev": true, + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "streamx": "^2.18.0" + } + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/basic-ftp": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/basic-ftp/-/basic-ftp-5.0.5.tgz", + "integrity": "sha512-4Bcg1P8xhUuqcii/S0Z9wiHIrQVPMermM1any+MX5GeGD7faD3/msQUDGLol9wOcz4/jbg/WJnGqoJF6LiBdtg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10.0.0" + } + }, "node_modules/binary-extensions": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", @@ -712,11 +1088,19 @@ } }, "node_modules/binaryen": { - "version": "116.0.0", - "resolved": "https://registry.npmjs.org/binaryen/-/binaryen-116.0.0.tgz", - "integrity": "sha512-Hp0dXC6Cb/rTwWEoUS2BRghObE7g/S9umKtxuTDt3f61G6fNTE/YVew/ezyy3IdHcLx3f17qfh6LwETgCfvWkQ==", + "version": "118.0.0", + "resolved": "https://registry.npmjs.org/binaryen/-/binaryen-118.0.0.tgz", + "integrity": "sha512-KzekjPjpLE1zk29BKQSHNWLSHPYAfa80lcsIi5bDnev8vyfDyiMCVFPjaplhfXIKs7LI3r1RPyhoAj4qsRQwwg==", + "license": "Apache-2.0", "bin": { + "wasm-as": "bin/wasm-as", + "wasm-ctor-eval": "bin/wasm-ctor-eval", + "wasm-dis": "bin/wasm-dis", + "wasm-merge": "bin/wasm-merge", + "wasm-metadce": "bin/wasm-metadce", "wasm-opt": "bin/wasm-opt", + "wasm-reduce": "bin/wasm-reduce", + "wasm-shell": "bin/wasm-shell", "wasm2js": "bin/wasm2js" } }, @@ -749,6 +1133,41 @@ "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", "dev": true }, + "node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "node_modules/buffer-crc32": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", + "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "*" + } + }, "node_modules/buffer-from": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", @@ -840,6 +1259,21 @@ "node": ">= 6" } }, + "node_modules/chromium-bidi": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/chromium-bidi/-/chromium-bidi-0.6.3.tgz", + "integrity": "sha512-qXlsCmpCZJAnoTYI83Iu6EdYQpMYdVkCfq08KDh2pmlVqK5t5IA9mGs4/LwCwp4fqisSOMXZxP3HIh8w8aRn0A==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "mitt": "3.0.1", + "urlpattern-polyfill": "10.0.0", + "zod": "3.23.8" + }, + "peerDependencies": { + "devtools-protocol": "*" + } + }, "node_modules/cli-cursor": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-4.0.0.tgz", @@ -928,6 +1362,33 @@ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", "dev": true }, + "node_modules/cosmiconfig": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-9.0.0.tgz", + "integrity": "sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg==", + "dev": true, + "license": "MIT", + "dependencies": { + "env-paths": "^2.2.1", + "import-fresh": "^3.3.0", + "js-yaml": "^4.1.0", + "parse-json": "^5.2.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/d-fischer" + }, + "peerDependencies": { + "typescript": ">=4.9.5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, "node_modules/cross-spawn": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", @@ -942,11 +1403,22 @@ "node": ">= 8" } }, + "node_modules/data-uri-to-buffer": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-6.0.2.tgz", + "integrity": "sha512-7hvf7/GW8e86rW0ptuwS3OcBGDjIi6SZva7hCyWC0yYry2cOPmLIjXAUHI6DK2HsnwJd9ifmt57i8eV2n4YNpw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 14" + } + }, "node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz", + "integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==", "dev": true, + "license": "MIT", "dependencies": { "ms": "2.1.2" }, @@ -977,11 +1449,34 @@ "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", "dev": true }, + "node_modules/degenerator": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/degenerator/-/degenerator-5.0.1.tgz", + "integrity": "sha512-TllpMR/t0M5sqCXfj85i4XaAzxmS5tVA16dqvdkMwGmzI+dXLXnw3J+3Vdv7VKw+ThlTMboK6i9rnZ6Nntj5CQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ast-types": "^0.13.4", + "escodegen": "^2.1.0", + "esprima": "^4.0.1" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/devtools-protocol": { + "version": "0.0.1312386", + "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.1312386.tgz", + "integrity": "sha512-DPnhUXvmvKT2dFA/j7B+riVLUt9Q6RKJlcppojL5CoRywJJKLDYnRlw0gTFKfgDPHP5E04UoB71SxoJlVZy8FA==", + "dev": true, + "license": "BSD-3-Clause" + }, "node_modules/diff": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", - "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-5.2.0.tgz", + "integrity": "sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==", "dev": true, + "license": "BSD-3-Clause", "engines": { "node": ">=0.3.1" } @@ -991,6 +1486,7 @@ "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", "dev": true, + "license": "MIT", "dependencies": { "path-type": "^4.0.0" }, @@ -1015,11 +1511,42 @@ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.3.0.tgz", "integrity": "sha512-QpLs9D9v9kArv4lfDEgg1X/gN5XLnf/A6l9cs8SPZLRZR3ZkY9+kwIQTxm+fsSej5UMYGE8fdoaZVIBlqG0XTw==" }, + "node_modules/end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/env-paths": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", + "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, "node_modules/es-module-lexer": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.5.0.tgz", - "integrity": "sha512-pqrTKmwEIgafsYZAGw9kszYzmagcE/n4dbgwGWLEXg7J4QFJVQRBld8j3Q3GNez79jzxZshq0bcT962QHOghjw==", - "dev": true + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.5.4.tgz", + "integrity": "sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw==", + "dev": true, + "license": "MIT" }, "node_modules/escalade": { "version": "3.1.2", @@ -1042,6 +1569,28 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/escodegen": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.1.0.tgz", + "integrity": "sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "esprima": "^4.0.1", + "estraverse": "^5.2.0", + "esutils": "^2.0.2" + }, + "bin": { + "escodegen": "bin/escodegen.js", + "esgenerate": "bin/esgenerate.js" + }, + "engines": { + "node": ">=6.0" + }, + "optionalDependencies": { + "source-map": "~0.6.1" + } + }, "node_modules/eslint": { "version": "8.57.0", "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz", @@ -1097,19 +1646,6 @@ "url": "https://opencollective.com/eslint" } }, - "node_modules/eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", - "dev": true, - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" - }, - "engines": { - "node": ">=8.0.0" - } - }, "node_modules/eslint-visitor-keys": { "version": "3.4.3", "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", @@ -1154,15 +1690,6 @@ "url": "https://opencollective.com/eslint" } }, - "node_modules/eslint/node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, "node_modules/eslint/node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -1192,6 +1719,20 @@ "url": "https://opencollective.com/eslint" } }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true, + "license": "BSD-2-Clause", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/esquery": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", @@ -1204,15 +1745,6 @@ "node": ">=0.10" } }, - "node_modules/esquery/node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, "node_modules/esrecurse": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", @@ -1225,20 +1757,12 @@ "node": ">=4.0" } }, - "node_modules/esrecurse/node_modules/estraverse": { + "node_modules/estraverse": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true, + "license": "BSD-2-Clause", "engines": { "node": ">=4.0" } @@ -1252,17 +1776,46 @@ "node": ">=0.10.0" } }, + "node_modules/extract-zip": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz", + "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "debug": "^4.1.1", + "get-stream": "^5.1.0", + "yauzl": "^2.10.0" + }, + "bin": { + "extract-zip": "cli.js" + }, + "engines": { + "node": ">= 10.17.0" + }, + "optionalDependencies": { + "@types/yauzl": "^2.9.1" + } + }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", "dev": true }, + "node_modules/fast-fifo": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/fast-fifo/-/fast-fifo-1.3.2.tgz", + "integrity": "sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==", + "dev": true, + "license": "MIT" + }, "node_modules/fast-glob": { "version": "3.3.2", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", "dev": true, + "license": "MIT", "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", @@ -1279,6 +1832,7 @@ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", "dev": true, + "license": "ISC", "dependencies": { "is-glob": "^4.0.1" }, @@ -1307,6 +1861,16 @@ "reusify": "^1.0.4" } }, + "node_modules/fd-slicer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", + "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "pend": "~1.2.0" + } + }, "node_modules/file-entry-cache": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", @@ -1377,6 +1941,21 @@ "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", "dev": true }, + "node_modules/fs-extra": { + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", + "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=14.14" + } + }, "node_modules/fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -1417,6 +1996,38 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "dev": true, + "license": "MIT", + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/get-uri": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/get-uri/-/get-uri-6.0.3.tgz", + "integrity": "sha512-BzUrJBS9EcUb4cFol8r4W3v1cPsSyajLSthNkz5BxbpDcHN5tIrM10E2eNvfnvBn3DaT3DUgx0OpsBKkaOpanw==", + "dev": true, + "license": "MIT", + "dependencies": { + "basic-ftp": "^5.0.2", + "data-uri-to-buffer": "^6.0.2", + "debug": "^4.3.4", + "fs-extra": "^11.2.0" + }, + "engines": { + "node": ">= 14" + } + }, "node_modules/glob": { "version": "8.1.0", "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", @@ -1489,6 +2100,7 @@ "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", "dev": true, + "license": "MIT", "dependencies": { "array-union": "^2.1.0", "dir-glob": "^3.0.1", @@ -1504,6 +2116,13 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true, + "license": "ISC" + }, "node_modules/graphemer": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", @@ -1528,6 +2147,55 @@ "he": "bin/he" } }, + "node_modules/http-proxy-agent": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", + "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", + "dev": true, + "license": "MIT", + "dependencies": { + "agent-base": "^7.1.0", + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/https-proxy-agent": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.5.tgz", + "integrity": "sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw==", + "dev": true, + "license": "MIT", + "dependencies": { + "agent-base": "^7.0.2", + "debug": "4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "BSD-3-Clause" + }, "node_modules/ignore": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", @@ -1578,6 +2246,27 @@ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", "dev": true }, + "node_modules/ip-address": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-9.0.5.tgz", + "integrity": "sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "jsbn": "1.1.0", + "sprintf-js": "^1.1.3" + }, + "engines": { + "node": ">= 12" + } + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "dev": true, + "license": "MIT" + }, "node_modules/is-binary-path": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", @@ -1677,6 +2366,13 @@ "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", "dev": true }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true, + "license": "MIT" + }, "node_modules/js-yaml": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", @@ -1689,12 +2385,26 @@ "js-yaml": "bin/js-yaml.js" } }, + "node_modules/jsbn": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-1.1.0.tgz", + "integrity": "sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==", + "dev": true, + "license": "MIT" + }, "node_modules/json-buffer": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", "dev": true }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true, + "license": "MIT" + }, "node_modules/json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", @@ -1707,6 +2417,19 @@ "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", "dev": true }, + "node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, "node_modules/keyv": { "version": "4.5.4", "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", @@ -1729,6 +2452,13 @@ "node": ">= 0.8.0" } }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "dev": true, + "license": "MIT" + }, "node_modules/locate-path": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", @@ -1795,15 +2525,13 @@ } }, "node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, + "license": "ISC", "engines": { - "node": ">=10" + "node": ">=12" } }, "node_modules/merge2": { @@ -1811,23 +2539,41 @@ "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", "dev": true, + "license": "MIT", "engines": { "node": ">= 8" } }, "node_modules/micromatch": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", - "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.7.tgz", + "integrity": "sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==", "dev": true, + "license": "MIT", "dependencies": { - "braces": "^3.0.2", + "braces": "^3.0.3", "picomatch": "^2.3.1" }, "engines": { "node": ">=8.6" } }, + "node_modules/mime": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/mime/-/mime-4.0.4.tgz", + "integrity": "sha512-v8yqInVjhXyqP6+Kw4fV3ZzeMRqEW6FotRsKXjRS5VMTNIuXsdRoAvklpoRgSqXm6o9VNH4/C0mgedko9DdLsQ==", + "dev": true, + "funding": [ + "https://github.com/sponsors/broofa" + ], + "license": "MIT", + "bin": { + "mime": "bin/cli.js" + }, + "engines": { + "node": ">=16" + } + }, "node_modules/mimic-fn": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", @@ -1848,6 +2594,13 @@ "node": "*" } }, + "node_modules/mitt": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mitt/-/mitt-3.0.1.tgz", + "integrity": "sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==", + "dev": true, + "license": "MIT" + }, "node_modules/mkdirp": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-3.0.1.tgz", @@ -1863,31 +2616,32 @@ } }, "node_modules/mocha": { - "version": "10.4.0", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.4.0.tgz", - "integrity": "sha512-eqhGB8JKapEYcC4ytX/xrzKforgEc3j1pGlAXVy3eRwrtAy5/nIfT1SvgGzfN0XZZxeLq0aQWkOUAmqIJiv+bA==", - "dev": true, - "dependencies": { - "ansi-colors": "4.1.1", - "browser-stdout": "1.3.1", - "chokidar": "3.5.3", - "debug": "4.3.4", - "diff": "5.0.0", - "escape-string-regexp": "4.0.0", - "find-up": "5.0.0", - "glob": "8.1.0", - "he": "1.2.0", - "js-yaml": "4.1.0", - "log-symbols": "4.1.0", - "minimatch": "5.0.1", - "ms": "2.1.3", - "serialize-javascript": "6.0.0", - "strip-json-comments": "3.1.1", - "supports-color": "8.1.1", - "workerpool": "6.2.1", - "yargs": "16.2.0", - "yargs-parser": "20.2.4", - "yargs-unparser": "2.0.0" + "version": "10.7.0", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.7.0.tgz", + "integrity": "sha512-v8/rBWr2VO5YkspYINnvu81inSz2y3ODJrhO175/Exzor1RcEZZkizgE2A+w/CAXXoESS8Kys5E62dOHGHzULA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-colors": "^4.1.3", + "browser-stdout": "^1.3.1", + "chokidar": "^3.5.3", + "debug": "^4.3.5", + "diff": "^5.2.0", + "escape-string-regexp": "^4.0.0", + "find-up": "^5.0.0", + "glob": "^8.1.0", + "he": "^1.2.0", + "js-yaml": "^4.1.0", + "log-symbols": "^4.1.0", + "minimatch": "^5.1.6", + "ms": "^2.1.3", + "serialize-javascript": "^6.0.2", + "strip-json-comments": "^3.1.1", + "supports-color": "^8.1.1", + "workerpool": "^6.5.1", + "yargs": "^16.2.0", + "yargs-parser": "^20.2.9", + "yargs-unparser": "^2.0.0" }, "bin": { "_mocha": "bin/_mocha", @@ -1902,15 +2656,17 @@ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", "dev": true, + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0" } }, "node_modules/mocha/node_modules/minimatch": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz", - "integrity": "sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==", + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", "dev": true, + "license": "ISC", "dependencies": { "brace-expansion": "^2.0.1" }, @@ -1936,11 +2692,15 @@ "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", "dev": true }, - "node_modules/natural-compare-lite": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz", - "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==", - "dev": true + "node_modules/netmask": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/netmask/-/netmask-2.0.2.tgz", + "integrity": "sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4.0" + } }, "node_modules/normalize-path": { "version": "3.0.0", @@ -2105,6 +2865,40 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/pac-proxy-agent": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/pac-proxy-agent/-/pac-proxy-agent-7.0.2.tgz", + "integrity": "sha512-BFi3vZnO9X5Qt6NRz7ZOaPja3ic0PhlsmCRYLOpN11+mWBCR6XJDqW5RF3j8jm4WGGQZtBA+bTfxYzeKW73eHg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@tootallnate/quickjs-emscripten": "^0.23.0", + "agent-base": "^7.0.2", + "debug": "^4.3.4", + "get-uri": "^6.0.1", + "http-proxy-agent": "^7.0.0", + "https-proxy-agent": "^7.0.5", + "pac-resolver": "^7.0.1", + "socks-proxy-agent": "^8.0.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/pac-resolver": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/pac-resolver/-/pac-resolver-7.0.1.tgz", + "integrity": "sha512-5NPgf87AT2STgwa2ntRMr45jTKrYBGkVU36yT0ig/n/GMAa3oPqhZfIQ2kMEimReg0+t9kZViDVZ83qfVUlckg==", + "dev": true, + "license": "MIT", + "dependencies": { + "degenerator": "^5.0.0", + "netmask": "^2.0.2" + }, + "engines": { + "node": ">= 14" + } + }, "node_modules/parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", @@ -2117,6 +2911,25 @@ "node": ">=6" } }, + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", @@ -2149,10 +2962,25 @@ "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, + "node_modules/pend": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", + "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==", + "dev": true, + "license": "MIT" + }, + "node_modules/picocolors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz", + "integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==", + "dev": true, + "license": "ISC" + }, "node_modules/picomatch": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", @@ -2174,6 +3002,54 @@ "node": ">= 0.8.0" } }, + "node_modules/progress": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/proxy-agent": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-6.4.0.tgz", + "integrity": "sha512-u0piLU+nCOHMgGjRbimiXmA9kM/L9EHh3zL81xCdp7m+Y2pHIsnmbdDoEDoAz5geaonNR6q6+yOPQs6n4T6sBQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "agent-base": "^7.0.2", + "debug": "^4.3.4", + "http-proxy-agent": "^7.0.1", + "https-proxy-agent": "^7.0.3", + "lru-cache": "^7.14.1", + "pac-proxy-agent": "^7.0.1", + "proxy-from-env": "^1.1.0", + "socks-proxy-agent": "^8.0.2" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", + "dev": true, + "license": "MIT" + }, + "node_modules/pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dev": true, + "license": "MIT", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, "node_modules/punycode": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", @@ -2183,6 +3059,43 @@ "node": ">=6" } }, + "node_modules/puppeteer": { + "version": "22.15.0", + "resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-22.15.0.tgz", + "integrity": "sha512-XjCY1SiSEi1T7iSYuxS82ft85kwDJUS7wj1Z0eGVXKdtr5g4xnVcbjwxhq5xBnpK/E7x1VZZoJDxpjAOasHT4Q==", + "dev": true, + "hasInstallScript": true, + "license": "Apache-2.0", + "dependencies": { + "@puppeteer/browsers": "2.3.0", + "cosmiconfig": "^9.0.0", + "devtools-protocol": "0.0.1312386", + "puppeteer-core": "22.15.0" + }, + "bin": { + "puppeteer": "lib/esm/puppeteer/node/cli.js" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/puppeteer-core": { + "version": "22.15.0", + "resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-22.15.0.tgz", + "integrity": "sha512-cHArnywCiAAVXa3t4GGL2vttNxh7GqXtIYGym99egkNJ3oG//wL9LkvO4WE8W1TJe95t1F1ocu9X4xWaGsOKOA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@puppeteer/browsers": "2.3.0", + "chromium-bidi": "0.6.3", + "debug": "^4.3.6", + "devtools-protocol": "0.0.1312386", + "ws": "^8.18.0" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", @@ -2203,11 +3116,19 @@ } ] }, + "node_modules/queue-tick": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/queue-tick/-/queue-tick-1.0.1.tgz", + "integrity": "sha512-kJt5qhMxoszgU/62PLP1CJytzd2NKetjSRnyuj31fDd3Rlcz3fzlFdFLD1SItunPwyqEOkca6GbV612BWfaBag==", + "dev": true, + "license": "MIT" + }, "node_modules/randombytes": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", "dev": true, + "license": "MIT", "dependencies": { "safe-buffer": "^5.1.0" } @@ -2343,16 +3264,15 @@ "type": "consulting", "url": "https://feross.org/support" } - ] + ], + "license": "MIT" }, "node_modules/semver": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", - "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, + "license": "ISC", "bin": { "semver": "bin/semver.js" }, @@ -2361,10 +3281,11 @@ } }, "node_modules/serialize-javascript": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", - "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", + "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "randombytes": "^2.1.0" } @@ -2400,10 +3321,52 @@ "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, + "node_modules/smart-buffer": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", + "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/socks": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.3.tgz", + "integrity": "sha512-l5x7VUUWbjVFbafGLxPWkYsHIhEvmF85tbIeFZWc8ZPtoMyybuEhL7Jye/ooC4/d48FgOjSJXgsF/AJPYCW8Zw==", + "dev": true, + "license": "MIT", + "dependencies": { + "ip-address": "^9.0.5", + "smart-buffer": "^4.2.0" + }, + "engines": { + "node": ">= 10.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/socks-proxy-agent": { + "version": "8.0.4", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.4.tgz", + "integrity": "sha512-GNAq/eg8Udq2x0eNiFkr9gRg5bA7PXEWagQdeRX4cPSG+X/8V38v637gim9bjFptMk1QWsCTr0ttrJEiXbNnRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "agent-base": "^7.1.1", + "debug": "^4.3.4", + "socks": "^2.8.3" + }, + "engines": { + "node": ">= 14" + } + }, "node_modules/source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", @@ -2423,6 +3386,13 @@ "source-map": "^0.6.0" } }, + "node_modules/sprintf-js": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", + "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==", + "dev": true, + "license": "BSD-3-Clause" + }, "node_modules/stdin-discarder": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/stdin-discarder/-/stdin-discarder-0.2.2.tgz", @@ -2434,6 +3404,21 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/streamx": { + "version": "2.18.0", + "resolved": "https://registry.npmjs.org/streamx/-/streamx-2.18.0.tgz", + "integrity": "sha512-LLUC1TWdjVdn1weXGcSxyTR3T4+acB6tVGXT95y0nGbca4t4o/ng1wKAGTljm9VicuCVLvRlqFYXYy5GwgM7sQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-fifo": "^1.3.2", + "queue-tick": "^1.0.1", + "text-decoder": "^1.1.0" + }, + "optionalDependencies": { + "bare-events": "^2.2.0" + } + }, "node_modules/string-width": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.1.0.tgz", @@ -2514,6 +3499,33 @@ "url": "https://github.com/chalk/supports-color?sponsor=1" } }, + "node_modules/tar-fs": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-3.0.6.tgz", + "integrity": "sha512-iokBDQQkUyeXhgPYaZxmczGPhnhXZ0CmrqI+MOb/WFGS9DW5wnfrLgtjUJBvz50vQ3qfRwJ62QVoCFu8mPVu5w==", + "dev": true, + "license": "MIT", + "dependencies": { + "pump": "^3.0.0", + "tar-stream": "^3.1.5" + }, + "optionalDependencies": { + "bare-fs": "^2.1.1", + "bare-path": "^2.1.0" + } + }, + "node_modules/tar-stream": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-3.1.7.tgz", + "integrity": "sha512-qJj60CXt7IU1Ffyc3NJMjh6EkuCFej46zUqJ4J7pqYlThyd9bO0XBTmcOIhSzZJVWfsLks0+nle/j538YAW9RQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "b4a": "^1.6.4", + "fast-fifo": "^1.2.0", + "streamx": "^2.15.0" + } + }, "node_modules/terser": { "version": "5.30.4", "resolved": "https://registry.npmjs.org/terser/-/terser-5.30.4.tgz", @@ -2538,12 +3550,29 @@ "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", "dev": true }, + "node_modules/text-decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/text-decoder/-/text-decoder-1.1.1.tgz", + "integrity": "sha512-8zll7REEv4GDD3x4/0pW+ppIxSNs7H1J10IKFZsuOMscumCdM2a+toDGLPA3T+1+fLBql4zbt5z83GEQGGV5VA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "b4a": "^1.6.4" + } + }, "node_modules/text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", "dev": true }, + "node_modules/through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", + "dev": true, + "license": "MIT" + }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -2557,27 +3586,26 @@ "node": ">=8.0" } }, - "node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true - }, - "node_modules/tsutils": { - "version": "3.21.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", - "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", + "node_modules/ts-api-utils": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz", + "integrity": "sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==", "dev": true, - "dependencies": { - "tslib": "^1.8.1" - }, + "license": "MIT", "engines": { - "node": ">= 6" + "node": ">=16" }, "peerDependencies": { - "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" + "typescript": ">=4.2.0" } }, + "node_modules/tslib": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz", + "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==", + "dev": true, + "license": "0BSD" + }, "node_modules/type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", @@ -2603,10 +3631,11 @@ } }, "node_modules/typescript": { - "version": "5.4.5", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.5.tgz", - "integrity": "sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==", + "version": "5.5.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.4.tgz", + "integrity": "sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==", "dev": true, + "license": "Apache-2.0", "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -2615,12 +3644,33 @@ "node": ">=14.17" } }, + "node_modules/unbzip2-stream": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.4.3.tgz", + "integrity": "sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg==", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer": "^5.2.1", + "through": "^2.3.8" + } + }, "node_modules/undici-types": { "version": "5.26.5", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", "dev": true }, + "node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } + }, "node_modules/uri-js": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", @@ -2630,6 +3680,13 @@ "punycode": "^2.1.0" } }, + "node_modules/urlpattern-polyfill": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/urlpattern-polyfill/-/urlpattern-polyfill-10.0.0.tgz", + "integrity": "sha512-H/A06tKD7sS1O1X2SshBVeA5FLycRpjqiBeqGKmBwBDBy28EnRjORxTNe269KSSr5un5qyWi1iL61wLxpd+ZOg==", + "dev": true, + "license": "MIT" + }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -2646,10 +3703,11 @@ } }, "node_modules/workerpool": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.1.tgz", - "integrity": "sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw==", - "dev": true + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.5.1.tgz", + "integrity": "sha512-Fs4dNYcsdpYSAfVxhnl1L5zTksjvOJxtC5hzMNl+1t9B8hTJTdKDyZ5ju7ztgPy+ft9tBFXoOlDNiOT9WUXZlA==", + "dev": true, + "license": "Apache-2.0" }, "node_modules/wrap-ansi": { "version": "7.0.0", @@ -2694,6 +3752,28 @@ "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", "dev": true }, + "node_modules/ws": { + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", + "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, "node_modules/y18n": { "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", @@ -2703,12 +3783,6 @@ "node": ">=10" } }, - "node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, "node_modules/yargs": { "version": "16.2.0", "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", @@ -2728,10 +3802,11 @@ } }, "node_modules/yargs-parser": { - "version": "20.2.4", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", - "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", "dev": true, + "license": "ISC", "engines": { "node": ">=10" } @@ -2771,6 +3846,17 @@ "node": ">=8" } }, + "node_modules/yauzl": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", + "integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer-crc32": "~0.2.3", + "fd-slicer": "~1.1.0" + } + }, "node_modules/yocto-queue": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", @@ -2783,9 +3869,19 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/zod": { + "version": "3.23.8", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.23.8.tgz", + "integrity": "sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + }, "packages/preview2-shim": { "name": "@bytecodealliance/preview2-shim", - "version": "0.16.2", + "version": "0.16.4", "license": "(Apache-2.0 WITH LLVM-exception)", "devDependencies": { "mocha": "^10.2.0" diff --git a/package.json b/package.json index 4ff15f42d..90904d561 100644 --- a/package.json +++ b/package.json @@ -1,14 +1,20 @@ { "name": "@golemcloud/jco", - "version": "1.2.4-golem.4", + "version": "1.4.0-golem.1", "description": "JavaScript tooling for working with WebAssembly Components", "author": "Guy Bedford", "bin": { "jco": "src/jco.js" }, "exports": { - "browser": "./src/browser.js", - "default": "./src/api.js" + ".": { + "browser": "./src/browser.js", + "default": "./src/api.js" + }, + "./component": { + "types": "./obj/js-component-bindgen-component.d.ts", + "default": "./src/browser.js" + } }, "imports": { "#ora": { @@ -18,8 +24,8 @@ }, "type": "module", "dependencies": { - "@bytecodealliance/preview2-shim": "^0.16.2", - "binaryen": "^116.0.0", + "@bytecodealliance/preview2-shim": "^0.16.4", + "binaryen": "^118.0.0", "chalk-template": "^1", "commander": "^12", "mkdirp": "^3", @@ -27,14 +33,16 @@ "terser": "^5" }, "devDependencies": { - "@golemcloud/componentize-js": "0.8.3-golem.2", - "@types/node": "^18.11.17", - "@typescript-eslint/eslint-plugin": "^5.41.0", - "@typescript-eslint/parser": "^5.41.0", - "eslint": "^8.30.0", - "mocha": "^10.2.0", + "@golemcloud/componentize-js": "0.10.2-golem.1", + "@types/node": "^20.14.12", + "@typescript-eslint/eslint-plugin": "^7.17.0", + "@typescript-eslint/parser": "^7.17.0", + "eslint": "^8.56.0", + "mime": "^4.0.4", + "mocha": "^10.7.0", + "puppeteer": "^22.14.0", "terser": "^5.16.1", - "typescript": "^5.3.3" + "typescript": "^5.5.4" }, "repository": { "type": "git", @@ -56,7 +64,7 @@ "build:types:preview2-shim": "cargo xtask generate wasi-types", "lint": "eslint -c eslintrc.cjs src/**/*.js packages/*/lib/**/*.js", "test:lts": "mocha -u tdd test/test.js --timeout 30000", - "test": "node --stack-trace-limit=100 --experimental-wasm-multi-memory node_modules/mocha/bin/mocha.js -u tdd test/test.js --timeout 30000", + "test": "node --stack-trace-limit=100 node_modules/mocha/bin/mocha.js -u tdd test/test.js --timeout 30000", "prepublishOnly": "cargo xtask build release && npm run test" }, "files": [ diff --git a/packages/preview2-shim/lib/nodejs/filesystem.js b/packages/preview2-shim/lib/nodejs/filesystem.js index b52870561..36ebaaffb 100644 --- a/packages/preview2-shim/lib/nodejs/filesystem.js +++ b/packages/preview2-shim/lib/nodejs/filesystem.js @@ -700,6 +700,13 @@ function convertFsError(e) { return "text-file-busy"; case "EXDEV": return "cross-device"; + case "UNKNOWN": + switch (e.errno) { + case -4094: + return "no-such-device"; + default: + throw e; + } default: throw e; } diff --git a/packages/preview2-shim/lib/nodejs/http.js b/packages/preview2-shim/lib/nodejs/http.js index 6fdb449ce..142ba5caa 100644 --- a/packages/preview2-shim/lib/nodejs/http.js +++ b/packages/preview2-shim/lib/nodejs/http.js @@ -262,7 +262,7 @@ class OutgoingRequest { if ( extra.length || (port !== undefined && - (portNum.toString() !== port || portNum > 9999)) || + (portNum.toString() !== port || portNum > 65535)) || !host.match(/^[a-zA-Z0-9-.]+$/) ) throw undefined; diff --git a/packages/preview2-shim/package.json b/packages/preview2-shim/package.json index a26f11a8d..6b1dbbd18 100644 --- a/packages/preview2-shim/package.json +++ b/packages/preview2-shim/package.json @@ -1,6 +1,6 @@ { "name": "@bytecodealliance/preview2-shim", - "version": "0.16.2", + "version": "0.16.4", "description": "WASI Preview2 shim for JS environments", "author": "Guy Bedford, Eduardo Rodrigues<16357187+eduardomourar@users.noreply.github.com>", "type": "module", diff --git a/src/browser.js b/src/browser.js index e134cde27..4023e6fb6 100644 --- a/src/browser.js +++ b/src/browser.js @@ -1,11 +1,14 @@ -import { $init, generate, generateTypes as _generateTypes } from '../obj/js-component-bindgen-component.js'; +import { $init, generate as _generate, generateTypes as _generateTypes } from '../obj/js-component-bindgen-component.js'; -export async function transpile () { +export async function generate () { await $init; - return generate.apply(this, arguments); + return _generate.apply(this, arguments); } export async function generateTypes () { await $init; return _generateTypes.apply(this, arguments); } + +// for backwards compat +export { generate as transpile } diff --git a/src/cmd/transpile.js b/src/cmd/transpile.js index 91e9765a6..1eef32343 100644 --- a/src/cmd/transpile.js +++ b/src/cmd/transpile.js @@ -101,7 +101,7 @@ async function wasm2Js (source) { * @param {{ * name: string, * instantiation?: 'async' | 'sync', - * importBindings?: 'js' | 'optimized', 'hybrid', 'direct-optimized', + * importBindings?: 'js' | 'optimized' | 'hybrid' | 'direct-optimized', * map?: Record, * validLiftingOptimization?: bool, * tracing?: bool, @@ -114,6 +114,7 @@ async function wasm2Js (source) { * namespacedExports?: bool, * outDir?: string, * multiMemory?: bool, + * experimentalIdlImports?: bool, * optArgs?: string[], * }} opts * @returns {Promise<{ files: { [filename: string]: Uint8Array }, imports: string[], exports: [string, 'function' | 'instance'][] }>} @@ -165,6 +166,7 @@ export async function transpileComponent (component, opts = {}) { base64Cutoff: opts.js ? 0 : opts.base64Cutoff ?? 5000, noNamespacedExports: opts.namespacedExports === false, multiMemory: opts.multiMemory === true, + idlImports: opts.experimentalIdlImports === true, }); let outDir = (opts.outDir ?? '').replace(/\\/g, '/'); diff --git a/src/jco.js b/src/jco.js index 129925aae..2035fb17a 100755 --- a/src/jco.js +++ b/src/jco.js @@ -12,7 +12,7 @@ program .name('jco') .description(c`{bold jco - WebAssembly JS Component Tools}\n JS Component Transpilation Bindgen & Wasm Tools for JS`) .usage(' [options]') - .version('1.2.4'); + .version('1.4.0'); function myParseInt(value) { return parseInt(value, 10); @@ -24,7 +24,7 @@ program.command('componentize') .argument('', 'JS source file to build') .requiredOption('-w, --wit ', 'WIT path to build with') .option('-n, --world-name ', 'WIT world to build') - .addOption(new Option('-d, --disable ', 'disable WASI features').choices(['stdio', 'random', 'clocks'])) + .addOption(new Option('-d, --disable ', 'disable WASI features').choices(['stdio', 'random', 'clocks', 'http'])) .option('--preview2-adapter ', 'provide a custom preview2 adapter path') .requiredOption('-o, --out ', 'output component file') .action(asyncAction(componentize)); diff --git a/submodules/WASI-Virt b/submodules/WASI-Virt index 45a4a3f18..3da2d1810 160000 --- a/submodules/WASI-Virt +++ b/submodules/WASI-Virt @@ -1 +1 @@ -Subproject commit 45a4a3f18dc352a8240470a9caf32716efe91666 +Subproject commit 3da2d1810db33278acaabf3c9191c952f6483a97 diff --git a/submodules/wasm-tools b/submodules/wasm-tools index 7589b29dd..fafea31f7 160000 --- a/submodules/wasm-tools +++ b/submodules/wasm-tools @@ -1 +1 @@ -Subproject commit 7589b29dd9dc973ae4380c54039c1d380fc1e566 +Subproject commit fafea31f7f0250c051ca22ca346997bccc1ccdfb diff --git a/submodules/wasmtime b/submodules/wasmtime index b104bf24a..81ffc5a28 160000 --- a/submodules/wasmtime +++ b/submodules/wasmtime @@ -1 +1 @@ -Subproject commit b104bf24a9ef240fbc06808fd840f14872814809 +Subproject commit 81ffc5a28259145c11982504dd3d53f1fe90b1de diff --git a/submodules/wit-bindgen b/submodules/wit-bindgen index 3452d7807..0977e2540 160000 --- a/submodules/wit-bindgen +++ b/submodules/wit-bindgen @@ -1 +1 @@ -Subproject commit 3452d7807716cd37b5400e2dced55651d13f65f9 +Subproject commit 0977e254014581e4f65de07b7b2df1d47c2e913b diff --git a/test/api.js b/test/api.js index a728dae69..51794c9ec 100644 --- a/test/api.js +++ b/test/api.js @@ -24,7 +24,7 @@ export async function apiTest(fixtures) { `test/fixtures/components/${name}.component.wasm` ); const { files, imports, exports } = await transpile(component, { name }); - strictEqual(imports.length, 2); + strictEqual(imports.length, 4); strictEqual(exports.length, 3); deepStrictEqual(exports[0], ["test", "instance"]); ok(files[name + ".js"]); @@ -43,10 +43,10 @@ export async function apiTest(fixtures) { optimize: true, base64Cutoff: 0, }); - strictEqual(imports.length, 2); + strictEqual(imports.length, 4); strictEqual(exports.length, 3); deepStrictEqual(exports[0], ["test", "instance"]); - ok(files[name + ".js"].length < 11_000); + ok(files[name + ".js"].length < 28_000); }); test("Transpile to JS", async () => { @@ -56,7 +56,7 @@ export async function apiTest(fixtures) { ); const { files, imports, exports } = await transpile(component, { map: { - "test*": "./*.js", + "test:flavorful/*": "./*.js", }, name, validLiftingOptimization: true, @@ -64,14 +64,13 @@ export async function apiTest(fixtures) { base64Cutoff: 0, js: true, }); - strictEqual(imports.length, 2); + strictEqual(imports.length, 4); strictEqual(exports.length, 3); deepStrictEqual(exports[0], ["test", "instance"]); deepStrictEqual(exports[1], ["test:flavorful/test", "instance"]); deepStrictEqual(exports[2], ["testImports", "function"]); const source = Buffer.from(files[name + ".js"]).toString(); - ok(source.includes("./wasi.js")); - ok(source.includes("testwasi")); + ok(source.includes("./test.js")); ok(source.includes("FUNCTION_TABLE")); for (let i = 0; i < 2; i++) ok(source.includes(exports[i][0])); }); @@ -87,7 +86,7 @@ export async function apiTest(fixtures) { "test:flavorful/*": "#*import", }, }); - strictEqual(imports.length, 2); + strictEqual(imports.length, 4); strictEqual(imports[0], "#testimport"); const source = Buffer.from(files[name + ".js"]).toString(); ok(source.includes("'#testimport'")); @@ -155,7 +154,7 @@ export async function apiTest(fixtures) { [ "processed-by", [ - ["wit-component", "0.202.0"], + ["wit-component", "0.212.0"], ["dummy-gen", "test"], ], ], @@ -196,7 +195,7 @@ export async function apiTest(fixtures) { [ "processed-by", [ - ["wit-component", "0.202.0"], + ["wit-component", "0.212.0"], ["dummy-gen", "test"], ], ], diff --git a/test/browser.html b/test/browser.html index 26d67bd91..f1250eac7 100644 --- a/test/browser.html +++ b/test/browser.html @@ -22,31 +22,60 @@ import "@bytecodealliance/preview2-shim/io"; import "@bytecodealliance/preview2-shim/random"; import "@bytecodealliance/preview2-shim/sockets"; - + import { transpile } from 'jco'; - const componentUrl = new URL('./fixtures/components/lists.component.wasm', import.meta.url); - document.body.innerHTML = '

Generating...

'; - const component = await (await fetch(componentUrl)).arrayBuffer(); - const output = await transpile(component, { - name: 'test', - noTypescript: true, - noNodejsCompat: true, - instantiation: { tag: 'async' }, - // force baseurls - // todo: support a hook for inline blob url construction - base64Cutoff: 1000000, - map: [ - ['wasi:cli/*', '@bytecodealliance/preview2-shim/cli#*'], - ['wasi:clocks/*', '@bytecodealliance/preview2-shim/clocks#*'], - ['wasi:filesystem/*', '@bytecodealliance/preview2-shim/filesystem#*'], - ['wasi:http/*', '@bytecodealliance/preview2-shim/http#*'], - ['wasi:io/*', '@bytecodealliance/preview2-shim/io#*'], - ['wasi:random/*', '@bytecodealliance/preview2-shim/random#*'], - ['wasi:sockets/*', '@bytecodealliance/preview2-shim/sockets#*'] - ] - }); - const source = output.files[4][1]; - const url = URL.createObjectURL(new Blob([source], { type: 'text/javascript' })); - const mod = await import(url); - document.body.innerHTML = '

OK

'; - \ No newline at end of file + const testName = window.location.hash.slice(1); + document.body.innerHTML = '

Running

'; + switch (testName) { + case 'transpile': { + const componentUrl = new URL('./fixtures/components/lists.component.wasm', import.meta.url); + const component = await (await fetch(componentUrl)).arrayBuffer(); + const output = await transpile(component, { + name: 'test', + noTypescript: true, + noNodejsCompat: true, + instantiation: { tag: 'async' }, + // force baseurls + // todo: support a hook for inline blob url construction + base64Cutoff: 1000000, + map: [ + ['wasi:cli/*', '@bytecodealliance/preview2-shim/cli#*'], + ['wasi:clocks/*', '@bytecodealliance/preview2-shim/clocks#*'], + ['wasi:filesystem/*', '@bytecodealliance/preview2-shim/filesystem#*'], + ['wasi:http/*', '@bytecodealliance/preview2-shim/http#*'], + ['wasi:io/*', '@bytecodealliance/preview2-shim/io#*'], + ['wasi:random/*', '@bytecodealliance/preview2-shim/random#*'], + ['wasi:sockets/*', '@bytecodealliance/preview2-shim/sockets#*'] + ] + }); + const source = output.files[4][1]; + const url = URL.createObjectURL(new Blob([source], { type: 'text/javascript' })); + const mod = await import(url); + ok(); + break; + } + default: { + if (testName.startsWith('test:')) { + const testModule = `/tmpdir/${testName.slice(5)}`; + try { + const mod = await import(testModule); + if (!mod.test) + throw new Error(`Expected test module "${testModule}" to export a "test" function`); + mod.test(); + ok(); + } catch (e) { + err(e.toString() + `\nrunning "${testModule}"`); + } + } else { + err(`Unknown test case "${testName}"`); + } + } + } + + function ok () { + document.body.innerHTML = '

OK

'; + } + function err (e) { + document.body.innerHTML = `

Error: ${e}`; + } + diff --git a/test/browser.js b/test/browser.js new file mode 100644 index 000000000..4bb797014 --- /dev/null +++ b/test/browser.js @@ -0,0 +1,167 @@ +// import { deepStrictEqual, ok, strictEqual } from "node:assert"; +import puppeteer from "puppeteer"; +import { mkdir, readFile, writeFile, rm, symlink, mkdtemp } from "node:fs/promises"; +import { createServer } from "node:http"; +import { fileURLToPath, pathToFileURL } from "url"; +import { tmpdir } from "node:os"; +import { resolve, normalize, sep, extname, dirname } from "node:path"; +import { ok, strictEqual } from "node:assert"; +import { transpile } from '../src/api.js'; +import mime from 'mime'; +import { exec, jcoPath } from "./helpers.js"; + +export async function browserTest() { + suite("Browser", () => { + /** + * Securely creates a temporary directory and returns its path. + * + * The new directory is created using `fsPromises.mkdtemp()`. + */ + async function getTmpDir() { + return await mkdtemp(normalize(tmpdir() + sep)); + } + + let tmpDir, outDir, outFile, outDirUrl; + let server, browser; + suiteSetup(async function () { + tmpDir = await getTmpDir(); + outDir = resolve(tmpDir, "out-component-dir"); + outDirUrl = pathToFileURL(outDir + '/'); + outFile = resolve(tmpDir, "out-component-file"); + + const modulesDir = resolve(tmpDir, "node_modules", "@bytecodealliance"); + await mkdir(modulesDir, { recursive: true }); + await symlink( + fileURLToPath(new URL("../packages/preview2-shim", import.meta.url)), + resolve(modulesDir, "preview2-shim"), + "dir" + ); + + // run a local server on 8080 + server = createServer(async (req, res) => { + let fileUrl; + if (req.url.startsWith('/tmpdir/')) { + fileUrl = new URL(`.${req.url.slice(7)}`, outDirUrl); + } else { + fileUrl = new URL(`../${req.url}`, import.meta.url); + } + try { + const html = await readFile(fileUrl); + res.writeHead(200, { 'content-type': mime.getType(extname(req.url)) }); + res.end(html); + } catch (e) { + if (e.code === 'ENOENT') { + res.writeHead(404); + res.end(e.message); + } else { + res.writeHead(500); + res.end(e.message); + } + } + }).listen(8080); + + browser = await puppeteer.launch(); + }); + suiteTeardown(async function () { + try { + await rm(tmpDir, { recursive: true }); + } catch {} + await browser.close(); + await new Promise((resolve) => server.close(resolve)); + }); + + teardown(async function () { + try { + await rm(outDir, { recursive: true }); + await rm(outFile); + } catch {} + }); + + async function testBrowserPage (hash) { + const page = await browser.newPage(); + ok((await page.goto(`http://localhost:8080/test/browser.html#${hash}`)).ok()); + + const body = await page.locator('body').waitHandle(); + + let bodyHtml = await body.evaluate(el => el.innerHTML); + while (bodyHtml === '

Running

') { + bodyHtml = await body.evaluate(el => el.innerHTML); + } + strictEqual(bodyHtml, '

OK

'); + await page.close(); + } + + test("Transpilation", async () => { + await testBrowserPage('transpile'); + }); + + test('IDL window', async () => { + // Componentize the webidl DOM window test + const { stdout: _, stderr } = await exec( + jcoPath, + "componentize", + "test/fixtures/idl/dom.test.js", + "-d", + "clocks", + "-d", + "random", + "-d", + "stdio", + "-w", + "test/fixtures/idl/dom.wit", + "-n", + "window-test", + "-o", + outFile + ); + strictEqual(stderr, ''); + + // Transpile the test component + const component = await readFile(outFile); + const { files } = await transpile(component, { name: 'dom' }); + + for (const [file, source] of Object.entries(files)) { + const outPath = resolve(outDir, file); + await mkdir(dirname(outPath), { recursive: true }); + await writeFile(outPath, source); + } + + // Run the test function in the browser from the generated tmpdir + await testBrowserPage('test:dom.js'); + }); + + test('IDL console', async () => { + // Componentize the webidl DOM window test + const { stdout: _, stderr } = await exec( + jcoPath, + "componentize", + "test/fixtures/idl/console.test.js", + "-d", + "clocks", + "-d", + "random", + "-d", + "stdio", + "-w", + "test/fixtures/idl/console.wit", + "-n", + "console-test", + "-o", + outFile + ); + strictEqual(stderr, ''); + + // Transpile the test component + const component = await readFile(outFile); + const { files } = await transpile(component, { name: 'console' }); + + for (const [file, source] of Object.entries(files)) { + const outPath = resolve(outDir, file); + await mkdir(dirname(outPath), { recursive: true }); + await writeFile(outPath, source); + } + + await testBrowserPage('test:console.js'); + }); + }); +} diff --git a/test/cli.js b/test/cli.js index 5b156e689..e735b2f9c 100644 --- a/test/cli.js +++ b/test/cli.js @@ -9,7 +9,7 @@ import { } from "node:fs/promises"; import { fileURLToPath, pathToFileURL } from "url"; import { exec, jcoPath } from "./helpers.js"; -import { tmpdir, EOL } from "node:os"; +import { tmpdir } from "node:os"; import { resolve, normalize, sep } from "node:path"; import { execArgv } from "node:process"; @@ -228,7 +228,7 @@ export async function cliTest(fixtures) { "--name", name, "--map", - "testwasi=./wasi.js", + "test:flavorful/test=./flavorful.js", "--valid-lifting-optimization", "--tla-compat", "--js", @@ -238,8 +238,7 @@ export async function cliTest(fixtures) { ); strictEqual(stderr, ""); const source = await readFile(`${outDir}/${name}.js`, "utf8"); - ok(source.includes("./wasi.js")); - ok(source.includes("testwasi")); + ok(source.includes("./flavorful.js")); ok(source.includes("FUNCTION_TABLE")); ok(source.includes("export {\n $init")); }); @@ -413,7 +412,7 @@ export async function cliTest(fixtures) { [ "processed-by", [ - ["wit-component", "0.202.0"], + ["wit-component", "0.212.0"], ["dummy-gen", "test"], ], ], diff --git a/test/eslintrc.cjs b/test/eslintrc.cjs index 5fbdc8405..584f4f70c 100644 --- a/test/eslintrc.cjs +++ b/test/eslintrc.cjs @@ -14,6 +14,7 @@ module.exports = { "no-empty-pattern": 0, // TODO: we generate some unused functions by accident, let's fix that later "no-unused-vars": 0, - "no-sparse-arrays": 0 + "no-sparse-arrays": 0, + "require-yield": 0 } }; diff --git a/test/fixtures/component-gen/import-fn.wit b/test/fixtures/component-gen/import-fn.wit index 9e578765d..ac7bb5c24 100644 --- a/test/fixtures/component-gen/import-fn.wit +++ b/test/fixtures/component-gen/import-fn.wit @@ -1,4 +1,4 @@ -package example:protocol +package example:protocol; world my-world { record point { @@ -6,9 +6,9 @@ world my-world { y: s32, } - import print: func(msg: string) - import import-point: func(pnt: point) -> point + import print: func(msg: string); + import import-point: func(pnt: point) -> point; - export run: func() - export move-point: func(pnt: point) -> point + export run: func(); + export move-point: func(pnt: point) -> point; } diff --git a/test/fixtures/components/borrowing-duplicate-if-necessary.component.wasm b/test/fixtures/components/borrowing-duplicate-if-necessary.component.wasm index 4a290862b..080bb16cd 100644 Binary files a/test/fixtures/components/borrowing-duplicate-if-necessary.component.wasm and b/test/fixtures/components/borrowing-duplicate-if-necessary.component.wasm differ diff --git a/test/fixtures/components/borrowing.component.wasm b/test/fixtures/components/borrowing.component.wasm index 750046bbd..079b9c6c2 100644 Binary files a/test/fixtures/components/borrowing.component.wasm and b/test/fixtures/components/borrowing.component.wasm differ diff --git a/test/fixtures/components/flavorful.component.wasm b/test/fixtures/components/flavorful.component.wasm index 9caaf83fb..81707edca 100644 Binary files a/test/fixtures/components/flavorful.component.wasm and b/test/fixtures/components/flavorful.component.wasm differ diff --git a/test/fixtures/components/import-fn.component.wasm b/test/fixtures/components/import-fn.component.wasm index 72d087456..ec0f4bf18 100644 Binary files a/test/fixtures/components/import-fn.component.wasm and b/test/fixtures/components/import-fn.component.wasm differ diff --git a/test/fixtures/components/lists.component.wasm b/test/fixtures/components/lists.component.wasm index d698bb770..b31035f18 100644 Binary files a/test/fixtures/components/lists.component.wasm and b/test/fixtures/components/lists.component.wasm differ diff --git a/test/fixtures/components/many-arguments.component.wasm b/test/fixtures/components/many-arguments.component.wasm index 6fd4a5deb..ee1359b7a 100644 Binary files a/test/fixtures/components/many-arguments.component.wasm and b/test/fixtures/components/many-arguments.component.wasm differ diff --git a/test/fixtures/components/many_arguments.component.wasm b/test/fixtures/components/many_arguments.component.wasm index d1036288e..24bd58aea 100644 Binary files a/test/fixtures/components/many_arguments.component.wasm and b/test/fixtures/components/many_arguments.component.wasm differ diff --git a/test/fixtures/components/numbers.component.wasm b/test/fixtures/components/numbers.component.wasm index 0c4353d35..a4c4eec3c 100644 Binary files a/test/fixtures/components/numbers.component.wasm and b/test/fixtures/components/numbers.component.wasm differ diff --git a/test/fixtures/components/owning.component.wasm b/test/fixtures/components/owning.component.wasm index d9c1a7c7b..e3d6371a0 100644 Binary files a/test/fixtures/components/owning.component.wasm and b/test/fixtures/components/owning.component.wasm differ diff --git a/test/fixtures/components/records.component.wasm b/test/fixtures/components/records.component.wasm index 7d21b2982..38eed41e1 100644 Binary files a/test/fixtures/components/records.component.wasm and b/test/fixtures/components/records.component.wasm differ diff --git a/test/fixtures/components/smoke.component.wasm b/test/fixtures/components/smoke.component.wasm index a716f81b7..c967df4f6 100644 Binary files a/test/fixtures/components/smoke.component.wasm and b/test/fixtures/components/smoke.component.wasm differ diff --git a/test/fixtures/components/strings.component.wasm b/test/fixtures/components/strings.component.wasm index 3ee01a8f8..938f0d895 100644 Binary files a/test/fixtures/components/strings.component.wasm and b/test/fixtures/components/strings.component.wasm differ diff --git a/test/fixtures/components/variants.component.wasm b/test/fixtures/components/variants.component.wasm index ab9c269a8..c62e673fa 100644 Binary files a/test/fixtures/components/variants.component.wasm and b/test/fixtures/components/variants.component.wasm differ diff --git a/test/fixtures/idl/console.test.js b/test/fixtures/idl/console.test.js new file mode 100644 index 000000000..1a394ed05 --- /dev/null +++ b/test/fixtures/idl/console.test.js @@ -0,0 +1,5 @@ +import { log } from 'webidl:console/global-console@0.0.1'; + +export function test() { + log(['HI']); +} diff --git a/test/fixtures/idl/console.webidl b/test/fixtures/idl/console.webidl new file mode 100644 index 000000000..722b89661 --- /dev/null +++ b/test/fixtures/idl/console.webidl @@ -0,0 +1,29 @@ +[Exposed=*] +interface console { // but see namespace object requirements below + // Logging + undefined assert(optional boolean condition = false, DOMString... data); + undefined clear(); + undefined debug(DOMString... data); + undefined error(DOMString... data); + undefined info(DOMString... data); + undefined log(DOMString... data); + undefined table(optional DOMString tabularData, optional sequence properties); + undefined trace(DOMString... data); + undefined warn(DOMString... data); + undefined dir(optional DOMString item); + undefined dirxml(DOMString... data); + + // Counting + undefined count(optional DOMString label = "default"); + undefined countReset(optional DOMString label = "default"); + + // Grouping + undefined group(DOMString... data); + undefined groupCollapsed(DOMString... data); + undefined groupEnd(); + + // Timing + undefined time(optional DOMString label = "default"); + undefined timeLog(optional DOMString label = "default", DOMString... data); + undefined timeEnd(optional DOMString label = "default"); +}; \ No newline at end of file diff --git a/test/fixtures/idl/console.wit b/test/fixtures/idl/console.wit new file mode 100644 index 000000000..2916aecf1 --- /dev/null +++ b/test/fixtures/idl/console.wit @@ -0,0 +1,30 @@ + + package webidl:console@0.0.1; + +interface global-console { + assert: func(condition: option, data: list); + clear: func(); + debug: func(data: list); + error: func(data: list); + info: func(data: list); + log: func(data: list); + table: func(tabular-data: option, properties: option>); + trace: func(data: list); + warn: func(data: list); + dir: func(item: option); + dirxml: func(data: list); + count: func(label: option); + count-reset: func(label: option); + group: func(data: list); + group-collapsed: func(data: list); + group-end: func(); + time: func(label: option); + time-log: func(label: option, data: list); + time-end: func(label: option); +} + + world console-test { + import global-console; + export test: func(); + } + \ No newline at end of file diff --git a/test/fixtures/idl/dom.test.js b/test/fixtures/idl/dom.test.js new file mode 100644 index 000000000..0c55533a9 --- /dev/null +++ b/test/fixtures/idl/dom.test.js @@ -0,0 +1,7 @@ +import { getWindow } from 'webidl:dom/dom@0.0.1'; + +export function test() { + const window = getWindow(); + window.document().body().setInnerHtml('

hello world

'); + window.console().log(["HI"]); +} diff --git a/test/fixtures/idl/dom.webidl b/test/fixtures/idl/dom.webidl new file mode 100644 index 000000000..4f16445dd --- /dev/null +++ b/test/fixtures/idl/dom.webidl @@ -0,0 +1,518 @@ +[Exposed=*] +interface console { // but see namespace object requirements below + // Logging + undefined assert(optional boolean condition = false, DOMString... data); + undefined clear(); + undefined debug(DOMString... data); + undefined error(DOMString... data); + undefined info(DOMString... data); + undefined log(DOMString... data); + undefined table(optional DOMString tabularData, optional sequence properties); + undefined trace(DOMString... data); + undefined warn(DOMString... data); + undefined dir(optional DOMString item); + undefined dirxml(DOMString... data); + + // Counting + undefined count(optional DOMString label = "default"); + undefined countReset(optional DOMString label = "default"); + + // Grouping + undefined group(DOMString... data); + undefined groupCollapsed(DOMString... data); + undefined groupEnd(); + + // Timing + undefined time(optional DOMString label = "default"); + undefined timeLog(optional DOMString label = "default", DOMString... data); + undefined timeEnd(optional DOMString label = "default"); +}; + +interface Node : EventTarget { + // const unsigned short ELEMENT_NODE = 1; + // const unsigned short ATTRIBUTE_NODE = 2; + // const unsigned short TEXT_NODE = 3; + // const unsigned short CDATA_SECTION_NODE = 4; + // const unsigned short ENTITY_REFERENCE_NODE = 5; // legacy + // const unsigned short ENTITY_NODE = 6; // legacy + // const unsigned short PROCESSING_INSTRUCTION_NODE = 7; + // const unsigned short COMMENT_NODE = 8; + // const unsigned short DOCUMENT_NODE = 9; + // const unsigned short DOCUMENT_TYPE_NODE = 10; + // const unsigned short DOCUMENT_FRAGMENT_NODE = 11; + // const unsigned short NOTATION_NODE = 12; // legacy + readonly attribute unsigned short nodeType; + readonly attribute DOMString nodeName; + + readonly attribute USVString baseURI; + + readonly attribute boolean isConnected; + readonly attribute Document? ownerDocument; + Node getRootNode(optional GetRootNodeOptions options = {}); + readonly attribute Node? parentNode; + readonly attribute Element? parentElement; + boolean hasChildNodes(); + [SameObject] readonly attribute NodeList childNodes; + readonly attribute Node? firstChild; + readonly attribute Node? lastChild; + readonly attribute Node? previousSibling; + readonly attribute Node? nextSibling; + + [CEReactions] attribute DOMString? nodeValue; + [CEReactions] attribute DOMString? textContent; + [CEReactions] undefined normalize(); + + [CEReactions, NewObject] Node cloneNode(optional boolean deep = false); + boolean isEqualNode(Node? otherNode); + boolean isSameNode(Node? otherNode); // legacy alias of === + + // const unsigned short DOCUMENT_POSITION_DISCONNECTED = 0x01; + // const unsigned short DOCUMENT_POSITION_PRECEDING = 0x02; + // const unsigned short DOCUMENT_POSITION_FOLLOWING = 0x04; + // const unsigned short DOCUMENT_POSITION_CONTAINS = 0x08; + // const unsigned short DOCUMENT_POSITION_CONTAINED_BY = 0x10; + // const unsigned short DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC = 0x20; + unsigned short compareDocumentPosition(Node other); + boolean contains(Node? other); + + DOMString? lookupPrefix(DOMString? namespace); + DOMString? lookupNamespaceURI(DOMString? prefix); + boolean isDefaultNamespace(DOMString? namespace); + + [CEReactions] Node insertBefore(Node node, Node? child); + [CEReactions] Node appendChild(Node node); + [CEReactions] Node replaceChild(Node node, Node child); + [CEReactions] Node removeChild(Node child); +}; + +dictionary GetRootNodeOptions { + boolean composed = false; +}; + +[Exposed=Window] +interface Element : Node { + readonly attribute DOMString? namespaceURI; + readonly attribute DOMString? prefix; + readonly attribute DOMString localName; + readonly attribute DOMString tagName; + + [CEReactions] attribute DOMString id; + [CEReactions] attribute DOMString className; + [SameObject, PutForwards=value] readonly attribute DOMTokenList classList; + [CEReactions, Unscopable] attribute DOMString slot; + + boolean hasAttributes(); + [SameObject] readonly attribute NamedNodeMap attributes; + sequence getAttributeNames(); + DOMString? getAttribute(DOMString qualifiedName); + DOMString? getAttributeNS(DOMString? namespace, DOMString localName); + [CEReactions] undefined setAttribute(DOMString qualifiedName, DOMString value); + [CEReactions] undefined setAttributeNS(DOMString? namespace, DOMString qualifiedName, DOMString value); + [CEReactions] undefined removeAttribute(DOMString qualifiedName); + [CEReactions] undefined removeAttributeNS(DOMString? namespace, DOMString localName); + [CEReactions] boolean toggleAttribute(DOMString qualifiedName, optional boolean force); + boolean hasAttribute(DOMString qualifiedName); + boolean hasAttributeNS(DOMString? namespace, DOMString localName); + + Attr? getAttributeNode(DOMString qualifiedName); + Attr? getAttributeNodeNS(DOMString? namespace, DOMString localName); + [CEReactions] Attr? setAttributeNode(Attr attr); + [CEReactions] Attr? setAttributeNodeNS(Attr attr); + [CEReactions] Attr removeAttributeNode(Attr attr); + + ShadowRoot attachShadow(ShadowRootInit init); + readonly attribute ShadowRoot? shadowRoot; + + Element? closest(DOMString selectors); + boolean matches(DOMString selectors); + boolean webkitMatchesSelector(DOMString selectors); // legacy alias of .matches + + HTMLCollection getElementsByTagName(DOMString qualifiedName); + HTMLCollection getElementsByTagNameNS(DOMString? namespace, DOMString localName); + HTMLCollection getElementsByClassName(DOMString classNames); + + [CEReactions] Element? insertAdjacentElement(DOMString where, Element element); // legacy + undefined insertAdjacentText(DOMString where, DOMString data); // legacy +}; + +dictionary ShadowRootInit { + required ShadowRootMode mode; + boolean delegatesFocus = false; + SlotAssignmentMode slotAssignment = "named"; + boolean clonable = false; + boolean serializable = false; +}; + +[Exposed=Window] +interface ShadowRoot : DocumentFragment { + readonly attribute ShadowRootMode mode; + readonly attribute boolean delegatesFocus; + readonly attribute SlotAssignmentMode slotAssignment; + readonly attribute boolean clonable; + readonly attribute boolean serializable; + readonly attribute Element host; + // attribute EventHandler onslotchange; +}; + +enum ShadowRootMode { "open", "closed" }; +enum SlotAssignmentMode { "manual", "named" }; + +[Exposed=Window] +interface DocumentFragment : Node { + constructor(); +}; + +interface mixin HTMLOrSVGElement { + [SameObject] readonly attribute DOMStringMap dataset; + attribute DOMString nonce; // intentionally no [CEReactions] + + [CEReactions] attribute boolean autofocus; + [CEReactions] attribute long tabIndex; + undefined focus(optional FocusOptions options = {}); + undefined blur(); +}; + +[Exposed=Window] +interface HTMLElement : Element { + [HTMLConstructor] constructor(); + + // metadata attributes + [CEReactions] attribute DOMString title; + [CEReactions] attribute DOMString lang; + [CEReactions] attribute boolean translate; + [CEReactions] attribute DOMString dir; + + // user interaction + [CEReactions] attribute (boolean or unrestricted double or DOMString)? hidden; + [CEReactions] attribute boolean inert; + undefined click(); + [CEReactions] attribute DOMString accessKey; + readonly attribute DOMString accessKeyLabel; + [CEReactions] attribute boolean draggable; + [CEReactions] attribute boolean spellcheck; + [CEReactions] attribute DOMString writingSuggestions; + [CEReactions] attribute DOMString autocapitalize; + + [CEReactions] attribute [LegacyNullToEmptyString] DOMString innerText; + [CEReactions] attribute [LegacyNullToEmptyString] DOMString outerText; + + // For some reason this is just not in IDL??? + [CEReactions] attribute [LegacyNullToEmptyString] DOMString innerHTML; + + ElementInternals attachInternals(); + + // The popover API + undefined showPopover(); + undefined hidePopover(); + boolean togglePopover(optional boolean force); + [CEReactions] attribute DOMString? popover; +}; + +[Exposed=Window] +interface ElementInternals { + // Shadow root access + readonly attribute ShadowRoot? shadowRoot; + + // Form-associated custom elements + undefined setFormValue((/*File or */USVString or FormData)? value, + optional (/*File or */USVString or FormData)? state); + + // readonly attribute HTMLFormElement? form; + + undefined setValidity(optional ValidityStateFlags flags = {}, + optional DOMString message, + optional HTMLElement anchor); + readonly attribute boolean willValidate; + readonly attribute ValidityState validity; + readonly attribute DOMString validationMessage; + boolean checkValidity(); + boolean reportValidity(); + + readonly attribute NodeList labels; + + // Custom state pseudo-class + // [SameObject] readonly attribute CustomStateSet states; +}; + +[Exposed=Window] +interface ValidityState { + readonly attribute boolean valueMissing; + readonly attribute boolean typeMismatch; + readonly attribute boolean patternMismatch; + readonly attribute boolean tooLong; + readonly attribute boolean tooShort; + readonly attribute boolean rangeUnderflow; + readonly attribute boolean rangeOverflow; + readonly attribute boolean stepMismatch; + readonly attribute boolean badInput; + readonly attribute boolean customError; + readonly attribute boolean valid; +}; + +typedef (/*File or */USVString) FormDataEntryValue; + +[Exposed=(Window,Worker)] +interface FormData { + constructor(/*optional HTMLFormElement form, optional HTMLElement? submitter = null*/); + + undefined append(USVString name, USVString value); + // undefined append(USVString name, Blob blobValue, optional USVString filename); + undefined delete(USVString name); + FormDataEntryValue? get(USVString name); + sequence getAll(USVString name); + boolean has(USVString name); + undefined set(USVString name, USVString value); + // undefined set(USVString name, Blob blobValue, optional USVString filename); + // iterable; +}; + +// Accessibility semantics +// ElementInternals includes ARIAMixin; + +dictionary ValidityStateFlags { + boolean valueMissing = false; + boolean typeMismatch = false; + boolean patternMismatch = false; + boolean tooLong = false; + boolean tooShort = false; + boolean rangeUnderflow = false; + boolean rangeOverflow = false; + boolean stepMismatch = false; + boolean badInput = false; + boolean customError = false; +}; + +[Exposed=Window] +interface HTMLUnknownElement : HTMLElement { + // Note: intentionally no [HTMLConstructor] +}; + +enum DocumentReadyState { "loading", "interactive", "complete" }; +enum DocumentVisibilityState { "visible", "hidden" }; +// typedef (HTMLScriptElement or SVGScriptElement) HTMLOrSVGScriptElement; + +[Exposed=Window] +interface HTMLScriptElement : HTMLElement { + [HTMLConstructor] constructor(); + + [CEReactions] attribute USVString src; + [CEReactions] attribute DOMString type; + [CEReactions] attribute boolean noModule; + [CEReactions] attribute boolean async; + [CEReactions] attribute boolean defer; + [CEReactions] attribute DOMString? crossOrigin; + [CEReactions] attribute DOMString text; + [CEReactions] attribute DOMString integrity; + [CEReactions] attribute DOMString referrerPolicy; + [SameObject, PutForwards=value] readonly attribute DOMTokenList blocking; + [CEReactions] attribute DOMString fetchPriority; + + static boolean supports(DOMString type); + + // also has obsolete members +}; + +[Exposed=Window] +interface HTMLHeadElement : HTMLElement { + [HTMLConstructor] constructor(); +}; + +[Exposed=(Window,Worker)] +interface DOMStringList { + readonly attribute unsigned long length; + getter DOMString? item(unsigned long index); + boolean contains(DOMString string); +}; + +[Exposed=Window] +interface Location { // but see also additional creation steps and overridden internal methods + [LegacyUnforgeable] stringifier attribute USVString href; + [LegacyUnforgeable] readonly attribute USVString origin; + [LegacyUnforgeable] attribute USVString protocol; + [LegacyUnforgeable] attribute USVString host; + [LegacyUnforgeable] attribute USVString hostname; + [LegacyUnforgeable] attribute USVString port; + [LegacyUnforgeable] attribute USVString pathname; + [LegacyUnforgeable] attribute USVString search; + [LegacyUnforgeable] attribute USVString hash; + + [LegacyUnforgeable] undefined assign(USVString url); + [LegacyUnforgeable] undefined replace(USVString url); + [LegacyUnforgeable] undefined reload(); + + [LegacyUnforgeable, SameObject] readonly attribute DOMStringList ancestorOrigins; +}; + +[LegacyOverrideBuiltIns] +interface Document { + static Document parseHTMLUnsafe((DOMString) html); + + // resource metadata management + [PutForwards=href, LegacyUnforgeable] readonly attribute Location? location; + attribute USVString domain; + readonly attribute USVString referrer; + attribute USVString cookie; + readonly attribute DOMString lastModified; + readonly attribute DocumentReadyState readyState; + + // DOM tree accessors + // TODO getter object (DOMString name); + [CEReactions] attribute DOMString title; + [CEReactions] attribute DOMString dir; + [CEReactions] attribute HTMLElement? body; + readonly attribute HTMLHeadElement? head; + [SameObject] readonly attribute HTMLCollection images; + [SameObject] readonly attribute HTMLCollection embeds; + [SameObject] readonly attribute HTMLCollection plugins; + [SameObject] readonly attribute HTMLCollection links; + [SameObject] readonly attribute HTMLCollection forms; + [SameObject] readonly attribute HTMLCollection scripts; + NodeList getElementsByName(DOMString elementName); + readonly attribute HTMLElement? currentScript; // classic scripts in a document tree only + + // dynamic markup insertion + // [CEReactions] Document open(optional DOMString unused1, optional DOMString unused2); // both arguments are ignored + WindowProxy? open(USVString url, DOMString name, DOMString features); + [CEReactions] undefined close(); + [CEReactions] undefined write((/*TrustedHTML or */DOMString)... text); + [CEReactions] undefined writeln((/*TrustedHTML or */DOMString)... text); + + // user interaction + readonly attribute WindowProxy? defaultView; + boolean hasFocus(); + [CEReactions] attribute DOMString designMode; + [CEReactions] boolean execCommand(DOMString commandId, optional boolean showUI = false, optional DOMString value = ""); + boolean queryCommandEnabled(DOMString commandId); + boolean queryCommandIndeterm(DOMString commandId); + boolean queryCommandState(DOMString commandId); + boolean queryCommandSupported(DOMString commandId); + DOMString queryCommandValue(DOMString commandId); + readonly attribute boolean hidden; + readonly attribute DocumentVisibilityState visibilityState; + + // special event handler IDL attributes that only apply to Document objects + // [LegacyLenientThis] attribute EventHandler onreadystatechange; + // attribute EventHandler onvisibilitychange; + + // also has obsolete members +}; + +[Exposed=Window] +interface Attr : Node { + readonly attribute DOMString? namespaceURI; + readonly attribute DOMString? prefix; + readonly attribute DOMString localName; + readonly attribute DOMString name; + [CEReactions] attribute DOMString value; + + readonly attribute Element? ownerElement; + + readonly attribute boolean specified; // useless; always returns true +}; + +[Exposed=Window, LegacyUnenumerableNamedProperties] +interface HTMLCollection { + readonly attribute unsigned long length; + getter Element? item(unsigned long index); + getter Element? namedItem(DOMString name); +}; + +[Exposed=Window] +interface NodeList { + getter Node? item(unsigned long index); + readonly attribute unsigned long length; + // iterable; +}; + +[Exposed=Window, + LegacyUnenumerableNamedProperties] +interface NamedNodeMap { + readonly attribute unsigned long length; + getter Attr? item(unsigned long index); + getter Attr? getNamedItem(DOMString qualifiedName); + Attr? getNamedItemNS(DOMString? namespace, DOMString localName); + [CEReactions] Attr? setNamedItem(Attr attr); + [CEReactions] Attr? setNamedItemNS(Attr attr); + [CEReactions] Attr removeNamedItem(DOMString qualifiedName); + [CEReactions] Attr removeNamedItemNS(DOMString? namespace, DOMString localName); +}; + +[Exposed=Window] +interface DOMTokenList { + readonly attribute unsigned long length; + getter DOMString? item(unsigned long index); + boolean contains(DOMString token); + [CEReactions] undefined add(DOMString... tokens); + [CEReactions] undefined remove(DOMString... tokens); + [CEReactions] boolean toggle(DOMString token, optional boolean force); + [CEReactions] boolean replace(DOMString token, DOMString newToken); + boolean supports(DOMString token); + [CEReactions] stringifier attribute DOMString value; + // iterable; +}; + +[Exposed=Window] +interface BarProp { + readonly attribute boolean visible; +}; + +[Global=Window, + Exposed=Window, + LegacyUnenumerableNamedProperties] +interface Window : EventTarget { + attribute Console console; + // the current browsing context + [LegacyUnforgeable] readonly attribute WindowProxy window; + [Replaceable] readonly attribute WindowProxy self; + [LegacyUnforgeable] readonly attribute Document document; + attribute DOMString name; + [PutForwards=href, LegacyUnforgeable] readonly attribute Location location; + + // readonly attribute Navigation navigation; + // readonly attribute CustomElementRegistry customElements; + [Replaceable] readonly attribute BarProp locationbar; + [Replaceable] readonly attribute BarProp menubar; + [Replaceable] readonly attribute BarProp personalbar; + [Replaceable] readonly attribute BarProp scrollbars; + [Replaceable] readonly attribute BarProp statusbar; + [Replaceable] readonly attribute BarProp toolbar; + attribute DOMString status; + undefined close(); + readonly attribute boolean closed; + undefined stop(); + undefined focus(); + undefined blur(); + + // other browsing contexts + [Replaceable] readonly attribute WindowProxy frames; + [Replaceable] readonly attribute unsigned long length; + [LegacyUnforgeable] readonly attribute WindowProxy? top; + // attribute any opener; + [Replaceable] readonly attribute WindowProxy? parent; + readonly attribute Element? frameElement; + WindowProxy? open(optional USVString url = "", optional DOMString target = "_blank", optional [LegacyNullToEmptyString] DOMString features = ""); + + // Since this is the global object, the IDL named getter adds a NamedPropertiesObject exotic + // object on the prototype chain. Indeed, this does not make the global object an exotic object. + // Indexed access is taken care of by the WindowProxy exotic object. + // getter object (DOMString name); + + // the user agent + // readonly attribute Navigator navigator; + // [Replaceable] readonly attribute Navigator clientInformation; // legacy alias of .navigator + readonly attribute boolean originAgentCluster; + + // user prompts + // undefined alert(); + undefined alert(DOMString message); + boolean confirm(optional DOMString message = ""); + DOMString? prompt(optional DOMString message = "", optional DOMString default = ""); + undefined print(); + + // undefined postMessage(any message, USVString targetOrigin, optional sequence transfer = []); + // undefined postMessage(any message, optional WindowPostMessageOptions options = {}); + + // also has obsolete members +}; + +typedef Window WindowProxy; \ No newline at end of file diff --git a/test/fixtures/idl/dom.wit b/test/fixtures/idl/dom.wit new file mode 100644 index 000000000..0fda7ed0b --- /dev/null +++ b/test/fixtures/idl/dom.wit @@ -0,0 +1,421 @@ + + package webidl:dom@0.0.1; + +world window { + import dom; +} + +interface dom { + resource console { + assert: func(condition: option, data: list); + clear: func(); + debug: func(data: list); + error: func(data: list); + info: func(data: list); + log: func(data: list); + table: func(tabular-data: option, properties: option>); + trace: func(data: list); + warn: func(data: list); + dir: func(item: option); + dirxml: func(data: list); + count: func(label: option); + count-reset: func(label: option); + group: func(data: list); + group-collapsed: func(data: list); + group-end: func(); + time: func(label: option); + time-log: func(label: option, data: list); + time-end: func(label: option); + } + resource node { + node-type: func() -> u16; + node-name: func() -> string; + base-uri: func() -> string; + is-connected: func() -> bool; + owner-document: func() -> option; + get-root-node: func(options: option) -> node; + parent-node: func() -> option; + parent-element: func() -> option; + has-child-nodes: func() -> bool; + child-nodes: func() -> node-list; + first-child: func() -> option; + last-child: func() -> option; + previous-sibling: func() -> option; + next-sibling: func() -> option; + node-value: func() -> string; + set-node-value: func(node-value: string); + text-content: func() -> string; + set-text-content: func(text-content: string); + normalize: func(); + clone-node: func(deep: option) -> node; + is-equal-node: func(other-node: option>) -> bool; + is-same-node: func(other-node: option>) -> bool; + compare-document-position: func(other: borrow) -> u16; + contains: func(other: option>) -> bool; + lookup-prefix: func(namespace: string) -> string; + lookup-namespace-uri: func(prefix: string) -> string; + is-default-namespace: func(namespace: string) -> bool; + insert-before: func(node: borrow, child: option>) -> node; + append-child: func(node: borrow) -> node; + replace-child: func(node: borrow, child: borrow) -> node; + remove-child: func(child: borrow) -> node; + } + record get-root-node-options { + composed: option, + } + resource element { + namespace-uri: func() -> string; + prefix: func() -> string; + local-name: func() -> string; + tag-name: func() -> string; + id: func() -> string; + set-id: func(id: string); + class-name: func() -> string; + set-class-name: func(class-name: string); + class-list: func() -> dom-token-list; + slot: func() -> string; + set-slot: func(slot: string); + has-attributes: func() -> bool; + attributes: func() -> named-node-map; + get-attribute-names: func() -> list; + get-attribute: func(qualified-name: string) -> string; + get-attribute-ns: func(namespace: string, local-name: string) -> string; + set-attribute: func(qualified-name: string, value: string); + set-attribute-ns: func(namespace: string, qualified-name: string, value: string); + remove-attribute: func(qualified-name: string); + remove-attribute-ns: func(namespace: string, local-name: string); + toggle-attribute: func(qualified-name: string, force: option) -> bool; + has-attribute: func(qualified-name: string) -> bool; + has-attribute-ns: func(namespace: string, local-name: string) -> bool; + get-attribute-node: func(qualified-name: string) -> option; + get-attribute-node-ns: func(namespace: string, local-name: string) -> option; + set-attribute-node: func(attr: borrow) -> option; + set-attribute-node-ns: func(attr: borrow) -> option; + remove-attribute-node: func(attr: borrow) -> attr; + attach-shadow: func(init: shadow-root-init) -> shadow-root; + shadow-root: func() -> option; + closest: func(selectors: string) -> option; + matches: func(selectors: string) -> bool; + webkit-matches-selector: func(selectors: string) -> bool; + get-elements-by-tag-name: func(qualified-name: string) -> html-collection; + get-elements-by-tag-name-ns: func(namespace: string, local-name: string) -> html-collection; + get-elements-by-class-name: func(class-names: string) -> html-collection; + insert-adjacent-element: func(where: string, element: borrow) -> option; + insert-adjacent-text: func(where: string, data: string); + } + record shadow-root-init { + mode: shadow-root-mode, + delegates-focus: option, + slot-assignment: option, + clonable: option, + serializable: option, + } + resource shadow-root { + mode: func() -> shadow-root-mode; + delegates-focus: func() -> bool; + slot-assignment: func() -> slot-assignment-mode; + clonable: func() -> bool; + serializable: func() -> bool; + host: func() -> element; + } + enum shadow-root-mode { + open, + closed, + } + enum slot-assignment-mode { + manual, + named, + } + resource document-fragment { + constructor(); + } + resource html-element { + constructor(); + title: func() -> string; + set-title: func(title: string); + lang: func() -> string; + set-lang: func(lang: string); + translate: func() -> bool; + set-translate: func(translate: bool); + dir: func() -> string; + set-dir: func(dir: string); + hidden: func() -> bool-or-f64-or-string; + set-hidden: func(hidden: bool-or-f64-or-string); + inert: func() -> bool; + set-inert: func(inert: bool); + click: func(); + access-key: func() -> string; + set-access-key: func(access-key: string); + access-key-label: func() -> string; + draggable: func() -> bool; + set-draggable: func(draggable: bool); + spellcheck: func() -> bool; + set-spellcheck: func(spellcheck: bool); + writing-suggestions: func() -> string; + set-writing-suggestions: func(writing-suggestions: string); + autocapitalize: func() -> string; + set-autocapitalize: func(autocapitalize: string); + inner-text: func() -> string; + set-inner-text: func(inner-text: string); + outer-text: func() -> string; + set-outer-text: func(outer-text: string); + inner-html: func() -> string; + set-inner-html: func(inner-html: string); + attach-internals: func() -> element-internals; + show-popover: func(); + hide-popover: func(); + toggle-popover: func(force: option) -> bool; + popover: func() -> string; + set-popover: func(popover: string); + } + variant bool-or-f64-or-string { + %bool(bool), + %f64(f64), + %string(string), + } + resource element-internals { + shadow-root: func() -> option; + set-form-value: func(value: form-data-or-string, state: form-data-or-string); + set-validity: func(%flags: option, message: option, anchor: option>); + will-validate: func() -> bool; + validity: func() -> validity-state; + validation-message: func() -> string; + check-validity: func() -> bool; + report-validity: func() -> bool; + labels: func() -> node-list; + } + variant form-data-or-string { + form-data(borrow), + %string(string), + } + resource validity-state { + value-missing: func() -> bool; + type-mismatch: func() -> bool; + pattern-mismatch: func() -> bool; + too-long: func() -> bool; + too-short: func() -> bool; + range-underflow: func() -> bool; + range-overflow: func() -> bool; + step-mismatch: func() -> bool; + bad-input: func() -> bool; + custom-error: func() -> bool; + valid: func() -> bool; + } + type form-data-entry-value = string; + resource form-data { + constructor(); + append: func(name: string, value: string); + delete: func(name: string); + get: func(name: string) -> option; + get-all: func(name: string) -> list; + has: func(name: string) -> bool; + set: func(name: string, value: string); + } + record validity-state-flags { + value-missing: option, + type-mismatch: option, + pattern-mismatch: option, + too-long: option, + too-short: option, + range-underflow: option, + range-overflow: option, + step-mismatch: option, + bad-input: option, + custom-error: option, + } + resource html-unknown-element { + } + enum document-ready-state { + loading, + interactive, + complete, + } + enum document-visibility-state { + visible, + hidden, + } + resource html-script-element { + constructor(); + src: func() -> string; + set-src: func(src: string); + %type: func() -> string; + set-type: func(%type: string); + no-module: func() -> bool; + set-no-module: func(no-module: bool); + async: func() -> bool; + set-async: func(async: bool); + defer: func() -> bool; + set-defer: func(defer: bool); + cross-origin: func() -> string; + set-cross-origin: func(cross-origin: string); + text: func() -> string; + set-text: func(text: string); + integrity: func() -> string; + set-integrity: func(integrity: string); + referrer-policy: func() -> string; + set-referrer-policy: func(referrer-policy: string); + blocking: func() -> dom-token-list; + fetch-priority: func() -> string; + set-fetch-priority: func(fetch-priority: string); + supports: static func(%type: string) -> bool; + } + resource html-head-element { + constructor(); + } + resource dom-string-list { + length: func() -> u32; + item: func(index: u32) -> string; + contains: func(%string: string) -> bool; + } + resource location { + href: func() -> string; + set-href: func(href: string); + origin: func() -> string; + protocol: func() -> string; + set-protocol: func(protocol: string); + host: func() -> string; + set-host: func(host: string); + hostname: func() -> string; + set-hostname: func(hostname: string); + port: func() -> string; + set-port: func(port: string); + pathname: func() -> string; + set-pathname: func(pathname: string); + search: func() -> string; + set-search: func(search: string); + hash: func() -> string; + set-hash: func(hash: string); + assign: func(url: string); + replace: func(url: string); + reload: func(); + ancestor-origins: func() -> dom-string-list; + } + resource document { + parse-html-unsafe: static func(html: string) -> document; + location: func() -> option; + domain: func() -> string; + set-domain: func(domain: string); + referrer: func() -> string; + cookie: func() -> string; + set-cookie: func(cookie: string); + last-modified: func() -> string; + ready-state: func() -> document-ready-state; + title: func() -> string; + set-title: func(title: string); + dir: func() -> string; + set-dir: func(dir: string); + body: func() -> option; + set-body: func(body: option); + head: func() -> option; + images: func() -> html-collection; + embeds: func() -> html-collection; + plugins: func() -> html-collection; + links: func() -> html-collection; + forms: func() -> html-collection; + scripts: func() -> html-collection; + get-elements-by-name: func(element-name: string) -> node-list; + current-script: func() -> option; + open: func(url: string, name: string, features: string) -> option; + close: func(); + write: func(text: list); + writeln: func(text: list); + default-view: func() -> option; + has-focus: func() -> bool; + design-mode: func() -> string; + set-design-mode: func(design-mode: string); + exec-command: func(command-id: string, show-ui: option, value: option) -> bool; + query-command-enabled: func(command-id: string) -> bool; + query-command-indeterm: func(command-id: string) -> bool; + query-command-state: func(command-id: string) -> bool; + query-command-supported: func(command-id: string) -> bool; + query-command-value: func(command-id: string) -> string; + hidden: func() -> bool; + visibility-state: func() -> document-visibility-state; + } + resource attr { + namespace-uri: func() -> string; + prefix: func() -> string; + local-name: func() -> string; + name: func() -> string; + value: func() -> string; + set-value: func(value: string); + owner-element: func() -> option; + specified: func() -> bool; + } + resource html-collection { + length: func() -> u32; + item: func(index: u32) -> option; + named-item: func(name: string) -> option; + } + resource node-list { + item: func(index: u32) -> option; + length: func() -> u32; + } + resource named-node-map { + length: func() -> u32; + item: func(index: u32) -> option; + get-named-item: func(qualified-name: string) -> option; + get-named-item-ns: func(namespace: string, local-name: string) -> option; + set-named-item: func(attr: borrow) -> option; + set-named-item-ns: func(attr: borrow) -> option; + remove-named-item: func(qualified-name: string) -> attr; + remove-named-item-ns: func(namespace: string, local-name: string) -> attr; + } + resource dom-token-list { + length: func() -> u32; + item: func(index: u32) -> string; + contains: func(token: string) -> bool; + add: func(tokens: list); + remove: func(tokens: list); + toggle: func(token: string, force: option) -> bool; + replace: func(token: string, new-token: string) -> bool; + supports: func(token: string) -> bool; + value: func() -> string; + set-value: func(value: string); + } + resource bar-prop { + visible: func() -> bool; + } + resource window { + console: func() -> console; + set-console: func(console: console); + window: func() -> window-proxy; + self: func() -> window-proxy; + document: func() -> document; + name: func() -> string; + set-name: func(name: string); + location: func() -> location; + locationbar: func() -> bar-prop; + menubar: func() -> bar-prop; + personalbar: func() -> bar-prop; + scrollbars: func() -> bar-prop; + statusbar: func() -> bar-prop; + toolbar: func() -> bar-prop; + status: func() -> string; + set-status: func(status: string); + close: func(); + closed: func() -> bool; + stop: func(); + focus: func(); + blur: func(); + frames: func() -> window-proxy; + length: func() -> u32; + top: func() -> option; + parent: func() -> option; + frame-element: func() -> option; + open: func(url: option, target: option, features: option) -> option; + origin-agent-cluster: func() -> bool; + alert: func(message: string); + confirm: func(message: option) -> bool; + prompt: func(message: option, default: option) -> string; + print: func(); + } + type window-proxy = window; + get-window: func() -> window; +} + + world window-test { + include window; + export test: func(); + } + \ No newline at end of file diff --git a/test/fixtures/wit/deps/flavorful/flavorful.wit b/test/fixtures/wit/deps/flavorful/flavorful.wit index 570cc588a..920346d88 100644 --- a/test/fixtures/wit/deps/flavorful/flavorful.wit +++ b/test/fixtures/wit/deps/flavorful/flavorful.wit @@ -28,10 +28,10 @@ interface test { type list-typedef = string; type list-typedef2 = list; type list-typedef3 = list; - list-typedefs: func(a: list-typedef, c: list-typedef3) -> (a: list-typedef2, b: list-typedef3); + list-typedefs: func(a: list-typedef, c: list-typedef3) -> tuple; list-of-variants: func(a: list, b: list, c: list) - -> (a: list, b: list, c: list); + -> tuple, list, list>; } world flavorful { diff --git a/test/runtime/helpers.ts b/test/runtime/helpers.ts index a045fb7c2..749f1a153 100644 --- a/test/runtime/helpers.ts +++ b/test/runtime/helpers.ts @@ -32,3 +32,39 @@ export function log (bytes: Uint8Array) { export function logErr (bytes: Uint8Array) { stderr.write(bytes); } + +export const wasi = { + 'wasi:cli/stderr': { + getStderr () { + + } + }, + 'wasi:cli/stdin': { + getStdin () { + + } + }, + 'wasi:cli/stdout': { + getStdout () { + + } + }, + 'wasi:filesystem/preopens': { + getDirectores () { + + } + }, + 'wasi:filesystem/types': { + Descriptor: class Descriptor {}, + filsystemErrorCode () { + return 0; + } + }, + 'wasi:io/error': { + Error: class WasiError {} + }, + 'wasi:io/streams': { + InputStream: class InputStream {}, + OutputStream: class OutputStream {} + } +}; diff --git a/test/runtime/lists.ts b/test/runtime/lists.ts index 9da869ce9..f32a69a81 100644 --- a/test/runtime/lists.ts +++ b/test/runtime/lists.ts @@ -1,5 +1,6 @@ // Flags: --instantiation +// @ts-ignore import * as helpers from "./helpers.js"; import { instantiate } from "../output/lists/lists.js"; @@ -7,8 +8,9 @@ import { instantiate } from "../output/lists/lists.js"; import * as assert from 'assert'; async function run() { + // @ts-ignore const wasm = await instantiate(helpers.loadWasm, { - testwasi: helpers, + ...helpers.wasi, 'test:lists/test': { emptyListParam(a) { assert.deepStrictEqual(Array.from(a), []); diff --git a/test/runtime/many-arguments.ts b/test/runtime/many-arguments.ts index a7f0d4c47..05f3f5db5 100644 --- a/test/runtime/many-arguments.ts +++ b/test/runtime/many-arguments.ts @@ -14,8 +14,9 @@ function assert(x: boolean) { } async function run() { + // @ts-ignore const wasm = await instantiate(helpers.loadWasm, { - testwasi: helpers, + ...helpers.wasi, imports: { manyArguments( a1, diff --git a/test/runtime/numbers.ts b/test/runtime/numbers.ts index d26b3ebe9..800683e35 100644 --- a/test/runtime/numbers.ts +++ b/test/runtime/numbers.ts @@ -29,8 +29,9 @@ world root { async function run() { let scalar = 0; + // @ts-ignore const wasm = await instantiate(helpers.loadWasm, { - testwasi: helpers, + ...helpers.wasi, 'test:numbers/test': { roundtripU8(x) { return x; }, roundtripS8(x) { return x; }, @@ -40,8 +41,8 @@ async function run() { roundtripS32(x) { return x; }, roundtripU64(x) { return x; }, roundtripS64(x) { return x; }, - roundtripFloat32(x) { return x; }, - roundtripFloat64(x) { return x; }, + roundtripF32(x) { return x; }, + roundtripF64(x) { return x; }, roundtripChar(x) { return x; }, setScalar(x) { scalar = x; }, getScalar() { return scalar; }, @@ -80,15 +81,15 @@ async function run() { strictEqual(wasm.test.roundtripS64((1n << 63n) - 1n), (1n << 63n) - 1n); strictEqual(wasm.test.roundtripS64(-(1n << 63n)), -(1n << 63n)); - strictEqual(wasm.test.roundtripFloat32(1), 1); - strictEqual(wasm.test.roundtripFloat32(Infinity), Infinity); - strictEqual(wasm.test.roundtripFloat32(-Infinity), -Infinity); - assert(Number.isNaN(wasm.test.roundtripFloat32(NaN))); + strictEqual(wasm.test.roundtripF32(1), 1); + strictEqual(wasm.test.roundtripF32(Infinity), Infinity); + strictEqual(wasm.test.roundtripF32(-Infinity), -Infinity); + assert(Number.isNaN(wasm.test.roundtripF32(NaN))); - strictEqual(wasm.test.roundtripFloat64(1), 1); - strictEqual(wasm.test.roundtripFloat64(Infinity), Infinity); - strictEqual(wasm.test.roundtripFloat64(-Infinity), -Infinity); - assert(Number.isNaN(wasm.test.roundtripFloat64(NaN))); + strictEqual(wasm.test.roundtripF64(1), 1); + strictEqual(wasm.test.roundtripF64(Infinity), Infinity); + strictEqual(wasm.test.roundtripF64(-Infinity), -Infinity); + assert(Number.isNaN(wasm.test.roundtripF64(NaN))); strictEqual(wasm.test.roundtripChar('a'), 'a'); strictEqual(wasm.test.roundtripChar(' '), ' '); diff --git a/test/runtime/records.ts b/test/runtime/records.ts index 747eae776..22804f9f8 100644 --- a/test/runtime/records.ts +++ b/test/runtime/records.ts @@ -6,14 +6,15 @@ import { instantiate, ImportObject } from "../output/records/records.js"; import * as assert from 'node:assert'; async function run() { + // @ts-ignore const wasm = await instantiate(helpers.loadWasm, { - testwasi: helpers, + ...helpers.wasi, 'test:records/test': { multipleResults() { return [4, 5]; }, swapTuple([a, b]) { return [b, a]; }, roundtripFlags1(x) { return x; }, roundtripFlags2(x) { return x; }, - roundtripFlags3(r0, r1, r2, r3) { return [r0, r1, r2, r3]; }, + roundtripFlags3(r0, r1, r2) { return [r0, r1, r2]; }, roundtripRecord1(x) { return x; }, tuple1([x]) { return [x]; }, } diff --git a/test/runtime/strings.async+js.ts b/test/runtime/strings.async+js.ts index 058fcea35..792a902b0 100644 --- a/test/runtime/strings.async+js.ts +++ b/test/runtime/strings.async+js.ts @@ -7,8 +7,9 @@ import { instantiate } from '../output/strings.async+js/strings.async+js.js'; import * as assert from 'assert'; async function run() { + // @ts-ignore const wasm = await instantiate(helpers.loadWasm, { - testwasi: helpers, + ...helpers.wasi, 'test:strings/imports': { takeBasic(s: string) { assert.strictEqual(s, 'latin utf16'); diff --git a/test/runtime/strings.sync+js.ts b/test/runtime/strings.sync+js.ts index 4b2765dc8..114e364c4 100644 --- a/test/runtime/strings.sync+js.ts +++ b/test/runtime/strings.sync+js.ts @@ -7,8 +7,9 @@ import { instantiate } from '../output/strings.sync+js/strings.sync+js.js'; import * as assert from 'assert'; function run() { + // @ts-ignore const wasm = instantiate(helpers.loadWasmSync, { - testwasi: helpers, + ...helpers.wasi, 'test:strings/imports': { takeBasic(s: string) { assert.strictEqual(s, 'latin utf16'); diff --git a/test/runtime/strings.sync.ts b/test/runtime/strings.sync.ts index 55eaf7f51..53407bf14 100644 --- a/test/runtime/strings.sync.ts +++ b/test/runtime/strings.sync.ts @@ -7,8 +7,8 @@ import { instantiate } from '../output/strings.sync/strings.sync.js'; import * as assert from 'assert'; function run() { + // @ts-ignore const wasm = instantiate(helpers.loadWasmSync, { - testwasi: helpers, 'test:strings/imports': { takeBasic(s: string) { assert.strictEqual(s, 'latin utf16'); diff --git a/test/runtime/strings.ts b/test/runtime/strings.ts index 579b1c226..8bc19aa9d 100644 --- a/test/runtime/strings.ts +++ b/test/runtime/strings.ts @@ -7,8 +7,9 @@ import { instantiate } from '../output/strings/strings.js'; import * as assert from 'assert'; async function run() { + // @ts-ignore const wasm = await instantiate(helpers.loadWasm, { - testwasi: helpers, + ...helpers.wasi, 'test:strings/imports': { takeBasic(s: string) { assert.strictEqual(s, 'latin utf16'); diff --git a/test/runtime/variants.ts b/test/runtime/variants.ts index a45a260aa..384b93f1e 100644 --- a/test/runtime/variants.ts +++ b/test/runtime/variants.ts @@ -6,8 +6,9 @@ import { instantiate } from "../output/variants/variants.js"; import * as assert from 'assert'; async function run() { + // @ts-ignore const wasm = await instantiate(helpers.loadWasm, { - testwasi: helpers, + ...helpers.wasi, 'test:variants/test': { roundtripOption(x) { return x; }, roundtripResult(x) { diff --git a/test/test.js b/test/test.js index ea843e365..a3a65b184 100644 --- a/test/test.js +++ b/test/test.js @@ -12,7 +12,7 @@ * When the runtime test is present, the flags in the runtime host.ts file will be used * as the flags of the code generation step. */ -import { env } from 'node:process'; +import { env, versions } from 'node:process'; import { readdir } from 'node:fs/promises'; const componentFixtures = env.COMPONENT_FIXTURES @@ -34,3 +34,8 @@ await runtimeTest(componentFixtures); await commandsTest(); await apiTest(componentFixtures); await cliTest(componentFixtures); + +if (versions.node.split('.')[0] !== '22') { + const { browserTest } = await import('./browser.js'); + await browserTest(); +} diff --git a/update-tests.sh b/update-tests.sh index 0ed2746ad..68efdcce1 100755 --- a/update-tests.sh +++ b/update-tests.sh @@ -1,9 +1,6 @@ #!/bin/bash set -ex -# update dependencies -git submodule foreach git pull origin main -git submodule update --init --recursive cd submodules/wit-bindgen # build tests @@ -13,8 +10,8 @@ cargo test -p wit-bindgen-cli --no-default-features -F rust -F c for t in target/runtime-tests/*/rust.wasm do name="$(basename $(dirname $t))" - echo "cp $t ../test/fixtures/components/${name}.component.wasm" - cp $t ../test/fixtures/components/${name}.component.wasm + echo "cp $t ../../test/fixtures/components/${name}.component.wasm" + cp $t ../../test/fixtures/components/${name}.component.wasm done # copy over the C-based wit-bindgen tests to our repo. @@ -23,12 +20,12 @@ for t in target/runtime-tests/*/c-*/*.component.wasm do name="$(basename $(dirname $t))" name=${name:2} - echo "cp $t ../test/fixtures/components/${name}.component.wasm" + echo "cp $t ../../test/fixtures/components/${name}.component.wasm" cp $t ../../test/fixtures/components/${name}.component.wasm done # copy flavorful wit case -cp tests/runtime/flavorful/world.wit ../../test/fixtures/wit/flavorful.wit +cp tests/runtime/flavorful/world.wit ../../test/fixtures/wit/deps/flavorful/flavorful.wit cd ../.. # convert the js test fixtures into a wasm component diff --git a/xtask/Cargo.toml b/xtask/Cargo.toml index 8a55839e1..d67d649c8 100644 --- a/xtask/Cargo.toml +++ b/xtask/Cargo.toml @@ -7,11 +7,10 @@ edition = "2021" [dependencies] anyhow = { workspace = true } js-component-bindgen = { workspace = true } +semver = "1.0.23" structopt = { workspace = true } +webidl2wit = { git = "https://github.com/wasi-gfx/webidl2wit", rev = "9cf1e53c5393e02e4b5ecc437012caf23ef1002f" } +weedle = "0.13.0" wit-component = { workspace = true } -xshell = "0.2" - -[build-dependencies] -anyhow = { workspace = true } -js-component-bindgen = { workspace = true } -wit-component = { workspace = true } +wit-encoder = "0.214.0" +xshell = { workspace = true } diff --git a/xtask/src/build/jco.rs b/xtask/src/build/jco.rs index b0a331f08..8f2577eae 100644 --- a/xtask/src/build/jco.rs +++ b/xtask/src/build/jco.rs @@ -7,12 +7,12 @@ use xshell::{cmd, Shell}; pub(crate) fn run(release: bool) -> Result<()> { let build = if release { "release" } else { "debug" }; transpile( - &format!("target/wasm32-wasi/{build}/js_component_bindgen_component.wasm"), + &format!("target/wasm32-wasip1/{build}/js_component_bindgen_component.wasm"), "js-component-bindgen-component".to_string(), release, )?; transpile( - &format!("target/wasm32-wasi/{build}/wasm_tools_js.wasm"), + &format!("target/wasm32-wasip1/{build}/wasm_tools_js.wasm"), "wasm-tools".to_string(), release, )?; diff --git a/xtask/src/build/workspace.rs b/xtask/src/build/workspace.rs index 9f9f35b23..ae1777005 100644 --- a/xtask/src/build/workspace.rs +++ b/xtask/src/build/workspace.rs @@ -3,9 +3,13 @@ use xshell::{cmd, Shell}; pub(crate) fn run(release: bool) -> anyhow::Result<()> { let sh = Shell::new()?; if release { - cmd!(sh, "cargo build --workspace --release --target wasm32-wasi").read()?; + cmd!( + sh, + "cargo build --workspace --release --target wasm32-wasip1" + ) + .read()?; } else { - cmd!(sh, "cargo build --workspace --target wasm32-wasi").read()?; + cmd!(sh, "cargo build --workspace --target wasm32-wasip1").read()?; } cmd!(sh, "node node_modules/typescript/bin/tsc -p tsconfig.json").read()?; sh.copy_file( diff --git a/xtask/src/generate/mod.rs b/xtask/src/generate/mod.rs index dc6c23862..dbfe6680c 100644 --- a/xtask/src/generate/mod.rs +++ b/xtask/src/generate/mod.rs @@ -1,2 +1,3 @@ -pub(crate) mod tests; +pub(crate) mod preview2_tests; pub(crate) mod wasi_types; +pub(crate) mod webidl_tests; diff --git a/xtask/src/generate/tests.rs b/xtask/src/generate/preview2_tests.rs similarity index 95% rename from xtask/src/generate/tests.rs rename to xtask/src/generate/preview2_tests.rs index 7da875551..57ec56fb8 100644 --- a/xtask/src/generate/tests.rs +++ b/xtask/src/generate/preview2_tests.rs @@ -6,7 +6,7 @@ const TRACE: bool = false; const DENO: bool = true; const TEST_FILTER: &[&str] = &[]; -const TEST_IGNORE: &[&str] = &["nn_image_classification", "nn_image_classification_named"]; +const TEST_IGNORE: &[&str] = &["preview2_file_read_write"]; const DENO_IGNORE: &[&str] = &[ "api_read_only", @@ -29,6 +29,7 @@ const DENO_IGNORE: &[&str] = &[ "preview1_fd_filestat_set", "preview1_fd_flags_set", "preview1_fd_readdir", + "preview1_file_pread_pwrite", "preview1_file_read_write", "preview1_file_seek_tell", "preview1_file_truncation", @@ -73,7 +74,7 @@ pub fn run() -> anyhow::Result<()> { // Compile wasmtime test programs let guard = sh.push_dir("submodules/wasmtime/crates/test-programs"); - cmd!(sh, "cargo build --target wasm32-wasi").run()?; + cmd!(sh, "cargo build --target wasm32-wasip1").run()?; drop(guard); // Tidy up the dir and recreate it. @@ -85,7 +86,7 @@ pub fn run() -> anyhow::Result<()> { let mut test_names = vec![]; - for entry in fs::read_dir("submodules/wasmtime/target/wasm32-wasi/debug")? { + for entry in fs::read_dir("submodules/wasmtime/target/wasm32-wasip1/debug")? { let entry = entry?; // skip all files which don't end with `.wasm` if entry.path().extension().and_then(|p| p.to_str()) != Some("wasm") { @@ -93,6 +94,10 @@ pub fn run() -> anyhow::Result<()> { } let file_name = String::from(entry.file_name().to_str().unwrap()); let test_name = String::from(&file_name[0..file_name.len() - 5]); + // ignore wasi-nn tests for now + if test_name.starts_with("nn_") { + continue; + } if TEST_IGNORE.contains(&test_name.as_ref()) { continue; } @@ -111,7 +116,7 @@ pub fn run() -> anyhow::Result<()> { let mut all_names = Vec::new(); for test_name in test_names { - let path = format!("submodules/wasmtime/target/wasm32-wasi/debug/{test_name}.wasm"); + let path = format!("submodules/wasmtime/target/wasm32-wasip1/debug/{test_name}.wasm"); // compile into generated dir let dest_file = format!("./tests/gen/{test_name}.component.wasm"); @@ -129,13 +134,13 @@ pub fn run() -> anyhow::Result<()> { continue; } - let windows_skip = DENO || TEST_IGNORE_WINDOWS.contains(&test_name.as_ref()); + let windows_skip = TEST_IGNORE_WINDOWS.contains(&test_name.as_ref()); let content = generate_test(&test_name, windows_skip, false); fs::write(format!("tests/gen/node_{test_name}.rs"), content)?; if DENO && !DENO_IGNORE.contains(&test_name.as_ref()) { - let content = generate_test(&test_name, windows_skip, true); + let content = generate_test(&test_name, true, true); let test_name = format!("deno_{test_name}"); fs::write(format!("tests/gen/{test_name}.rs"), content)?; all_names.push(test_name); diff --git a/xtask/src/generate/wasi_types.rs b/xtask/src/generate/wasi_types.rs index f4942d06c..9fe7cc396 100644 --- a/xtask/src/generate/wasi_types.rs +++ b/xtask/src/generate/wasi_types.rs @@ -23,7 +23,7 @@ pub(crate) fn run() -> Result<()> { .unwrap() .1; - let world = resolve.select_world(preview2, Some(world_name))?; + let world = resolve.select_world(&[preview2], Some(world_name))?; let opts = js_component_bindgen::TranspileOpts { name: "component".to_string(), diff --git a/xtask/src/generate/webidl_tests.rs b/xtask/src/generate/webidl_tests.rs new file mode 100644 index 000000000..64020e1d7 --- /dev/null +++ b/xtask/src/generate/webidl_tests.rs @@ -0,0 +1,91 @@ +use std::{ + collections::HashSet, + fs::{read_dir, read_to_string, write}, +}; + +use anyhow::Result; + +use webidl2wit::{webidl_to_wit, ConversionOptions, HandleUnsupported}; +use wit_encoder::PackageName; + +const IDL_VERSION_MAJOR: u64 = 0; +const IDL_VERSION_MINOR: u64 = 0; +const IDL_VERSION_PATCH: u64 = 1; + +pub(crate) fn run() -> Result<()> { + for file in read_dir("test/fixtures/idl")? { + let file = file?; + let file_name = file.file_name(); + let file_name_str = file_name.to_string_lossy().to_string(); + let Some(name) = file_name_str.strip_suffix(".webidl") else { + continue; + }; + let name = name.to_string(); + let interface_name = name.to_string(); + let idl_source = read_to_string(file.path())?; + let idl = weedle::parse(&idl_source).unwrap(); + let mut global_singletons = HashSet::new(); + global_singletons.insert("Window".to_string()); + let wit = webidl_to_wit( + idl, + ConversionOptions { + package_name: PackageName::new( + "webidl", + name.to_string(), + Some(semver::Version { + major: IDL_VERSION_MAJOR, + minor: IDL_VERSION_MINOR, + patch: IDL_VERSION_PATCH, + pre: semver::Prerelease::default(), + build: semver::BuildMetadata::default(), + }), + ), + interface_name: if interface_name == "console" { + format!("global-{interface_name}") + } else { + interface_name.clone() + }, + unsupported_features: HandleUnsupported::Bail, + singleton_interface: if interface_name == "console" { + Some(interface_name.clone()) + } else { + None + }, + global_singletons, + }, + )?; + + let wit_str = wit.to_string(); + + let world_definition = if interface_name == "console" { + format!( + "world {interface_name}-test {{ + import global-{interface_name}; + export test: func(); + }}" + ) + } else { + "world window-test { + include window; + export test: func(); + }" + .to_string() + }; + + let output_file = format!("test/fixtures/idl/{name}.wit"); + write( + &output_file, + format!( + " + {wit_str} + {world_definition} + " + ), + ) + .unwrap(); + + println!("Generated {output_file}"); + } + + Ok(()) +} diff --git a/xtask/src/main.rs b/xtask/src/main.rs index 7dac75b4f..a3ed418cb 100644 --- a/xtask/src/main.rs +++ b/xtask/src/main.rs @@ -33,9 +33,11 @@ enum Build { #[derive(StructOpt)] enum Generate { /// Generate WASI conformance tests from Wasmtime - Tests, + Preview2Tests, /// Generate the WASI Preview 2 types WasiTypes, + /// Generate WebIDL tests + WebidlTests, } fn main() -> anyhow::Result<()> { @@ -52,7 +54,8 @@ fn main() -> anyhow::Result<()> { } Opts::Test(Platform::Node) => test::run(false), Opts::Test(Platform::Deno) => test::run(true), - Opts::Generate(Generate::Tests) => generate::tests::run(), + Opts::Generate(Generate::Preview2Tests) => generate::preview2_tests::run(), + Opts::Generate(Generate::WebidlTests) => generate::webidl_tests::run(), Opts::Generate(Generate::WasiTypes) => generate::wasi_types::run(), } }