From 41417d9e0feff2aa3ae0ca66a7b8777bfaa88dc2 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Fri, 26 May 2023 11:39:52 -0500 Subject: [PATCH] Update Wasmtime for upcoming WIT changes (#6390) * Update Wasmtime for upcoming WIT changes This PR integrates bytecodealliance/wasm-tools#1027 into Wasmtime. The main changes here are: * WIT syntax is updated with WebAssembly/component-model#193 * Generated bindings in the `bindgen!` macro have been updated to reflect the new structure of WIT. * The accepted component model binary format has been updated to account for changes. This PR disables wasi-http tests and the on-by-default feature because the WIT syntax has been updated but the submodule containing the WITs has not been updated yet so there's no way to get that building temporarily. Once that's updated then this can be reenabled. * Update wasmtime-wasi crate with new WIT * Add wit-bindgen override for the updated version * Officially disable wasi-http tests/building * Move test-reactor WIT into the main WIT files Don't store duplicates with the rest of the WASI WIT files we have. * Remove adapter's copy of WIT files * Disable default features for wit-bindgen * Plumb disabling wasi-http tests a bit more * Fix reactor tests and adapter build * Remove no-longer-needed feature * Update adapter verification script * Back out some wasi-http hacks * Update vet and some dependency sources * Move where wit-bindgen comes from Make it a more "official" location which is also less likely to be accidentally deleted in the future. * Don't document wasi-http-tests --- .github/workflows/main.yml | 1 + Cargo.lock | 188 ++++----- Cargo.toml | 25 +- cranelift/wasm/src/sections_translator.rs | 3 + crates/component-macro/src/bindgen.rs | 26 +- crates/component-macro/tests/codegen.rs | 6 - crates/component-macro/tests/codegen/char.wit | 8 +- .../tests/codegen/conventions.wit | 7 +- .../tests/codegen/direct-import.wit | 4 +- .../component-macro/tests/codegen/empty.wit | 3 +- .../component-macro/tests/codegen/flags.wit | 8 +- .../component-macro/tests/codegen/floats.wit | 8 +- .../tests/codegen/function-new.wit | 3 +- .../tests/codegen/integers.wit | 8 +- .../component-macro/tests/codegen/lists.wit | 8 +- .../tests/codegen/many-arguments.wit | 8 +- .../tests/codegen/multi-return.wit | 8 +- .../component-macro/tests/codegen/records.wit | 8 +- .../component-macro/tests/codegen/rename.wit | 10 +- .../tests/codegen/share-types.wit | 8 +- .../tests/codegen/simple-functions.wit | 8 +- .../tests/codegen/simple-lists.wit | 8 +- .../tests/codegen/simple-wasi.wit | 8 +- .../tests/codegen/small-anonymous.wit | 8 +- .../tests/codegen/smoke-default.wit | 4 +- .../tests/codegen/smoke-export.wit | 4 +- .../component-macro/tests/codegen/smoke.wit | 4 +- .../component-macro/tests/codegen/strings.wit | 8 +- .../component-macro/tests/codegen/unions.wit | 8 +- .../tests/codegen/use-paths.wit | 14 +- .../tests/codegen/variants.wit | 8 +- .../tests/codegen/worlds-with-types.wit | 6 +- crates/environ/src/component/translate.rs | 16 +- .../environ/src/component/translate/inline.rs | 13 +- crates/environ/src/component/types.rs | 27 +- crates/environ/src/module_environ.rs | 3 + crates/test-programs/Cargo.toml | 1 + crates/test-programs/build.rs | 27 +- crates/test-programs/reactor-tests/src/lib.rs | 6 +- .../test-programs/reactor-tests/wit/deps.lock | 41 -- .../test-programs/reactor-tests/wit/deps.toml | 1 - .../wit/deps/clocks/monotonic-clock.wit | 32 -- .../wit/deps/clocks/timezone.wit | 61 --- .../wit/deps/clocks/wall-clock.wit | 41 -- .../reactor-tests/wit/deps/io/streams.wit | 213 ----------- .../reactor-tests/wit/deps/poll/poll.wit | 39 -- .../wit/deps/wasi-cli-base/environment.wit | 14 - .../wit/deps/wasi-cli-base/exit.wit | 4 - .../reactor-tests/wit/test-reactor.wit | 18 - crates/test-programs/tests/reactor.rs | 48 +-- crates/test-programs/tests/wasi-http.rs | 2 +- crates/types/src/lib.rs | 2 +- crates/wasi-http/src/lib.rs | 4 + .../Cargo.toml | 2 +- .../src/descriptors.rs | 19 +- .../src/lib.rs | 20 +- .../src/macros.rs | 5 +- .../verify/src/main.rs | 33 +- .../wit/deps/clocks/monotonic-clock.wit | 32 -- .../wit/deps/clocks/timezone.wit | 61 --- .../wit/deps/clocks/wall-clock.wit | 41 -- .../wit/deps/http/incoming-handler.wit | 24 -- .../wit/deps/http/outgoing-handler.wit | 18 - .../wit/deps/http/types.wit | 157 -------- .../wit/deps/io/streams.wit | 213 ----------- .../wit/deps/logging/handler.wit | 32 -- .../wit/deps/poll/poll.wit | 39 -- .../wit/deps/preview/reactor.wit | 21 - .../wit/deps/sockets/instance-network.wit | 9 - .../wit/deps/wasi-cli-base/environment.wit | 14 - .../wit/deps/wasi-cli-base/exit.wit | 4 - crates/wasi/src/preview2/preview1/mod.rs | 362 ++++++++---------- crates/wasi/src/preview2/preview2/clocks.rs | 8 +- crates/wasi/src/preview2/preview2/env.rs | 27 +- crates/wasi/src/preview2/preview2/exit.rs | 2 +- .../wasi/src/preview2/preview2/filesystem.rs | 289 +++++++------- crates/wasi/src/preview2/preview2/io.rs | 4 +- crates/wasi/src/preview2/preview2/poll.rs | 9 +- crates/wasi/src/preview2/preview2/random.rs | 12 +- crates/wasi/src/preview2/wasi/command.rs | 55 ++- crates/wasi/src/preview2/wasi/mod.rs | 32 +- crates/wasi/wit/command.wit | 26 -- .../wasi/wit/deps/clocks/monotonic-clock.wit | 6 +- crates/wasi/wit/deps/clocks/timezone.wit | 6 +- crates/wasi/wit/deps/clocks/wall-clock.wit | 4 +- .../wasi/wit/deps/filesystem/filesystem.wit | 8 +- .../wasi/wit/deps/http/incoming-handler.wit | 4 +- .../wasi/wit/deps/http/outgoing-handler.wit | 4 +- crates/wasi/wit/deps/http/types.wit | 10 +- crates/wasi/wit/deps/io/streams.wit | 6 +- crates/wasi/wit/deps/logging/handler.wit | 4 +- crates/wasi/wit/deps/poll/poll.wit | 4 +- .../wit/deps/preview/command-extended.wit | 49 +-- crates/wasi/wit/deps/preview/command.wit | 43 ++- crates/wasi/wit/deps/preview/proxy.wit | 15 +- crates/wasi/wit/deps/preview/reactor.wit | 43 ++- crates/wasi/wit/deps/random/insecure-seed.wit | 2 +- crates/wasi/wit/deps/random/insecure.wit | 2 +- crates/wasi/wit/deps/random/random.wit | 4 +- .../wit/deps/sockets/instance-network.wit | 4 +- .../wasi/wit/deps/sockets/ip-name-lookup.wit | 28 +- crates/wasi/wit/deps/sockets/network.wit | 11 +- .../wit/deps/sockets/tcp-create-socket.wit | 16 +- crates/wasi/wit/deps/sockets/tcp.wit | 92 ++--- .../wit/deps/sockets/udp-create-socket.wit | 16 +- crates/wasi/wit/deps/sockets/udp.wit | 72 ++-- .../wit/deps/wasi-cli-base/environment.wit | 4 +- crates/wasi/wit/deps/wasi-cli-base/exit.wit | 2 +- .../wasi/wit/deps/wasi-cli-base/preopens.wit | 6 +- crates/wasi/wit/deps/wasi-cli-base/stdio.wit | 6 +- crates/wasi/wit/main.wit | 1 + crates/wasi/wit/reactor.wit | 26 -- crates/wasi/wit/test.wit | 19 + crates/wasmtime/src/component/matching.rs | 2 +- crates/wasmtime/src/component/mod.rs | 28 +- crates/wit-bindgen/src/lib.rs | 292 ++++++++++---- supply-chain/imports.lock | 87 +++-- tests/all/component_model/bindgen.rs | 8 +- tests/all/component_model/bindgen/results.rs | 41 +- 119 files changed, 1314 insertions(+), 2280 deletions(-) delete mode 100644 crates/test-programs/reactor-tests/wit/deps.lock delete mode 100644 crates/test-programs/reactor-tests/wit/deps.toml delete mode 100644 crates/test-programs/reactor-tests/wit/deps/clocks/monotonic-clock.wit delete mode 100644 crates/test-programs/reactor-tests/wit/deps/clocks/timezone.wit delete mode 100644 crates/test-programs/reactor-tests/wit/deps/clocks/wall-clock.wit delete mode 100644 crates/test-programs/reactor-tests/wit/deps/io/streams.wit delete mode 100644 crates/test-programs/reactor-tests/wit/deps/poll/poll.wit delete mode 100644 crates/test-programs/reactor-tests/wit/deps/wasi-cli-base/environment.wit delete mode 100644 crates/test-programs/reactor-tests/wit/deps/wasi-cli-base/exit.wit delete mode 100644 crates/test-programs/reactor-tests/wit/test-reactor.wit delete mode 100644 crates/wasi-preview1-component-adapter/wit/deps/clocks/monotonic-clock.wit delete mode 100644 crates/wasi-preview1-component-adapter/wit/deps/clocks/timezone.wit delete mode 100644 crates/wasi-preview1-component-adapter/wit/deps/clocks/wall-clock.wit delete mode 100644 crates/wasi-preview1-component-adapter/wit/deps/http/incoming-handler.wit delete mode 100644 crates/wasi-preview1-component-adapter/wit/deps/http/outgoing-handler.wit delete mode 100644 crates/wasi-preview1-component-adapter/wit/deps/http/types.wit delete mode 100644 crates/wasi-preview1-component-adapter/wit/deps/io/streams.wit delete mode 100644 crates/wasi-preview1-component-adapter/wit/deps/logging/handler.wit delete mode 100644 crates/wasi-preview1-component-adapter/wit/deps/poll/poll.wit delete mode 100644 crates/wasi-preview1-component-adapter/wit/deps/preview/reactor.wit delete mode 100644 crates/wasi-preview1-component-adapter/wit/deps/sockets/instance-network.wit delete mode 100644 crates/wasi-preview1-component-adapter/wit/deps/wasi-cli-base/environment.wit delete mode 100644 crates/wasi-preview1-component-adapter/wit/deps/wasi-cli-base/exit.wit delete mode 100644 crates/wasi/wit/command.wit create mode 100644 crates/wasi/wit/main.wit delete mode 100644 crates/wasi/wit/reactor.wit create mode 100644 crates/wasi/wit/test.wit diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 4b0fa85aba8a..8de9ac36eef9 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -222,6 +222,7 @@ jobs: cargo doc --no-deps --workspace \ --exclude wasmtime-cli \ --exclude test-programs \ + --exclude wasi-http-tests \ --exclude cranelift-codegen-meta \ --features component-model - run: cargo doc --package cranelift-codegen-meta --document-private-items diff --git a/Cargo.lock b/Cargo.lock index 4ebf1c4322a9..1121cd24ed89 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -686,7 +686,7 @@ dependencies = [ "target-lexicon", "thiserror", "toml", - "wasmparser 0.105.0", + "wasmparser 0.107.0", "wat", ] @@ -862,7 +862,7 @@ dependencies = [ "serde", "smallvec", "target-lexicon", - "wasmparser 0.105.0", + "wasmparser 0.107.0", "wasmtime-types", "wat", ] @@ -3150,7 +3150,7 @@ dependencies = [ "wasmtime", "wasmtime-wasi", "wasmtime-wasi-http", - "wit-component 0.9.0", + "wit-component", ] [[package]] @@ -3675,74 +3675,52 @@ dependencies = [ [[package]] name = "wasm-encoder" -version = "0.26.0" +version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d05d0b6fcd0aeb98adf16e7975331b3c17222aa815148f5b976370ce589d80ef" +checksum = "18c41dbd92eaebf3612a39be316540b8377c871cb9bde6b064af962984912881" dependencies = [ "leb128", ] -[[package]] -name = "wasm-encoder" -version = "0.27.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e77053dc709db790691d3732cfc458adc5acc881dec524965c608effdcd9c581" -dependencies = [ - "leb128", -] - -[[package]] -name = "wasm-metadata" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbdef99fafff010c57fabb7bc703f0903ec16fcee49207a22dcc4f78ea44562f" -dependencies = [ - "anyhow", - "indexmap", - "serde", - "wasm-encoder 0.26.0", - "wasmparser 0.104.0", -] - [[package]] name = "wasm-metadata" -version = "0.6.0" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27e6532071b112df81d756fabafab8cc882b84ae3d6ce9b90f3d90c80e4abe05" +checksum = "36e5156581ff4a302405c44ca7c85347563ca431d15f1a773f12c9c7b9a6cdc9" dependencies = [ "anyhow", "indexmap", "serde", - "wasm-encoder 0.27.0", - "wasmparser 0.105.0", + "wasm-encoder 0.29.0", + "wasmparser 0.107.0", ] [[package]] name = "wasm-mutate" -version = "0.2.25" +version = "0.2.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b8c74fd20d97b9ba8b1a6e3ccc6ec715e6c6d4605668926e582e88580180d96" +checksum = "f354beb7e2ccaf66dd263328486240899755ae0df3ac4b76305dace67fbd2169" dependencies = [ "egg", "log", "rand 0.8.5", "thiserror", - "wasm-encoder 0.27.0", - "wasmparser 0.105.0", + "wasm-encoder 0.29.0", + "wasmparser 0.107.0", ] [[package]] name = "wasm-smith" -version = "0.12.8" +version = "0.12.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13c11c745f6f4ff2f953d8a94ef056b04b468fc021285cfaf614e77791c05499" +checksum = "027ec1c470cd5d56c43b8e02040250b136ddb5975dd76a1c16915137f5f17e76" dependencies = [ "arbitrary", "flagset", "indexmap", "leb128", - "wasm-encoder 0.27.0", - "wasmparser 0.105.0", + "wasm-encoder 0.29.0", + "wasmparser 0.107.0", ] [[package]] @@ -3794,22 +3772,12 @@ dependencies = [ [[package]] name = "wasmparser" -version = "0.104.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a396af81a7c56ad976131d6a35e4b693b78a1ea0357843bd436b4577e254a7d" -dependencies = [ - "indexmap", - "url", -] - -[[package]] -name = "wasmparser" -version = "0.105.0" +version = "0.107.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83be9e0b3f9570dc1979a33ae7b89d032c73211564232b99976553e5c155ec32" +checksum = "29e3ac9b780c7dda0cac7a52a5d6d2d6707cc6e3451c9db209b6c758f40d7acb" dependencies = [ "indexmap", - "url", + "semver", ] [[package]] @@ -3823,12 +3791,12 @@ dependencies = [ [[package]] name = "wasmprinter" -version = "0.2.57" +version = "0.2.59" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50b0e5ed7a74a065637f0d7798ce5f29cadb064980d24b0c82af5200122fa0d8" +checksum = "cc960b30b84abca377768f3c62cff3a1c74db8c0f6759ed581827da0bd3a3fed" dependencies = [ "anyhow", - "wasmparser 0.105.0", + "wasmparser 0.107.0", ] [[package]] @@ -3855,7 +3823,7 @@ dependencies = [ "target-lexicon", "tempfile", "wasi-cap-std-sync", - "wasmparser 0.105.0", + "wasmparser 0.107.0", "wasmtime-cache", "wasmtime-component-macro", "wasmtime-component-util", @@ -3970,8 +3938,8 @@ dependencies = [ "test-programs", "tokio", "walkdir", - "wasm-encoder 0.27.0", - "wasmparser 0.105.0", + "wasm-encoder 0.29.0", + "wasmparser 0.107.0", "wasmtime", "wasmtime-cache", "wasmtime-cli-flags", @@ -3986,7 +3954,7 @@ dependencies = [ "wasmtime-wasi-nn", "wasmtime-wasi-threads", "wasmtime-wast", - "wast 58.0.0", + "wast 60.0.0", "wat", "windows-sys 0.48.0", ] @@ -4039,7 +4007,7 @@ dependencies = [ "object", "target-lexicon", "thiserror", - "wasmparser 0.105.0", + "wasmparser 0.107.0", "wasmtime-cranelift-shared", "wasmtime-environ", ] @@ -4074,8 +4042,8 @@ dependencies = [ "serde", "target-lexicon", "thiserror", - "wasm-encoder 0.27.0", - "wasmparser 0.105.0", + "wasm-encoder 0.29.0", + "wasmparser 0.107.0", "wasmprinter", "wasmtime-component-util", "wasmtime-types", @@ -4090,7 +4058,7 @@ dependencies = [ "component-fuzz-util", "env_logger 0.10.0", "libfuzzer-sys", - "wasmparser 0.105.0", + "wasmparser 0.107.0", "wasmprinter", "wasmtime-environ", "wat", @@ -4144,7 +4112,7 @@ dependencies = [ "rand 0.8.5", "smallvec", "target-lexicon", - "wasmparser 0.105.0", + "wasmparser 0.107.0", "wasmtime", "wasmtime-fuzzing", ] @@ -4164,12 +4132,12 @@ dependencies = [ "target-lexicon", "tempfile", "v8", - "wasm-encoder 0.27.0", + "wasm-encoder 0.29.0", "wasm-mutate", "wasm-smith", "wasm-spec-interpreter", "wasmi", - "wasmparser 0.105.0", + "wasmparser 0.107.0", "wasmprinter", "wasmtime", "wasmtime-wast", @@ -4251,7 +4219,7 @@ dependencies = [ "cranelift-entity", "serde", "thiserror", - "wasmparser 0.105.0", + "wasmparser 0.107.0", ] [[package]] @@ -4338,7 +4306,7 @@ dependencies = [ "anyhow", "log", "wasmtime", - "wast 58.0.0", + "wast 60.0.0", ] [[package]] @@ -4350,7 +4318,7 @@ dependencies = [ "gimli", "object", "target-lexicon", - "wasmparser 0.105.0", + "wasmparser 0.107.0", "wasmtime-cranelift-shared", "wasmtime-environ", "winch-codegen", @@ -4376,23 +4344,23 @@ dependencies = [ [[package]] name = "wast" -version = "58.0.0" +version = "60.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "372eecae2d10a5091c2005b32377d7ecd6feecdf2c05838056d02d8b4f07c429" +checksum = "bd06cc744b536e30387e72a48fdd492105b9c938bb4f415c39c616a7a0a697ad" dependencies = [ "leb128", "memchr", "unicode-width", - "wasm-encoder 0.27.0", + "wasm-encoder 0.29.0", ] [[package]] name = "wat" -version = "1.0.64" +version = "1.0.66" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d47446190e112ab1579ab40b3ad7e319d859d74e5134683f04e9f0747bf4173" +checksum = "5abe520f0ab205366e9ac7d3e6b2fc71de44e32a2b58f2ec871b6b575bdcea3b" dependencies = [ - "wast 58.0.0", + "wast 60.0.0", ] [[package]] @@ -4520,7 +4488,7 @@ dependencies = [ "regalloc2", "smallvec", "target-lexicon", - "wasmparser 0.105.0", + "wasmparser 0.107.0", "wasmtime-environ", ] @@ -4564,7 +4532,7 @@ dependencies = [ "similar", "target-lexicon", "toml", - "wasmparser 0.105.0", + "wasmparser 0.107.0", "wasmtime-environ", "wat", "winch-codegen", @@ -4717,9 +4685,8 @@ dependencies = [ [[package]] name = "wit-bindgen" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad22d93d3f55847ac4b3df31607a26f35231754ef472382319de032770d8b5bf" +version = "0.7.0" +source = "git+https://github.com/bytecodealliance/wit-bindgen?branch=wasmtime-2023-05-26-wit-changes#7df2c15f54d7c20593ff2d38db48014889c9a46d" dependencies = [ "bitflags 2.2.1", "wit-bindgen-rust-macro", @@ -4727,33 +4694,30 @@ dependencies = [ [[package]] name = "wit-bindgen-core" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5bc1b5a6e87f16491f2297f75312dc0fb354f8c88c8bece53ea0d3167fc98867" +version = "0.7.0" +source = "git+https://github.com/bytecodealliance/wit-bindgen?branch=wasmtime-2023-05-26-wit-changes#7df2c15f54d7c20593ff2d38db48014889c9a46d" dependencies = [ "anyhow", - "wit-component 0.8.2", + "wit-component", "wit-parser", ] [[package]] name = "wit-bindgen-rust" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7946a66f1132d3322c29de9d28097bd263f67e1e0909054f91253aa103cdf8be" +version = "0.7.0" +source = "git+https://github.com/bytecodealliance/wit-bindgen?branch=wasmtime-2023-05-26-wit-changes#7df2c15f54d7c20593ff2d38db48014889c9a46d" dependencies = [ "heck", - "wasm-metadata 0.5.0", + "wasm-metadata", "wit-bindgen-core", "wit-bindgen-rust-lib", - "wit-component 0.8.2", + "wit-component", ] [[package]] name = "wit-bindgen-rust-lib" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0baf7325748c5d363ab6ed3ddbd155c241cfe385410c61f2505ec978a61a2d2c" +version = "0.7.0" +source = "git+https://github.com/bytecodealliance/wit-bindgen?branch=wasmtime-2023-05-26-wit-changes#7df2c15f54d7c20593ff2d38db48014889c9a46d" dependencies = [ "heck", "wit-bindgen-core", @@ -4761,63 +4725,45 @@ dependencies = [ [[package]] name = "wit-bindgen-rust-macro" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42c131da5d2ba7746908e1401d474640371c31ad05281528c2a9e945a87d19be" +version = "0.7.0" +source = "git+https://github.com/bytecodealliance/wit-bindgen?branch=wasmtime-2023-05-26-wit-changes#7df2c15f54d7c20593ff2d38db48014889c9a46d" dependencies = [ "anyhow", "proc-macro2", "syn 2.0.16", "wit-bindgen-core", "wit-bindgen-rust", - "wit-component 0.8.2", -] - -[[package]] -name = "wit-component" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e291ff83cb9c8e59963cc6922bdda77ed8f5517d6835f0c98070c4e7f1ae4996" -dependencies = [ - "anyhow", - "bitflags 1.3.2", - "indexmap", - "log", - "url", - "wasm-encoder 0.26.0", - "wasm-metadata 0.5.0", - "wasmparser 0.104.0", - "wit-parser", + "wit-component", ] [[package]] name = "wit-component" -version = "0.9.0" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3cc435c15009f80d5e114d0dd3792959171f1fc28be2418e0f570d83b925a33" +checksum = "7cbd4c7f8f400327c482c88571f373844b7889e61460650d650fc5881bb3575c" dependencies = [ "anyhow", "bitflags 1.3.2", "indexmap", "log", - "url", - "wasm-encoder 0.27.0", - "wasm-metadata 0.6.0", - "wasmparser 0.105.0", + "wasm-encoder 0.29.0", + "wasm-metadata", + "wasmparser 0.107.0", "wit-parser", ] [[package]] name = "wit-parser" -version = "0.7.1" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ca2581061573ef6d1754983d7a9b3ed5871ef859d52708ea9a0f5af32919172" +checksum = "6daec9f093dbaea0e94043eeb92ece327bbbe70c86b1f41aca9bbfefd7f050f0" dependencies = [ "anyhow", "id-arena", "indexmap", "log", "pulldown-cmark", + "semver", "unicode-xid", "url", ] diff --git a/Cargo.toml b/Cargo.toml index 201494b6981f..6c33b266fe7e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -197,18 +197,18 @@ io-lifetimes = { version = "1.0.0", default-features = false } rustix = "0.37.13" # wit-bindgen: -wit-bindgen = "0.6.0" +wit-bindgen = { version = "0.7.0", default-features = false } # wasm-tools family: -wasmparser = "0.105.0" -wat = "1.0.64" -wast = "58.0.0" -wasmprinter = "0.2.57" -wasm-encoder = "0.27.0" -wasm-smith = "0.12.8" -wasm-mutate = "0.2.25" -wit-parser = "0.7.1" -wit-component = "0.9.0" +wasmparser = "0.107.0" +wat = "1.0.66" +wast = "60.0.0" +wasmprinter = "0.2.59" +wasm-encoder = "0.29.0" +wasm-smith = "0.12.10" +wasm-mutate = "0.2.27" +wit-parser = "0.8.0" +wit-component = "0.11.0" # Non-Bytecode Alliance maintained dependencies: # -------------------------- @@ -248,7 +248,8 @@ default = [ "vtune", "wasi-nn", "wasi-threads", - "wasi-http", + # TODO: the WIT needs to be updated + #"wasi-http", "pooling-allocator", ] jitdump = ["wasmtime/jitdump"] @@ -311,3 +312,5 @@ debug-assertions = false # string initializers. overflow-checks = false +[patch.crates-io] +wit-bindgen = { git = 'https://github.com/bytecodealliance/wit-bindgen', branch = 'wasmtime-2023-05-26-wit-changes' } diff --git a/cranelift/wasm/src/sections_translator.rs b/cranelift/wasm/src/sections_translator.rs index 68705ad4a775..e7b0486ea6ce 100644 --- a/cranelift/wasm/src/sections_translator.rs +++ b/cranelift/wasm/src/sections_translator.rs @@ -56,6 +56,9 @@ pub fn parse_type_section<'a>( let ty = environ.convert_func_type(&wasm_func_ty); environ.declare_type_func(ty)?; } + Type::Array(_) => { + unimplemented!("gc proposal"); + } } } Ok(()) diff --git a/crates/component-macro/src/bindgen.rs b/crates/component-macro/src/bindgen.rs index 02865920458e..e41e0fa2abcf 100644 --- a/crates/component-macro/src/bindgen.rs +++ b/crates/component-macro/src/bindgen.rs @@ -78,7 +78,16 @@ impl Parse for Config { if inline.is_some() { return Err(Error::new(s.span(), "cannot specify a second source")); } - inline = Some(format!("default world interfaces {{ {} }}", s.value())); + inline = Some(format!( + " + package wasmtime:component-macro-synthesized + + world interfaces {{ + {} + }} + ", + s.value() + )); if world.is_some() { return Err(Error::new( @@ -86,7 +95,7 @@ impl Parse for Config { "cannot specify a world with `interfaces`", )); } - world = Some("macro-input.interfaces".to_string()); + world = Some("interfaces".to_string()); opts.only_interfaces = true; } @@ -130,7 +139,7 @@ fn parse_source( } else { let pkg = UnresolvedPackage::parse_file(path)?; files.extend(pkg.source_files().map(|s| s.to_owned())); - resolve.push(pkg, &Default::default()) + resolve.push(pkg) } }; @@ -141,16 +150,7 @@ fn parse_source( }; let inline_pkg = if let Some(inline) = inline { - let deps = resolve - .packages - .iter() - .map(|(id, p)| (p.name.clone(), id)) - .collect(); - - Some(resolve.push( - UnresolvedPackage::parse("macro-input".as_ref(), &inline)?, - &deps, - )?) + Some(resolve.push(UnresolvedPackage::parse("macro-input".as_ref(), &inline)?)?) } else { None }; diff --git a/crates/component-macro/tests/codegen.rs b/crates/component-macro/tests/codegen.rs index ac39534022c0..616f3253c614 100644 --- a/crates/component-macro/tests/codegen.rs +++ b/crates/component-macro/tests/codegen.rs @@ -4,9 +4,6 @@ macro_rules! gentest { mod sugar { wasmtime::component::bindgen!(in $path); } - mod normal { - wasmtime::component::bindgen!($name in $path); - } mod async_ { wasmtime::component::bindgen!({ path: $path, @@ -16,15 +13,12 @@ macro_rules! gentest { mod tracing { wasmtime::component::bindgen!({ path: $path, - world: $name, tracing: true, duplicate_if_necessary: true, }); } } - // ... }; - } component_macro_test_helpers::foreach!(gentest); diff --git a/crates/component-macro/tests/codegen/char.wit b/crates/component-macro/tests/codegen/char.wit index 01b20f70077f..b49947b38abb 100644 --- a/crates/component-macro/tests/codegen/char.wit +++ b/crates/component-macro/tests/codegen/char.wit @@ -1,3 +1,5 @@ +package foo:foo + interface chars { /// A function that accepts a character take-char: func(x: char) @@ -5,7 +7,7 @@ interface chars { return-char: func() -> char } -default world the-world { - import imports: self.chars - export exports: self.chars +world the-world { + import chars + export chars } diff --git a/crates/component-macro/tests/codegen/conventions.wit b/crates/component-macro/tests/codegen/conventions.wit index 2c5645c66313..a96b5afd3444 100644 --- a/crates/component-macro/tests/codegen/conventions.wit +++ b/crates/component-macro/tests/codegen/conventions.wit @@ -1,4 +1,5 @@ // hello 🐱 world +package foo:foo interface conventions { kebab-case: func() @@ -32,7 +33,7 @@ interface conventions { %bool: func() } -default world the-world { - import imports: self.conventions - export exports: self.conventions +world the-world { + import conventions + export conventions } diff --git a/crates/component-macro/tests/codegen/direct-import.wit b/crates/component-macro/tests/codegen/direct-import.wit index d2b612d6de71..67d252a4a898 100644 --- a/crates/component-macro/tests/codegen/direct-import.wit +++ b/crates/component-macro/tests/codegen/direct-import.wit @@ -1,3 +1,5 @@ -default world foo { +package foo:foo + +world foo { import foo: func() } diff --git a/crates/component-macro/tests/codegen/empty.wit b/crates/component-macro/tests/codegen/empty.wit index 1f99081f58cb..b720c27d628e 100644 --- a/crates/component-macro/tests/codegen/empty.wit +++ b/crates/component-macro/tests/codegen/empty.wit @@ -1 +1,2 @@ -default world empty {} +package foo:foo +world empty {} diff --git a/crates/component-macro/tests/codegen/flags.wit b/crates/component-macro/tests/codegen/flags.wit index b5a2fa2d1c83..8c9c1437169d 100644 --- a/crates/component-macro/tests/codegen/flags.wit +++ b/crates/component-macro/tests/codegen/flags.wit @@ -1,3 +1,5 @@ +package foo:foo + interface flegs { flags flag1 { b0, @@ -47,7 +49,7 @@ interface flegs { roundtrip-flag64: func(x: flag64) -> flag64 } -default world the-flags { - import import-flags: self.flegs - export export-flags: self.flegs +world the-flags { + import flegs + export flegs } diff --git a/crates/component-macro/tests/codegen/floats.wit b/crates/component-macro/tests/codegen/floats.wit index 4a0c67ce2c29..6cd720a8dc39 100644 --- a/crates/component-macro/tests/codegen/floats.wit +++ b/crates/component-macro/tests/codegen/floats.wit @@ -1,3 +1,5 @@ +package foo:foo + interface floats { float32-param: func(x: float32) float64-param: func(x: float64) @@ -5,7 +7,7 @@ interface floats { float64-result: func() -> float64 } -default world the-world { - import imports: self.floats - export exports: self.floats +world the-world { + import floats + export floats } diff --git a/crates/component-macro/tests/codegen/function-new.wit b/crates/component-macro/tests/codegen/function-new.wit index fed79c6633c6..2f4e407566cd 100644 --- a/crates/component-macro/tests/codegen/function-new.wit +++ b/crates/component-macro/tests/codegen/function-new.wit @@ -1,3 +1,4 @@ -default world foo { +package foo:foo +world foo { export new: func() } diff --git a/crates/component-macro/tests/codegen/integers.wit b/crates/component-macro/tests/codegen/integers.wit index bfad272882d0..2f5866bb2ae6 100644 --- a/crates/component-macro/tests/codegen/integers.wit +++ b/crates/component-macro/tests/codegen/integers.wit @@ -1,3 +1,5 @@ +package foo:foo + interface integers { a1: func(x: u8) a2: func(x: s8) @@ -32,7 +34,7 @@ interface integers { pair-ret: func() -> tuple } -default world the-world { - import imports: self.integers - export exports: self.integers +world the-world { + import integers + export integers } diff --git a/crates/component-macro/tests/codegen/lists.wit b/crates/component-macro/tests/codegen/lists.wit index 19b946068706..256a1cdf8fcf 100644 --- a/crates/component-macro/tests/codegen/lists.wit +++ b/crates/component-macro/tests/codegen/lists.wit @@ -1,3 +1,5 @@ +package foo:foo + interface lists { list-u8-param: func(x: list) list-u16-param: func(x: list) @@ -77,7 +79,7 @@ interface lists { load-store-everything: func(a: load-store-all-sizes) -> load-store-all-sizes } -default world the-lists { - import import-lists: self.lists - export export-lists: self.lists +world the-lists { + import lists + export lists } diff --git a/crates/component-macro/tests/codegen/many-arguments.wit b/crates/component-macro/tests/codegen/many-arguments.wit index a5b67b2184b1..cbfc123144fa 100644 --- a/crates/component-macro/tests/codegen/many-arguments.wit +++ b/crates/component-macro/tests/codegen/many-arguments.wit @@ -1,3 +1,5 @@ +package foo:foo + interface manyarg { many-args: func( a1: u64, @@ -44,7 +46,7 @@ interface manyarg { big-argument: func(x: big-struct) } -default world the-world { - import imports: self.manyarg - export exports: self.manyarg +world the-world { + import manyarg + export manyarg } diff --git a/crates/component-macro/tests/codegen/multi-return.wit b/crates/component-macro/tests/codegen/multi-return.wit index 716e77a6c850..69951b2c3393 100644 --- a/crates/component-macro/tests/codegen/multi-return.wit +++ b/crates/component-macro/tests/codegen/multi-return.wit @@ -1,3 +1,5 @@ +package foo:foo + interface multi-return { mra: func() mrb: func() -> () @@ -6,7 +8,7 @@ interface multi-return { mre: func() -> (a: u32, b: float32) } -default world the-world { - import imports: self.multi-return - export exports: self.multi-return +world the-world { + import multi-return + export multi-return } diff --git a/crates/component-macro/tests/codegen/records.wit b/crates/component-macro/tests/codegen/records.wit index 39d5e81694e8..f51bb8f28f75 100644 --- a/crates/component-macro/tests/codegen/records.wit +++ b/crates/component-macro/tests/codegen/records.wit @@ -1,3 +1,5 @@ +package foo:foo + interface records { tuple-arg: func(x: tuple) tuple-result: func() -> tuple @@ -53,7 +55,7 @@ interface records { typedef-inout: func(e: tuple-typedef2) -> s32 } -default world the-world { - import imports: self.records - export exports: self.records +world the-world { + import records + export records } diff --git a/crates/component-macro/tests/codegen/rename.wit b/crates/component-macro/tests/codegen/rename.wit index d60d4f6f9f43..8bfc7f36862b 100644 --- a/crates/component-macro/tests/codegen/rename.wit +++ b/crates/component-macro/tests/codegen/rename.wit @@ -1,5 +1,7 @@ +package foo:foo + interface red { - use self.green.{thing} + use green.{thing} foo: func() -> thing } @@ -8,7 +10,7 @@ interface green { type thing = s32 } -default world neptune { - import blue: self.red - import orange: self.green +world neptune { + import red + import green } diff --git a/crates/component-macro/tests/codegen/share-types.wit b/crates/component-macro/tests/codegen/share-types.wit index 106ee70936d9..8d36d1b0aa88 100644 --- a/crates/component-macro/tests/codegen/share-types.wit +++ b/crates/component-macro/tests/codegen/share-types.wit @@ -1,3 +1,5 @@ +package foo:foo + interface http-types{ record request { method: string @@ -7,13 +9,13 @@ interface http-types{ } } -default world http-interface { +world http-interface { export http-handler: interface { - use self.http-types.{request,response} + use http-types.{request,response} handle-request: func(request: request) -> response } import http-fetch: interface { - use self.http-types.{request,response} + use http-types.{request,response} fetch-request: func(request: request) -> response } } diff --git a/crates/component-macro/tests/codegen/simple-functions.wit b/crates/component-macro/tests/codegen/simple-functions.wit index cdb1183790fa..2593d199e565 100644 --- a/crates/component-macro/tests/codegen/simple-functions.wit +++ b/crates/component-macro/tests/codegen/simple-functions.wit @@ -1,3 +1,5 @@ +package foo:foo + interface simple { f1: func() f2: func(a: u32) @@ -9,7 +11,7 @@ interface simple { f6: func(a: u32, b: u32, c: u32) -> tuple } -default world the-world { - import imports: self.simple - export exports: self.simple +world the-world { + import simple + export simple } diff --git a/crates/component-macro/tests/codegen/simple-lists.wit b/crates/component-macro/tests/codegen/simple-lists.wit index 885cdeb74305..8e082b6e34e7 100644 --- a/crates/component-macro/tests/codegen/simple-lists.wit +++ b/crates/component-macro/tests/codegen/simple-lists.wit @@ -1,3 +1,5 @@ +package foo:foo + interface simple-lists { simple-list1: func(l: list) simple-list2: func() -> list @@ -5,7 +7,7 @@ interface simple-lists { simple-list4: func(l: list>) -> list> } -default world my-world { - import imports: self.simple-lists - export exports: self.simple-lists +world my-world { + import simple-lists + export simple-lists } diff --git a/crates/component-macro/tests/codegen/simple-wasi.wit b/crates/component-macro/tests/codegen/simple-wasi.wit index 02c47dc9b8f4..60192473d99e 100644 --- a/crates/component-macro/tests/codegen/simple-wasi.wit +++ b/crates/component-macro/tests/codegen/simple-wasi.wit @@ -1,3 +1,5 @@ +package foo:foo + interface wasi-filesystem { record descriptor-stat { } @@ -15,7 +17,7 @@ interface wall-clock { } } -default world wasi { - import wasi-filesystem: self.wasi-filesystem - import wall-clock: self.wall-clock +world wasi { + import wasi-filesystem + import wall-clock } diff --git a/crates/component-macro/tests/codegen/small-anonymous.wit b/crates/component-macro/tests/codegen/small-anonymous.wit index 96436091344d..ad9c67287d4e 100644 --- a/crates/component-macro/tests/codegen/small-anonymous.wit +++ b/crates/component-macro/tests/codegen/small-anonymous.wit @@ -1,3 +1,5 @@ +package foo:foo + interface anon { enum error { success, @@ -7,7 +9,7 @@ interface anon { option-test: func() -> result, error> } -default world the-world { - import imports: self.anon - export exports: self.anon +world the-world { + import anon + export anon } diff --git a/crates/component-macro/tests/codegen/smoke-default.wit b/crates/component-macro/tests/codegen/smoke-default.wit index 0d269359063f..90be0b1e3cdc 100644 --- a/crates/component-macro/tests/codegen/smoke-default.wit +++ b/crates/component-macro/tests/codegen/smoke-default.wit @@ -1,3 +1,5 @@ -default world the-world { +package foo:foo + +world the-world { export y: func() } diff --git a/crates/component-macro/tests/codegen/smoke-export.wit b/crates/component-macro/tests/codegen/smoke-export.wit index cefdc19823a0..983f1c35066e 100644 --- a/crates/component-macro/tests/codegen/smoke-export.wit +++ b/crates/component-macro/tests/codegen/smoke-export.wit @@ -1,4 +1,6 @@ -default world the-world { +package foo:foo + +world the-world { export the-name: interface { y: func() } diff --git a/crates/component-macro/tests/codegen/smoke.wit b/crates/component-macro/tests/codegen/smoke.wit index 6d8e80ccea86..0476bd988ec1 100644 --- a/crates/component-macro/tests/codegen/smoke.wit +++ b/crates/component-macro/tests/codegen/smoke.wit @@ -1,4 +1,6 @@ -default world the-world { +package foo:foo + +world the-world { import imports: interface { y: func() } diff --git a/crates/component-macro/tests/codegen/strings.wit b/crates/component-macro/tests/codegen/strings.wit index 7fc1885529bc..650300acfb9d 100644 --- a/crates/component-macro/tests/codegen/strings.wit +++ b/crates/component-macro/tests/codegen/strings.wit @@ -1,10 +1,12 @@ +package foo:foo + interface strings { a: func(x: string) b: func() -> string c: func(a: string, b: string) -> string } -default world the-world { - import imports: self.strings - export exports: self.strings +world the-world { + import strings + export strings } diff --git a/crates/component-macro/tests/codegen/unions.wit b/crates/component-macro/tests/codegen/unions.wit index 07e0f380a0d0..252f513f2de8 100644 --- a/crates/component-macro/tests/codegen/unions.wit +++ b/crates/component-macro/tests/codegen/unions.wit @@ -1,3 +1,5 @@ +package foo:foo + interface unions { /// A union of all of the integral types union all-integers { @@ -58,7 +60,7 @@ interface unions { identify-distinguishable-num: func(num: distinguishable-num) -> u8 } -default world the-unions { - import import-unions: self.unions - export export-unions: self.unions +world the-unions { + import unions + export unions } diff --git a/crates/component-macro/tests/codegen/use-paths.wit b/crates/component-macro/tests/codegen/use-paths.wit index 1e877379caf4..dab6646afac8 100644 --- a/crates/component-macro/tests/codegen/use-paths.wit +++ b/crates/component-macro/tests/codegen/use-paths.wit @@ -1,3 +1,5 @@ +package foo:foo + interface a { record foo {} @@ -5,22 +7,22 @@ interface a { } interface b { - use self.a.{foo} + use a.{foo} a: func() -> foo } interface c { - use self.b.{foo} + use b.{foo} a: func() -> foo } -default world d { - import a: self.a - import b: self.b +world d { + import a + import b import d: interface { - use self.c.{foo} + use c.{foo} b: func() -> foo } diff --git a/crates/component-macro/tests/codegen/variants.wit b/crates/component-macro/tests/codegen/variants.wit index 590675dcf6c0..b6c47d89650e 100644 --- a/crates/component-macro/tests/codegen/variants.wit +++ b/crates/component-macro/tests/codegen/variants.wit @@ -1,3 +1,5 @@ +package foo:foo + interface variants { enum e1 { a, @@ -139,7 +141,7 @@ interface variants { return-named-result: func() -> (a: result) } -default world my-world { - import imports: self.variants - export exports: self.variants +world my-world { + import variants + export variants } diff --git a/crates/component-macro/tests/codegen/worlds-with-types.wit b/crates/component-macro/tests/codegen/worlds-with-types.wit index 25db9036da12..dc4cbddcbabe 100644 --- a/crates/component-macro/tests/codegen/worlds-with-types.wit +++ b/crates/component-macro/tests/codegen/worlds-with-types.wit @@ -1,9 +1,11 @@ +package foo:foo + interface i { type t = u16 } -default world foo { - use self.i.{t as u} +world foo { + use i.{t as u} type t = u32 diff --git a/crates/environ/src/component/translate.rs b/crates/environ/src/component/translate.rs index 5abd9e77755f..cb2306e25f2c 100644 --- a/crates/environ/src/component/translate.rs +++ b/crates/environ/src/component/translate.rs @@ -8,7 +8,7 @@ use anyhow::{bail, Result}; use indexmap::IndexMap; use std::collections::HashMap; use std::mem; -use wasmparser::{Chunk, Encoding, Parser, Payload, Validator}; +use wasmparser::{Chunk, ComponentExternName, Encoding, Parser, Payload, Validator}; mod adapt; pub use self::adapt::*; @@ -164,7 +164,7 @@ struct Translation<'data> { #[allow(missing_docs)] enum LocalInitializer<'data> { // imports - Import(&'data str, TypeDef), + Import(ComponentExternName<'data>, TypeDef), // canonical function sections Lower(ComponentFuncIndex, LocalCanonicalOptions), @@ -622,7 +622,7 @@ impl<'a, 'data> Translator<'a, 'data> { for export in s { let export = export?; let item = self.kind_to_item(export.kind, export.index); - let prev = self.result.exports.insert(export.name, item); + let prev = self.result.exports.insert(export.name.as_str(), item); assert!(prev.is_none()); self.result .initializers @@ -831,9 +831,9 @@ impl<'a, 'data> Translator<'a, 'data> { ComponentItem::Type(ty) => Some(ComponentItemType::Type(ty)), ComponentItem::Module(_) => None, }; - map.insert(export.name, idx); + map.insert(export.name.as_str(), idx); if let Some(ty) = ty { - types.insert(export.name, ty); + types.insert(export.name.as_str(), ty); } } @@ -900,15 +900,15 @@ impl<'a, 'data> Translator<'a, 'data> { // An imported component instance is being aliased, so the type of // the aliased item is directly available from the instance type. ComponentInstanceType::Index(ty) => { - let (_url, ty) = &self.types[ty].exports[name]; - self.push_typedef(*ty); + let ty = self.types[ty].exports[name]; + self.push_typedef(ty); } // An imported component was instantiated so the type of the aliased // export is available through the type of the export on the // original component. ComponentInstanceType::InstantiatedIndex(ty) => { - let (_, ty) = self.types[ty].exports[name]; + let ty = self.types[ty].exports[name]; self.push_typedef(ty); } diff --git a/crates/environ/src/component/translate/inline.rs b/crates/environ/src/component/translate/inline.rs index 95aa449c1e9b..62a7d007a318 100644 --- a/crates/environ/src/component/translate/inline.rs +++ b/crates/environ/src/component/translate/inline.rs @@ -82,9 +82,12 @@ pub(super) fn run( LocalInitializer::Import(name, ty) => (name, ty), _ => continue, }; - let index = inliner.result.import_types.push((name.to_string(), ty)); + let index = inliner + .result + .import_types + .push((name.as_str().to_string(), ty)); let path = ImportPath::root(index); - args.insert(name, ComponentItemDef::from_import(path, ty)?); + args.insert(name.as_str(), ComponentItemDef::from_import(path, ty)?); } // This will run the inliner to completion after being seeded with the @@ -376,7 +379,7 @@ impl<'a> Inliner<'a> { // but for sub-components this will do resolution to connect what // was provided as an import at the instantiation-site to what was // needed during the component's instantiation. - Import(name, _ty) => match &frame.args[name] { + Import(name, _ty) => match &frame.args[name.as_str()] { ComponentItemDef::Module(i) => { frame.modules.push(i.clone()); } @@ -674,7 +677,7 @@ impl<'a> Inliner<'a> { ComponentInstanceDef::Import(path, ty) => { let mut path = path.clone(); path.path.push(name); - match self.types[*ty].exports[*name].1 { + match self.types[*ty].exports[*name] { TypeDef::ComponentFunc(_) => { frame.component_funcs.push(ComponentFuncDef::Import(path)); } @@ -939,7 +942,7 @@ impl<'a> Inliner<'a> { // Note that for now this would only work with // module-exporting instances. ComponentInstanceDef::Import(path, ty) => { - for (name, (_url, ty)) in self.types[ty].exports.iter() { + for (name, ty) in self.types[ty].exports.iter() { let mut path = path.clone(); path.path.push(name); let def = ComponentItemDef::from_import(path, *ty)?; diff --git a/crates/environ/src/component/types.rs b/crates/environ/src/component/types.rs index d3424256ee53..e98271b4c85d 100644 --- a/crates/environ/src/component/types.rs +++ b/crates/environ/src/component/types.rs @@ -499,6 +499,9 @@ impl ComponentTypesBuilder { let ty = TypeDef::CoreFunc(self.module_types.wasm_func_type(f)); self.push_core_typedef(ty); } + wasmparser::ModuleTypeDeclaration::Type(wasmparser::Type::Array(_)) => { + unimplemented!("gc types"); + } wasmparser::ModuleTypeDeclaration::Export { name, ty } => { let prev = result .exports @@ -556,17 +559,13 @@ impl ComponentTypesBuilder { ComponentTypeDeclaration::Type(ty) => self.type_declaration_type(ty)?, ComponentTypeDeclaration::CoreType(ty) => self.type_declaration_core_type(ty)?, ComponentTypeDeclaration::Alias(alias) => self.type_declaration_alias(alias)?, - ComponentTypeDeclaration::Export { name, url, ty } => { + ComponentTypeDeclaration::Export { name, ty } => { let ty = self.type_declaration_define(ty); - result - .exports - .insert(name.to_string(), (url.to_string(), ty)); + result.exports.insert(name.as_str().to_string(), ty); } ComponentTypeDeclaration::Import(import) => { let ty = self.type_declaration_define(&import.ty); - result - .imports - .insert(import.name.to_string(), (import.url.to_string(), ty)); + result.imports.insert(import.name.as_str().to_string(), ty); } } } @@ -588,11 +587,9 @@ impl ComponentTypesBuilder { InstanceTypeDeclaration::Type(ty) => self.type_declaration_type(ty)?, InstanceTypeDeclaration::CoreType(ty) => self.type_declaration_core_type(ty)?, InstanceTypeDeclaration::Alias(alias) => self.type_declaration_alias(alias)?, - InstanceTypeDeclaration::Export { name, url, ty } => { + InstanceTypeDeclaration::Export { name, ty } => { let ty = self.type_declaration_define(ty); - result - .exports - .insert(name.to_string(), (url.to_string(), ty)); + result.exports.insert(name.as_str().to_string(), ty); } } } @@ -639,7 +636,7 @@ impl ComponentTypesBuilder { } => { let ty = self.type_scopes.last().unwrap().instances [ComponentInstanceIndex::from_u32(*instance_index)]; - let (_, ty) = self.component_types[ty].exports[*name]; + let ty = self.component_types[ty].exports[*name]; self.push_component_typedef(ty); } a => unreachable!("invalid alias {a:?}"), @@ -1031,9 +1028,9 @@ pub struct TypeModule { #[derive(Serialize, Deserialize, Default)] pub struct TypeComponent { /// The named values that this component imports. - pub imports: IndexMap, + pub imports: IndexMap, /// The named values that this component exports. - pub exports: IndexMap, + pub exports: IndexMap, } /// The type of a component instance in the component model, or an instantiated @@ -1043,7 +1040,7 @@ pub struct TypeComponent { #[derive(Serialize, Deserialize, Default)] pub struct TypeComponentInstance { /// The list of exports that this component has along with their types. - pub exports: IndexMap, + pub exports: IndexMap, } /// A component function type in the component model. diff --git a/crates/environ/src/module_environ.rs b/crates/environ/src/module_environ.rs index 06f8f158fd2d..bfa81fd8b2ed 100644 --- a/crates/environ/src/module_environ.rs +++ b/crates/environ/src/module_environ.rs @@ -243,6 +243,9 @@ impl<'a, 'data> ModuleEnvironment<'a, 'data> { let ty = self.convert_func_type(&wasm_func_ty); self.declare_type_func(ty)?; } + Type::Array(_) => { + unimplemented!("gc proposal") + } } } } diff --git a/crates/test-programs/Cargo.toml b/crates/test-programs/Cargo.toml index 6e07ab9ea993..37a97b40b384 100644 --- a/crates/test-programs/Cargo.toml +++ b/crates/test-programs/Cargo.toml @@ -13,6 +13,7 @@ cargo_metadata = "0.15.3" wit-component = { workspace = true } heck = { workspace = true } + [dev-dependencies] anyhow = { workspace = true } tempfile = { workspace = true } diff --git a/crates/test-programs/build.rs b/crates/test-programs/build.rs index e36db9162e00..e96ed83e32af 100644 --- a/crates/test-programs/build.rs +++ b/crates/test-programs/build.rs @@ -7,6 +7,11 @@ use std::path::PathBuf; use std::process::Command; use wit_component::ComponentEncoder; +// NB: this is set to `false` when a breaking change to WIT is made since the +// wasi-http WIT is currently a submodule and can't be updated atomically with +// the rest of Wasmtime. +const BUILD_WASI_HTTP_TESTS: bool = false; + fn main() { #[cfg(feature = "test_programs")] build_and_generate_tests(); @@ -23,9 +28,13 @@ fn build_and_generate_tests() { ); println!("cargo:rerun-if-changed=./wasi-tests"); - println!("cargo:rerun-if-changed=./wasi-http-tests"); println!("cargo:rerun-if-changed=./command-tests"); println!("cargo:rerun-if-changed=./reactor-tests"); + if BUILD_WASI_HTTP_TESTS { + println!("cargo:rerun-if-changed=./wasi-http-tests"); + } else { + println!("cargo:rustc-cfg=skip_wasi_http_tests"); + } // Build the test programs: let mut cmd = Command::new("rustup"); @@ -35,12 +44,14 @@ fn build_and_generate_tests() { .arg("build") .arg("--target=wasm32-wasi") .arg("--package=wasi-tests") - .arg("--package=wasi-http-tests") .arg("--package=command-tests") .arg("--package=reactor-tests") .env("CARGO_TARGET_DIR", &out_dir) .env("CARGO_PROFILE_DEV_DEBUG", "1") .env_remove("CARGO_ENCODED_RUSTFLAGS"); + if BUILD_WASI_HTTP_TESTS { + cmd.arg("--package=wasi-http-tests"); + } let status = cmd.status().unwrap(); assert!(status.success()); @@ -49,11 +60,13 @@ fn build_and_generate_tests() { modules_rs(&meta, "wasi-tests", "bin", &out_dir); components_rs(&meta, "wasi-tests", "bin", &command_adapter, &out_dir); - modules_rs(&meta, "wasi-http-tests", "bin", &out_dir); - // FIXME this is broken at the moment because guest bindgen is embedding the proxy world type, - // so wit-component expects the module to contain the proxy's exports. we need a different - // world to pass guest bindgen that is just "a command that also can do outbound http" - //components_rs(&meta, "wasi-http-tests", "bin", &command_adapter, &out_dir); + if BUILD_WASI_HTTP_TESTS { + modules_rs(&meta, "wasi-http-tests", "bin", &out_dir); + // FIXME this is broken at the moment because guest bindgen is embedding the proxy world type, + // so wit-component expects the module to contain the proxy's exports. we need a different + // world to pass guest bindgen that is just "a command that also can do outbound http" + //components_rs(&meta, "wasi-http-tests", "bin", &command_adapter, &out_dir); + } components_rs(&meta, "command-tests", "bin", &command_adapter, &out_dir); components_rs(&meta, "reactor-tests", "cdylib", &reactor_adapter, &out_dir); diff --git a/crates/test-programs/reactor-tests/src/lib.rs b/crates/test-programs/reactor-tests/src/lib.rs index c38640ac07c3..ff1c0cab78ff 100644 --- a/crates/test-programs/reactor-tests/src/lib.rs +++ b/crates/test-programs/reactor-tests/src/lib.rs @@ -1,4 +1,4 @@ -wit_bindgen::generate!("test-reactor"); +wit_bindgen::generate!("test-reactor" in "../../wasi/wit"); export_test_reactor!(T); @@ -26,12 +26,12 @@ impl TestReactor for T { fn write_strings_to(o: OutputStream) -> Result<(), ()> { unsafe { for s in STATE.iter() { - streams::write(o, s.as_bytes()).map_err(|_| ())?; + wasi::io::streams::write(o, s.as_bytes()).map_err(|_| ())?; } Ok(()) } } - fn pass_an_imported_record(stat: filesystem::DescriptorStat) -> String { + fn pass_an_imported_record(stat: wasi::filesystem::filesystem::DescriptorStat) -> String { format!("{stat:?}") } } diff --git a/crates/test-programs/reactor-tests/wit/deps.lock b/crates/test-programs/reactor-tests/wit/deps.lock deleted file mode 100644 index bfa0b9d4f662..000000000000 --- a/crates/test-programs/reactor-tests/wit/deps.lock +++ /dev/null @@ -1,41 +0,0 @@ -[clocks] -sha256 = "16155da02fdba4a51515b44dbd1c65e0909bb8c4d383bd32875c777044ce5389" -sha512 = "30efd2697885954f3846322adf94f28a28f958595708407696ef66e8fe5bb62c79525e6f13ec469476cba8f2a12d3d9aef8250b1fe04c90a28542d3245db11f2" - -[filesystem] -sha256 = "a3f57790dfd6af70758df33df82aa064f915eb795b71a190f272f10da9cfc9df" -sha512 = "2b0059ffae0a4b1ce3bd8d489a40d08c1faa229bf1bb4cc8df0a98e0fd13d4694742117b2bc609d7fb75db1ed4aa148d3af7beca6a84866d87d65a1769b1d988" - -[http] -sha256 = "b6a245b8f37f3be93650c1a8ae41c01923f3b7303bbf2d016d8d03a1c92b3c10" -sha512 = "e2e0612213bb1272153b3858b13110a7fee0d89dc97d0021ab5ccccc8822ccc1f1629c8fa8dc582862411b2517ef3f79e7e51986c946654bf6ddd3f390cf36f2" - -[io] -sha256 = "87d8bf336f37184edc9290af9a14f7cac38c8fe087a786e66d08d1a94e48d186" -sha512 = "cdb5b35860c46c637ad37d784dd17f6023cf1c7c689d37973ec7c4094718baee4a16864e64622173b5578eed3950ad73211d9fe48a5b61b951809fdd9242b607" - -[logging] -sha256 = "8c32c7f893c938e0b76cd42e3de97e268dfe8fd0e7525d1f42b7ad10a88b00bb" -sha512 = "e9ce2adf02bb518c179a40b7d7af84bf44b99b2098609a897a114fb5af24946992dd7bd08da02c60d2768963f94414a16165f11343ec053a44b9e586058c812a" - -[poll] -sha256 = "9f2e6b5ea1a017575f96a3c415c737fe31513b043d9b47aefeb21f6c27ab8425" -sha512 = "f65965395742a0290fd9e4e55408c2b5ce3a4eae0ee22be1ff012e3db75910110da21c5f0a61083e043b4c510967a0a73ff4491ae9719e9158543f512dbeea5f" - -[preview] -path = "../../../wit" -sha256 = "007d4902193faef77b2df60714a8dfe8ec243e030c1ce61fb11c52788e3a5fe0" -sha512 = "bd06e8338e7fad0fc2e56ae01c5b184282c66ca79d2040eaec5a11efb14a4002b2a6234baaf354aff3cd57dc99835e4979eb71cdbd5d12800ea289d9a13252f2" -deps = ["clocks", "filesystem", "http", "io", "logging", "poll", "random", "sockets", "wasi-cli-base"] - -[random] -sha256 = "19d57f2262530016ec2b32991db3d8b6705b3a0bc5a7b6ae8fff3bcef0cf1088" -sha512 = "f9eba7dfd858d1edcaa868ce636f69545323bf010c3b0d4a2a1b23584d8027240c592d13e91882617e70a4dbf290754a8697724b5633147d11fa3db7869a2afe" - -[sockets] -sha256 = "d5a51604d53eec88d2735356ce7089a0eeb06886262e7ad2fc74be6b4dd943b2" -sha512 = "99bd86c0c59174bc9dafc559ca7dbab1aa9ed04a9b54ae3f7bb2d974b3a97bae8846acf1d77232edecda0aef5b23b9e4010d53ebf4a1d04292581078763530b7" - -[wasi-cli-base] -sha256 = "a0beee69392d2b55baff0b5f2285f50f717473b1369bdb3fbbfbefbaa3bd6c86" -sha512 = "d80eada98646bfeec1066437f1a4f69d67d117f38407f35c48d8b31667c171656059c5abf638c5b31169119ef5fa73bbf199933ac198f815f58281f124cb4f8d" diff --git a/crates/test-programs/reactor-tests/wit/deps.toml b/crates/test-programs/reactor-tests/wit/deps.toml deleted file mode 100644 index c90a145d08ce..000000000000 --- a/crates/test-programs/reactor-tests/wit/deps.toml +++ /dev/null @@ -1 +0,0 @@ -preview = "../../../wit" diff --git a/crates/test-programs/reactor-tests/wit/deps/clocks/monotonic-clock.wit b/crates/test-programs/reactor-tests/wit/deps/clocks/monotonic-clock.wit deleted file mode 100644 index 42e2981f579a..000000000000 --- a/crates/test-programs/reactor-tests/wit/deps/clocks/monotonic-clock.wit +++ /dev/null @@ -1,32 +0,0 @@ -/// WASI Monotonic Clock is a clock API intended to let users measure elapsed -/// time. -/// -/// It is intended to be portable at least between Unix-family platforms and -/// Windows. -/// -/// A monotonic clock is a clock which has an unspecified initial value, and -/// successive reads of the clock will produce non-decreasing values. -/// -/// It is intended for measuring elapsed time. -default interface monotonic-clock { - use poll.poll.{pollable} - - /// A timestamp in nanoseconds. - type instant = u64 - - /// Read the current value of the clock. - /// - /// The clock is monotonic, therefore calling this function repeatedly will - /// produce a sequence of non-decreasing values. - now: func() -> instant - - /// Query the resolution of the clock. - resolution: func() -> instant - - /// Create a `pollable` which will resolve once the specified time has been - /// reached. - subscribe: func( - when: instant, - absolute: bool - ) -> pollable -} diff --git a/crates/test-programs/reactor-tests/wit/deps/clocks/timezone.wit b/crates/test-programs/reactor-tests/wit/deps/clocks/timezone.wit deleted file mode 100644 index 63f99cc401b1..000000000000 --- a/crates/test-programs/reactor-tests/wit/deps/clocks/timezone.wit +++ /dev/null @@ -1,61 +0,0 @@ -default interface timezone { - use pkg.wall-clock.{datetime} - - /// A timezone. - /// - /// In timezones that recognize daylight saving time, also known as daylight - /// time and summer time, the information returned from the functions varies - /// over time to reflect these adjustments. - /// - /// This [represents a resource](https://github.com/WebAssembly/WASI/blob/main/docs/WitInWasi.md#Resources). - type timezone = u32 - - /// Return information needed to display the given `datetime`. This includes - /// the UTC offset, the time zone name, and a flag indicating whether - /// daylight saving time is active. - /// - /// If the timezone cannot be determined for the given `datetime`, return a - /// `timezone-display` for `UTC` with a `utc-offset` of 0 and no daylight - /// saving time. - display: func(this: timezone, when: datetime) -> timezone-display - - /// The same as `display`, but only return the UTC offset. - utc-offset: func(this: timezone, when: datetime) -> s32 - - /// Dispose of the specified input-stream, after which it may no longer - /// be used. - drop-timezone: func(this: timezone) - - /// Information useful for displaying the timezone of a specific `datetime`. - /// - /// This information may vary within a single `timezone` to reflect daylight - /// saving time adjustments. - record timezone-display { - /// The number of seconds difference between UTC time and the local - /// time of the timezone. - /// - /// The returned value will always be less than 86400 which is the - /// number of seconds in a day (24*60*60). - /// - /// In implementations that do not expose an actual time zone, this - /// should return 0. - utc-offset: s32, - - /// The abbreviated name of the timezone to display to a user. The name - /// `UTC` indicates Coordinated Universal Time. Otherwise, this should - /// reference local standards for the name of the time zone. - /// - /// In implementations that do not expose an actual time zone, this - /// should be the string `UTC`. - /// - /// In time zones that do not have an applicable name, a formatted - /// representation of the UTC offset may be returned, such as `-04:00`. - name: string, - - /// Whether daylight saving time is active. - /// - /// In implementations that do not expose an actual time zone, this - /// should return false. - in-daylight-saving-time: bool, - } -} diff --git a/crates/test-programs/reactor-tests/wit/deps/clocks/wall-clock.wit b/crates/test-programs/reactor-tests/wit/deps/clocks/wall-clock.wit deleted file mode 100644 index 89c5a75da68b..000000000000 --- a/crates/test-programs/reactor-tests/wit/deps/clocks/wall-clock.wit +++ /dev/null @@ -1,41 +0,0 @@ -/// WASI Wall Clock is a clock API intended to let users query the current -/// time. The name "wall" makes an analogy to a "clock on the wall", which -/// is not necessarily monotonic as it may be reset. -/// -/// It is intended to be portable at least between Unix-family platforms and -/// Windows. -/// -/// A wall clock is a clock which measures the date and time according to -/// some external reference. -/// -/// External references may be reset, so this clock is not necessarily -/// monotonic, making it unsuitable for measuring elapsed time. -/// -/// It is intended for reporting the current date and time for humans. -default interface wall-clock { - /// A time and date in seconds plus nanoseconds. - record datetime { - seconds: u64, - nanoseconds: u32, - } - - /// Read the current value of the clock. - /// - /// This clock is not monotonic, therefore calling this function repeatedly - /// will not necessarily produce a sequence of non-decreasing values. - /// - /// The returned timestamps represent the number of seconds since - /// 1970-01-01T00:00:00Z, also known as [POSIX's Seconds Since the Epoch], - /// also known as [Unix Time]. - /// - /// The nanoseconds field of the output is always less than 1000000000. - /// - /// [POSIX's Seconds Since the Epoch]: https://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_xbd_chap04.html#tag_21_04_16 - /// [Unix Time]: https://en.wikipedia.org/wiki/Unix_time - now: func() -> datetime - - /// Query the resolution of the clock. - /// - /// The nanoseconds field of the output is always less than 1000000000. - resolution: func() -> datetime -} diff --git a/crates/test-programs/reactor-tests/wit/deps/io/streams.wit b/crates/test-programs/reactor-tests/wit/deps/io/streams.wit deleted file mode 100644 index c1567fd4c1c8..000000000000 --- a/crates/test-programs/reactor-tests/wit/deps/io/streams.wit +++ /dev/null @@ -1,213 +0,0 @@ -/// WASI I/O is an I/O abstraction API which is currently focused on providing -/// stream types. -/// -/// In the future, the component model is expected to add built-in stream types; -/// when it does, they are expected to subsume this API. -default interface streams { - use poll.poll.{pollable} - - /// An error type returned from a stream operation. Currently this - /// doesn't provide any additional information. - record stream-error {} - - /// An input bytestream. In the future, this will be replaced by handle - /// types. - /// - /// This conceptually represents a `stream`. It's temporary - /// scaffolding until component-model's async features are ready. - /// - /// `input-stream`s are *non-blocking* to the extent practical on underlying - /// platforms. I/O operations always return promptly; if fewer bytes are - /// promptly available than requested, they return the number of bytes promptly - /// available, which could even be zero. To wait for data to be available, - /// use the `subscribe-to-input-stream` function to obtain a `pollable` which - /// can be polled for using `wasi_poll`. - /// - /// And at present, it is a `u32` instead of being an actual handle, until - /// the wit-bindgen implementation of handles and resources is ready. - /// - /// This [represents a resource](https://github.com/WebAssembly/WASI/blob/main/docs/WitInWasi.md#Resources). - type input-stream = u32 - - /// Read bytes from a stream. - /// - /// This function returns a list of bytes containing the data that was - /// read, along with a bool which, when true, indicates that the end of the - /// stream was reached. The returned list will contain up to `len` bytes; it - /// may return fewer than requested, but not more. - /// - /// Once a stream has reached the end, subsequent calls to read or - /// `skip` will always report end-of-stream rather than producing more - /// data. - /// - /// If `len` is 0, it represents a request to read 0 bytes, which should - /// always succeed, assuming the stream hasn't reached its end yet, and - /// return an empty list. - /// - /// The len here is a `u64`, but some callees may not be able to allocate - /// a buffer as large as that would imply. - /// FIXME: describe what happens if allocation fails. - read: func( - this: input-stream, - /// The maximum number of bytes to read - len: u64 - ) -> result, bool>, stream-error> - - /// Read bytes from a stream, with blocking. - /// - /// This is similar to `read`, except that it blocks until at least one - /// byte can be read. - blocking-read: func( - this: input-stream, - /// The maximum number of bytes to read - len: u64 - ) -> result, bool>, stream-error> - - /// Skip bytes from a stream. - /// - /// This is similar to the `read` function, but avoids copying the - /// bytes into the instance. - /// - /// Once a stream has reached the end, subsequent calls to read or - /// `skip` will always report end-of-stream rather than producing more - /// data. - /// - /// This function returns the number of bytes skipped, along with a bool - /// indicating whether the end of the stream was reached. The returned - /// value will be at most `len`; it may be less. - skip: func( - this: input-stream, - /// The maximum number of bytes to skip. - len: u64, - ) -> result, stream-error> - - /// Skip bytes from a stream, with blocking. - /// - /// This is similar to `skip`, except that it blocks until at least one - /// byte can be consumed. - blocking-skip: func( - this: input-stream, - /// The maximum number of bytes to skip. - len: u64, - ) -> result, stream-error> - - /// Create a `pollable` which will resolve once either the specified stream - /// has bytes available to read or the other end of the stream has been - /// closed. - subscribe-to-input-stream: func(this: input-stream) -> pollable - - /// Dispose of the specified `input-stream`, after which it may no longer - /// be used. - drop-input-stream: func(this: input-stream) - - /// An output bytestream. In the future, this will be replaced by handle - /// types. - /// - /// This conceptually represents a `stream`. It's temporary - /// scaffolding until component-model's async features are ready. - /// - /// `output-stream`s are *non-blocking* to the extent practical on - /// underlying platforms. Except where specified otherwise, I/O operations also - /// always return promptly, after the number of bytes that can be written - /// promptly, which could even be zero. To wait for the stream to be ready to - /// accept data, the `subscribe-to-output-stream` function to obtain a - /// `pollable` which can be polled for using `wasi_poll`. - /// - /// And at present, it is a `u32` instead of being an actual handle, until - /// the wit-bindgen implementation of handles and resources is ready. - /// - /// This [represents a resource](https://github.com/WebAssembly/WASI/blob/main/docs/WitInWasi.md#Resources). - type output-stream = u32 - - /// Write bytes to a stream. - /// - /// This function returns a `u64` indicating the number of bytes from - /// `buf` that were written; it may be less than the full list. - write: func( - this: output-stream, - /// Data to write - buf: list - ) -> result - - /// Write bytes to a stream, with blocking. - /// - /// This is similar to `write`, except that it blocks until at least one - /// byte can be written. - blocking-write: func( - this: output-stream, - /// Data to write - buf: list - ) -> result - - /// Write multiple zero bytes to a stream. - /// - /// This function returns a `u64` indicating the number of zero bytes - /// that were written; it may be less than `len`. - write-zeroes: func( - this: output-stream, - /// The number of zero bytes to write - len: u64 - ) -> result - - /// Write multiple zero bytes to a stream, with blocking. - /// - /// This is similar to `write-zeroes`, except that it blocks until at least - /// one byte can be written. - blocking-write-zeroes: func( - this: output-stream, - /// The number of zero bytes to write - len: u64 - ) -> result - - /// Read from one stream and write to another. - /// - /// This function returns the number of bytes transferred; it may be less - /// than `len`. - /// - /// Unlike other I/O functions, this function blocks until all the data - /// read from the input stream has been written to the output stream. - splice: func( - this: output-stream, - /// The stream to read from - src: input-stream, - /// The number of bytes to splice - len: u64, - ) -> result, stream-error> - - /// Read from one stream and write to another, with blocking. - /// - /// This is similar to `splice`, except that it blocks until at least - /// one byte can be read. - blocking-splice: func( - this: output-stream, - /// The stream to read from - src: input-stream, - /// The number of bytes to splice - len: u64, - ) -> result, stream-error> - - /// Forward the entire contents of an input stream to an output stream. - /// - /// This function repeatedly reads from the input stream and writes - /// the data to the output stream, until the end of the input stream - /// is reached, or an error is encountered. - /// - /// Unlike other I/O functions, this function blocks until the end - /// of the input stream is seen and all the data has been written to - /// the output stream. - /// - /// This function returns the number of bytes transferred. - forward: func( - this: output-stream, - /// The stream to read from - src: input-stream - ) -> result - - /// Create a `pollable` which will resolve once either the specified stream - /// is ready to accept bytes or the other end of the stream has been closed. - subscribe-to-output-stream: func(this: output-stream) -> pollable - - /// Dispose of the specified `output-stream`, after which it may no longer - /// be used. - drop-output-stream: func(this: output-stream) -} diff --git a/crates/test-programs/reactor-tests/wit/deps/poll/poll.wit b/crates/test-programs/reactor-tests/wit/deps/poll/poll.wit deleted file mode 100644 index 28f08e17d755..000000000000 --- a/crates/test-programs/reactor-tests/wit/deps/poll/poll.wit +++ /dev/null @@ -1,39 +0,0 @@ -/// A poll API intended to let users wait for I/O events on multiple handles -/// at once. -default interface poll { - /// A "pollable" handle. - /// - /// This is conceptually represents a `stream<_, _>`, or in other words, - /// a stream that one can wait on, repeatedly, but which does not itself - /// produce any data. It's temporary scaffolding until component-model's - /// async features are ready. - /// - /// And at present, it is a `u32` instead of being an actual handle, until - /// the wit-bindgen implementation of handles and resources is ready. - /// - /// `pollable` lifetimes are not automatically managed. Users must ensure - /// that they do not outlive the resource they reference. - /// - /// This [represents a resource](https://github.com/WebAssembly/WASI/blob/main/docs/WitInWasi.md#Resources). - type pollable = u32 - - /// Dispose of the specified `pollable`, after which it may no longer - /// be used. - drop-pollable: func(this: pollable) - - /// Poll for completion on a set of pollables. - /// - /// The "oneoff" in the name refers to the fact that this function must do a - /// linear scan through the entire list of subscriptions, which may be - /// inefficient if the number is large and the same subscriptions are used - /// many times. In the future, this is expected to be obsoleted by the - /// component model async proposal, which will include a scalable waiting - /// facility. - /// - /// Note that the return type would ideally be `list`, but that would - /// be more difficult to polyfill given the current state of `wit-bindgen`. - /// See - /// for details. For now, we use zero to mean "not ready" and non-zero to - /// mean "ready". - poll-oneoff: func(in: list) -> list -} diff --git a/crates/test-programs/reactor-tests/wit/deps/wasi-cli-base/environment.wit b/crates/test-programs/reactor-tests/wit/deps/wasi-cli-base/environment.wit deleted file mode 100644 index 876ea3a0c921..000000000000 --- a/crates/test-programs/reactor-tests/wit/deps/wasi-cli-base/environment.wit +++ /dev/null @@ -1,14 +0,0 @@ -default interface environment { - /// Get the POSIX-style environment variables. - /// - /// Each environment variable is provided as a pair of string variable names - /// and string value. - /// - /// Morally, these are a value import, but until value imports are available - /// in the component model, this import function should return the same - /// values each time it is called. - get-environment: func() -> list> - - /// Get the POSIX-style arguments to the program. - get-arguments: func() -> list -} diff --git a/crates/test-programs/reactor-tests/wit/deps/wasi-cli-base/exit.wit b/crates/test-programs/reactor-tests/wit/deps/wasi-cli-base/exit.wit deleted file mode 100644 index 2759e9dd989c..000000000000 --- a/crates/test-programs/reactor-tests/wit/deps/wasi-cli-base/exit.wit +++ /dev/null @@ -1,4 +0,0 @@ -default interface wasi-exit { - /// Exit the curerent instance and any linked instances. - exit: func(status: result) -} diff --git a/crates/test-programs/reactor-tests/wit/test-reactor.wit b/crates/test-programs/reactor-tests/wit/test-reactor.wit deleted file mode 100644 index 12abad593df0..000000000000 --- a/crates/test-programs/reactor-tests/wit/test-reactor.wit +++ /dev/null @@ -1,18 +0,0 @@ -default world test-reactor { - - import environment: wasi-cli-base.environment - import streams: io.streams - import preopens: wasi-cli-base.preopens - import filesystem: filesystem.filesystem - import exit: wasi-cli-base.exit - - export add-strings: func(s: list) -> u32 - export get-strings: func() -> list - - use io.streams.{output-stream} - - export write-strings-to: func(o: output-stream) -> result - - use filesystem.filesystem.{descriptor-stat} - export pass-an-imported-record: func(d: descriptor-stat) -> string -} diff --git a/crates/test-programs/tests/reactor.rs b/crates/test-programs/tests/reactor.rs index 16b61c7f376c..9cd6ececb55e 100644 --- a/crates/test-programs/tests/reactor.rs +++ b/crates/test-programs/tests/reactor.rs @@ -4,7 +4,9 @@ use wasmtime::{ component::{Component, Linker}, Config, Engine, Store, }; -use wasmtime_wasi::preview2::{wasi, Table, WasiCtx, WasiCtxBuilder, WasiView}; +use wasmtime_wasi::preview2::wasi::clocks::wall_clock; +use wasmtime_wasi::preview2::wasi::filesystem::filesystem; +use wasmtime_wasi::preview2::{self, Table, WasiCtx, WasiCtxBuilder, WasiView}; lazy_static::lazy_static! { static ref ENGINE: Engine = { @@ -22,18 +24,18 @@ lazy_static::lazy_static! { include!(concat!(env!("OUT_DIR"), "/reactor_tests_components.rs")); wasmtime::component::bindgen!({ - path: "../test-programs/reactor-tests/wit", + path: "../wasi/wit", world: "test-reactor", async: true, with: { - "environment": wasi::environment, - "streams": wasi::streams, - "preopens": wasi::preopens, - "stdin": wasi::stdin, - "stdout": wasi::stdout, - "stderr": wasi::stderr, - "filesystem": wasi::filesystem, - "exit": wasi::exit, + "wasi:io/streams": preview2::wasi::io::streams, + "wasi:filesystem/filesystem": preview2::wasi::filesystem::filesystem, + "wasi:cli-base/environment": preview2::wasi::cli_base::environment, + "wasi:cli-base/preopens": preview2::wasi::cli_base::preopens, + "wasi:cli-base/exit": preview2::wasi::cli_base::exit, + "wasi:cli-base/stdin": preview2::wasi::cli_base::stdin, + "wasi:cli-base/stdout": preview2::wasi::cli_base::stdout, + "wasi:cli-base/stderr": preview2::wasi::cli_base::stderr, }, }); @@ -64,14 +66,14 @@ async fn instantiate( let mut linker = Linker::new(&ENGINE); // All of the imports available to the world are provided by the wasi-common crate: - wasi::filesystem::add_to_linker(&mut linker, |x| x)?; - wasi::streams::add_to_linker(&mut linker, |x| x)?; - wasi::environment::add_to_linker(&mut linker, |x| x)?; - wasi::preopens::add_to_linker(&mut linker, |x| x)?; - wasi::stdin::add_to_linker(&mut linker, |x| x)?; - wasi::stdout::add_to_linker(&mut linker, |x| x)?; - wasi::stderr::add_to_linker(&mut linker, |x| x)?; - wasi::exit::add_to_linker(&mut linker, |x| x)?; + preview2::wasi::filesystem::filesystem::add_to_linker(&mut linker, |x| x)?; + preview2::wasi::io::streams::add_to_linker(&mut linker, |x| x)?; + preview2::wasi::cli_base::environment::add_to_linker(&mut linker, |x| x)?; + preview2::wasi::cli_base::preopens::add_to_linker(&mut linker, |x| x)?; + preview2::wasi::cli_base::exit::add_to_linker(&mut linker, |x| x)?; + preview2::wasi::cli_base::stdin::add_to_linker(&mut linker, |x| x)?; + preview2::wasi::cli_base::stdout::add_to_linker(&mut linker, |x| x)?; + preview2::wasi::cli_base::stderr::add_to_linker(&mut linker, |x| x)?; let mut store = Store::new(&ENGINE, wasi_ctx); @@ -131,12 +133,12 @@ async fn reactor_tests() -> Result<()> { // Show that the `with` invocation in the macro means we get to re-use the // type definitions from inside the `host` crate for these structures: - let ds = wasi::filesystem::DescriptorStat { - data_access_timestamp: wasi::wall_clock::Datetime { + let ds = filesystem::DescriptorStat { + data_access_timestamp: wall_clock::Datetime { nanoseconds: 123, seconds: 45, }, - data_modification_timestamp: wasi::wall_clock::Datetime { + data_modification_timestamp: wall_clock::Datetime { nanoseconds: 789, seconds: 10, }, @@ -144,11 +146,11 @@ async fn reactor_tests() -> Result<()> { inode: 0, link_count: 0, size: 0, - status_change_timestamp: wasi::wall_clock::Datetime { + status_change_timestamp: wall_clock::Datetime { nanoseconds: 0, seconds: 1, }, - type_: wasi::filesystem::DescriptorType::Unknown, + type_: filesystem::DescriptorType::Unknown, }; let expected = format!("{ds:?}"); let got = reactor.call_pass_an_imported_record(&mut store, ds).await?; diff --git a/crates/test-programs/tests/wasi-http.rs b/crates/test-programs/tests/wasi-http.rs index 78c99dc939af..0b1a4fd70567 100644 --- a/crates/test-programs/tests/wasi-http.rs +++ b/crates/test-programs/tests/wasi-http.rs @@ -1,4 +1,4 @@ -#![cfg(feature = "test_programs")] +#![cfg(all(feature = "test_programs", not(skip_wasi_http_tests)))] use wasmtime::{Config, Engine, Linker, Store}; use wasmtime_wasi::{sync::WasiCtxBuilder, WasiCtx}; use wasmtime_wasi_http::WasiHttp; diff --git a/crates/types/src/lib.rs b/crates/types/src/lib.rs index 68150ba639a3..0fbd349400de 100644 --- a/crates/types/src/lib.rs +++ b/crates/types/src/lib.rs @@ -441,7 +441,7 @@ pub trait TypeConvert { match ty { wasmparser::HeapType::Func => WasmHeapType::Func, wasmparser::HeapType::Extern => WasmHeapType::Extern, - wasmparser::HeapType::TypedFunc(i) => self.lookup_heap_type(TypeIndex::from_u32(i)), + wasmparser::HeapType::Indexed(i) => self.lookup_heap_type(TypeIndex::from_u32(i)), wasmparser::HeapType::Any | wasmparser::HeapType::None diff --git a/crates/wasi-http/src/lib.rs b/crates/wasi-http/src/lib.rs index 4f90015cc5ce..8f1ef030c67f 100644 --- a/crates/wasi-http/src/lib.rs +++ b/crates/wasi-http/src/lib.rs @@ -1,3 +1,7 @@ +// NB: this crate is temporarily disabled for a breaking change to WIT. This can +// be re-enabled when the WIT in the wasi-http submodule is updated. +#![cfg(FALSE)] + use crate::component_impl::add_component_to_linker; pub use crate::r#struct::WasiHttp; diff --git a/crates/wasi-preview1-component-adapter/Cargo.toml b/crates/wasi-preview1-component-adapter/Cargo.toml index c2ca4c9c61e6..16af98f56bc9 100644 --- a/crates/wasi-preview1-component-adapter/Cargo.toml +++ b/crates/wasi-preview1-component-adapter/Cargo.toml @@ -7,7 +7,7 @@ publish = false [dependencies] wasi = { version = "0.11.0", default-features = false } -wit-bindgen = { version = "0.6.0", default-features = false, features = ["macros"] } +wit-bindgen = { workspace = true, default-features = false, features = ["macros"] } byte-array-literals = { workspace = true } [build-dependencies] diff --git a/crates/wasi-preview1-component-adapter/src/descriptors.rs b/crates/wasi-preview1-component-adapter/src/descriptors.rs index 8b17ac7e6bbc..cdeff86082b5 100644 --- a/crates/wasi-preview1-component-adapter/src/descriptors.rs +++ b/crates/wasi-preview1-component-adapter/src/descriptors.rs @@ -1,5 +1,7 @@ -use crate::bindings::streams::{self, InputStream, OutputStream}; -use crate::bindings::{filesystem, tcp}; +use crate::bindings::wasi::cli_base::{stderr, stdin, stdout}; +use crate::bindings::wasi::filesystem::filesystem; +use crate::bindings::wasi::io::streams::{self, InputStream, OutputStream}; +use crate::bindings::wasi::sockets::tcp; use crate::{set_stderr_stream, BumpArena, File, ImportAlloc, TrappingUnwrap, WasmStr}; use core::cell::{Cell, UnsafeCell}; use core::mem::MaybeUninit; @@ -140,9 +142,9 @@ impl Descriptors { preopens: Cell::new(None), }; - let stdin = crate::bindings::stdin::get_stdin(); - let stdout = crate::bindings::stdout::get_stdout(); - let stderr = crate::bindings::stderr::get_stderr(); + let stdin = stdin::get_stdin(); + let stdout = stdout::get_stdout(); + let stderr = stderr::get_stderr(); unsafe { set_stderr_stream(stderr) }; d.push(Descriptor::Streams(Streams { @@ -164,7 +166,7 @@ impl Descriptors { })) .trapping_unwrap(); - #[link(wasm_import_module = "preopens")] + #[link(wasm_import_module = "wasi:cli-base/preopens")] extern "C" { #[link_name = "get-directories"] fn get_preopens_import(rval: *mut PreopenList); @@ -189,8 +191,7 @@ impl Descriptors { output: Cell::new(None), type_: StreamType::File(File { fd: preopen.descriptor, - descriptor_type: crate::bindings::filesystem::get_type(preopen.descriptor) - .trapping_unwrap(), + descriptor_type: filesystem::get_type(preopen.descriptor).trapping_unwrap(), position: Cell::new(0), append: false, blocking: false, @@ -346,7 +347,7 @@ impl Descriptors { } #[allow(dead_code)] // until Socket is implemented - pub fn get_socket(&self, fd: Fd) -> Result { + pub fn get_socket(&self, fd: Fd) -> Result { match self.get(fd)? { Descriptor::Streams(Streams { type_: StreamType::Socket(socket), diff --git a/crates/wasi-preview1-component-adapter/src/lib.rs b/crates/wasi-preview1-component-adapter/src/lib.rs index c368a57b2355..d10fc48cd87d 100644 --- a/crates/wasi-preview1-component-adapter/src/lib.rs +++ b/crates/wasi-preview1-component-adapter/src/lib.rs @@ -1,8 +1,12 @@ #![allow(unused_variables)] // TODO: remove this when more things are implemented -use crate::bindings::{ - exit, filesystem, monotonic_clock, network, poll, random, streams, wall_clock, -}; +use crate::bindings::wasi::cli_base::exit; +use crate::bindings::wasi::clocks::{monotonic_clock, wall_clock}; +use crate::bindings::wasi::filesystem::filesystem; +use crate::bindings::wasi::io::streams; +use crate::bindings::wasi::poll::poll; +use crate::bindings::wasi::random::random; +use crate::bindings::wasi::sockets::network; use core::cell::{Cell, RefCell, RefMut, UnsafeCell}; use core::cmp::min; use core::ffi::c_void; @@ -26,7 +30,8 @@ use crate::descriptors::{Descriptor, Descriptors, StreamType, Streams}; pub mod bindings { #[cfg(feature = "command")] wit_bindgen::generate!({ - world: "command", + path: "../wasi/wit", + world: "wasi:preview/command", std_feature, raw_strings, // The generated definition of command will pull in std, so we are defining it @@ -36,7 +41,8 @@ pub mod bindings { #[cfg(feature = "reactor")] wit_bindgen::generate!({ - world: "reactor", + path: "../wasi/wit", + world: "wasi:preview/reactor", std_feature, raw_strings, skip: ["get-directories", "get-environment"], @@ -2335,7 +2341,7 @@ impl State { fn get_environment(&self) -> &[StrTuple] { if self.env_vars.get().is_none() { - #[link(wasm_import_module = "environment")] + #[link(wasm_import_module = "wasi:cli-base/environment")] extern "C" { #[link_name = "get-environment"] fn get_environment_import(rval: *mut StrTupleList); @@ -2359,7 +2365,7 @@ impl State { fn get_args(&self) -> &[WasmStr] { if self.args.get().is_none() { - #[link(wasm_import_module = "environment")] + #[link(wasm_import_module = "wasi:cli-base/environment")] extern "C" { #[link_name = "get-arguments"] fn get_args_import(rval: *mut WasmStrList); diff --git a/crates/wasi-preview1-component-adapter/src/macros.rs b/crates/wasi-preview1-component-adapter/src/macros.rs index 13faf6bc62fc..ca46aacacf1c 100644 --- a/crates/wasi-preview1-component-adapter/src/macros.rs +++ b/crates/wasi-preview1-component-adapter/src/macros.rs @@ -2,10 +2,13 @@ //! //! We're avoiding static initializers, so we can't have things like string //! literals. Replace the standard assert macros with simpler implementations. + +use crate::bindings::wasi::io::streams; + #[allow(dead_code)] #[doc(hidden)] pub fn print(message: &[u8]) { - let _ = unsafe { crate::bindings::streams::write(crate::get_stderr_stream(), message) }; + let _ = unsafe { streams::write(crate::get_stderr_stream(), message) }; } /// A minimal `eprint` for debugging. diff --git a/crates/wasi-preview1-component-adapter/verify/src/main.rs b/crates/wasi-preview1-component-adapter/verify/src/main.rs index 8fb23617f33f..2a8b391d7c97 100644 --- a/crates/wasi-preview1-component-adapter/verify/src/main.rs +++ b/crates/wasi-preview1-component-adapter/verify/src/main.rs @@ -2,31 +2,6 @@ use anyhow::{bail, Result}; use std::env; use wasmparser::*; -const ALLOWED_IMPORT_MODULES: &[&str] = &[ - "wall-clock", - "monotonic-clock", - "timezone", - "filesystem", - "instance-network", - "ip-name-lookup", - "network", - "tcp-create-socket", - "tcp", - "udp-create-socket", - "udp", - "random", - "poll", - "streams", - "environment", - "preopens", - "exit", - "canonical_abi", - "stdin", - "stdout", - "stderr", - "__main_module__", -]; - fn main() -> Result<()> { let file = env::args() .nth(1) @@ -50,9 +25,13 @@ fn main() -> Result<()> { let i = i?; match i.ty { TypeRef::Func(_) => { - if !ALLOWED_IMPORT_MODULES.contains(&i.module) { - bail!("import from unknown module `{}`", i.module); + if i.module.starts_with("wasi:") { + continue; + } + if i.module == "__main_module__" { + continue; } + bail!("import from unknown module `{}`", i.module); } TypeRef::Table(_) => bail!("should not import table"), TypeRef::Global(_) => bail!("should not import globals"), diff --git a/crates/wasi-preview1-component-adapter/wit/deps/clocks/monotonic-clock.wit b/crates/wasi-preview1-component-adapter/wit/deps/clocks/monotonic-clock.wit deleted file mode 100644 index 42e2981f579a..000000000000 --- a/crates/wasi-preview1-component-adapter/wit/deps/clocks/monotonic-clock.wit +++ /dev/null @@ -1,32 +0,0 @@ -/// WASI Monotonic Clock is a clock API intended to let users measure elapsed -/// time. -/// -/// It is intended to be portable at least between Unix-family platforms and -/// Windows. -/// -/// A monotonic clock is a clock which has an unspecified initial value, and -/// successive reads of the clock will produce non-decreasing values. -/// -/// It is intended for measuring elapsed time. -default interface monotonic-clock { - use poll.poll.{pollable} - - /// A timestamp in nanoseconds. - type instant = u64 - - /// Read the current value of the clock. - /// - /// The clock is monotonic, therefore calling this function repeatedly will - /// produce a sequence of non-decreasing values. - now: func() -> instant - - /// Query the resolution of the clock. - resolution: func() -> instant - - /// Create a `pollable` which will resolve once the specified time has been - /// reached. - subscribe: func( - when: instant, - absolute: bool - ) -> pollable -} diff --git a/crates/wasi-preview1-component-adapter/wit/deps/clocks/timezone.wit b/crates/wasi-preview1-component-adapter/wit/deps/clocks/timezone.wit deleted file mode 100644 index 63f99cc401b1..000000000000 --- a/crates/wasi-preview1-component-adapter/wit/deps/clocks/timezone.wit +++ /dev/null @@ -1,61 +0,0 @@ -default interface timezone { - use pkg.wall-clock.{datetime} - - /// A timezone. - /// - /// In timezones that recognize daylight saving time, also known as daylight - /// time and summer time, the information returned from the functions varies - /// over time to reflect these adjustments. - /// - /// This [represents a resource](https://github.com/WebAssembly/WASI/blob/main/docs/WitInWasi.md#Resources). - type timezone = u32 - - /// Return information needed to display the given `datetime`. This includes - /// the UTC offset, the time zone name, and a flag indicating whether - /// daylight saving time is active. - /// - /// If the timezone cannot be determined for the given `datetime`, return a - /// `timezone-display` for `UTC` with a `utc-offset` of 0 and no daylight - /// saving time. - display: func(this: timezone, when: datetime) -> timezone-display - - /// The same as `display`, but only return the UTC offset. - utc-offset: func(this: timezone, when: datetime) -> s32 - - /// Dispose of the specified input-stream, after which it may no longer - /// be used. - drop-timezone: func(this: timezone) - - /// Information useful for displaying the timezone of a specific `datetime`. - /// - /// This information may vary within a single `timezone` to reflect daylight - /// saving time adjustments. - record timezone-display { - /// The number of seconds difference between UTC time and the local - /// time of the timezone. - /// - /// The returned value will always be less than 86400 which is the - /// number of seconds in a day (24*60*60). - /// - /// In implementations that do not expose an actual time zone, this - /// should return 0. - utc-offset: s32, - - /// The abbreviated name of the timezone to display to a user. The name - /// `UTC` indicates Coordinated Universal Time. Otherwise, this should - /// reference local standards for the name of the time zone. - /// - /// In implementations that do not expose an actual time zone, this - /// should be the string `UTC`. - /// - /// In time zones that do not have an applicable name, a formatted - /// representation of the UTC offset may be returned, such as `-04:00`. - name: string, - - /// Whether daylight saving time is active. - /// - /// In implementations that do not expose an actual time zone, this - /// should return false. - in-daylight-saving-time: bool, - } -} diff --git a/crates/wasi-preview1-component-adapter/wit/deps/clocks/wall-clock.wit b/crates/wasi-preview1-component-adapter/wit/deps/clocks/wall-clock.wit deleted file mode 100644 index 89c5a75da68b..000000000000 --- a/crates/wasi-preview1-component-adapter/wit/deps/clocks/wall-clock.wit +++ /dev/null @@ -1,41 +0,0 @@ -/// WASI Wall Clock is a clock API intended to let users query the current -/// time. The name "wall" makes an analogy to a "clock on the wall", which -/// is not necessarily monotonic as it may be reset. -/// -/// It is intended to be portable at least between Unix-family platforms and -/// Windows. -/// -/// A wall clock is a clock which measures the date and time according to -/// some external reference. -/// -/// External references may be reset, so this clock is not necessarily -/// monotonic, making it unsuitable for measuring elapsed time. -/// -/// It is intended for reporting the current date and time for humans. -default interface wall-clock { - /// A time and date in seconds plus nanoseconds. - record datetime { - seconds: u64, - nanoseconds: u32, - } - - /// Read the current value of the clock. - /// - /// This clock is not monotonic, therefore calling this function repeatedly - /// will not necessarily produce a sequence of non-decreasing values. - /// - /// The returned timestamps represent the number of seconds since - /// 1970-01-01T00:00:00Z, also known as [POSIX's Seconds Since the Epoch], - /// also known as [Unix Time]. - /// - /// The nanoseconds field of the output is always less than 1000000000. - /// - /// [POSIX's Seconds Since the Epoch]: https://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_xbd_chap04.html#tag_21_04_16 - /// [Unix Time]: https://en.wikipedia.org/wiki/Unix_time - now: func() -> datetime - - /// Query the resolution of the clock. - /// - /// The nanoseconds field of the output is always less than 1000000000. - resolution: func() -> datetime -} diff --git a/crates/wasi-preview1-component-adapter/wit/deps/http/incoming-handler.wit b/crates/wasi-preview1-component-adapter/wit/deps/http/incoming-handler.wit deleted file mode 100644 index 1ecff0aa5f5b..000000000000 --- a/crates/wasi-preview1-component-adapter/wit/deps/http/incoming-handler.wit +++ /dev/null @@ -1,24 +0,0 @@ -// The `wasi:http/incoming-handler` interface is meant to be exported by -// components and called by the host in response to a new incoming HTTP -// response. -// -// NOTE: in Preview3, this interface will be merged with -// `wasi:http/outgoing-handler` into a single `wasi:http/handler` interface -// that takes a `request` parameter and returns a `response` result. -// -default interface incoming-handler { - use pkg.types.{incoming-request, response-outparam} - - // The `handle` function takes an outparam instead of returning its response - // so that the component may stream its response while streaming any other - // request or response bodies. The callee MUST write a response to the - // `response-out` and then finish the response before returning. The `handle` - // function is allowed to continue execution after finishing the response's - // output stream. While this post-response execution is taken off the - // critical path, since there is no return value, there is no way to report - // its success or failure. - handle: func( - request: incoming-request, - response-out: response-outparam - ) -} diff --git a/crates/wasi-preview1-component-adapter/wit/deps/http/outgoing-handler.wit b/crates/wasi-preview1-component-adapter/wit/deps/http/outgoing-handler.wit deleted file mode 100644 index abe812ffaba7..000000000000 --- a/crates/wasi-preview1-component-adapter/wit/deps/http/outgoing-handler.wit +++ /dev/null @@ -1,18 +0,0 @@ -// The `wasi:http/outgoing-handler` interface is meant to be imported by -// components and implemented by the host. -// -// NOTE: in Preview3, this interface will be merged with -// `wasi:http/outgoing-handler` into a single `wasi:http/handler` interface -// that takes a `request` parameter and returns a `response` result. -// -default interface outgoing-handler { - use pkg.types.{outgoing-request, request-options, future-incoming-response} - - // The parameter and result types of the `handle` function allow the caller - // to concurrently stream the bodies of the outgoing request and the incoming - // response. - handle: func( - request: outgoing-request, - options: option - ) -> future-incoming-response -} diff --git a/crates/wasi-preview1-component-adapter/wit/deps/http/types.wit b/crates/wasi-preview1-component-adapter/wit/deps/http/types.wit deleted file mode 100644 index bdcf79737273..000000000000 --- a/crates/wasi-preview1-component-adapter/wit/deps/http/types.wit +++ /dev/null @@ -1,157 +0,0 @@ -// The `wasi:http/types` interface is meant to be imported by components to -// define the HTTP resource types and operations used by the component's -// imported and exported interfaces. -default interface types { - use io.streams.{input-stream, output-stream} - use poll.poll.{pollable} - - // This type corresponds to HTTP standard Methods. - variant method { - get, - head, - post, - put, - delete, - connect, - options, - trace, - patch, - other(string) - } - - // This type corresponds to HTTP standard Related Schemes. - variant scheme { - HTTP, - HTTPS, - other(string) - } - - // TODO: perhaps better align with HTTP semantics? - // This type enumerates the different kinds of errors that may occur when - // initially returning a response. - variant error { - invalid-url(string), - timeout-error(string), - protocol-error(string), - unexpected-error(string) - } - - // This following block defines the `fields` resource which corresponds to - // HTTP standard Fields. Soon, when resource types are added, the `type - // fields = u32` type alias can be replaced by a proper `resource fields` - // definition containing all the functions using the method syntactic sugar. - type fields = u32 - drop-fields: func(fields: fields) - new-fields: func(entries: list>) -> fields - fields-get: func(fields: fields, name: string) -> list - fields-set: func(fields: fields, name: string, value: list) - fields-delete: func(fields: fields, name: string) - fields-append: func(fields: fields, name: string, value: string) - fields-entries: func(fields: fields) -> list> - fields-clone: func(fields: fields) -> fields - - type headers = fields - type trailers = fields - - // The following block defines stream types which corresponds to the HTTP - // standard Contents and Trailers. With Preview3, all of these fields can be - // replaced by a stream>. In the interim, we need to - // build on separate resource types defined by `wasi:io/streams`. The - // `finish-` functions emulate the stream's result value and MUST be called - // exactly once after the final read/write from/to the stream before dropping - // the stream. - type incoming-stream = input-stream - type outgoing-stream = output-stream - finish-incoming-stream: func(s: incoming-stream) -> option - finish-outgoing-stream: func(s: outgoing-stream, trailers: option) - - // The following block defines the `incoming-request` and `outgoing-request` - // resource types that correspond to HTTP standard Requests. Soon, when - // resource types are added, the `u32` type aliases can be replaced by - // proper `resource` type definitions containing all the functions as - // methods. Later, Preview2 will allow both types to be merged together into - // a single `request` type (that uses the single `stream` type mentioned - // above). The `consume` and `write` methods may only be called once (and - // return failure thereafter). - type incoming-request = u32 - type outgoing-request = u32 - drop-incoming-request: func(request: incoming-request) - drop-outgoing-request: func(request: outgoing-request) - incoming-request-method: func(request: incoming-request) -> method - incoming-request-path: func(request: incoming-request) -> string - incoming-request-query: func(request: incoming-request) -> string - incoming-request-scheme: func(request: incoming-request) -> option - incoming-request-authority: func(request: incoming-request) -> string - incoming-request-headers: func(request: incoming-request) -> headers - incoming-request-consume: func(request: incoming-request) -> result - new-outgoing-request: func( - method: method, - path: string, - query: string, - scheme: option, - authority: string, - headers: headers - ) -> outgoing-request - outgoing-request-write: func(request: outgoing-request) -> result - - // Additional optional parameters that can be set when making a request. - record request-options { - // The following timeouts are specific to the HTTP protocol and work - // independently of the overall timeouts passed to `io.poll.poll-oneoff`. - - // The timeout for the initial connect. - connect-timeout-ms: option, - - // The timeout for receiving the first byte of the response body. - first-byte-timeout-ms: option, - - // The timeout for receiving the next chunk of bytes in the response body - // stream. - between-bytes-timeout-ms: option - } - - // The following block defines a special resource type used by the - // `wasi:http/incoming-handler` interface. When resource types are added, this - // block can be replaced by a proper `resource response-outparam { ... }` - // definition. Later, with Preview3, the need for an outparam goes away entirely - // (the `wasi:http/handler` interface used for both incoming and outgoing can - // simply return a `stream`). - type response-outparam = u32 - drop-response-outparam: func(response: response-outparam) - set-response-outparam: func(response: result) -> result - - // This type corresponds to the HTTP standard Status Code. - type status-code = u16 - - // The following block defines the `incoming-response` and `outgoing-response` - // resource types that correspond to HTTP standard Responses. Soon, when - // resource types are added, the `u32` type aliases can be replaced by proper - // `resource` type definitions containing all the functions as methods. Later, - // Preview2 will allow both types to be merged together into a single `response` - // type (that uses the single `stream` type mentioned above). The `consume` and - // `write` methods may only be called once (and return failure thereafter). - type incoming-response = u32 - type outgoing-response = u32 - drop-incoming-response: func(response: incoming-response) - drop-outgoing-response: func(response: outgoing-response) - incoming-response-status: func(response: incoming-response) -> status-code - incoming-response-headers: func(response: incoming-response) -> headers - incoming-response-consume: func(response: incoming-response) -> result - new-outgoing-response: func( - status-code: status-code, - headers: headers - ) -> outgoing-response - outgoing-response-write: func(response: outgoing-response) -> result - - // The following block defines a special resource type used by the - // `wasi:http/outgoing-handler` interface to emulate - // `future>` in advance of Preview3. Given a - // `future-incoming-response`, the client can call the non-blocking `get` - // method to get the result if it is available. If the result is not available, - // the client can call `listen` to get a `pollable` that can be passed to - // `io.poll.poll-oneoff`. - type future-incoming-response = u32 - drop-future-incoming-response: func(f: future-incoming-response) - future-incoming-response-get: func(f: future-incoming-response) -> option> - listen-to-future-incoming-response: func(f: future-incoming-response) -> pollable -} diff --git a/crates/wasi-preview1-component-adapter/wit/deps/io/streams.wit b/crates/wasi-preview1-component-adapter/wit/deps/io/streams.wit deleted file mode 100644 index c1567fd4c1c8..000000000000 --- a/crates/wasi-preview1-component-adapter/wit/deps/io/streams.wit +++ /dev/null @@ -1,213 +0,0 @@ -/// WASI I/O is an I/O abstraction API which is currently focused on providing -/// stream types. -/// -/// In the future, the component model is expected to add built-in stream types; -/// when it does, they are expected to subsume this API. -default interface streams { - use poll.poll.{pollable} - - /// An error type returned from a stream operation. Currently this - /// doesn't provide any additional information. - record stream-error {} - - /// An input bytestream. In the future, this will be replaced by handle - /// types. - /// - /// This conceptually represents a `stream`. It's temporary - /// scaffolding until component-model's async features are ready. - /// - /// `input-stream`s are *non-blocking* to the extent practical on underlying - /// platforms. I/O operations always return promptly; if fewer bytes are - /// promptly available than requested, they return the number of bytes promptly - /// available, which could even be zero. To wait for data to be available, - /// use the `subscribe-to-input-stream` function to obtain a `pollable` which - /// can be polled for using `wasi_poll`. - /// - /// And at present, it is a `u32` instead of being an actual handle, until - /// the wit-bindgen implementation of handles and resources is ready. - /// - /// This [represents a resource](https://github.com/WebAssembly/WASI/blob/main/docs/WitInWasi.md#Resources). - type input-stream = u32 - - /// Read bytes from a stream. - /// - /// This function returns a list of bytes containing the data that was - /// read, along with a bool which, when true, indicates that the end of the - /// stream was reached. The returned list will contain up to `len` bytes; it - /// may return fewer than requested, but not more. - /// - /// Once a stream has reached the end, subsequent calls to read or - /// `skip` will always report end-of-stream rather than producing more - /// data. - /// - /// If `len` is 0, it represents a request to read 0 bytes, which should - /// always succeed, assuming the stream hasn't reached its end yet, and - /// return an empty list. - /// - /// The len here is a `u64`, but some callees may not be able to allocate - /// a buffer as large as that would imply. - /// FIXME: describe what happens if allocation fails. - read: func( - this: input-stream, - /// The maximum number of bytes to read - len: u64 - ) -> result, bool>, stream-error> - - /// Read bytes from a stream, with blocking. - /// - /// This is similar to `read`, except that it blocks until at least one - /// byte can be read. - blocking-read: func( - this: input-stream, - /// The maximum number of bytes to read - len: u64 - ) -> result, bool>, stream-error> - - /// Skip bytes from a stream. - /// - /// This is similar to the `read` function, but avoids copying the - /// bytes into the instance. - /// - /// Once a stream has reached the end, subsequent calls to read or - /// `skip` will always report end-of-stream rather than producing more - /// data. - /// - /// This function returns the number of bytes skipped, along with a bool - /// indicating whether the end of the stream was reached. The returned - /// value will be at most `len`; it may be less. - skip: func( - this: input-stream, - /// The maximum number of bytes to skip. - len: u64, - ) -> result, stream-error> - - /// Skip bytes from a stream, with blocking. - /// - /// This is similar to `skip`, except that it blocks until at least one - /// byte can be consumed. - blocking-skip: func( - this: input-stream, - /// The maximum number of bytes to skip. - len: u64, - ) -> result, stream-error> - - /// Create a `pollable` which will resolve once either the specified stream - /// has bytes available to read or the other end of the stream has been - /// closed. - subscribe-to-input-stream: func(this: input-stream) -> pollable - - /// Dispose of the specified `input-stream`, after which it may no longer - /// be used. - drop-input-stream: func(this: input-stream) - - /// An output bytestream. In the future, this will be replaced by handle - /// types. - /// - /// This conceptually represents a `stream`. It's temporary - /// scaffolding until component-model's async features are ready. - /// - /// `output-stream`s are *non-blocking* to the extent practical on - /// underlying platforms. Except where specified otherwise, I/O operations also - /// always return promptly, after the number of bytes that can be written - /// promptly, which could even be zero. To wait for the stream to be ready to - /// accept data, the `subscribe-to-output-stream` function to obtain a - /// `pollable` which can be polled for using `wasi_poll`. - /// - /// And at present, it is a `u32` instead of being an actual handle, until - /// the wit-bindgen implementation of handles and resources is ready. - /// - /// This [represents a resource](https://github.com/WebAssembly/WASI/blob/main/docs/WitInWasi.md#Resources). - type output-stream = u32 - - /// Write bytes to a stream. - /// - /// This function returns a `u64` indicating the number of bytes from - /// `buf` that were written; it may be less than the full list. - write: func( - this: output-stream, - /// Data to write - buf: list - ) -> result - - /// Write bytes to a stream, with blocking. - /// - /// This is similar to `write`, except that it blocks until at least one - /// byte can be written. - blocking-write: func( - this: output-stream, - /// Data to write - buf: list - ) -> result - - /// Write multiple zero bytes to a stream. - /// - /// This function returns a `u64` indicating the number of zero bytes - /// that were written; it may be less than `len`. - write-zeroes: func( - this: output-stream, - /// The number of zero bytes to write - len: u64 - ) -> result - - /// Write multiple zero bytes to a stream, with blocking. - /// - /// This is similar to `write-zeroes`, except that it blocks until at least - /// one byte can be written. - blocking-write-zeroes: func( - this: output-stream, - /// The number of zero bytes to write - len: u64 - ) -> result - - /// Read from one stream and write to another. - /// - /// This function returns the number of bytes transferred; it may be less - /// than `len`. - /// - /// Unlike other I/O functions, this function blocks until all the data - /// read from the input stream has been written to the output stream. - splice: func( - this: output-stream, - /// The stream to read from - src: input-stream, - /// The number of bytes to splice - len: u64, - ) -> result, stream-error> - - /// Read from one stream and write to another, with blocking. - /// - /// This is similar to `splice`, except that it blocks until at least - /// one byte can be read. - blocking-splice: func( - this: output-stream, - /// The stream to read from - src: input-stream, - /// The number of bytes to splice - len: u64, - ) -> result, stream-error> - - /// Forward the entire contents of an input stream to an output stream. - /// - /// This function repeatedly reads from the input stream and writes - /// the data to the output stream, until the end of the input stream - /// is reached, or an error is encountered. - /// - /// Unlike other I/O functions, this function blocks until the end - /// of the input stream is seen and all the data has been written to - /// the output stream. - /// - /// This function returns the number of bytes transferred. - forward: func( - this: output-stream, - /// The stream to read from - src: input-stream - ) -> result - - /// Create a `pollable` which will resolve once either the specified stream - /// is ready to accept bytes or the other end of the stream has been closed. - subscribe-to-output-stream: func(this: output-stream) -> pollable - - /// Dispose of the specified `output-stream`, after which it may no longer - /// be used. - drop-output-stream: func(this: output-stream) -} diff --git a/crates/wasi-preview1-component-adapter/wit/deps/logging/handler.wit b/crates/wasi-preview1-component-adapter/wit/deps/logging/handler.wit deleted file mode 100644 index c9632b9cc4f8..000000000000 --- a/crates/wasi-preview1-component-adapter/wit/deps/logging/handler.wit +++ /dev/null @@ -1,32 +0,0 @@ -/// WASI Logging is a logging API intended to let users emit log messages with -/// simple priority levels and context values. -default interface handler { - /// A log level, describing a kind of message. - enum level { - /// Describes messages about the values of variables and the flow of - /// control within a program. - trace, - - /// Describes messages likely to be of interest to someone debugging a - /// program. - debug, - - /// Describes messages likely to be of interest to someone monitoring a - /// program. - info, - - /// Describes messages indicating hazardous situations. - warn, - - /// Describes messages indicating serious errors. - error, - } - - /// Emit a log message. - /// - /// A log message has a `level` describing what kind of message is being - /// sent, a context, which is an uninterpreted string meant to help - /// consumers group similar messages, and a string containing the message - /// text. - log: func(level: level, context: string, message: string) -} diff --git a/crates/wasi-preview1-component-adapter/wit/deps/poll/poll.wit b/crates/wasi-preview1-component-adapter/wit/deps/poll/poll.wit deleted file mode 100644 index 28f08e17d755..000000000000 --- a/crates/wasi-preview1-component-adapter/wit/deps/poll/poll.wit +++ /dev/null @@ -1,39 +0,0 @@ -/// A poll API intended to let users wait for I/O events on multiple handles -/// at once. -default interface poll { - /// A "pollable" handle. - /// - /// This is conceptually represents a `stream<_, _>`, or in other words, - /// a stream that one can wait on, repeatedly, but which does not itself - /// produce any data. It's temporary scaffolding until component-model's - /// async features are ready. - /// - /// And at present, it is a `u32` instead of being an actual handle, until - /// the wit-bindgen implementation of handles and resources is ready. - /// - /// `pollable` lifetimes are not automatically managed. Users must ensure - /// that they do not outlive the resource they reference. - /// - /// This [represents a resource](https://github.com/WebAssembly/WASI/blob/main/docs/WitInWasi.md#Resources). - type pollable = u32 - - /// Dispose of the specified `pollable`, after which it may no longer - /// be used. - drop-pollable: func(this: pollable) - - /// Poll for completion on a set of pollables. - /// - /// The "oneoff" in the name refers to the fact that this function must do a - /// linear scan through the entire list of subscriptions, which may be - /// inefficient if the number is large and the same subscriptions are used - /// many times. In the future, this is expected to be obsoleted by the - /// component model async proposal, which will include a scalable waiting - /// facility. - /// - /// Note that the return type would ideally be `list`, but that would - /// be more difficult to polyfill given the current state of `wit-bindgen`. - /// See - /// for details. For now, we use zero to mean "not ready" and non-zero to - /// mean "ready". - poll-oneoff: func(in: list) -> list -} diff --git a/crates/wasi-preview1-component-adapter/wit/deps/preview/reactor.wit b/crates/wasi-preview1-component-adapter/wit/deps/preview/reactor.wit deleted file mode 100644 index 2abfa466ba3b..000000000000 --- a/crates/wasi-preview1-component-adapter/wit/deps/preview/reactor.wit +++ /dev/null @@ -1,21 +0,0 @@ -default world reactor { - import wall-clock: clocks.wall-clock - import monotonic-clock: clocks.monotonic-clock - import timezone: clocks.timezone - import filesystem: filesystem.filesystem - import instance-network: sockets.instance-network - import ip-name-lookup: sockets.ip-name-lookup - import network: sockets.network - import tcp-create-socket: sockets.tcp-create-socket - import tcp: sockets.tcp - import udp-create-socket: sockets.udp-create-socket - import udp: sockets.udp - import random: random.random - import poll: poll.poll - import streams: io.streams - import console: logging.handler - import default-outgoing-HTTP: http.outgoing-handler - import environment: wasi-cli-base.environment - import preopens: wasi-cli-base.preopens - import exit: wasi-cli-base.exit -} diff --git a/crates/wasi-preview1-component-adapter/wit/deps/sockets/instance-network.wit b/crates/wasi-preview1-component-adapter/wit/deps/sockets/instance-network.wit deleted file mode 100644 index b1f5c982d976..000000000000 --- a/crates/wasi-preview1-component-adapter/wit/deps/sockets/instance-network.wit +++ /dev/null @@ -1,9 +0,0 @@ - -/// This interface provides a value-export of the default network handle.. -default interface instance-network { - use pkg.network.{network} - - /// Get a handle to the default network. - instance-network: func() -> network - -} diff --git a/crates/wasi-preview1-component-adapter/wit/deps/wasi-cli-base/environment.wit b/crates/wasi-preview1-component-adapter/wit/deps/wasi-cli-base/environment.wit deleted file mode 100644 index 876ea3a0c921..000000000000 --- a/crates/wasi-preview1-component-adapter/wit/deps/wasi-cli-base/environment.wit +++ /dev/null @@ -1,14 +0,0 @@ -default interface environment { - /// Get the POSIX-style environment variables. - /// - /// Each environment variable is provided as a pair of string variable names - /// and string value. - /// - /// Morally, these are a value import, but until value imports are available - /// in the component model, this import function should return the same - /// values each time it is called. - get-environment: func() -> list> - - /// Get the POSIX-style arguments to the program. - get-arguments: func() -> list -} diff --git a/crates/wasi-preview1-component-adapter/wit/deps/wasi-cli-base/exit.wit b/crates/wasi-preview1-component-adapter/wit/deps/wasi-cli-base/exit.wit deleted file mode 100644 index 2759e9dd989c..000000000000 --- a/crates/wasi-preview1-component-adapter/wit/deps/wasi-cli-base/exit.wit +++ /dev/null @@ -1,4 +0,0 @@ -default interface wasi-exit { - /// Exit the curerent instance and any linked instances. - exit: func(status: result) -} diff --git a/crates/wasi/src/preview2/preview1/mod.rs b/crates/wasi/src/preview2/preview1/mod.rs index 3fb1a5806b2b..9040425acf33 100644 --- a/crates/wasi/src/preview2/preview1/mod.rs +++ b/crates/wasi/src/preview2/preview1/mod.rs @@ -1,25 +1,27 @@ use crate::preview2::filesystem::TableFsExt; use crate::preview2::preview2::filesystem::TableReaddirExt; +use crate::preview2::wasi::cli_base::{preopens, stderr, stdin, stdout}; +use crate::preview2::wasi::clocks::monotonic_clock; +use crate::preview2::wasi::clocks::wall_clock; +use crate::preview2::wasi::filesystem::filesystem; +use crate::preview2::wasi::io::streams; use crate::preview2::{wasi, TableError, WasiView}; - -use core::borrow::Borrow; -use core::cell::Cell; -use core::mem::{size_of, size_of_val}; -use core::ops::{Deref, DerefMut}; -use core::slice; -use core::sync::atomic::{AtomicU64, Ordering}; - +use anyhow::{anyhow, bail, Context}; +use std::borrow::Borrow; +use std::cell::Cell; use std::collections::BTreeMap; +use std::mem::{size_of, size_of_val}; +use std::ops::{Deref, DerefMut}; +use std::slice; +use std::sync::atomic::{AtomicU64, Ordering}; use std::sync::Arc; - -use anyhow::{anyhow, bail, Context}; use wiggle::tracing::instrument; use wiggle::{GuestPtr, GuestSliceMut, GuestStrCow, GuestType}; #[derive(Clone, Debug)] struct File { /// The handle to the preview2 descriptor that this file is referencing. - fd: wasi::filesystem::Descriptor, + fd: filesystem::Descriptor, /// The current-position pointer. position: Arc, @@ -35,10 +37,10 @@ struct File { #[derive(Clone, Debug)] enum Descriptor { - Stdin(wasi::preopens::InputStream), - Stdout(wasi::preopens::OutputStream), - Stderr(wasi::preopens::OutputStream), - PreopenDirectory((wasi::filesystem::Descriptor, String)), + Stdin(preopens::InputStream), + Stdout(preopens::OutputStream), + Stderr(preopens::OutputStream), + PreopenDirectory((filesystem::Descriptor, String)), File(File), } @@ -70,11 +72,7 @@ impl DerefMut for Descriptors { impl Descriptors { /// Initializes [Self] using `preopens` async fn new( - preopens: &mut (impl wasi::preopens::Host - + wasi::stdin::Host - + wasi::stdout::Host - + wasi::stderr::Host - + ?Sized), + preopens: &mut (impl preopens::Host + stdin::Host + stdout::Host + stderr::Host + ?Sized), ) -> Result { let stdin = preopens .get_stdin() @@ -245,8 +243,8 @@ impl Transaction<'_, T> { } } - /// Returns [`wasi::filesystem::Descriptor`] corresponding to `fd` - fn get_fd(&mut self, fd: types::Fd) -> ErrnoResult { + /// Returns [`filesystem::Descriptor`] corresponding to `fd` + fn get_fd(&mut self, fd: types::Fd) -> ErrnoResult { match self.get_descriptor(fd)? { Descriptor::File(File { fd, .. }) => Ok(*fd), Descriptor::PreopenDirectory((fd, _)) => Ok(*fd), @@ -255,16 +253,16 @@ impl Transaction<'_, T> { } } - /// Returns [`wasi::filesystem::Descriptor`] corresponding to `fd` + /// Returns [`filesystem::Descriptor`] corresponding to `fd` /// if it describes a [`Descriptor::File`] of [`crate::preview2::filesystem::File`] type - fn get_file_fd(&mut self, fd: types::Fd) -> ErrnoResult { + fn get_file_fd(&mut self, fd: types::Fd) -> ErrnoResult { self.get_file(fd).map(|File { fd, .. }| *fd) } - /// Returns [`wasi::filesystem::Descriptor`] corresponding to `fd` + /// Returns [`filesystem::Descriptor`] corresponding to `fd` /// if it describes a [`Descriptor::File`] or [`Descriptor::PreopenDirectory`] /// of [`crate::preview2::filesystem::Dir`] type - fn get_dir_fd(&mut self, fd: types::Fd) -> ErrnoResult { + fn get_dir_fd(&mut self, fd: types::Fd) -> ErrnoResult { let fd = fd.into(); match self.descriptors.get_mut().get(&fd) { Some(Descriptor::File(File { fd, .. })) if self.view.table().is_dir(*fd) => Ok(*fd), @@ -276,11 +274,7 @@ impl Transaction<'_, T> { #[wiggle::async_trait] trait WasiPreview1ViewExt: - WasiPreview1View - + wasi::preopens::Host - + wasi::stdin::Host - + wasi::stdout::Host - + wasi::stderr::Host + WasiPreview1View + preopens::Host + stdin::Host + stdout::Host + stderr::Host { /// Lazily initializes [`WasiPreview1Adapter`] returned by [`WasiPreview1View::adapter_mut`] /// and returns [`Transaction`] on success @@ -298,55 +292,46 @@ trait WasiPreview1ViewExt: } /// Lazily initializes [`WasiPreview1Adapter`] returned by [`WasiPreview1View::adapter_mut`] - /// and returns [`wasi::filesystem::Descriptor`] corresponding to `fd` - async fn get_fd( - &mut self, - fd: types::Fd, - ) -> Result { + /// and returns [`filesystem::Descriptor`] corresponding to `fd` + async fn get_fd(&mut self, fd: types::Fd) -> Result { let mut st = self.transact().await?; let fd = st.get_fd(fd)?; Ok(fd) } /// Lazily initializes [`WasiPreview1Adapter`] returned by [`WasiPreview1View::adapter_mut`] - /// and returns [`wasi::filesystem::Descriptor`] corresponding to `fd` + /// and returns [`filesystem::Descriptor`] corresponding to `fd` /// if it describes a [`Descriptor::File`] of [`crate::preview2::filesystem::File`] type - async fn get_file_fd( - &mut self, - fd: types::Fd, - ) -> Result { + async fn get_file_fd(&mut self, fd: types::Fd) -> Result { let mut st = self.transact().await?; let fd = st.get_file_fd(fd)?; Ok(fd) } /// Lazily initializes [`WasiPreview1Adapter`] returned by [`WasiPreview1View::adapter_mut`] - /// and returns [`wasi::filesystem::Descriptor`] corresponding to `fd` + /// and returns [`filesystem::Descriptor`] corresponding to `fd` /// if it describes a [`Descriptor::File`] or [`Descriptor::PreopenDirectory`] /// of [`crate::preview2::filesystem::Dir`] type - async fn get_dir_fd( - &mut self, - fd: types::Fd, - ) -> Result { + async fn get_dir_fd(&mut self, fd: types::Fd) -> Result { let mut st = self.transact().await?; let fd = st.get_dir_fd(fd)?; Ok(fd) } } -impl WasiPreview1ViewExt for T {} +impl WasiPreview1ViewExt for T {} pub fn add_to_linker< T: WasiPreview1View - + wasi::environment::Host - + wasi::exit::Host - + wasi::filesystem::Host - + wasi::monotonic_clock::Host - + wasi::poll::Host - + wasi::preopens::Host - + wasi::random::Host - + wasi::streams::Host - + wasi::wall_clock::Host, + + wasi::cli_base::environment::Host + + wasi::cli_base::exit::Host + + wasi::cli_base::preopens::Host + + wasi::filesystem::filesystem::Host + + wasi::poll::poll::Host + + wasi::random::random::Host + + wasi::io::streams::Host + + wasi::clocks::monotonic_clock::Host + + wasi::clocks::wall_clock::Host, >( linker: &mut wasmtime::Linker, ) -> anyhow::Result<()> { @@ -373,31 +358,29 @@ fn systimespec( set: bool, ts: types::Timestamp, now: bool, -) -> ErrnoResult { +) -> ErrnoResult { if set && now { Err(types::Errno::Inval) } else if set { - Ok(wasi::filesystem::NewTimestamp::Timestamp( - wasi::filesystem::Datetime { - seconds: ts / 1_000_000_000, - nanoseconds: (ts % 1_000_000_000) as _, - }, - )) + Ok(filesystem::NewTimestamp::Timestamp(filesystem::Datetime { + seconds: ts / 1_000_000_000, + nanoseconds: (ts % 1_000_000_000) as _, + })) } else if now { - Ok(wasi::filesystem::NewTimestamp::Now) + Ok(filesystem::NewTimestamp::Now) } else { - Ok(wasi::filesystem::NewTimestamp::NoChange) + Ok(filesystem::NewTimestamp::NoChange) } } -impl TryFrom for types::Timestamp { +impl TryFrom for types::Timestamp { type Error = types::Errno; fn try_from( - wasi::wall_clock::Datetime { + wall_clock::Datetime { seconds, nanoseconds, - }: wasi::wall_clock::Datetime, + }: wall_clock::Datetime, ) -> Result { types::Timestamp::from(seconds) .checked_mul(1_000_000_000) @@ -406,126 +389,124 @@ impl TryFrom for types::Timestamp { } } -impl From for wasi::filesystem::PathFlags { +impl From for filesystem::PathFlags { fn from(flags: types::Lookupflags) -> Self { if flags.contains(types::Lookupflags::SYMLINK_FOLLOW) { - wasi::filesystem::PathFlags::SYMLINK_FOLLOW + filesystem::PathFlags::SYMLINK_FOLLOW } else { - wasi::filesystem::PathFlags::empty() + filesystem::PathFlags::empty() } } } -impl From for wasi::filesystem::OpenFlags { +impl From for filesystem::OpenFlags { fn from(flags: types::Oflags) -> Self { - let mut out = wasi::filesystem::OpenFlags::empty(); + let mut out = filesystem::OpenFlags::empty(); if flags.contains(types::Oflags::CREAT) { - out |= wasi::filesystem::OpenFlags::CREATE; + out |= filesystem::OpenFlags::CREATE; } if flags.contains(types::Oflags::DIRECTORY) { - out |= wasi::filesystem::OpenFlags::DIRECTORY; + out |= filesystem::OpenFlags::DIRECTORY; } if flags.contains(types::Oflags::EXCL) { - out |= wasi::filesystem::OpenFlags::EXCLUSIVE; + out |= filesystem::OpenFlags::EXCLUSIVE; } if flags.contains(types::Oflags::TRUNC) { - out |= wasi::filesystem::OpenFlags::TRUNCATE; + out |= filesystem::OpenFlags::TRUNCATE; } out } } -impl From for wasi::filesystem::Advice { +impl From for filesystem::Advice { fn from(advice: types::Advice) -> Self { match advice { - types::Advice::Normal => wasi::filesystem::Advice::Normal, - types::Advice::Sequential => wasi::filesystem::Advice::Sequential, - types::Advice::Random => wasi::filesystem::Advice::Random, - types::Advice::Willneed => wasi::filesystem::Advice::WillNeed, - types::Advice::Dontneed => wasi::filesystem::Advice::DontNeed, - types::Advice::Noreuse => wasi::filesystem::Advice::NoReuse, + types::Advice::Normal => filesystem::Advice::Normal, + types::Advice::Sequential => filesystem::Advice::Sequential, + types::Advice::Random => filesystem::Advice::Random, + types::Advice::Willneed => filesystem::Advice::WillNeed, + types::Advice::Dontneed => filesystem::Advice::DontNeed, + types::Advice::Noreuse => filesystem::Advice::NoReuse, } } } -impl TryFrom for types::Filetype { +impl TryFrom for types::Filetype { type Error = anyhow::Error; - fn try_from(ty: wasi::filesystem::DescriptorType) -> Result { + fn try_from(ty: filesystem::DescriptorType) -> Result { match ty { - wasi::filesystem::DescriptorType::RegularFile => Ok(types::Filetype::RegularFile), - wasi::filesystem::DescriptorType::Directory => Ok(types::Filetype::Directory), - wasi::filesystem::DescriptorType::BlockDevice => Ok(types::Filetype::BlockDevice), - wasi::filesystem::DescriptorType::CharacterDevice => { - Ok(types::Filetype::CharacterDevice) - } + filesystem::DescriptorType::RegularFile => Ok(types::Filetype::RegularFile), + filesystem::DescriptorType::Directory => Ok(types::Filetype::Directory), + filesystem::DescriptorType::BlockDevice => Ok(types::Filetype::BlockDevice), + filesystem::DescriptorType::CharacterDevice => Ok(types::Filetype::CharacterDevice), // preview1 never had a FIFO code. - wasi::filesystem::DescriptorType::Fifo => Ok(types::Filetype::Unknown), + filesystem::DescriptorType::Fifo => Ok(types::Filetype::Unknown), // TODO: Add a way to disginguish between FILETYPE_SOCKET_STREAM and // FILETYPE_SOCKET_DGRAM. - wasi::filesystem::DescriptorType::Socket => { + filesystem::DescriptorType::Socket => { bail!("sockets are not currently supported") } - wasi::filesystem::DescriptorType::SymbolicLink => Ok(types::Filetype::SymbolicLink), - wasi::filesystem::DescriptorType::Unknown => Ok(types::Filetype::Unknown), + filesystem::DescriptorType::SymbolicLink => Ok(types::Filetype::SymbolicLink), + filesystem::DescriptorType::Unknown => Ok(types::Filetype::Unknown), } } } -impl From for types::Errno { - fn from(code: wasi::filesystem::ErrorCode) -> Self { +impl From for types::Errno { + fn from(code: filesystem::ErrorCode) -> Self { match code { - wasi::filesystem::ErrorCode::Access => types::Errno::Acces, - wasi::filesystem::ErrorCode::WouldBlock => types::Errno::Again, - wasi::filesystem::ErrorCode::Already => types::Errno::Already, - wasi::filesystem::ErrorCode::BadDescriptor => types::Errno::Badf, - wasi::filesystem::ErrorCode::Busy => types::Errno::Busy, - wasi::filesystem::ErrorCode::Deadlock => types::Errno::Deadlk, - wasi::filesystem::ErrorCode::Quota => types::Errno::Dquot, - wasi::filesystem::ErrorCode::Exist => types::Errno::Exist, - wasi::filesystem::ErrorCode::FileTooLarge => types::Errno::Fbig, - wasi::filesystem::ErrorCode::IllegalByteSequence => types::Errno::Ilseq, - wasi::filesystem::ErrorCode::InProgress => types::Errno::Inprogress, - wasi::filesystem::ErrorCode::Interrupted => types::Errno::Intr, - wasi::filesystem::ErrorCode::Invalid => types::Errno::Inval, - wasi::filesystem::ErrorCode::Io => types::Errno::Io, - wasi::filesystem::ErrorCode::IsDirectory => types::Errno::Isdir, - wasi::filesystem::ErrorCode::Loop => types::Errno::Loop, - wasi::filesystem::ErrorCode::TooManyLinks => types::Errno::Mlink, - wasi::filesystem::ErrorCode::MessageSize => types::Errno::Msgsize, - wasi::filesystem::ErrorCode::NameTooLong => types::Errno::Nametoolong, - wasi::filesystem::ErrorCode::NoDevice => types::Errno::Nodev, - wasi::filesystem::ErrorCode::NoEntry => types::Errno::Noent, - wasi::filesystem::ErrorCode::NoLock => types::Errno::Nolck, - wasi::filesystem::ErrorCode::InsufficientMemory => types::Errno::Nomem, - wasi::filesystem::ErrorCode::InsufficientSpace => types::Errno::Nospc, - wasi::filesystem::ErrorCode::Unsupported => types::Errno::Notsup, - wasi::filesystem::ErrorCode::NotDirectory => types::Errno::Notdir, - wasi::filesystem::ErrorCode::NotEmpty => types::Errno::Notempty, - wasi::filesystem::ErrorCode::NotRecoverable => types::Errno::Notrecoverable, - wasi::filesystem::ErrorCode::NoTty => types::Errno::Notty, - wasi::filesystem::ErrorCode::NoSuchDevice => types::Errno::Nxio, - wasi::filesystem::ErrorCode::Overflow => types::Errno::Overflow, - wasi::filesystem::ErrorCode::NotPermitted => types::Errno::Perm, - wasi::filesystem::ErrorCode::Pipe => types::Errno::Pipe, - wasi::filesystem::ErrorCode::ReadOnly => types::Errno::Rofs, - wasi::filesystem::ErrorCode::InvalidSeek => types::Errno::Spipe, - wasi::filesystem::ErrorCode::TextFileBusy => types::Errno::Txtbsy, - wasi::filesystem::ErrorCode::CrossDevice => types::Errno::Xdev, + filesystem::ErrorCode::Access => types::Errno::Acces, + filesystem::ErrorCode::WouldBlock => types::Errno::Again, + filesystem::ErrorCode::Already => types::Errno::Already, + filesystem::ErrorCode::BadDescriptor => types::Errno::Badf, + filesystem::ErrorCode::Busy => types::Errno::Busy, + filesystem::ErrorCode::Deadlock => types::Errno::Deadlk, + filesystem::ErrorCode::Quota => types::Errno::Dquot, + filesystem::ErrorCode::Exist => types::Errno::Exist, + filesystem::ErrorCode::FileTooLarge => types::Errno::Fbig, + filesystem::ErrorCode::IllegalByteSequence => types::Errno::Ilseq, + filesystem::ErrorCode::InProgress => types::Errno::Inprogress, + filesystem::ErrorCode::Interrupted => types::Errno::Intr, + filesystem::ErrorCode::Invalid => types::Errno::Inval, + filesystem::ErrorCode::Io => types::Errno::Io, + filesystem::ErrorCode::IsDirectory => types::Errno::Isdir, + filesystem::ErrorCode::Loop => types::Errno::Loop, + filesystem::ErrorCode::TooManyLinks => types::Errno::Mlink, + filesystem::ErrorCode::MessageSize => types::Errno::Msgsize, + filesystem::ErrorCode::NameTooLong => types::Errno::Nametoolong, + filesystem::ErrorCode::NoDevice => types::Errno::Nodev, + filesystem::ErrorCode::NoEntry => types::Errno::Noent, + filesystem::ErrorCode::NoLock => types::Errno::Nolck, + filesystem::ErrorCode::InsufficientMemory => types::Errno::Nomem, + filesystem::ErrorCode::InsufficientSpace => types::Errno::Nospc, + filesystem::ErrorCode::Unsupported => types::Errno::Notsup, + filesystem::ErrorCode::NotDirectory => types::Errno::Notdir, + filesystem::ErrorCode::NotEmpty => types::Errno::Notempty, + filesystem::ErrorCode::NotRecoverable => types::Errno::Notrecoverable, + filesystem::ErrorCode::NoTty => types::Errno::Notty, + filesystem::ErrorCode::NoSuchDevice => types::Errno::Nxio, + filesystem::ErrorCode::Overflow => types::Errno::Overflow, + filesystem::ErrorCode::NotPermitted => types::Errno::Perm, + filesystem::ErrorCode::Pipe => types::Errno::Pipe, + filesystem::ErrorCode::ReadOnly => types::Errno::Rofs, + filesystem::ErrorCode::InvalidSeek => types::Errno::Spipe, + filesystem::ErrorCode::TextFileBusy => types::Errno::Txtbsy, + filesystem::ErrorCode::CrossDevice => types::Errno::Xdev, } } } -impl From for types::Error { - fn from(code: wasi::filesystem::ErrorCode) -> Self { +impl From for types::Error { + fn from(code: filesystem::ErrorCode) -> Self { types::Errno::from(code).into() } } -impl TryFrom for types::Errno { +impl TryFrom for types::Errno { type Error = anyhow::Error; - fn try_from(err: wasi::filesystem::Error) -> Result { + fn try_from(err: filesystem::Error) -> Result { match err.downcast() { Ok(code) => Ok(code.into()), Err(e) => Err(e), @@ -533,10 +514,10 @@ impl TryFrom for types::Errno { } } -impl TryFrom for types::Error { +impl TryFrom for types::Error { type Error = anyhow::Error; - fn try_from(err: wasi::filesystem::Error) -> Result { + fn try_from(err: filesystem::Error) -> Result { match err.downcast() { Ok(code) => Ok(code.into()), Err(e) => Err(e), @@ -642,15 +623,15 @@ fn first_non_empty_iovec<'a>( #[wiggle::async_trait] impl< T: WasiPreview1View - + wasi::environment::Host - + wasi::exit::Host - + wasi::filesystem::Host - + wasi::monotonic_clock::Host - + wasi::poll::Host - + wasi::preopens::Host - + wasi::random::Host - + wasi::streams::Host - + wasi::wall_clock::Host, + + wasi::cli_base::environment::Host + + wasi::cli_base::exit::Host + + wasi::cli_base::preopens::Host + + wasi::filesystem::filesystem::Host + + wasi::poll::poll::Host + + wasi::random::random::Host + + wasi::io::streams::Host + + wasi::clocks::monotonic_clock::Host + + wasi::clocks::wall_clock::Host, > wasi_snapshot_preview1::WasiSnapshotPreview1 for T { #[instrument(skip(self))] @@ -756,12 +737,12 @@ impl< id: types::Clockid, ) -> Result { let res = match id { - types::Clockid::Realtime => wasi::wall_clock::Host::resolution(self) + types::Clockid::Realtime => wall_clock::Host::resolution(self) .await .context("failed to call `wall_clock::resolution`") .map_err(types::Error::trap)? .try_into()?, - types::Clockid::Monotonic => wasi::monotonic_clock::Host::resolution(self) + types::Clockid::Monotonic => monotonic_clock::Host::resolution(self) .await .context("failed to call `monotonic_clock::resolution`") .map_err(types::Error::trap)?, @@ -779,12 +760,12 @@ impl< _precision: types::Timestamp, ) -> Result { let now = match id { - types::Clockid::Realtime => wasi::wall_clock::Host::now(self) + types::Clockid::Realtime => wall_clock::Host::now(self) .await .context("failed to call `wall_clock::now`") .map_err(types::Error::trap)? .try_into()?, - types::Clockid::Monotonic => wasi::monotonic_clock::Host::now(self) + types::Clockid::Monotonic => monotonic_clock::Host::now(self) .await .context("failed to call `monotonic_clock::now`") .map_err(types::Error::trap)?, @@ -918,19 +899,19 @@ impl< .map_err(types::Error::trap)?; let mut fs_flags = types::Fdflags::empty(); let mut fs_rights_base = types::Rights::all(); - if !flags.contains(wasi::filesystem::DescriptorFlags::READ) { + if !flags.contains(filesystem::DescriptorFlags::READ) { fs_rights_base &= !types::Rights::FD_READ; } - if !flags.contains(wasi::filesystem::DescriptorFlags::WRITE) { + if !flags.contains(filesystem::DescriptorFlags::WRITE) { fs_rights_base &= !types::Rights::FD_WRITE; } - if flags.contains(wasi::filesystem::DescriptorFlags::DATA_INTEGRITY_SYNC) { + if flags.contains(filesystem::DescriptorFlags::DATA_INTEGRITY_SYNC) { fs_flags |= types::Fdflags::DSYNC; } - if flags.contains(wasi::filesystem::DescriptorFlags::REQUESTED_WRITE_SYNC) { + if flags.contains(filesystem::DescriptorFlags::REQUESTED_WRITE_SYNC) { fs_flags |= types::Fdflags::RSYNC; } - if flags.contains(wasi::filesystem::DescriptorFlags::FILE_INTEGRITY_SYNC) { + if flags.contains(filesystem::DescriptorFlags::FILE_INTEGRITY_SYNC) { fs_flags |= types::Fdflags::SYNC; } if append { @@ -1002,7 +983,7 @@ impl< }) } Descriptor::PreopenDirectory((fd, _)) | Descriptor::File(File { fd, .. }) => { - let wasi::filesystem::DescriptorStat { + let filesystem::DescriptorStat { device: dev, inode: ino, type_, @@ -1109,7 +1090,7 @@ impl< let (read, end) = if blocking { self.blocking_read(stream, max) } else { - wasi::streams::Host::read(self, stream, max) + streams::Host::read(self, stream, max) } .await .map_err(|_| types::Errno::Io)?; @@ -1124,13 +1105,10 @@ impl< let Some(buf) = first_non_empty_iovec(iovs)? else { return Ok(0) }; - let (read, end) = wasi::streams::Host::read( - self, - stream, - buf.len().try_into().unwrap_or(u64::MAX), - ) - .await - .map_err(|_| types::Errno::Io)?; + let (read, end) = + streams::Host::read(self, stream, buf.len().try_into().unwrap_or(u64::MAX)) + .await + .map_err(|_| types::Errno::Io)?; (buf, read, end) } _ => return Err(types::Errno::Badf.into()), @@ -1172,7 +1150,7 @@ impl< let (read, end) = if blocking { self.blocking_read(stream, max) } else { - wasi::streams::Host::read(self, stream, max) + streams::Host::read(self, stream, max) } .await .map_err(|_| types::Errno::Io)?; @@ -1235,7 +1213,7 @@ impl< let n = if blocking { self.blocking_write(stream, buf) } else { - wasi::streams::Host::write(self, stream, buf) + streams::Host::write(self, stream, buf) } .await .map_err(|_| types::Errno::Io)?; @@ -1249,7 +1227,7 @@ impl< let Some(buf) = first_non_empty_ciovec(ciovs)? else { return Ok(0) }; - wasi::streams::Host::write(self, stream, buf) + streams::Host::write(self, stream, buf) .await .map_err(|_| types::Errno::Io)? } @@ -1283,7 +1261,7 @@ impl< if blocking { self.blocking_write(stream, buf) } else { - wasi::streams::Host::write(self, stream, buf) + streams::Host::write(self, stream, buf) } .await .map_err(|_| types::Errno::Io)? @@ -1359,12 +1337,11 @@ impl< .checked_add_signed(offset) .ok_or(types::Errno::Inval)?, types::Whence::End => { - let wasi::filesystem::DescriptorStat { size, .. } = - self.stat(fd).await.map_err(|e| { - e.try_into() - .context("failed to call `stat`") - .unwrap_or_else(types::Error::trap) - })?; + let filesystem::DescriptorStat { size, .. } = self.stat(fd).await.map_err(|e| { + e.try_into() + .context("failed to call `stat`") + .unwrap_or_else(types::Error::trap) + })?; size.checked_add_signed(offset).ok_or(types::Errno::Inval)? } _ => return Err(types::Errno::Inval.into()), @@ -1411,7 +1388,7 @@ impl< .context("failed to call `read-directory`") .unwrap_or_else(types::Error::trap) })?; - let wasi::filesystem::DescriptorStat { + let filesystem::DescriptorStat { inode: fd_inode, .. } = self.stat(fd).await.map_err(|e| { e.try_into() @@ -1450,12 +1427,11 @@ impl< .into_iter() .zip(3u64..) .map(|(entry, d_next)| { - let wasi::filesystem::DirectoryEntry { inode, type_, name } = - entry.map_err(|e| { - e.try_into() - .context("failed to inspect `read-directory` entry") - .unwrap_or_else(types::Error::trap) - })?; + let filesystem::DirectoryEntry { inode, type_, name } = entry.map_err(|e| { + e.try_into() + .context("failed to inspect `read-directory` entry") + .unwrap_or_else(types::Error::trap) + })?; let d_type = type_.try_into().map_err(types::Error::trap)?; let d_namlen: u32 = name.len().try_into().map_err(|_| types::Errno::Overflow)?; Ok(( @@ -1534,7 +1510,7 @@ impl< ) -> Result { let dirfd = self.get_dir_fd(dirfd).await?; let path = read_string(path)?; - let wasi::filesystem::DescriptorStat { + let filesystem::DescriptorStat { device: dev, inode: ino, type_, @@ -1637,21 +1613,21 @@ impl< ) -> Result { let path = read_string(path)?; - let mut flags = wasi::filesystem::DescriptorFlags::empty(); + let mut flags = filesystem::DescriptorFlags::empty(); if fs_rights_base.contains(types::Rights::FD_READ) { - flags |= wasi::filesystem::DescriptorFlags::READ; + flags |= filesystem::DescriptorFlags::READ; } if fs_rights_base.contains(types::Rights::FD_WRITE) { - flags |= wasi::filesystem::DescriptorFlags::WRITE; + flags |= filesystem::DescriptorFlags::WRITE; } if fdflags.contains(types::Fdflags::SYNC) { - flags |= wasi::filesystem::DescriptorFlags::FILE_INTEGRITY_SYNC; + flags |= filesystem::DescriptorFlags::FILE_INTEGRITY_SYNC; } if fdflags.contains(types::Fdflags::DSYNC) { - flags |= wasi::filesystem::DescriptorFlags::DATA_INTEGRITY_SYNC; + flags |= filesystem::DescriptorFlags::DATA_INTEGRITY_SYNC; } if fdflags.contains(types::Fdflags::RSYNC) { - flags |= wasi::filesystem::DescriptorFlags::REQUESTED_WRITE_SYNC; + flags |= filesystem::DescriptorFlags::REQUESTED_WRITE_SYNC; } let desc = self.transact().await?.get_descriptor(dirfd)?.clone(); @@ -1671,7 +1647,7 @@ impl< path, oflags.into(), flags, - wasi::filesystem::Modes::READABLE | wasi::filesystem::Modes::WRITABLE, + filesystem::Modes::READABLE | filesystem::Modes::WRITABLE, ) .await .map_err(|e| { diff --git a/crates/wasi/src/preview2/preview2/clocks.rs b/crates/wasi/src/preview2/preview2/clocks.rs index d704c646d497..75d2927515eb 100644 --- a/crates/wasi/src/preview2/preview2/clocks.rs +++ b/crates/wasi/src/preview2/preview2/clocks.rs @@ -2,10 +2,10 @@ use crate::preview2::preview2::poll::PollableEntry; use crate::preview2::wasi::{ - monotonic_clock::{self, Instant}, - poll::Pollable, - timezone::{self, Timezone, TimezoneDisplay}, - wall_clock::{self, Datetime}, + clocks::monotonic_clock::{self, Instant}, + clocks::timezone::{self, Timezone, TimezoneDisplay}, + clocks::wall_clock::{self, Datetime}, + poll::poll::Pollable, }; use crate::preview2::WasiView; use cap_std::time::SystemTime; diff --git a/crates/wasi/src/preview2/preview2/env.rs b/crates/wasi/src/preview2/preview2/env.rs index 580a126e2632..b4288fc37f76 100644 --- a/crates/wasi/src/preview2/preview2/env.rs +++ b/crates/wasi/src/preview2/preview2/env.rs @@ -1,7 +1,14 @@ -use crate::preview2::{wasi, WasiView}; +use crate::preview2::wasi::cli_base::environment; +use crate::preview2::wasi::cli_base::preopens; +use crate::preview2::wasi::cli_base::stderr; +use crate::preview2::wasi::cli_base::stdin; +use crate::preview2::wasi::cli_base::stdout; +use crate::preview2::wasi::filesystem::filesystem; +use crate::preview2::wasi::io::streams; +use crate::preview2::WasiView; #[async_trait::async_trait] -impl wasi::environment::Host for T { +impl environment::Host for T { async fn get_environment(&mut self) -> anyhow::Result> { Ok(self.ctx().env.clone()) } @@ -11,31 +18,31 @@ impl wasi::environment::Host for T { } #[async_trait::async_trait] -impl wasi::preopens::Host for T { +impl preopens::Host for T { async fn get_directories( &mut self, - ) -> Result, anyhow::Error> { + ) -> Result, anyhow::Error> { Ok(self.ctx().preopens.clone()) } } #[async_trait::async_trait] -impl wasi::stdin::Host for T { - async fn get_stdin(&mut self) -> Result { +impl stdin::Host for T { + async fn get_stdin(&mut self) -> Result { Ok(self.ctx().stdin) } } #[async_trait::async_trait] -impl wasi::stdout::Host for T { - async fn get_stdout(&mut self) -> Result { +impl stdout::Host for T { + async fn get_stdout(&mut self) -> Result { Ok(self.ctx().stdout) } } #[async_trait::async_trait] -impl wasi::stderr::Host for T { - async fn get_stderr(&mut self) -> Result { +impl stderr::Host for T { + async fn get_stderr(&mut self) -> Result { Ok(self.ctx().stderr) } } diff --git a/crates/wasi/src/preview2/preview2/exit.rs b/crates/wasi/src/preview2/preview2/exit.rs index 164e142eae42..45754d594b13 100644 --- a/crates/wasi/src/preview2/preview2/exit.rs +++ b/crates/wasi/src/preview2/preview2/exit.rs @@ -1,4 +1,4 @@ -use crate::preview2::{wasi::exit, I32Exit, WasiView}; +use crate::preview2::{wasi::cli_base::exit, I32Exit, WasiView}; #[async_trait::async_trait] impl exit::Host for T { diff --git a/crates/wasi/src/preview2/preview2/filesystem.rs b/crates/wasi/src/preview2/preview2/filesystem.rs index bd542ca4c984..73c572314b7c 100644 --- a/crates/wasi/src/preview2/preview2/filesystem.rs +++ b/crates/wasi/src/preview2/preview2/filesystem.rs @@ -1,29 +1,32 @@ use crate::preview2::filesystem::{Dir, File, TableFsExt}; use crate::preview2::stream::TableStreamExt; -use crate::preview2::{wasi, DirPerms, FilePerms, Table, TableError, WasiView}; +use crate::preview2::wasi::clocks::wall_clock; +use crate::preview2::wasi::filesystem::filesystem; +use crate::preview2::wasi::io::streams; +use crate::preview2::{DirPerms, FilePerms, Table, TableError, WasiView}; -use wasi::filesystem::ErrorCode; +use filesystem::ErrorCode; -impl From for wasi::filesystem::Error { - fn from(error: TableError) -> wasi::filesystem::Error { +impl From for filesystem::Error { + fn from(error: TableError) -> filesystem::Error { match error { - TableError::Full => wasi::filesystem::Error::trap(anyhow::anyhow!(error)), + TableError::Full => filesystem::Error::trap(anyhow::anyhow!(error)), TableError::NotPresent | TableError::WrongType => ErrorCode::BadDescriptor.into(), } } } #[async_trait::async_trait] -impl wasi::filesystem::Host for T { +impl filesystem::Host for T { async fn advise( &mut self, - fd: wasi::filesystem::Descriptor, - offset: wasi::filesystem::Filesize, - len: wasi::filesystem::Filesize, - advice: wasi::filesystem::Advice, - ) -> Result<(), wasi::filesystem::Error> { + fd: filesystem::Descriptor, + offset: filesystem::Filesize, + len: filesystem::Filesize, + advice: filesystem::Advice, + ) -> Result<(), filesystem::Error> { + use filesystem::Advice; use system_interface::fs::{Advice as A, FileIoExt}; - use wasi::filesystem::Advice; let advice = match advice { Advice::Normal => A::Normal, @@ -39,10 +42,7 @@ impl wasi::filesystem::Host for T { Ok(()) } - async fn sync_data( - &mut self, - fd: wasi::filesystem::Descriptor, - ) -> Result<(), wasi::filesystem::Error> { + async fn sync_data(&mut self, fd: filesystem::Descriptor) -> Result<(), filesystem::Error> { let table = self.table(); if table.is_file(fd) { match table.get_file(fd)?.file.sync_data() { @@ -72,11 +72,11 @@ impl wasi::filesystem::Host for T { async fn get_flags( &mut self, - fd: wasi::filesystem::Descriptor, - ) -> Result { + fd: filesystem::Descriptor, + ) -> Result { use cap_std::io_lifetimes::AsFilelike; + use filesystem::DescriptorFlags; use system_interface::fs::{FdFlags, GetSetFdFlags}; - use wasi::filesystem::DescriptorFlags; fn get_from_fdflags(f: impl AsFilelike) -> std::io::Result { let flags = f.as_filelike().get_fd_flags()?; @@ -121,15 +121,15 @@ impl wasi::filesystem::Host for T { async fn get_type( &mut self, - fd: wasi::filesystem::Descriptor, - ) -> Result { + fd: filesystem::Descriptor, + ) -> Result { let table = self.table(); if table.is_file(fd) { let meta = table.get_file(fd)?.file.metadata()?; Ok(descriptortype_from(meta.file_type())) } else if table.is_dir(fd) { - Ok(wasi::filesystem::DescriptorType::Directory) + Ok(filesystem::DescriptorType::Directory) } else { Err(ErrorCode::BadDescriptor.into()) } @@ -137,9 +137,9 @@ impl wasi::filesystem::Host for T { async fn set_size( &mut self, - fd: wasi::filesystem::Descriptor, - size: wasi::filesystem::Filesize, - ) -> Result<(), wasi::filesystem::Error> { + fd: filesystem::Descriptor, + size: filesystem::Filesize, + ) -> Result<(), filesystem::Error> { let f = self.table().get_file(fd)?; if !f.perms.contains(FilePerms::WRITE) { Err(ErrorCode::NotPermitted)?; @@ -150,10 +150,10 @@ impl wasi::filesystem::Host for T { async fn set_times( &mut self, - fd: wasi::filesystem::Descriptor, - atim: wasi::filesystem::NewTimestamp, - mtim: wasi::filesystem::NewTimestamp, - ) -> Result<(), wasi::filesystem::Error> { + fd: filesystem::Descriptor, + atim: filesystem::NewTimestamp, + mtim: filesystem::NewTimestamp, + ) -> Result<(), filesystem::Error> { use fs_set_times::SetTimes; let table = self.table(); @@ -182,10 +182,10 @@ impl wasi::filesystem::Host for T { async fn read( &mut self, - fd: wasi::filesystem::Descriptor, - len: wasi::filesystem::Filesize, - offset: wasi::filesystem::Filesize, - ) -> Result<(Vec, bool), wasi::filesystem::Error> { + fd: filesystem::Descriptor, + len: filesystem::Filesize, + offset: filesystem::Filesize, + ) -> Result<(Vec, bool), filesystem::Error> { use std::io::IoSliceMut; use system_interface::fs::FileIoExt; @@ -213,10 +213,10 @@ impl wasi::filesystem::Host for T { async fn write( &mut self, - fd: wasi::filesystem::Descriptor, + fd: filesystem::Descriptor, buf: Vec, - offset: wasi::filesystem::Filesize, - ) -> Result { + offset: filesystem::Filesize, + ) -> Result { use std::io::IoSlice; use system_interface::fs::FileIoExt; @@ -228,13 +228,13 @@ impl wasi::filesystem::Host for T { let bytes_written = f.file.write_vectored_at(&[IoSlice::new(&buf)], offset)?; - Ok(wasi::filesystem::Filesize::try_from(bytes_written).expect("usize fits in Filesize")) + Ok(filesystem::Filesize::try_from(bytes_written).expect("usize fits in Filesize")) } async fn read_directory( &mut self, - fd: wasi::filesystem::Descriptor, - ) -> Result { + fd: filesystem::Descriptor, + ) -> Result { use cap_fs_ext::{DirEntryExt, MetadataExt}; let table = self.table_mut(); @@ -262,7 +262,7 @@ impl wasi::filesystem::Host for T { .file_name() .into_string() .map_err(|_| ReaddirError::IllegalSequence)?; - Ok(wasi::filesystem::DirectoryEntry { inode, type_, name }) + Ok(filesystem::DirectoryEntry { inode, type_, name }) }); // On windows, filter out files like `C:\DumpStack.log.tmp` which we // can't get full metadata for. @@ -280,7 +280,7 @@ impl wasi::filesystem::Host for T { }); let entries = entries.map(|r| match r { Ok(r) => Ok(r), - Err(ReaddirError::Io(e)) => Err(wasi::filesystem::Error::from(e)), + Err(ReaddirError::Io(e)) => Err(filesystem::Error::from(e)), Err(ReaddirError::IllegalSequence) => Err(ErrorCode::IllegalByteSequence.into()), }); Ok(table.push_readdir(ReaddirIterator::new(entries))?) @@ -288,8 +288,8 @@ impl wasi::filesystem::Host for T { async fn read_directory_entry( &mut self, - stream: wasi::filesystem::DirectoryEntryStream, - ) -> Result, wasi::filesystem::Error> { + stream: filesystem::DirectoryEntryStream, + ) -> Result, filesystem::Error> { let table = self.table(); let readdir = table.get_readdir(stream)?; readdir.next() @@ -297,16 +297,13 @@ impl wasi::filesystem::Host for T { async fn drop_directory_entry_stream( &mut self, - stream: wasi::filesystem::DirectoryEntryStream, + stream: filesystem::DirectoryEntryStream, ) -> anyhow::Result<()> { self.table_mut().delete_readdir(stream)?; Ok(()) } - async fn sync( - &mut self, - fd: wasi::filesystem::Descriptor, - ) -> Result<(), wasi::filesystem::Error> { + async fn sync(&mut self, fd: filesystem::Descriptor) -> Result<(), filesystem::Error> { let table = self.table(); if table.is_file(fd) { match table.get_file(fd)?.file.sync_all() { @@ -336,9 +333,9 @@ impl wasi::filesystem::Host for T { async fn create_directory_at( &mut self, - fd: wasi::filesystem::Descriptor, + fd: filesystem::Descriptor, path: String, - ) -> Result<(), wasi::filesystem::Error> { + ) -> Result<(), filesystem::Error> { let table = self.table(); let d = table.get_dir(fd)?; if !d.perms.contains(DirPerms::MUTATE) { @@ -350,8 +347,8 @@ impl wasi::filesystem::Host for T { async fn stat( &mut self, - fd: wasi::filesystem::Descriptor, - ) -> Result { + fd: filesystem::Descriptor, + ) -> Result { let table = self.table(); if table.is_file(fd) { let f = table.get_file(fd)?; @@ -374,10 +371,10 @@ impl wasi::filesystem::Host for T { async fn stat_at( &mut self, - fd: wasi::filesystem::Descriptor, - path_flags: wasi::filesystem::PathFlags, + fd: filesystem::Descriptor, + path_flags: filesystem::PathFlags, path: String, - ) -> Result { + ) -> Result { let table = self.table(); let d = table.get_dir(fd)?; if !d.perms.contains(DirPerms::READ) { @@ -394,12 +391,12 @@ impl wasi::filesystem::Host for T { async fn set_times_at( &mut self, - fd: wasi::filesystem::Descriptor, - path_flags: wasi::filesystem::PathFlags, + fd: filesystem::Descriptor, + path_flags: filesystem::PathFlags, path: String, - atim: wasi::filesystem::NewTimestamp, - mtim: wasi::filesystem::NewTimestamp, - ) -> Result<(), wasi::filesystem::Error> { + atim: filesystem::NewTimestamp, + mtim: filesystem::NewTimestamp, + ) -> Result<(), filesystem::Error> { use cap_fs_ext::DirExt; let table = self.table(); @@ -427,13 +424,13 @@ impl wasi::filesystem::Host for T { async fn link_at( &mut self, - fd: wasi::filesystem::Descriptor, + fd: filesystem::Descriptor, // TODO delete the path flags from this function - old_path_flags: wasi::filesystem::PathFlags, + old_path_flags: filesystem::PathFlags, old_path: String, - new_descriptor: wasi::filesystem::Descriptor, + new_descriptor: filesystem::Descriptor, new_path: String, - ) -> Result<(), wasi::filesystem::Error> { + ) -> Result<(), filesystem::Error> { let table = self.table(); let old_dir = table.get_dir(fd)?; if !old_dir.perms.contains(DirPerms::MUTATE) { @@ -452,18 +449,18 @@ impl wasi::filesystem::Host for T { async fn open_at( &mut self, - fd: wasi::filesystem::Descriptor, - path_flags: wasi::filesystem::PathFlags, + fd: filesystem::Descriptor, + path_flags: filesystem::PathFlags, path: String, - oflags: wasi::filesystem::OpenFlags, - flags: wasi::filesystem::DescriptorFlags, + oflags: filesystem::OpenFlags, + flags: filesystem::DescriptorFlags, // TODO: These are the permissions to use when creating a new file. // Not implemented yet. - _mode: wasi::filesystem::Modes, - ) -> Result { + _mode: filesystem::Modes, + ) -> Result { use cap_fs_ext::{FollowSymlinks, OpenOptionsFollowExt, OpenOptionsMaybeDirExt}; + use filesystem::{DescriptorFlags, OpenFlags}; use system_interface::fs::{FdFlags, GetSetFdFlags}; - use wasi::filesystem::{DescriptorFlags, OpenFlags}; let table = self.table_mut(); if table.is_file(fd) { @@ -548,7 +545,7 @@ impl wasi::filesystem::Host for T { } } - async fn drop_descriptor(&mut self, fd: wasi::filesystem::Descriptor) -> anyhow::Result<()> { + async fn drop_descriptor(&mut self, fd: filesystem::Descriptor) -> anyhow::Result<()> { let table = self.table_mut(); if table.delete_file(fd).is_err() { table.delete_dir(fd)?; @@ -558,9 +555,9 @@ impl wasi::filesystem::Host for T { async fn readlink_at( &mut self, - fd: wasi::filesystem::Descriptor, + fd: filesystem::Descriptor, path: String, - ) -> Result { + ) -> Result { let table = self.table(); let d = table.get_dir(fd)?; if !d.perms.contains(DirPerms::READ) { @@ -575,9 +572,9 @@ impl wasi::filesystem::Host for T { async fn remove_directory_at( &mut self, - fd: wasi::filesystem::Descriptor, + fd: filesystem::Descriptor, path: String, - ) -> Result<(), wasi::filesystem::Error> { + ) -> Result<(), filesystem::Error> { let table = self.table(); let d = table.get_dir(fd)?; if !d.perms.contains(DirPerms::MUTATE) { @@ -588,11 +585,11 @@ impl wasi::filesystem::Host for T { async fn rename_at( &mut self, - fd: wasi::filesystem::Descriptor, + fd: filesystem::Descriptor, old_path: String, - new_fd: wasi::filesystem::Descriptor, + new_fd: filesystem::Descriptor, new_path: String, - ) -> Result<(), wasi::filesystem::Error> { + ) -> Result<(), filesystem::Error> { let table = self.table(); let old_dir = table.get_dir(fd)?; if !old_dir.perms.contains(DirPerms::MUTATE) { @@ -608,10 +605,10 @@ impl wasi::filesystem::Host for T { async fn symlink_at( &mut self, - fd: wasi::filesystem::Descriptor, + fd: filesystem::Descriptor, src_path: String, dest_path: String, - ) -> Result<(), wasi::filesystem::Error> { + ) -> Result<(), filesystem::Error> { // On windows, Dir.symlink is provided by DirExt #[cfg(windows)] use cap_fs_ext::DirExt; @@ -627,9 +624,9 @@ impl wasi::filesystem::Host for T { async fn unlink_file_at( &mut self, - fd: wasi::filesystem::Descriptor, + fd: filesystem::Descriptor, path: String, - ) -> Result<(), wasi::filesystem::Error> { + ) -> Result<(), filesystem::Error> { use cap_fs_ext::DirExt; let table = self.table(); @@ -643,74 +640,68 @@ impl wasi::filesystem::Host for T { async fn access_at( &mut self, - _fd: wasi::filesystem::Descriptor, - _path_flags: wasi::filesystem::PathFlags, + _fd: filesystem::Descriptor, + _path_flags: filesystem::PathFlags, _path: String, - _access: wasi::filesystem::AccessType, - ) -> Result<(), wasi::filesystem::Error> { + _access: filesystem::AccessType, + ) -> Result<(), filesystem::Error> { todo!() } async fn change_file_permissions_at( &mut self, - _fd: wasi::filesystem::Descriptor, - _path_flags: wasi::filesystem::PathFlags, + _fd: filesystem::Descriptor, + _path_flags: filesystem::PathFlags, _path: String, - _mode: wasi::filesystem::Modes, - ) -> Result<(), wasi::filesystem::Error> { + _mode: filesystem::Modes, + ) -> Result<(), filesystem::Error> { todo!() } async fn change_directory_permissions_at( &mut self, - _fd: wasi::filesystem::Descriptor, - _path_flags: wasi::filesystem::PathFlags, + _fd: filesystem::Descriptor, + _path_flags: filesystem::PathFlags, _path: String, - _mode: wasi::filesystem::Modes, - ) -> Result<(), wasi::filesystem::Error> { + _mode: filesystem::Modes, + ) -> Result<(), filesystem::Error> { todo!() } - async fn lock_shared( - &mut self, - _fd: wasi::filesystem::Descriptor, - ) -> Result<(), wasi::filesystem::Error> { + async fn lock_shared(&mut self, _fd: filesystem::Descriptor) -> Result<(), filesystem::Error> { todo!() } async fn lock_exclusive( &mut self, - _fd: wasi::filesystem::Descriptor, - ) -> Result<(), wasi::filesystem::Error> { + _fd: filesystem::Descriptor, + ) -> Result<(), filesystem::Error> { todo!() } async fn try_lock_shared( &mut self, - _fd: wasi::filesystem::Descriptor, - ) -> Result<(), wasi::filesystem::Error> { + _fd: filesystem::Descriptor, + ) -> Result<(), filesystem::Error> { todo!() } async fn try_lock_exclusive( &mut self, - _fd: wasi::filesystem::Descriptor, - ) -> Result<(), wasi::filesystem::Error> { + _fd: filesystem::Descriptor, + ) -> Result<(), filesystem::Error> { todo!() } - async fn unlock( - &mut self, - _fd: wasi::filesystem::Descriptor, - ) -> Result<(), wasi::filesystem::Error> { + async fn unlock(&mut self, _fd: filesystem::Descriptor) -> Result<(), filesystem::Error> { todo!() } async fn read_via_stream( &mut self, - fd: wasi::filesystem::Descriptor, - offset: wasi::filesystem::Filesize, - ) -> anyhow::Result { + fd: filesystem::Descriptor, + offset: filesystem::Filesize, + ) -> anyhow::Result { // FIXME: this skips the perm check. We can't return a NotPermitted // error code here. Do we need to change the interface? @@ -731,9 +722,9 @@ impl wasi::filesystem::Host for T { async fn write_via_stream( &mut self, - fd: wasi::filesystem::Descriptor, - offset: wasi::filesystem::Filesize, - ) -> anyhow::Result { + fd: filesystem::Descriptor, + offset: filesystem::Filesize, + ) -> anyhow::Result { // Trap if fd lookup fails: let f = self.table().get_file(fd)?; @@ -751,8 +742,8 @@ impl wasi::filesystem::Host for T { async fn append_via_stream( &mut self, - fd: wasi::filesystem::Descriptor, - ) -> anyhow::Result { + fd: filesystem::Descriptor, + ) -> anyhow::Result { // Trap if fd lookup fails: let f = self.table().get_file(fd)?; @@ -770,7 +761,7 @@ impl wasi::filesystem::Host for T { } #[cfg(unix)] -fn from_raw_os_error(err: Option) -> Option { +fn from_raw_os_error(err: Option) -> Option { use rustix::io::Errno as RustixErrno; if err.is_none() { return None; @@ -810,7 +801,7 @@ fn from_raw_os_error(err: Option) -> Option { }) } #[cfg(windows)] -fn from_raw_os_error(raw_os_error: Option) -> Option { +fn from_raw_os_error(raw_os_error: Option) -> Option { use windows_sys::Win32::Foundation; Some(match raw_os_error.map(|code| code as u32) { Some(Foundation::ERROR_FILE_NOT_FOUND) => ErrorCode::NoEntry.into(), @@ -839,8 +830,8 @@ fn from_raw_os_error(raw_os_error: Option) -> Option for wasi::filesystem::Error { - fn from(err: std::io::Error) -> wasi::filesystem::Error { +impl From for filesystem::Error { + fn from(err: std::io::Error) -> filesystem::Error { match from_raw_os_error(err.raw_os_error()) { Some(errno) => errno, None => match err.kind() { @@ -848,31 +839,29 @@ impl From for wasi::filesystem::Error { std::io::ErrorKind::PermissionDenied => ErrorCode::NotPermitted.into(), std::io::ErrorKind::AlreadyExists => ErrorCode::Exist.into(), std::io::ErrorKind::InvalidInput => ErrorCode::Invalid.into(), - _ => { - wasi::filesystem::Error::trap(anyhow::anyhow!(err).context("Unknown OS error")) - } + _ => filesystem::Error::trap(anyhow::anyhow!(err).context("Unknown OS error")), }, } } } -impl From for wasi::filesystem::Error { - fn from(err: cap_rand::Error) -> wasi::filesystem::Error { +impl From for filesystem::Error { + fn from(err: cap_rand::Error) -> filesystem::Error { // I picked Error::Io as a 'reasonable default', FIXME dan is this ok? from_raw_os_error(err.raw_os_error()) - .unwrap_or_else(|| wasi::filesystem::Error::from(ErrorCode::Io)) + .unwrap_or_else(|| filesystem::Error::from(ErrorCode::Io)) } } -impl From for wasi::filesystem::Error { - fn from(_err: std::num::TryFromIntError) -> wasi::filesystem::Error { +impl From for filesystem::Error { + fn from(_err: std::num::TryFromIntError) -> filesystem::Error { ErrorCode::Overflow.into() } } -fn descriptortype_from(ft: cap_std::fs::FileType) -> wasi::filesystem::DescriptorType { +fn descriptortype_from(ft: cap_std::fs::FileType) -> filesystem::DescriptorType { use cap_fs_ext::FileTypeExt; - use wasi::filesystem::DescriptorType; + use filesystem::DescriptorType; if ft.is_dir() { DescriptorType::Directory } else if ft.is_symlink() { @@ -889,10 +878,10 @@ fn descriptortype_from(ft: cap_std::fs::FileType) -> wasi::filesystem::Descripto } fn systemtimespec_from( - t: wasi::filesystem::NewTimestamp, -) -> Result, wasi::filesystem::Error> { + t: filesystem::NewTimestamp, +) -> Result, filesystem::Error> { + use filesystem::NewTimestamp; use fs_set_times::SystemTimeSpec; - use wasi::filesystem::NewTimestamp; match t { NewTimestamp::NoChange => Ok(None), NewTimestamp::Now => Ok(Some(SystemTimeSpec::SymbolicNow)), @@ -900,23 +889,21 @@ fn systemtimespec_from( } } -fn systemtime_from( - t: wasi::wall_clock::Datetime, -) -> Result { +fn systemtime_from(t: wall_clock::Datetime) -> Result { use std::time::{Duration, SystemTime}; SystemTime::UNIX_EPOCH .checked_add(Duration::new(t.seconds, t.nanoseconds)) .ok_or_else(|| ErrorCode::Overflow.into()) } -fn datetime_from(t: std::time::SystemTime) -> wasi::wall_clock::Datetime { +fn datetime_from(t: std::time::SystemTime) -> wall_clock::Datetime { // FIXME make this infallible or handle errors properly - wasi::wall_clock::Datetime::try_from(cap_std::time::SystemTime::from_std(t)).unwrap() + wall_clock::Datetime::try_from(cap_std::time::SystemTime::from_std(t)).unwrap() } -fn descriptorstat_from(meta: cap_std::fs::Metadata) -> wasi::filesystem::DescriptorStat { +fn descriptorstat_from(meta: cap_std::fs::Metadata) -> filesystem::DescriptorStat { use cap_fs_ext::MetadataExt; - wasi::filesystem::DescriptorStat { + filesystem::DescriptorStat { // FIXME didn't we agree that the wit could be changed to make the device and ino fields // optional? device: meta.dev(), @@ -928,35 +915,35 @@ fn descriptorstat_from(meta: cap_std::fs::Metadata) -> wasi::filesystem::Descrip data_access_timestamp: meta .accessed() .map(|t| datetime_from(t.into_std())) - .unwrap_or(wasi::wall_clock::Datetime { + .unwrap_or(wall_clock::Datetime { seconds: 0, nanoseconds: 0, }), data_modification_timestamp: meta .modified() .map(|t| datetime_from(t.into_std())) - .unwrap_or(wasi::wall_clock::Datetime { + .unwrap_or(wall_clock::Datetime { seconds: 0, nanoseconds: 0, }), status_change_timestamp: meta .created() .map(|t| datetime_from(t.into_std())) - .unwrap_or(wasi::wall_clock::Datetime { + .unwrap_or(wall_clock::Datetime { seconds: 0, nanoseconds: 0, }), } } -fn symlink_follow(path_flags: wasi::filesystem::PathFlags) -> bool { - path_flags.contains(wasi::filesystem::PathFlags::SYMLINK_FOLLOW) +fn symlink_follow(path_flags: filesystem::PathFlags) -> bool { + path_flags.contains(filesystem::PathFlags::SYMLINK_FOLLOW) } pub(crate) struct ReaddirIterator( std::sync::Mutex< Box< - dyn Iterator> + dyn Iterator> + Send + 'static, >, @@ -965,19 +952,17 @@ pub(crate) struct ReaddirIterator( impl ReaddirIterator { fn new( - i: impl Iterator> - + Send - + 'static, + i: impl Iterator> + Send + 'static, ) -> Self { ReaddirIterator(std::sync::Mutex::new(Box::new(i))) } - fn next(&self) -> Result, wasi::filesystem::Error> { + fn next(&self) -> Result, filesystem::Error> { self.0.lock().unwrap().next().transpose() } } impl IntoIterator for ReaddirIterator { - type Item = Result; + type Item = Result; type IntoIter = Box>; fn into_iter(self) -> Self::IntoIter { diff --git a/crates/wasi/src/preview2/preview2/io.rs b/crates/wasi/src/preview2/preview2/io.rs index 407ae2c54d1d..4e9971f2dc05 100644 --- a/crates/wasi/src/preview2/preview2/io.rs +++ b/crates/wasi/src/preview2/preview2/io.rs @@ -1,8 +1,8 @@ use crate::preview2::{ preview2::poll::PollableEntry, stream::TableStreamExt, - wasi::poll::Pollable, - wasi::streams::{self, InputStream, OutputStream, StreamError}, + wasi::io::streams::{self, InputStream, OutputStream, StreamError}, + wasi::poll::poll::Pollable, TableError, WasiView, }; use anyhow::anyhow; diff --git a/crates/wasi/src/preview2/preview2/poll.rs b/crates/wasi/src/preview2/preview2/poll.rs index 311c36ab1406..d3b9380c71bc 100644 --- a/crates/wasi/src/preview2/preview2/poll.rs +++ b/crates/wasi/src/preview2/preview2/poll.rs @@ -1,9 +1,8 @@ use crate::preview2::{ stream::TableStreamExt, - wasi, - wasi::monotonic_clock::Instant, - wasi::poll::Pollable, - wasi::streams::{InputStream, OutputStream}, + wasi::clocks::monotonic_clock::Instant, + wasi::io::streams::{InputStream, OutputStream}, + wasi::poll::poll::{self, Pollable}, WasiView, }; @@ -29,7 +28,7 @@ pub(crate) enum PollableEntry { // this PR. #[async_trait::async_trait] -impl wasi::poll::Host for T { +impl poll::Host for T { async fn drop_pollable(&mut self, pollable: Pollable) -> anyhow::Result<()> { self.table_mut().delete::(pollable)?; Ok(()) diff --git a/crates/wasi/src/preview2/preview2/random.rs b/crates/wasi/src/preview2/preview2/random.rs index f94afed84a28..2cabe352b260 100644 --- a/crates/wasi/src/preview2/preview2/random.rs +++ b/crates/wasi/src/preview2/preview2/random.rs @@ -1,9 +1,11 @@ +use crate::preview2::wasi::random::insecure; +use crate::preview2::wasi::random::insecure_seed; +use crate::preview2::wasi::random::random; +use crate::preview2::WasiView; use cap_rand::{distributions::Standard, Rng}; -use crate::preview2::{wasi, WasiView}; - #[async_trait::async_trait] -impl wasi::random::Host for T { +impl random::Host for T { async fn get_random_bytes(&mut self, len: u64) -> anyhow::Result> { Ok((&mut self.ctx_mut().random) .sample_iter(Standard) @@ -17,7 +19,7 @@ impl wasi::random::Host for T { } #[async_trait::async_trait] -impl wasi::insecure_random::Host for T { +impl insecure::Host for T { async fn get_insecure_random_bytes(&mut self, len: u64) -> anyhow::Result> { Ok((&mut self.ctx_mut().insecure_random) .sample_iter(Standard) @@ -31,7 +33,7 @@ impl wasi::insecure_random::Host for T { } #[async_trait::async_trait] -impl wasi::insecure_random_seed::Host for T { +impl insecure_seed::Host for T { async fn insecure_seed(&mut self) -> anyhow::Result<(u64, u64)> { let seed: u128 = self.ctx_mut().insecure_random_seed; Ok((seed as u64, (seed >> 64) as u64)) diff --git a/crates/wasi/src/preview2/wasi/command.rs b/crates/wasi/src/preview2/wasi/command.rs index 6bc26f20bfb8..9dc472536ca3 100644 --- a/crates/wasi/src/preview2/wasi/command.rs +++ b/crates/wasi/src/preview2/wasi/command.rs @@ -1,8 +1,7 @@ use crate::preview2::WasiView; wasmtime::component::bindgen!({ - path: "wit", - world: "command", + world: "wasi:preview/command", tracing: true, async: true, trappable_error_type: { @@ -10,35 +9,35 @@ wasmtime::component::bindgen!({ "streams"::"stream-error": Error, }, with: { - "filesystem": crate::preview2::wasi::filesystem, - "monotonic_clock": crate::preview2::wasi::monotonic_clock, - "poll": crate::preview2::wasi::poll, - "streams": crate::preview2::wasi::streams, - "timezone": crate::preview2::wasi::timezone, - "wall_clock": crate::preview2::wasi::wall_clock, - "random": crate::preview2::wasi::random, - "environment": crate::preview2::wasi::environment, - "exit": crate::preview2::wasi::exit, - "preopens": crate::preview2::wasi::preopens, - "stdin": crate::preview2::wasi::stdin, - "stdout": crate::preview2::wasi::stdout, - "stderr": crate::preview2::wasi::stderr, + "wasi:filesystem/filesystem": crate::preview2::wasi::filesystem::filesystem, + "wasi:clocks/monotonic_clock": crate::preview2::wasi::clocks::monotonic_clock, + "wasi:poll/poll": crate::preview2::wasi::poll::poll, + "wasi:io/streams": crate::preview2::wasi::io::streams, + "wasi:clocks/timezone": crate::preview2::wasi::clocks::timezone, + "wasi:clocks/wall_clock": crate::preview2::wasi::clocks::wall_clock, + "wasi:random/random": crate::preview2::wasi::random::random, + "wasi:cli_base/environment": crate::preview2::wasi::cli_base::environment, + "wasi:cli_base/exit": crate::preview2::wasi::cli_base::exit, + "wasi:cli_base/preopens": crate::preview2::wasi::cli_base::preopens, + "wasi:cli_base/stdin": crate::preview2::wasi::cli_base::stdin, + "wasi:cli_base/stdout": crate::preview2::wasi::cli_base::stdout, + "wasi:cli_base/stderr": crate::preview2::wasi::cli_base::stderr, }, }); pub fn add_to_linker(l: &mut wasmtime::component::Linker) -> anyhow::Result<()> { - crate::preview2::wasi::wall_clock::add_to_linker(l, |t| t)?; - crate::preview2::wasi::monotonic_clock::add_to_linker(l, |t| t)?; - crate::preview2::wasi::timezone::add_to_linker(l, |t| t)?; - crate::preview2::wasi::filesystem::add_to_linker(l, |t| t)?; - crate::preview2::wasi::poll::add_to_linker(l, |t| t)?; - crate::preview2::wasi::streams::add_to_linker(l, |t| t)?; - crate::preview2::wasi::random::add_to_linker(l, |t| t)?; - crate::preview2::wasi::exit::add_to_linker(l, |t| t)?; - crate::preview2::wasi::environment::add_to_linker(l, |t| t)?; - crate::preview2::wasi::preopens::add_to_linker(l, |t| t)?; - crate::preview2::wasi::stdin::add_to_linker(l, |t| t)?; - crate::preview2::wasi::stdout::add_to_linker(l, |t| t)?; - crate::preview2::wasi::stderr::add_to_linker(l, |t| t)?; + crate::preview2::wasi::clocks::wall_clock::add_to_linker(l, |t| t)?; + crate::preview2::wasi::clocks::monotonic_clock::add_to_linker(l, |t| t)?; + crate::preview2::wasi::clocks::timezone::add_to_linker(l, |t| t)?; + crate::preview2::wasi::filesystem::filesystem::add_to_linker(l, |t| t)?; + crate::preview2::wasi::poll::poll::add_to_linker(l, |t| t)?; + crate::preview2::wasi::io::streams::add_to_linker(l, |t| t)?; + crate::preview2::wasi::random::random::add_to_linker(l, |t| t)?; + crate::preview2::wasi::cli_base::exit::add_to_linker(l, |t| t)?; + crate::preview2::wasi::cli_base::environment::add_to_linker(l, |t| t)?; + crate::preview2::wasi::cli_base::preopens::add_to_linker(l, |t| t)?; + crate::preview2::wasi::cli_base::stdin::add_to_linker(l, |t| t)?; + crate::preview2::wasi::cli_base::stdout::add_to_linker(l, |t| t)?; + crate::preview2::wasi::cli_base::stderr::add_to_linker(l, |t| t)?; Ok(()) } diff --git a/crates/wasi/src/preview2/wasi/mod.rs b/crates/wasi/src/preview2/wasi/mod.rs index 40aa9af2d476..aa1a1708a5c1 100644 --- a/crates/wasi/src/preview2/wasi/mod.rs +++ b/crates/wasi/src/preview2/wasi/mod.rs @@ -3,21 +3,21 @@ pub mod command; wasmtime::component::bindgen!({ path: "wit", interfaces: " - import wall-clock: clocks.wall-clock - import monotonic-clock: clocks.monotonic-clock - import timezone: clocks.timezone - import filesystem: filesystem.filesystem - import random: random.random - import insecure-random: random.insecure - import insecure-random-seed: random.insecure-seed - import poll: poll.poll - import streams: io.streams - import environment: wasi-cli-base.environment - import preopens: wasi-cli-base.preopens - import stdin: wasi-cli-base.stdio.stdin - import stdout: wasi-cli-base.stdio.stdout - import stderr: wasi-cli-base.stdio.stderr - import exit: wasi-cli-base.exit + import wasi:clocks/wall-clock + import wasi:clocks/monotonic-clock + import wasi:clocks/timezone + import wasi:filesystem/filesystem + import wasi:random/random + import wasi:random/insecure + import wasi:random/insecure-seed + import wasi:poll/poll + import wasi:io/streams + import wasi:cli-base/environment + import wasi:cli-base/preopens + import wasi:cli-base/exit + import wasi:cli-base/stdin + import wasi:cli-base/stdout + import wasi:cli-base/stderr ", tracing: true, async: true, @@ -26,3 +26,5 @@ wasmtime::component::bindgen!({ "streams"::"stream-error": Error, } }); + +pub use wasi::*; diff --git a/crates/wasi/wit/command.wit b/crates/wasi/wit/command.wit deleted file mode 100644 index 29845b60e887..000000000000 --- a/crates/wasi/wit/command.wit +++ /dev/null @@ -1,26 +0,0 @@ -default world command { - import wall-clock: clocks.wall-clock - import monotonic-clock: clocks.monotonic-clock - import timezone: clocks.timezone - import filesystem: filesystem.filesystem - import instance-network: sockets.instance-network - import ip-name-lookup: sockets.ip-name-lookup - import network: sockets.network - import tcp-create-socket: sockets.tcp-create-socket - import tcp: sockets.tcp - import udp-create-socket: sockets.udp-create-socket - import udp: sockets.udp - import random: random.random - import insecure-random: random.insecure - import insecure-random-seed: random.insecure-seed - import poll: poll.poll - import streams: io.streams - import environment: wasi-cli-base.environment - import preopens: wasi-cli-base.preopens - import stdin: wasi-cli-base.stdio.stdin - import stdout: wasi-cli-base.stdio.stdout - import stderr: wasi-cli-base.stdio.stderr - import exit: wasi-cli-base.exit - - export run: func() -> result -} diff --git a/crates/wasi/wit/deps/clocks/monotonic-clock.wit b/crates/wasi/wit/deps/clocks/monotonic-clock.wit index 42e2981f579a..50eb4de111af 100644 --- a/crates/wasi/wit/deps/clocks/monotonic-clock.wit +++ b/crates/wasi/wit/deps/clocks/monotonic-clock.wit @@ -1,3 +1,5 @@ +package wasi:clocks + /// WASI Monotonic Clock is a clock API intended to let users measure elapsed /// time. /// @@ -8,8 +10,8 @@ /// successive reads of the clock will produce non-decreasing values. /// /// It is intended for measuring elapsed time. -default interface monotonic-clock { - use poll.poll.{pollable} +interface monotonic-clock { + use wasi:poll/poll.{pollable} /// A timestamp in nanoseconds. type instant = u64 diff --git a/crates/wasi/wit/deps/clocks/timezone.wit b/crates/wasi/wit/deps/clocks/timezone.wit index 63f99cc401b1..2b6855668e1d 100644 --- a/crates/wasi/wit/deps/clocks/timezone.wit +++ b/crates/wasi/wit/deps/clocks/timezone.wit @@ -1,5 +1,7 @@ -default interface timezone { - use pkg.wall-clock.{datetime} +package wasi:clocks + +interface timezone { + use wall-clock.{datetime} /// A timezone. /// diff --git a/crates/wasi/wit/deps/clocks/wall-clock.wit b/crates/wasi/wit/deps/clocks/wall-clock.wit index 89c5a75da68b..6137724f60b1 100644 --- a/crates/wasi/wit/deps/clocks/wall-clock.wit +++ b/crates/wasi/wit/deps/clocks/wall-clock.wit @@ -1,3 +1,5 @@ +package wasi:clocks + /// WASI Wall Clock is a clock API intended to let users query the current /// time. The name "wall" makes an analogy to a "clock on the wall", which /// is not necessarily monotonic as it may be reset. @@ -12,7 +14,7 @@ /// monotonic, making it unsuitable for measuring elapsed time. /// /// It is intended for reporting the current date and time for humans. -default interface wall-clock { +interface wall-clock { /// A time and date in seconds plus nanoseconds. record datetime { seconds: u64, diff --git a/crates/wasi/wit/deps/filesystem/filesystem.wit b/crates/wasi/wit/deps/filesystem/filesystem.wit index a5716427829a..2477264a7367 100644 --- a/crates/wasi/wit/deps/filesystem/filesystem.wit +++ b/crates/wasi/wit/deps/filesystem/filesystem.wit @@ -1,3 +1,5 @@ +package wasi:filesystem + /// WASI filesystem is a filesystem API primarily intended to let users run WASI /// programs that access their files on their existing filesystems, without /// significant overhead. @@ -17,9 +19,9 @@ /// `..` and symbolic link steps, reaches a directory outside of the base /// directory, or reaches a symlink to an absolute or rooted path in the /// underlying filesystem, the function fails with `error-code::not-permitted`. -default interface filesystem { - use io.streams.{input-stream, output-stream} - use clocks.wall-clock.{datetime} +interface filesystem { + use wasi:io/streams.{input-stream, output-stream} + use wasi:clocks/wall-clock.{datetime} /// File size or length of a region within a file. type filesize = u64 diff --git a/crates/wasi/wit/deps/http/incoming-handler.wit b/crates/wasi/wit/deps/http/incoming-handler.wit index 1ecff0aa5f5b..d0e270465593 100644 --- a/crates/wasi/wit/deps/http/incoming-handler.wit +++ b/crates/wasi/wit/deps/http/incoming-handler.wit @@ -6,8 +6,8 @@ // `wasi:http/outgoing-handler` into a single `wasi:http/handler` interface // that takes a `request` parameter and returns a `response` result. // -default interface incoming-handler { - use pkg.types.{incoming-request, response-outparam} +interface incoming-handler { + use types.{incoming-request, response-outparam} // The `handle` function takes an outparam instead of returning its response // so that the component may stream its response while streaming any other diff --git a/crates/wasi/wit/deps/http/outgoing-handler.wit b/crates/wasi/wit/deps/http/outgoing-handler.wit index abe812ffaba7..06c8e469f95b 100644 --- a/crates/wasi/wit/deps/http/outgoing-handler.wit +++ b/crates/wasi/wit/deps/http/outgoing-handler.wit @@ -5,8 +5,8 @@ // `wasi:http/outgoing-handler` into a single `wasi:http/handler` interface // that takes a `request` parameter and returns a `response` result. // -default interface outgoing-handler { - use pkg.types.{outgoing-request, request-options, future-incoming-response} +interface outgoing-handler { + use types.{outgoing-request, request-options, future-incoming-response} // The parameter and result types of the `handle` function allow the caller // to concurrently stream the bodies of the outgoing request and the incoming diff --git a/crates/wasi/wit/deps/http/types.wit b/crates/wasi/wit/deps/http/types.wit index bdcf79737273..ee4227f423a8 100644 --- a/crates/wasi/wit/deps/http/types.wit +++ b/crates/wasi/wit/deps/http/types.wit @@ -1,10 +1,12 @@ +package wasi:http + // The `wasi:http/types` interface is meant to be imported by components to // define the HTTP resource types and operations used by the component's // imported and exported interfaces. -default interface types { - use io.streams.{input-stream, output-stream} - use poll.poll.{pollable} - +interface types { + use wasi:io/streams.{input-stream, output-stream} + use wasi:poll/poll.{pollable} + // This type corresponds to HTTP standard Methods. variant method { get, diff --git a/crates/wasi/wit/deps/io/streams.wit b/crates/wasi/wit/deps/io/streams.wit index c1567fd4c1c8..008e36cf59c8 100644 --- a/crates/wasi/wit/deps/io/streams.wit +++ b/crates/wasi/wit/deps/io/streams.wit @@ -1,10 +1,12 @@ +package wasi:io + /// WASI I/O is an I/O abstraction API which is currently focused on providing /// stream types. /// /// In the future, the component model is expected to add built-in stream types; /// when it does, they are expected to subsume this API. -default interface streams { - use poll.poll.{pollable} +interface streams { + use wasi:poll/poll.{pollable} /// An error type returned from a stream operation. Currently this /// doesn't provide any additional information. diff --git a/crates/wasi/wit/deps/logging/handler.wit b/crates/wasi/wit/deps/logging/handler.wit index c9632b9cc4f8..e6b077be8a60 100644 --- a/crates/wasi/wit/deps/logging/handler.wit +++ b/crates/wasi/wit/deps/logging/handler.wit @@ -1,6 +1,8 @@ +package wasi:logging + /// WASI Logging is a logging API intended to let users emit log messages with /// simple priority levels and context values. -default interface handler { +interface handler { /// A log level, describing a kind of message. enum level { /// Describes messages about the values of variables and the flow of diff --git a/crates/wasi/wit/deps/poll/poll.wit b/crates/wasi/wit/deps/poll/poll.wit index 28f08e17d755..cf5d8779c17e 100644 --- a/crates/wasi/wit/deps/poll/poll.wit +++ b/crates/wasi/wit/deps/poll/poll.wit @@ -1,6 +1,8 @@ +package wasi:poll + /// A poll API intended to let users wait for I/O events on multiple handles /// at once. -default interface poll { +interface poll { /// A "pollable" handle. /// /// This is conceptually represents a `stream<_, _>`, or in other words, diff --git a/crates/wasi/wit/deps/preview/command-extended.wit b/crates/wasi/wit/deps/preview/command-extended.wit index 92e3d7d81022..2beb119da319 100644 --- a/crates/wasi/wit/deps/preview/command-extended.wit +++ b/crates/wasi/wit/deps/preview/command-extended.wit @@ -1,29 +1,34 @@ -default world command-extended { - import wall-clock: clocks.wall-clock - import monotonic-clock: clocks.monotonic-clock - import timezone: clocks.timezone - import filesystem: filesystem.filesystem - import instance-network: sockets.instance-network - import ip-name-lookup: sockets.ip-name-lookup - import network: sockets.network - import tcp-create-socket: sockets.tcp-create-socket - import tcp: sockets.tcp - import udp-create-socket: sockets.udp-create-socket - import udp: sockets.udp - import random: random.random - import insecure-random: random.insecure - import insecure-random-seed: random.insecure-seed - import poll: poll.poll - import streams: io.streams - import environment: wasi-cli-base.environment - import preopens: wasi-cli-base.preopens - import exit: wasi-cli-base.exit +package wasi:preview + +world command-extended { + import wasi:clocks/wall-clock + import wasi:clocks/monotonic-clock + import wasi:clocks/timezone + import wasi:filesystem/filesystem + import wasi:sockets/instance-network + import wasi:sockets/ip-name-lookup + import wasi:sockets/network + import wasi:sockets/tcp-create-socket + import wasi:sockets/tcp + import wasi:sockets/udp-create-socket + import wasi:sockets/udp + import wasi:random/random + import wasi:random/insecure + import wasi:random/insecure-seed + import wasi:poll/poll + import wasi:io/streams + import wasi:cli-base/environment + import wasi:cli-base/preopens + import wasi:cli-base/exit + import wasi:cli-base/stdin + import wasi:cli-base/stdout + import wasi:cli-base/stderr // We should replace all others with `include self.command` // as soon as the unioning of worlds is available: // https://github.com/WebAssembly/component-model/issues/169 - import console: logging.handler - import default-outgoing-HTTP: http.outgoing-handler + import wasi:logging/handler + import wasi:http/outgoing-handler export run: func( args: list, diff --git a/crates/wasi/wit/deps/preview/command.wit b/crates/wasi/wit/deps/preview/command.wit index 780e2c4667ff..62608a05ccf9 100644 --- a/crates/wasi/wit/deps/preview/command.wit +++ b/crates/wasi/wit/deps/preview/command.wit @@ -1,23 +1,26 @@ -default world command { - import wall-clock: clocks.wall-clock - import monotonic-clock: clocks.monotonic-clock - import timezone: clocks.timezone - import filesystem: filesystem.filesystem - import instance-network: sockets.instance-network - import ip-name-lookup: sockets.ip-name-lookup - import network: sockets.network - import tcp-create-socket: sockets.tcp-create-socket - import tcp: sockets.tcp - import udp-create-socket: sockets.udp-create-socket - import udp: sockets.udp - import random: random.random - import insecure-random: random.insecure - import insecure-random-seed: random.insecure-seed - import poll: poll.poll - import streams: io.streams - import environment: wasi-cli-base.environment - import preopens: wasi-cli-base.preopens - import exit: wasi-cli-base.exit +world command { + import wasi:clocks/wall-clock + import wasi:clocks/monotonic-clock + import wasi:clocks/timezone + import wasi:filesystem/filesystem + import wasi:sockets/instance-network + import wasi:sockets/ip-name-lookup + import wasi:sockets/network + import wasi:sockets/tcp-create-socket + import wasi:sockets/tcp + import wasi:sockets/udp-create-socket + import wasi:sockets/udp + import wasi:random/random + import wasi:random/insecure + import wasi:random/insecure-seed + import wasi:poll/poll + import wasi:io/streams + import wasi:cli-base/environment + import wasi:cli-base/preopens + import wasi:cli-base/exit + import wasi:cli-base/stdin + import wasi:cli-base/stdout + import wasi:cli-base/stderr export run: func() -> result } diff --git a/crates/wasi/wit/deps/preview/proxy.wit b/crates/wasi/wit/deps/preview/proxy.wit index 03877e958e92..a616daa1c243 100644 --- a/crates/wasi/wit/deps/preview/proxy.wit +++ b/crates/wasi/wit/deps/preview/proxy.wit @@ -1,8 +1,9 @@ -default world proxy { - import random: random.random - import insecure-random: random.insecure - import insecure-random-seed: random.insecure-seed - import console: logging.handler - import default-outgoing-HTTP: http.outgoing-handler - export HTTP: http.incoming-handler +world proxy { + import wasi:random/random + import wasi:random/insecure + import wasi:random/insecure-seed + import wasi:logging/handler + import wasi:http/outgoing-handler + + export wasi:http/incoming-handler } diff --git a/crates/wasi/wit/deps/preview/reactor.wit b/crates/wasi/wit/deps/preview/reactor.wit index 2abfa466ba3b..4a262c551d3f 100644 --- a/crates/wasi/wit/deps/preview/reactor.wit +++ b/crates/wasi/wit/deps/preview/reactor.wit @@ -1,21 +1,24 @@ -default world reactor { - import wall-clock: clocks.wall-clock - import monotonic-clock: clocks.monotonic-clock - import timezone: clocks.timezone - import filesystem: filesystem.filesystem - import instance-network: sockets.instance-network - import ip-name-lookup: sockets.ip-name-lookup - import network: sockets.network - import tcp-create-socket: sockets.tcp-create-socket - import tcp: sockets.tcp - import udp-create-socket: sockets.udp-create-socket - import udp: sockets.udp - import random: random.random - import poll: poll.poll - import streams: io.streams - import console: logging.handler - import default-outgoing-HTTP: http.outgoing-handler - import environment: wasi-cli-base.environment - import preopens: wasi-cli-base.preopens - import exit: wasi-cli-base.exit +world reactor { + import wasi:clocks/wall-clock + import wasi:clocks/monotonic-clock + import wasi:clocks/timezone + import wasi:filesystem/filesystem + import wasi:sockets/instance-network + import wasi:sockets/ip-name-lookup + import wasi:sockets/network + import wasi:sockets/tcp-create-socket + import wasi:sockets/tcp + import wasi:sockets/udp-create-socket + import wasi:sockets/udp + import wasi:random/random + import wasi:poll/poll + import wasi:io/streams + import wasi:logging/handler + import wasi:http/outgoing-handler + import wasi:cli-base/environment + import wasi:cli-base/preopens + import wasi:cli-base/exit + import wasi:cli-base/stdin + import wasi:cli-base/stdout + import wasi:cli-base/stderr } diff --git a/crates/wasi/wit/deps/random/insecure-seed.wit b/crates/wasi/wit/deps/random/insecure-seed.wit index 93a2f17d4090..ff2ff65d0754 100644 --- a/crates/wasi/wit/deps/random/insecure-seed.wit +++ b/crates/wasi/wit/deps/random/insecure-seed.wit @@ -2,7 +2,7 @@ /// /// It is intended to be portable at least between Unix-family platforms and /// Windows. -default interface insecure-seed { +interface insecure-seed { /// Return a 128-bit value that may contain a pseudo-random value. /// /// The returned value is not required to be computed from a CSPRNG, and may diff --git a/crates/wasi/wit/deps/random/insecure.wit b/crates/wasi/wit/deps/random/insecure.wit index 1ef020a0998c..ff0826822d5f 100644 --- a/crates/wasi/wit/deps/random/insecure.wit +++ b/crates/wasi/wit/deps/random/insecure.wit @@ -2,7 +2,7 @@ /// /// It is intended to be portable at least between Unix-family platforms and /// Windows. -default interface insecure { +interface insecure { /// Return `len` insecure pseudo-random bytes. /// /// This function is not cryptographically secure. Do not use it for diff --git a/crates/wasi/wit/deps/random/random.wit b/crates/wasi/wit/deps/random/random.wit index 8f758578842f..f2bd6358c139 100644 --- a/crates/wasi/wit/deps/random/random.wit +++ b/crates/wasi/wit/deps/random/random.wit @@ -1,8 +1,10 @@ +package wasi:random + /// WASI Random is a random data API. /// /// It is intended to be portable at least between Unix-family platforms and /// Windows. -default interface random { +interface random { /// Return `len` cryptographically-secure pseudo-random bytes. /// /// This function must produce data from an adequately seeded diff --git a/crates/wasi/wit/deps/sockets/instance-network.wit b/crates/wasi/wit/deps/sockets/instance-network.wit index b1f5c982d976..d911a29cc8dd 100644 --- a/crates/wasi/wit/deps/sockets/instance-network.wit +++ b/crates/wasi/wit/deps/sockets/instance-network.wit @@ -1,7 +1,7 @@ /// This interface provides a value-export of the default network handle.. -default interface instance-network { - use pkg.network.{network} +interface instance-network { + use network.{network} /// Get a handle to the default network. instance-network: func() -> network diff --git a/crates/wasi/wit/deps/sockets/ip-name-lookup.wit b/crates/wasi/wit/deps/sockets/ip-name-lookup.wit index c4cc7268464c..6c64b4617b98 100644 --- a/crates/wasi/wit/deps/sockets/ip-name-lookup.wit +++ b/crates/wasi/wit/deps/sockets/ip-name-lookup.wit @@ -1,13 +1,13 @@ -default interface ip-name-lookup { - use poll.poll.{pollable} - use pkg.network.{network, error-code, ip-address, ip-address-family} +interface ip-name-lookup { + use wasi:poll/poll.{pollable} + use network.{network, error-code, ip-address, ip-address-family} /// Resolve an internet host name to a list of IP addresses. - /// + /// /// See the wasi-socket proposal README.md for a comparison with getaddrinfo. - /// + /// /// # Parameters /// - `name`: The name to look up. IP addresses are not allowed. Unicode domain names are automatically converted /// to ASCII using IDNA encoding. @@ -17,18 +17,18 @@ default interface ip-name-lookup { /// systems without an active IPv6 interface. Notes: /// - Even when no public IPv6 interfaces are present or active, names like "localhost" can still resolve to an IPv6 address. /// - Whatever is "available" or "unavailable" is volatile and can change everytime a network cable is unplugged. - /// + /// /// This function never blocks. It either immediately fails or immediately returns successfully with a `resolve-address-stream` /// that can be used to (asynchronously) fetch the results. - /// + /// /// At the moment, the stream never completes successfully with 0 items. Ie. the first call /// to `resolve-next-address` never returns `ok(none)`. This may change in the future. - /// + /// /// # Typical errors /// - `invalid-name`: `name` is a syntactically invalid domain name. /// - `invalid-name`: `name` is an IP address. /// - `address-family-not-supported`: The specified `address-family` is not supported. (EAI_FAMILY) - /// + /// /// # References: /// - /// - @@ -41,14 +41,14 @@ default interface ip-name-lookup { type resolve-address-stream = u32 /// Returns the next address from the resolver. - /// + /// /// This function should be called multiple times. On each call, it will /// return the next address in connection order preference. If all /// addresses have been exhausted, this function returns `none`. /// After which, you should release the stream with `drop-resolve-address-stream`. - /// + /// /// This function never returns IPv4-mapped IPv6 addresses. - /// + /// /// # Typical errors /// - `name-unresolvable`: Name does not exist or has no suitable associated IP addresses. (EAI_NONAME, EAI_NODATA, EAI_ADDRFAMILY) /// - `temporary-resolver-failure`: A temporary failure in name resolution occurred. (EAI_AGAIN) @@ -57,12 +57,12 @@ default interface ip-name-lookup { resolve-next-address: func(this: resolve-address-stream) -> result, error-code> /// Dispose of the specified `resolve-address-stream`, after which it may no longer be used. - /// + /// /// Note: this function is scheduled to be removed when Resources are natively supported in Wit. drop-resolve-address-stream: func(this: resolve-address-stream) /// Create a `pollable` which will resolve once the stream is ready for I/O. - /// + /// /// Note: this function is here for WASI Preview2 only. /// It's planned to be removed when `future` is natively supported in Preview3. subscribe: func(this: resolve-address-stream) -> pollable diff --git a/crates/wasi/wit/deps/sockets/network.wit b/crates/wasi/wit/deps/sockets/network.wit index 9176e6ba6594..c370214ce1f9 100644 --- a/crates/wasi/wit/deps/sockets/network.wit +++ b/crates/wasi/wit/deps/sockets/network.wit @@ -1,14 +1,15 @@ +package wasi:sockets -default interface network { +interface network { /// An opaque resource that represents access to (a subset of) the network. /// This enables context-based security for networking. /// There is no need for this to map 1:1 to a physical network interface. - /// + /// /// FYI, In the future this will be replaced by handle types. type network = u32 /// Dispose of the specified `network`, after which it may no longer be used. - /// + /// /// Note: this function is scheduled to be removed when Resources are natively supported in Wit. drop-network: func(this: network) @@ -152,7 +153,7 @@ default interface network { enum ip-address-family { /// Similar to `AF_INET` in POSIX. - ipv4, + ipv4, /// Similar to `AF_INET6` in POSIX. ipv6, @@ -183,4 +184,4 @@ default interface network { ipv6(ipv6-socket-address), } -} \ No newline at end of file +} diff --git a/crates/wasi/wit/deps/sockets/tcp-create-socket.wit b/crates/wasi/wit/deps/sockets/tcp-create-socket.wit index 6e948fae0a6c..f467d2856906 100644 --- a/crates/wasi/wit/deps/sockets/tcp-create-socket.wit +++ b/crates/wasi/wit/deps/sockets/tcp-create-socket.wit @@ -1,23 +1,23 @@ -default interface tcp-create-socket { - use pkg.network.{network, error-code, ip-address-family} - use pkg.tcp.{tcp-socket} +interface tcp-create-socket { + use network.{network, error-code, ip-address-family} + use tcp.{tcp-socket} /// Create a new TCP socket. - /// + /// /// Similar to `socket(AF_INET or AF_INET6, SOCK_STREAM, IPPROTO_TCP)` in POSIX. - /// + /// /// This function does not require a network capability handle. This is considered to be safe because /// at time of creation, the socket is not bound to any `network` yet. Up to the moment `bind`/`listen`/`connect` /// is called, the socket is effectively an in-memory configuration object, unable to communicate with the outside world. - /// + /// /// All sockets are non-blocking. Use the wasi-poll interface to block on asynchronous operations. - /// + /// /// # Typical errors /// - `not-supported`: The host does not support TCP sockets. (EOPNOTSUPP) /// - `address-family-not-supported`: The specified `address-family` is not supported. (EAFNOSUPPORT) /// - `new-socket-limit`: The new socket resource could not be created because of a system limit. (EMFILE, ENFILE) - /// + /// /// # References /// - /// - diff --git a/crates/wasi/wit/deps/sockets/tcp.wit b/crates/wasi/wit/deps/sockets/tcp.wit index b87153243c20..7ed46a690491 100644 --- a/crates/wasi/wit/deps/sockets/tcp.wit +++ b/crates/wasi/wit/deps/sockets/tcp.wit @@ -1,12 +1,12 @@ -default interface tcp { - use io.streams.{input-stream, output-stream} - use poll.poll.{pollable} - use pkg.network.{network, error-code, ip-socket-address, ip-address-family} +interface tcp { + use wasi:io/streams.{input-stream, output-stream} + use wasi:poll/poll.{pollable} + use network.{network, error-code, ip-socket-address, ip-address-family} /// A TCP socket handle. type tcp-socket = u32 - + enum shutdown-type { /// Similar to `SHUT_RD` in POSIX. @@ -25,24 +25,24 @@ default interface tcp { /// If the IP address is zero (`0.0.0.0` in IPv4, `::` in IPv6), it is left to the implementation to decide which /// network interface(s) to bind to. /// If the TCP/UDP port is zero, the socket will be bound to a random free port. - /// + /// /// When a socket is not explicitly bound, the first invocation to a listen or connect operation will /// implicitly bind the socket. - /// + /// /// Unlike in POSIX, this function is async. This enables interactive WASI hosts to inject permission prompts. - /// + /// /// # Typical `start` errors /// - `address-family-mismatch`: The `local-address` has the wrong address family. (EINVAL) /// - `already-bound`: The socket is already bound. (EINVAL) /// - `concurrency-conflict`: Another `bind`, `connect` or `listen` operation is already in progress. (EALREADY) - /// + /// /// # Typical `finish` errors /// - `ephemeral-ports-exhausted`: No ephemeral ports available. (EADDRINUSE, ENOBUFS on Windows) /// - `address-in-use`: Address is already in use. (EADDRINUSE) /// - `address-not-bindable`: `local-address` is not an address that the `network` can bind to. (EADDRNOTAVAIL) /// - `not-in-progress`: A `bind` operation is not in progress. /// - `would-block`: Can't finish the operation, it is still in progress. (EWOULDBLOCK, EAGAIN) - /// + /// /// # References /// - /// - @@ -52,11 +52,11 @@ default interface tcp { finish-bind: func(this: tcp-socket) -> result<_, error-code> /// Connect to a remote endpoint. - /// + /// /// On success: /// - the socket is transitioned into the Connection state /// - a pair of streams is returned that can be used to read & write to the connection - /// + /// /// # Typical `start` errors /// - `address-family-mismatch`: The `remote-address` has the wrong address family. (EAFNOSUPPORT) /// - `invalid-remote-address`: The IP address in `remote-address` is set to INADDR_ANY (`0.0.0.0` / `::`). (EADDRNOTAVAIL on Windows) @@ -65,7 +65,7 @@ default interface tcp { /// - `already-connected`: The socket is already in the Connection state. (EISCONN) /// - `already-listening`: The socket is already in the Listener state. (EOPNOTSUPP, EINVAL on Windows) /// - `concurrency-conflict`: Another `bind`, `connect` or `listen` operation is already in progress. (EALREADY) - /// + /// /// # Typical `finish` errors /// - `timeout`: Connection timed out. (ETIMEDOUT) /// - `connection-refused`: The connection was forcefully rejected. (ECONNREFUSED) @@ -74,7 +74,7 @@ default interface tcp { /// - `ephemeral-ports-exhausted`: Tried to perform an implicit bind, but there were no ephemeral ports available. (EADDRINUSE, EADDRNOTAVAIL on Linux, EAGAIN on BSD) /// - `not-in-progress`: A `connect` operation is not in progress. /// - `would-block`: Can't finish the operation, it is still in progress. (EWOULDBLOCK, EAGAIN) - /// + /// /// # References /// - /// - @@ -84,11 +84,11 @@ default interface tcp { finish-connect: func(this: tcp-socket) -> result, error-code> /// Start listening for new connections. - /// + /// /// Transitions the socket into the Listener state. - /// + /// /// Unlike in POSIX, this function is async. This enables interactive WASI hosts to inject permission prompts. - /// + /// /// # Typical `start` errors /// - `already-attached`: The socket is already attached to a different network. The `network` passed to `listen` must be identical to the one passed to `bind`. /// - `already-connected`: The socket is already in the Connection state. (EISCONN, EINVAL on BSD) @@ -109,18 +109,18 @@ default interface tcp { finish-listen: func(this: tcp-socket) -> result<_, error-code> /// Accept a new client socket. - /// + /// /// The returned socket is bound and in the Connection state. - /// + /// /// On success, this function returns the newly accepted client socket along with /// a pair of streams that can be used to read & write to the connection. - /// + /// /// # Typical errors /// - `not-listening`: Socket is not in the Listener state. (EINVAL) /// - `would-block`: No pending connections at the moment. (EWOULDBLOCK, EAGAIN) - /// + /// /// Host implementations must skip over transient errors returned by the native accept syscall. - /// + /// /// # References /// - /// - @@ -129,10 +129,10 @@ default interface tcp { accept: func(this: tcp-socket) -> result, error-code> /// Get the bound local address. - /// + /// /// # Typical errors /// - `not-bound`: The socket is not bound to any local address. - /// + /// /// # References /// - /// - @@ -141,10 +141,10 @@ default interface tcp { local-address: func(this: tcp-socket) -> result /// Get the bound remote address. - /// + /// /// # Typical errors /// - `not-connected`: The socket is not connected to a remote address. (ENOTCONN) - /// + /// /// # References /// - /// - @@ -153,14 +153,14 @@ default interface tcp { remote-address: func(this: tcp-socket) -> result /// Whether this is a IPv4 or IPv6 socket. - /// + /// /// Equivalent to the SO_DOMAIN socket option. address-family: func(this: tcp-socket) -> ip-address-family - + /// Whether IPv4 compatibility (dual-stack) mode is disabled or not. - /// + /// /// Equivalent to the IPV6_V6ONLY socket option. - /// + /// /// # Typical errors /// - `ipv6-only-operation`: (get/set) `this` socket is an IPv4 socket. /// - `already-bound`: (set) The socket is already bound. @@ -170,28 +170,28 @@ default interface tcp { set-ipv6-only: func(this: tcp-socket, value: bool) -> result<_, error-code> /// Hints the desired listen queue size. Implementations are free to ignore this. - /// + /// /// # Typical errors /// - `already-connected`: (set) The socket is already in the Connection state. /// - `concurrency-conflict`: (set) A `bind`, `connect` or `listen` operation is already in progress. (EALREADY) set-listen-backlog-size: func(this: tcp-socket, value: u64) -> result<_, error-code> /// Equivalent to the SO_KEEPALIVE socket option. - /// + /// /// # Typical errors /// - `concurrency-conflict`: (set) A `bind`, `connect` or `listen` operation is already in progress. (EALREADY) keep-alive: func(this: tcp-socket) -> result set-keep-alive: func(this: tcp-socket, value: bool) -> result<_, error-code> /// Equivalent to the TCP_NODELAY socket option. - /// + /// /// # Typical errors /// - `concurrency-conflict`: (set) A `bind`, `connect` or `listen` operation is already in progress. (EALREADY) no-delay: func(this: tcp-socket) -> result set-no-delay: func(this: tcp-socket, value: bool) -> result<_, error-code> - + /// Equivalent to the IP_TTL & IPV6_UNICAST_HOPS socket options. - /// + /// /// # Typical errors /// - `already-connected`: (set) The socket is already in the Connection state. /// - `already-listening`: (set) The socket is already in the Listener state. @@ -200,16 +200,16 @@ default interface tcp { set-unicast-hop-limit: func(this: tcp-socket, value: u8) -> result<_, error-code> /// The kernel buffer space reserved for sends/receives on this socket. - /// + /// /// Note #1: an implementation may choose to cap or round the buffer size when setting the value. /// In other words, after setting a value, reading the same setting back may return a different value. - /// + /// /// Note #2: there is not necessarily a direct relationship between the kernel buffer size and the bytes of /// actual data to be sent/received by the application, because the kernel might also use the buffer space /// for internal metadata structures. - /// + /// /// Equivalent to the SO_RCVBUF and SO_SNDBUF socket options. - /// + /// /// # Typical errors /// - `already-connected`: (set) The socket is already in the Connection state. /// - `already-listening`: (set) The socket is already in the Listener state. @@ -220,25 +220,25 @@ default interface tcp { set-send-buffer-size: func(this: tcp-socket, value: u64) -> result<_, error-code> /// Create a `pollable` which will resolve once the socket is ready for I/O. - /// + /// /// Note: this function is here for WASI Preview2 only. /// It's planned to be removed when `future` is natively supported in Preview3. subscribe: func(this: tcp-socket) -> pollable /// Initiate a graceful shutdown. - /// + /// /// - receive: the socket is not expecting to receive any more data from the peer. All subsequent read /// operations on the `input-stream` associated with this socket will return an End Of Stream indication. /// Any data still in the receive queue at time of calling `shutdown` will be discarded. /// - send: the socket is not expecting to send any more data to the peer. All subsequent write /// operations on the `output-stream` associated with this socket will return an error. /// - both: same effect as receive & send combined. - /// + /// /// The shutdown function does not close (drop) the socket. - /// + /// /// # Typical errors /// - `not-connected`: The socket is not in the Connection state. (ENOTCONN) - /// + /// /// # References /// - /// - @@ -247,9 +247,9 @@ default interface tcp { shutdown: func(this: tcp-socket, shutdown-type: shutdown-type) -> result<_, error-code> /// Dispose of the specified `tcp-socket`, after which it may no longer be used. - /// + /// /// Similar to the POSIX `close` function. - /// + /// /// Note: this function is scheduled to be removed when Resources are natively supported in Wit. drop-tcp-socket: func(this: tcp-socket) } diff --git a/crates/wasi/wit/deps/sockets/udp-create-socket.wit b/crates/wasi/wit/deps/sockets/udp-create-socket.wit index 2c987be08df5..1cfbd7f0bdd8 100644 --- a/crates/wasi/wit/deps/sockets/udp-create-socket.wit +++ b/crates/wasi/wit/deps/sockets/udp-create-socket.wit @@ -1,23 +1,23 @@ -default interface udp-create-socket { - use pkg.network.{network, error-code, ip-address-family} - use pkg.udp.{udp-socket} +interface udp-create-socket { + use network.{network, error-code, ip-address-family} + use udp.{udp-socket} /// Create a new UDP socket. - /// + /// /// Similar to `socket(AF_INET or AF_INET6, SOCK_DGRAM, IPPROTO_UDP)` in POSIX. - /// + /// /// This function does not require a network capability handle. This is considered to be safe because /// at time of creation, the socket is not bound to any `network` yet. Up to the moment `bind`/`connect` is called, /// the socket is effectively an in-memory configuration object, unable to communicate with the outside world. - /// + /// /// All sockets are non-blocking. Use the wasi-poll interface to block on asynchronous operations. - /// + /// /// # Typical errors /// - `not-supported`: The host does not support UDP sockets. (EOPNOTSUPP) /// - `address-family-not-supported`: The specified `address-family` is not supported. (EAFNOSUPPORT) /// - `new-socket-limit`: The new socket resource could not be created because of a system limit. (EMFILE, ENFILE) - /// + /// /// # References: /// - /// - diff --git a/crates/wasi/wit/deps/sockets/udp.wit b/crates/wasi/wit/deps/sockets/udp.wit index 271a2cb9f00f..9dd4573bd17c 100644 --- a/crates/wasi/wit/deps/sockets/udp.wit +++ b/crates/wasi/wit/deps/sockets/udp.wit @@ -1,7 +1,7 @@ -default interface udp { - use poll.poll.{pollable} - use pkg.network.{network, error-code, ip-socket-address, ip-address-family} +interface udp { + use wasi:poll/poll.{pollable} + use network.{network, error-code, ip-socket-address, ip-address-family} /// A UDP socket handle. @@ -27,23 +27,23 @@ default interface udp { /// If the IP address is zero (`0.0.0.0` in IPv4, `::` in IPv6), it is left to the implementation to decide which /// network interface(s) to bind to. /// If the TCP/UDP port is zero, the socket will be bound to a random free port. - /// + /// /// When a socket is not explicitly bound, the first invocation to connect will implicitly bind the socket. - /// + /// /// Unlike in POSIX, this function is async. This enables interactive WASI hosts to inject permission prompts. - /// + /// /// # Typical `start` errors /// - `address-family-mismatch`: The `local-address` has the wrong address family. (EINVAL) /// - `already-bound`: The socket is already bound. (EINVAL) /// - `concurrency-conflict`: Another `bind` or `connect` operation is already in progress. (EALREADY) - /// + /// /// # Typical `finish` errors /// - `ephemeral-ports-exhausted`: No ephemeral ports available. (EADDRINUSE, ENOBUFS on Windows) /// - `address-in-use`: Address is already in use. (EADDRINUSE) /// - `address-not-bindable`: `local-address` is not an address that the `network` can bind to. (EADDRNOTAVAIL) /// - `not-in-progress`: A `bind` operation is not in progress. /// - `would-block`: Can't finish the operation, it is still in progress. (EWOULDBLOCK, EAGAIN) - /// + /// /// # References /// - /// - @@ -53,29 +53,29 @@ default interface udp { finish-bind: func(this: udp-socket) -> result<_, error-code> /// Set the destination address. - /// + /// /// The local-address is updated based on the best network path to `remote-address`. - /// + /// /// When a destination address is set: /// - all receive operations will only return datagrams sent from the provided `remote-address`. /// - the `send` function can only be used to send to this destination. - /// + /// /// Note that this function does not generate any network traffic and the peer is not aware of this "connection". - /// + /// /// Unlike in POSIX, this function is async. This enables interactive WASI hosts to inject permission prompts. - /// + /// /// # Typical `start` errors /// - `address-family-mismatch`: The `remote-address` has the wrong address family. (EAFNOSUPPORT) /// - `invalid-remote-address`: The IP address in `remote-address` is set to INADDR_ANY (`0.0.0.0` / `::`). (EDESTADDRREQ, EADDRNOTAVAIL) /// - `invalid-remote-address`: The port in `remote-address` is set to 0. (EDESTADDRREQ, EADDRNOTAVAIL) /// - `already-attached`: The socket is already bound to a different network. The `network` passed to `connect` must be identical to the one passed to `bind`. /// - `concurrency-conflict`: Another `bind` or `connect` operation is already in progress. (EALREADY) - /// + /// /// # Typical `finish` errors /// - `ephemeral-ports-exhausted`: Tried to perform an implicit bind, but there were no ephemeral ports available. (EADDRINUSE, EADDRNOTAVAIL on Linux, EAGAIN on BSD) /// - `not-in-progress`: A `connect` operation is not in progress. /// - `would-block`: Can't finish the operation, it is still in progress. (EWOULDBLOCK, EAGAIN) - /// + /// /// # References /// - /// - @@ -85,16 +85,16 @@ default interface udp { finish-connect: func(this: udp-socket) -> result<_, error-code> /// Receive a message. - /// + /// /// Returns: /// - The sender address of the datagram /// - The number of bytes read. - /// + /// /// # Typical errors /// - `not-bound`: The socket is not bound to any local address. (EINVAL) /// - `remote-unreachable`: The remote address is not reachable. (ECONNREFUSED, ECONNRESET, ENETRESET on Windows, EHOSTUNREACH, EHOSTDOWN, ENETUNREACH, ENETDOWN) /// - `would-block`: There is no pending data available to be read at the moment. (EWOULDBLOCK, EAGAIN) - /// + /// /// # References /// - /// - @@ -106,10 +106,10 @@ default interface udp { receive: func(this: udp-socket) -> result /// Send a message to a specific destination address. - /// + /// /// The remote address option is required. To send a message to the "connected" peer, /// call `remote-address` to get their address. - /// + /// /// # Typical errors /// - `address-family-mismatch`: The `remote-address` has the wrong address family. (EAFNOSUPPORT) /// - `invalid-remote-address`: The IP address in `remote-address` is set to INADDR_ANY (`0.0.0.0` / `::`). (EDESTADDRREQ, EADDRNOTAVAIL) @@ -119,7 +119,7 @@ default interface udp { /// - `remote-unreachable`: The remote address is not reachable. (ECONNREFUSED, ECONNRESET, ENETRESET on Windows, EHOSTUNREACH, EHOSTDOWN, ENETUNREACH, ENETDOWN) /// - `datagram-too-large`: The datagram is too large. (EMSGSIZE) /// - `would-block`: The send buffer is currently full. (EWOULDBLOCK, EAGAIN) - /// + /// /// # References /// - /// - @@ -131,10 +131,10 @@ default interface udp { send: func(this: udp-socket, datagram: datagram) -> result<_, error-code> /// Get the current bound address. - /// + /// /// # Typical errors /// - `not-bound`: The socket is not bound to any local address. - /// + /// /// # References /// - /// - @@ -143,10 +143,10 @@ default interface udp { local-address: func(this: udp-socket) -> result /// Get the address set with `connect`. - /// + /// /// # Typical errors /// - `not-connected`: The socket is not connected to a remote address. (ENOTCONN) - /// + /// /// # References /// - /// - @@ -155,14 +155,14 @@ default interface udp { remote-address: func(this: udp-socket) -> result /// Whether this is a IPv4 or IPv6 socket. - /// + /// /// Equivalent to the SO_DOMAIN socket option. address-family: func(this: udp-socket) -> ip-address-family /// Whether IPv4 compatibility (dual-stack) mode is disabled or not. - /// + /// /// Equivalent to the IPV6_V6ONLY socket option. - /// + /// /// # Typical errors /// - `ipv6-only-operation`: (get/set) `this` socket is an IPv4 socket. /// - `already-bound`: (set) The socket is already bound. @@ -172,25 +172,25 @@ default interface udp { set-ipv6-only: func(this: udp-socket, value: bool) -> result<_, error-code> /// Equivalent to the IP_TTL & IPV6_UNICAST_HOPS socket options. - /// + /// /// # Typical errors /// - `concurrency-conflict`: (set) Another `bind` or `connect` operation is already in progress. (EALREADY) unicast-hop-limit: func(this: udp-socket) -> result set-unicast-hop-limit: func(this: udp-socket, value: u8) -> result<_, error-code> /// The kernel buffer space reserved for sends/receives on this socket. - /// + /// /// Note #1: an implementation may choose to cap or round the buffer size when setting the value. /// In other words, after setting a value, reading the same setting back may return a different value. - /// + /// /// Note #2: there is not necessarily a direct relationship between the kernel buffer size and the bytes of /// actual data to be sent/received by the application, because the kernel might also use the buffer space /// for internal metadata structures. - /// + /// /// Fails when this socket is in the Listening state. - /// + /// /// Equivalent to the SO_RCVBUF and SO_SNDBUF socket options. - /// + /// /// # Typical errors /// - `concurrency-conflict`: (set) Another `bind` or `connect` operation is already in progress. (EALREADY) receive-buffer-size: func(this: udp-socket) -> result @@ -199,13 +199,13 @@ default interface udp { set-send-buffer-size: func(this: udp-socket, value: u64) -> result<_, error-code> /// Create a `pollable` which will resolve once the socket is ready for I/O. - /// + /// /// Note: this function is here for WASI Preview2 only. /// It's planned to be removed when `future` is natively supported in Preview3. subscribe: func(this: udp-socket) -> pollable /// Dispose of the specified `udp-socket`, after which it may no longer be used. - /// + /// /// Note: this function is scheduled to be removed when Resources are natively supported in Wit. drop-udp-socket: func(this: udp-socket) } diff --git a/crates/wasi/wit/deps/wasi-cli-base/environment.wit b/crates/wasi/wit/deps/wasi-cli-base/environment.wit index 876ea3a0c921..4c97c85d1ab5 100644 --- a/crates/wasi/wit/deps/wasi-cli-base/environment.wit +++ b/crates/wasi/wit/deps/wasi-cli-base/environment.wit @@ -1,4 +1,6 @@ -default interface environment { +package wasi:cli-base + +interface environment { /// Get the POSIX-style environment variables. /// /// Each environment variable is provided as a pair of string variable names diff --git a/crates/wasi/wit/deps/wasi-cli-base/exit.wit b/crates/wasi/wit/deps/wasi-cli-base/exit.wit index 2759e9dd989c..66835aa7022d 100644 --- a/crates/wasi/wit/deps/wasi-cli-base/exit.wit +++ b/crates/wasi/wit/deps/wasi-cli-base/exit.wit @@ -1,4 +1,4 @@ -default interface wasi-exit { +interface exit { /// Exit the curerent instance and any linked instances. exit: func(status: result) } diff --git a/crates/wasi/wit/deps/wasi-cli-base/preopens.wit b/crates/wasi/wit/deps/wasi-cli-base/preopens.wit index 5595f8d392a2..f268f6b0b2e6 100644 --- a/crates/wasi/wit/deps/wasi-cli-base/preopens.wit +++ b/crates/wasi/wit/deps/wasi-cli-base/preopens.wit @@ -1,6 +1,6 @@ -default interface preopens { - use filesystem.filesystem.{descriptor} - use io.streams.{input-stream, output-stream} +interface preopens { + use wasi:filesystem/filesystem.{descriptor} + use wasi:io/streams.{input-stream, output-stream} /// Return the set of of preopened directories, and their path. get-directories: func() -> list> diff --git a/crates/wasi/wit/deps/wasi-cli-base/stdio.wit b/crates/wasi/wit/deps/wasi-cli-base/stdio.wit index 1f87e5485abb..6c9d4a41a6f9 100644 --- a/crates/wasi/wit/deps/wasi-cli-base/stdio.wit +++ b/crates/wasi/wit/deps/wasi-cli-base/stdio.wit @@ -1,17 +1,17 @@ interface stdin { - use io.streams.{input-stream} + use wasi:io/streams.{input-stream} get-stdin: func() -> input-stream } interface stdout { - use io.streams.{output-stream} + use wasi:io/streams.{output-stream} get-stdout: func() -> output-stream } interface stderr { - use io.streams.{output-stream} + use wasi:io/streams.{output-stream} get-stderr: func() -> output-stream } diff --git a/crates/wasi/wit/main.wit b/crates/wasi/wit/main.wit new file mode 100644 index 000000000000..264dfee8264d --- /dev/null +++ b/crates/wasi/wit/main.wit @@ -0,0 +1 @@ +package unused:main diff --git a/crates/wasi/wit/reactor.wit b/crates/wasi/wit/reactor.wit deleted file mode 100644 index fb6b1ac9647c..000000000000 --- a/crates/wasi/wit/reactor.wit +++ /dev/null @@ -1,26 +0,0 @@ -default world reactor { - import wall-clock: clocks.wall-clock - import monotonic-clock: clocks.monotonic-clock - import timezone: clocks.timezone - import filesystem: filesystem.filesystem - import instance-network: sockets.instance-network - import ip-name-lookup: sockets.ip-name-lookup - import network: sockets.network - import tcp-create-socket: sockets.tcp-create-socket - import tcp: sockets.tcp - import udp-create-socket: sockets.udp-create-socket - import udp: sockets.udp - import random: random.random - import insecure-random: random.insecure - import insecure-random-seed: random.insecure-seed - import poll: poll.poll - import streams: io.streams - import console: logging.handler - import default-outgoing-HTTP: http.outgoing-handler - import environment: wasi-cli-base.environment - import preopens: wasi-cli-base.preopens - import stdin: wasi-cli-base.stdio.stdin - import stdout: wasi-cli-base.stdio.stdout - import stderr: wasi-cli-base.stdio.stderr - import exit: wasi-cli-base.exit -} diff --git a/crates/wasi/wit/test.wit b/crates/wasi/wit/test.wit new file mode 100644 index 000000000000..a362fd4d906e --- /dev/null +++ b/crates/wasi/wit/test.wit @@ -0,0 +1,19 @@ +// only used as part of `test-programs` +world test-reactor { + + import wasi:cli-base/environment + import wasi:io/streams + import wasi:cli-base/preopens + import wasi:filesystem/filesystem + import wasi:cli-base/exit + + export add-strings: func(s: list) -> u32 + export get-strings: func() -> list + + use wasi:io/streams.{output-stream} + + export write-strings-to: func(o: output-stream) -> result + + use wasi:filesystem/filesystem.{descriptor-stat} + export pass-an-imported-record: func(d: descriptor-stat) -> string +} diff --git a/crates/wasmtime/src/component/matching.rs b/crates/wasmtime/src/component/matching.rs index 6f2cb5549baa..0f843032b97c 100644 --- a/crates/wasmtime/src/component/matching.rs +++ b/crates/wasmtime/src/component/matching.rs @@ -72,7 +72,7 @@ impl TypeChecker<'_> { // Like modules, every export in the expected type must be present in // the actual type. It's ok, though, to have extra exports in the actual // type. - for (name, (_url, expected)) in expected.exports.iter() { + for (name, expected) in expected.exports.iter() { // Interface types may be exported from a component in order to give them a name, but // they don't have a definition in the sense that this search is interested in, so // ignore them. diff --git a/crates/wasmtime/src/component/mod.rs b/crates/wasmtime/src/component/mod.rs index 671cce9d0bd8..f2066843e44a 100644 --- a/crates/wasmtime/src/component/mod.rs +++ b/crates/wasmtime/src/component/mod.rs @@ -73,7 +73,9 @@ pub(crate) use self::store::ComponentStoreData; /// ```text,ignore /// // wit/my-component.wit /// -/// default world hello-world { +/// package my:project +/// +/// world hello-world { /// import name: func() -> string /// export greet: func() /// } @@ -150,13 +152,15 @@ pub(crate) use self::store::ComponentStoreData; /// ```text,ignore /// // wit/my-component.wit /// +/// package my:project +/// /// interface host { /// gen-random-integer: func() -> u32 /// sha256: func(bytes: list) -> string /// } /// /// default world hello-world { -/// import host: self.host +/// import host /// /// export demo: interface { /// run: func() @@ -169,6 +173,7 @@ pub(crate) use self::store::ComponentStoreData; /// ```rust,ignore /// use wasmtime::component::*; /// use wasmtime::{Config, Engine, Store}; +/// use my::project::host::Host; /// /// bindgen!(); /// @@ -177,7 +182,7 @@ pub(crate) use self::store::ComponentStoreData; /// } /// /// // Note that the trait here is per-interface and within a submodule now. -/// impl host::Host for MyState { +/// impl Host for MyState { /// fn gen_random_integer(&mut self) -> wasmtime::Result { /// Ok(rand::thread_rng().gen()) /// } @@ -228,18 +233,12 @@ pub(crate) use self::store::ComponentStoreData; /// bindgen!(); /// /// // Parse the `wit/` folder adjacent to this crate's `Cargo.toml` and look -/// // for the document `foo`, which must have a `default world` contained -/// // within it. +/// // for the world `foo` contained in it. /// bindgen!("foo"); /// -/// // Parse the `wit/` folder adjacent to `Cargo.toml` and look up the document -/// // `foo` and the world named `bar`. -/// bindgen!("foo.bar"); -/// /// // Parse the folder `other/wit/folder` adjacent to `Cargo.toml`. /// bindgen!(in "other/wit/folder"); /// bindgen!("foo" in "other/wit/folder"); -/// bindgen!("foo.bar" in "other/wit/folder"); /// /// // Parse the file `foo.wit` as a single-file WIT package with no /// // dependencies. @@ -250,8 +249,7 @@ pub(crate) use self::store::ComponentStoreData; /// /// ```rust,ignore /// bindgen!({ -/// world: "foo", // or "foo.bar", same as in `bindgen!("foo")` -/// // not needed if `path` has one `default world` +/// world: "foo", // not needed if `path` has one `world` /// /// // same as in `bindgen!(in "other/wit/folder") /// path: "other/wit/folder", @@ -259,7 +257,9 @@ pub(crate) use self::store::ComponentStoreData; /// // Instead of `path` the WIT document can be provided inline if /// // desired. /// inline: " -/// default world foo { +/// package my:inline +/// +/// world foo { /// // ... /// } /// ", @@ -295,7 +295,7 @@ pub(crate) use self::store::ComponentStoreData; /// // Restrict the code generated to what's needed for the interface /// // imports in the inlined WIT document fragment. /// interfaces: " -/// import foo: package.foo; +/// import package.foo /// ", /// /// // Remap interface names to module names, imported from elsewhere. diff --git a/crates/wit-bindgen/src/lib.rs b/crates/wit-bindgen/src/lib.rs index a935912aab86..26ce89f8639f 100644 --- a/crates/wit-bindgen/src/lib.rs +++ b/crates/wit-bindgen/src/lib.rs @@ -31,28 +31,35 @@ struct InterfaceName { remapped: bool, /// The string name for this interface. - name: String, + path: String, } #[derive(Default)] struct Wasmtime { src: Source, opts: Opts, - imports: Vec, + import_interfaces: BTreeMap, Vec>, + import_functions: Vec, exports: Exports, types: Types, sizes: SizeAlign, interface_names: HashMap, + with_name_counter: usize, } -enum Import { - Interface { snake: String }, - Function { add_to_linker: String, sig: String }, +struct ImportInterface { + snake: String, + module: String, +} +struct ImportFunction { + add_to_linker: String, + sig: String, } #[derive(Default)] struct Exports { fields: BTreeMap, + modules: BTreeMap, Vec>, funcs: Vec, } @@ -111,16 +118,33 @@ impl Opts { } impl Wasmtime { - fn name_interface(&mut self, id: InterfaceId, name: String) -> bool { - let entry = if let Some(remapped_name) = self.opts.with.get(&name) { + fn name_interface(&mut self, resolve: &Resolve, id: InterfaceId, name: &WorldKey) -> bool { + let with_name = resolve.name_world_key(name); + let entry = if let Some(remapped_path) = self.opts.with.get(&with_name) { + let name = format!("__with_name{}", self.with_name_counter); + self.with_name_counter += 1; + uwriteln!(self.src, "use {remapped_path} as {name};"); InterfaceName { remapped: true, - name: remapped_name.clone(), + path: name, } } else { + let path = match name { + WorldKey::Name(name) => name.to_snake_case(), + WorldKey::Interface(_) => { + let iface = &resolve.interfaces[id]; + let pkgname = &resolve.packages[iface.package.unwrap()].name; + format!( + "{}::{}::{}", + pkgname.namespace.to_snake_case(), + pkgname.name.to_snake_case(), + iface.name.as_ref().unwrap().to_snake_case() + ) + } + }; InterfaceName { remapped: false, - name, + path, } }; @@ -146,30 +170,38 @@ impl Wasmtime { self.finish(resolve, id) } - fn import(&mut self, resolve: &Resolve, name: &str, item: &WorldItem) { - let snake = name.to_snake_case(); + fn import(&mut self, resolve: &Resolve, name: &WorldKey, item: &WorldItem) { let mut gen = InterfaceGenerator::new(self, resolve); - let import = match item { + match item { WorldItem::Function(func) => { gen.generate_function_trait_sig(TypeOwner::None, func); let sig = mem::take(&mut gen.src).into(); gen.generate_add_function_to_linker(TypeOwner::None, func, "linker"); let add_to_linker = gen.src.into(); - Import::Function { sig, add_to_linker } + self.import_functions + .push(ImportFunction { sig, add_to_linker }); } WorldItem::Interface(id) => { - if gen.gen.name_interface(*id, snake.clone()) { + if gen.gen.name_interface(resolve, *id, name) { return; } - gen.current_interface = Some(*id); + gen.current_interface = Some((*id, name, false)); gen.types(*id); gen.generate_trappable_error_types(TypeOwner::Interface(*id)); - gen.generate_add_to_linker(*id, name); + let key_name = resolve.name_world_key(name); + gen.generate_add_to_linker(*id, &key_name); let module = &gen.src[..]; - uwriteln!( - self.src, + let snake = match name { + WorldKey::Name(s) => s.to_snake_case(), + WorldKey::Interface(id) => resolve.interfaces[*id] + .name + .as_ref() + .unwrap() + .to_snake_case(), + }; + let module = format!( " #[allow(clippy::all)] pub mod {snake} {{ @@ -180,40 +212,55 @@ impl Wasmtime { }} " ); - Import::Interface { snake } + let pkg = resolve.interfaces[*id].package.unwrap(); + let pkgname = match name { + WorldKey::Name(_) => None, + WorldKey::Interface(_) => Some(resolve.packages[pkg].name.clone()), + }; + self.import_interfaces + .entry(pkgname) + .or_insert(Vec::new()) + .push(ImportInterface { snake, module }); } WorldItem::Type(ty) => { + let name = match name { + WorldKey::Name(name) => name, + WorldKey::Interface(_) => unreachable!(), + }; gen.define_type(name, *ty); let body = mem::take(&mut gen.src); self.src.push_str(&body); - return; } }; - - self.imports.push(import); } - fn export(&mut self, resolve: &Resolve, name: &str, item: &WorldItem) { - let snake = name.to_snake_case(); + fn export(&mut self, resolve: &Resolve, name: &WorldKey, item: &WorldItem) { let mut gen = InterfaceGenerator::new(self, resolve); - let (ty, getter) = match item { + let (field, ty, getter) = match item { WorldItem::Function(func) => { - gen.define_rust_guest_export(None, func); + gen.define_rust_guest_export(resolve, None, func); let body = mem::take(&mut gen.src).into(); let (_name, getter) = gen.extract_typed_function(func); assert!(gen.src.is_empty()); self.exports.funcs.push(body); - ("wasmtime::component::Func".to_string(), getter) + ( + func.name.to_snake_case(), + "wasmtime::component::Func".to_string(), + getter, + ) } WorldItem::Type(_) => unreachable!(), WorldItem::Interface(id) => { - gen.gen.name_interface(*id, snake.clone()); - gen.current_interface = Some(*id); + gen.gen.name_interface(resolve, *id, name); + gen.current_interface = Some((*id, name, true)); gen.types(*id); gen.generate_trappable_error_types(TypeOwner::Interface(*id)); let iface = &resolve.interfaces[*id]; - - let camel = to_rust_upper_camel_case(name); + let iface_name = match name { + WorldKey::Name(name) => name, + WorldKey::Interface(_) => iface.name.as_ref().unwrap(), + }; + let camel = to_rust_upper_camel_case(iface_name); uwriteln!(gen.src, "pub struct {camel} {{"); for (_, func) in iface.functions.iter() { uwriteln!( @@ -246,14 +293,14 @@ impl Wasmtime { uwriteln!(gen.src, "}})"); uwriteln!(gen.src, "}}"); for (_, func) in iface.functions.iter() { - gen.define_rust_guest_export(Some(name), func); + gen.define_rust_guest_export(resolve, Some(name), func); } uwriteln!(gen.src, "}}"); let module = &gen.src[..]; + let snake = iface_name.to_snake_case(); - uwriteln!( - self.src, + let module = format!( " #[allow(clippy::all)] pub mod {snake} {{ @@ -264,26 +311,54 @@ impl Wasmtime { }} " ); - + let pkgname = match name { + WorldKey::Name(_) => None, + WorldKey::Interface(_) => { + Some(resolve.packages[iface.package.unwrap()].name.clone()) + } + }; + self.exports + .modules + .entry(pkgname.clone()) + .or_insert(Vec::new()) + .push(module); + + let name = resolve.name_world_key(name); + let (path, method_name) = match pkgname { + Some(pkgname) => ( + format!( + "exports::{}::{}::{snake}::{camel}", + pkgname.namespace.to_snake_case(), + pkgname.name.to_snake_case(), + ), + format!( + "{}_{}_{snake}", + pkgname.namespace.to_snake_case(), + pkgname.name.to_snake_case() + ), + ), + None => (format!("exports::{snake}::{camel}"), snake.clone()), + }; let getter = format!( "\ - {snake}::{camel}::new( + {path}::new( &mut __exports.instance(\"{name}\") .ok_or_else(|| anyhow::anyhow!(\"exported instance `{name}` not present\"))? )?\ " ); + let field = format!("interface{}", self.exports.fields.len()); self.exports.funcs.push(format!( " - pub fn {snake}(&self) -> &{snake}::{camel} {{ - &self.{snake} + pub fn {method_name}(&self) -> &{path} {{ + &self.{field} }} - " + ", )); - (format!("{snake}::{camel}"), getter) + (field, path, getter) } }; - let prev = self.exports.fields.insert(snake.clone(), (ty, getter)); + let prev = self.exports.fields.insert(field, (ty, getter)); assert!(prev.is_none()); } @@ -375,6 +450,20 @@ impl Wasmtime { self.build_struct(resolve, world) } + let imports = mem::take(&mut self.import_interfaces); + self.emit_modules( + &imports + .into_iter() + .map(|(k, v)| (k, v.into_iter().map(|m| m.module).collect())) + .collect(), + ); + if !self.exports.modules.is_empty() { + uwriteln!(self.src, "pub mod exports {{"); + let exports = mem::take(&mut self.exports.modules); + self.emit_modules(&exports); + uwriteln!(self.src, "}}"); + } + let mut src = mem::take(&mut self.src); if self.opts.rustfmt { let mut child = Command::new("rustfmt") @@ -402,21 +491,42 @@ impl Wasmtime { src.into() } + + fn emit_modules(&mut self, modules: &BTreeMap, Vec>) { + let mut map = BTreeMap::new(); + for (pkg, modules) in modules { + match pkg { + Some(pkg) => { + let prev = map + .entry(&pkg.namespace) + .or_insert(BTreeMap::new()) + .insert(&pkg.name, modules); + assert!(prev.is_none()); + } + None => { + for module in modules { + uwriteln!(self.src, "{module}"); + } + } + } + } + for (ns, pkgs) in map { + uwriteln!(self.src, "pub mod {} {{", ns.to_snake_case()); + for (pkg, modules) in pkgs { + uwriteln!(self.src, "pub mod {} {{", pkg.to_snake_case()); + for module in modules { + uwriteln!(self.src, "{module}"); + } + uwriteln!(self.src, "}}"); + } + uwriteln!(self.src, "}}"); + } + } } impl Wasmtime { fn toplevel_import_trait(&mut self, resolve: &Resolve, world: WorldId) { - let mut functions = Vec::new(); - for import in self.imports.iter() { - match import { - Import::Interface { .. } => continue, - Import::Function { - sig, - add_to_linker: _, - } => functions.push(sig), - } - } - if functions.is_empty() { + if self.import_functions.is_empty() { return; } @@ -425,26 +535,29 @@ impl Wasmtime { uwriteln!(self.src, "#[wasmtime::component::__internal::async_trait]") } uwriteln!(self.src, "pub trait {world_camel}Imports {{"); - for sig in functions { - self.src.push_str(sig); + for f in self.import_functions.iter() { + self.src.push_str(&f.sig); self.src.push_str("\n"); } uwriteln!(self.src, "}}"); } fn toplevel_add_to_linker(&mut self, resolve: &Resolve, world: WorldId) { - if self.imports.is_empty() { + if self.import_interfaces.is_empty() && self.import_functions.is_empty() { return; } - let mut functions = Vec::new(); let mut interfaces = Vec::new(); - for import in self.imports.iter() { - match import { - Import::Interface { snake } => interfaces.push(snake), - Import::Function { - add_to_linker, - sig: _, - } => functions.push(add_to_linker), + for (pkg, imports) in self.import_interfaces.iter() { + for import in imports { + let mut path = String::new(); + if let Some(pkg) = pkg { + path.push_str(&pkg.namespace.to_snake_case()); + path.push_str("::"); + path.push_str(&pkg.name.to_snake_case()); + path.push_str("::"); + } + path.push_str(&import.snake); + interfaces.push(path) } } @@ -463,7 +576,7 @@ impl Wasmtime { for (i, name) in interfaces .iter() .map(|n| format!("{n}::Host")) - .chain(if functions.is_empty() { + .chain(if self.import_functions.is_empty() { None } else { Some(world_trait.clone()) @@ -485,11 +598,11 @@ impl Wasmtime { for name in interfaces.iter() { uwriteln!(self.src, "{name}::add_to_linker(linker, get)?;"); } - if !functions.is_empty() { + if !self.import_functions.is_empty() { uwriteln!(self.src, "Self::add_root_to_linker(linker, get)?;"); } uwriteln!(self.src, "Ok(())\n}}"); - if functions.is_empty() { + if self.import_functions.is_empty() { return; } @@ -505,8 +618,8 @@ impl Wasmtime { let mut linker = linker.root(); ", ); - for add_to_linker in functions { - self.src.push_str(add_to_linker); + for f in self.import_functions.iter() { + self.src.push_str(&f.add_to_linker); self.src.push_str("\n"); } uwriteln!(self.src, "Ok(())\n}}"); @@ -517,7 +630,7 @@ struct InterfaceGenerator<'a> { src: Source, gen: &'a mut Wasmtime, resolve: &'a Resolve, - current_interface: Option, + current_interface: Option<(InterfaceId, &'a WorldKey, bool)>, } impl<'a> InterfaceGenerator<'a> { @@ -1263,7 +1376,12 @@ impl<'a> InterfaceGenerator<'a> { ret } - fn define_rust_guest_export(&mut self, ns: Option<&str>, func: &Function) { + fn define_rust_guest_export( + &mut self, + resolve: &Resolve, + ns: Option<&WorldKey>, + func: &Function, + ) { let (async_, async__, await_) = if self.gen.opts.async_ { ("async", "_async", ".await") } else { @@ -1292,17 +1410,20 @@ impl<'a> InterfaceGenerator<'a> { } if self.gen.opts.tracing { + let ns = match ns { + Some(key) => resolve.name_world_key(key), + None => "default".to_string(), + }; self.src.push_str(&format!( " let span = tracing::span!( tracing::Level::TRACE, \"wit-bindgen export\", - module = \"{}\", + module = \"{ns}\", function = \"{}\", ); let _enter = span.enter(); ", - ns.unwrap_or("default"), func.name, )); } @@ -1466,17 +1587,26 @@ impl<'a> RustGenerator<'a> for InterfaceGenerator<'a> { } fn path_to_interface(&self, interface: InterfaceId) -> Option { - match self.current_interface { - Some(id) if id == interface => None, - _ => { - let InterfaceName { remapped, name } = &self.gen.interface_names[&interface]; - Some(if self.current_interface.is_some() && !remapped { - format!("super::{name}") - } else { - name.clone() - }) + let mut path_to_root = String::new(); + if let Some((cur, key, is_export)) = self.current_interface { + if cur == interface { + return None; + } + match key { + WorldKey::Name(_) => { + path_to_root.push_str("super::"); + } + WorldKey::Interface(_) => { + path_to_root.push_str("super::super::super::"); + } + } + if is_export { + path_to_root.push_str("super::"); } } + let InterfaceName { path, .. } = &self.gen.interface_names[&interface]; + path_to_root.push_str(path); + Some(path_to_root) } fn push_str(&mut self, s: &str) { diff --git a/supply-chain/imports.lock b/supply-chain/imports.lock index ea3707aac91a..f017f8768d14 100644 --- a/supply-chain/imports.lock +++ b/supply-chain/imports.lock @@ -64,6 +64,13 @@ user-id = 1 user-login = "alexcrichton" user-name = "Alex Crichton" +[[publisher.wasm-encoder]] +version = "0.29.0" +when = "2023-05-26" +user-id = 1 +user-login = "alexcrichton" +user-name = "Alex Crichton" + [[publisher.wasm-metadata]] version = "0.5.0" when = "2023-04-27" @@ -78,6 +85,13 @@ user-id = 1 user-login = "alexcrichton" user-name = "Alex Crichton" +[[publisher.wasm-metadata]] +version = "0.8.0" +when = "2023-05-26" +user-id = 1 +user-login = "alexcrichton" +user-name = "Alex Crichton" + [[publisher.wasm-mutate]] version = "0.2.25" when = "2023-05-15" @@ -85,6 +99,13 @@ user-id = 1 user-login = "alexcrichton" user-name = "Alex Crichton" +[[publisher.wasm-mutate]] +version = "0.2.27" +when = "2023-05-26" +user-id = 1 +user-login = "alexcrichton" +user-name = "Alex Crichton" + [[publisher.wasm-smith]] version = "0.12.8" when = "2023-05-15" @@ -92,6 +113,13 @@ user-id = 1 user-login = "alexcrichton" user-name = "Alex Crichton" +[[publisher.wasm-smith]] +version = "0.12.10" +when = "2023-05-26" +user-id = 1 +user-login = "alexcrichton" +user-name = "Alex Crichton" + [[publisher.wasmparser]] version = "0.104.0" when = "2023-04-27" @@ -106,72 +134,72 @@ user-id = 1 user-login = "alexcrichton" user-name = "Alex Crichton" -[[publisher.wasmprinter]] -version = "0.2.57" -when = "2023-05-15" +[[publisher.wasmparser]] +version = "0.107.0" +when = "2023-05-26" user-id = 1 user-login = "alexcrichton" user-name = "Alex Crichton" -[[publisher.wast]] -version = "58.0.0" +[[publisher.wasmprinter]] +version = "0.2.57" when = "2023-05-15" user-id = 1 user-login = "alexcrichton" user-name = "Alex Crichton" -[[publisher.wat]] -version = "1.0.64" -when = "2023-05-15" +[[publisher.wasmprinter]] +version = "0.2.59" +when = "2023-05-26" user-id = 1 user-login = "alexcrichton" user-name = "Alex Crichton" -[[publisher.wit-bindgen]] -version = "0.6.0" -when = "2023-04-27" +[[publisher.wast]] +version = "58.0.0" +when = "2023-05-15" user-id = 1 user-login = "alexcrichton" user-name = "Alex Crichton" -[[publisher.wit-bindgen-core]] -version = "0.6.0" -when = "2023-04-27" +[[publisher.wast]] +version = "60.0.0" +when = "2023-05-26" user-id = 1 user-login = "alexcrichton" user-name = "Alex Crichton" -[[publisher.wit-bindgen-rust]] -version = "0.6.0" -when = "2023-04-27" +[[publisher.wat]] +version = "1.0.64" +when = "2023-05-15" user-id = 1 user-login = "alexcrichton" user-name = "Alex Crichton" -[[publisher.wit-bindgen-rust-lib]] -version = "0.6.0" -when = "2023-04-27" +[[publisher.wat]] +version = "1.0.66" +when = "2023-05-26" user-id = 1 user-login = "alexcrichton" user-name = "Alex Crichton" -[[publisher.wit-bindgen-rust-macro]] -version = "0.6.0" +[[publisher.wit-component]] +version = "0.8.2" when = "2023-04-27" user-id = 1 user-login = "alexcrichton" user-name = "Alex Crichton" [[publisher.wit-component]] -version = "0.8.2" -when = "2023-04-27" +version = "0.9.0" +when = "2023-05-16" user-id = 1 user-login = "alexcrichton" user-name = "Alex Crichton" [[publisher.wit-component]] -version = "0.9.0" -when = "2023-05-16" +version = "0.11.0" +when = "2023-05-26" user-id = 1 user-login = "alexcrichton" user-name = "Alex Crichton" @@ -183,6 +211,13 @@ user-id = 1 user-login = "alexcrichton" user-name = "Alex Crichton" +[[publisher.wit-parser]] +version = "0.8.0" +when = "2023-05-26" +user-id = 1 +user-login = "alexcrichton" +user-name = "Alex Crichton" + [[audits.embark-studios.audits.anyhow]] who = "Johan Andersson " criteria = "safe-to-deploy" diff --git a/tests/all/component_model/bindgen.rs b/tests/all/component_model/bindgen.rs index d8c8f3023cd4..c377f08a6579 100644 --- a/tests/all/component_model/bindgen.rs +++ b/tests/all/component_model/bindgen.rs @@ -14,7 +14,9 @@ mod no_imports { wasmtime::component::bindgen!({ inline: " - default world no-imports { + package foo:foo + + world no-imports { export foo: interface { foo: func() } @@ -59,7 +61,9 @@ mod one_import { wasmtime::component::bindgen!({ inline: " - default world one-import { + package foo:foo + + world one-import { import foo: interface { foo: func() } diff --git a/tests/all/component_model/bindgen/results.rs b/tests/all/component_model/bindgen/results.rs index eaec5cc3ac4c..d0c49e40245e 100644 --- a/tests/all/component_model/bindgen/results.rs +++ b/tests/all/component_model/bindgen/results.rs @@ -9,7 +9,8 @@ mod empty_error { use super::*; wasmtime::component::bindgen!({ inline: " - default world result-playground { + package inline:inline + world result-playground { import imports: interface { empty-error: func(a: float64) -> result } @@ -109,7 +110,8 @@ mod string_error { use super::*; wasmtime::component::bindgen!({ inline: " - default world result-playground { + package inline:inline + world result-playground { import imports: interface { string-error: func(a: float64) -> result } @@ -219,14 +221,18 @@ mod string_error { mod enum_error { use super::*; + use exports::foo; + use inline::inline::imports; + wasmtime::component::bindgen!({ inline: " + package inline:inline interface imports { enum e1 { a, b, c } enum-error: func(a: float64) -> result } - default world result-playground { - import imports: self.imports + world result-playground { + import imports export foo: interface { enum e1 { a, b, c } enum-error: func(a: float64) -> result @@ -244,7 +250,7 @@ mod enum_error { r#" (component (type $err' (enum "a" "b" "c")) - (import "imports" (instance $i + (import (interface "inline:inline/imports") (instance $i (export $err "err" (type (eq $err'))) (export "enum-error" (func (param "a" float64) (result (result float64 (error $err))))) )) @@ -357,7 +363,7 @@ mod enum_error { .expect("no trap") .err() .expect("error returned"); - assert_eq!(e, enum_error::foo::E1::A); + assert_eq!(e, foo::E1::A); let e = results .foo() @@ -377,14 +383,18 @@ mod enum_error { mod record_error { use super::*; + use exports::foo; + use inline::inline::imports; + wasmtime::component::bindgen!({ inline: " + package inline:inline interface imports { record e2 { line: u32, col: u32 } record-error: func(a: float64) -> result } - default world result-playground { - import imports: self.imports + world result-playground { + import imports export foo: interface { record e2 { line: u32, col: u32 } record-error: func(a: float64) -> result @@ -407,7 +417,7 @@ mod record_error { (field "line" u32) (field "col" u32) )) - (import "imports" (instance $i + (import (interface "inline:inline/imports") (instance $i (export $e2 "e2" (type (eq $e2'))) (type $result (result float64 (error $e2))) (export "record-error" (func (param "a" float64) (result $result))) @@ -525,16 +535,20 @@ mod record_error { mod variant_error { use super::*; + use exports::foo; + use inline::inline::imports; + wasmtime::component::bindgen!({ inline: " + package inline:inline interface imports { enum e1 { a, b, c } record e2 { line: u32, col: u32 } variant e3 { E1(e1), E2(e2) } variant-error: func(a: float64) -> result } - default world result-playground { - import imports: self.imports + world result-playground { + import imports export foo: interface { enum e1 { a, b, c } record e2 { line: u32, col: u32 } @@ -559,7 +573,7 @@ mod variant_error { (case "E1" $e1') (case "E2" $e2') )) - (import "imports" (instance $i + (import (interface "inline:inline/imports") (instance $i (export $e1 "e1" (type (eq $e1'))) (export $e2 "e2" (type (eq $e2'))) (type $e3' (variant @@ -710,7 +724,8 @@ mod with_remapping { wasmtime::component::bindgen!({ inline: " - default world result-playground { + package inline:inline + world result-playground { import imports: interface { empty-error: func(a: float64) -> result }