Repository: bytecodealliance/wasmtime
Pull request #7800 (2024-01-20 00:13:29)

Release Wasmtime 17.0.0
This is an [automated pull request][process] from CI which is
intended to notify maintainers that it's time to release Wasmtime
17.0.0. The [release branch][branch] was created roughly two weeks ago
and it's now time for it to be published and released.

It's recommended that maintainers double-check that [RELEASES.md]
is up-to-date and that there are no known issues before merging this
PR. When this PR is merged a release tag will automatically be
created, crates will be published, and CI artifacts will be produced.

[RELEASES.md]: https://github.com/bytecodealliance/wasmtime/blob/main/RELEASES.md
[process]: https://docs.wasmtime.dev/contributing-release-process.html
[branch]: https://github.com/bytecodealliance/wasmtime/tree/release-17.0.0


pchickey: We're planning to hold off the release of Wasmtime 17 until WASI Preview 2 is completed, which is pending vote at the 1/25/2024 WASI Subgroup meeting.
alexcrichton: I cherry-picked https://github.com/bytecodealliance/wasmtime/pull/7760 to this PR to fix CI

Patch:
diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
index 5eec5e795..55dcc0c51 100644
--- a/.github/workflows/main.yml
+++ b/.github/workflows/main.yml
@@ -431,7 +431,7 @@ jobs:
       if: matrix.target == 'x86_64-pc-windows-gnu'
 
     # Update binutils if MinGW due to https://github.com/rust-lang/rust/issues/112368
-    - run: C:/msys64/usr/bin/pacman.exe -Syu --needed mingw-w64-x86_64-gcc --noconfirm
+    - run: C:/msys64/usr/bin/pacman.exe -S --needed mingw-w64-x86_64-gcc --noconfirm
       if: matrix.target == 'x86_64-pc-windows-gnu'
     - shell: pwsh
       run: echo "C:\msys64\mingw64\bin" >> $Env:GITHUB_PATH
diff --git a/RELEASES.md b/RELEASES.md
index 78c49dbaa..b3bfea5f7 100644
--- a/RELEASES.md
+++ b/RELEASES.md
@@ -2,12 +2,79 @@
 
 ## 17.0.0
 
-Unreleased.
+Released 2024-01-25
+
+The major feature of this release is that the WASI support in Wasmtime is now
+considered stable and flagged at an 0.2.0 version approved by the WASI subgroup.
+The release was delayed a few days to hold off until the WASI subgroup voted to
+approve the CLI and HTTP worlds and they're now on-by-default! Additionally the
+component model is now enabled by default in Wasmtime, for example an opt-in
+flag is no longer required on the CLI. Note that embeddings still must opt-in to
+using the component model by using the `wasmtime::component` module.
 
 ### Added
 
+* Cranelift optimizations have been added for "3-way comparisons", or `Ord::cmp`
+  in Rust or `<=>` in C++.
+  [#7636](https://github.com/bytecodealliance/wasmtime/pull/7636)
+  [#7702](https://github.com/bytecodealliance/wasmtime/pull/7702)
+
+* Components now use Wasmtime's compilation cache used for core wasm modules by
+  default.
+  [#7649](https://github.com/bytecodealliance/wasmtime/pull/7649)
+
+* The `Resource<T>` and `ResourceAny` types can now be converted between each
+  other.
+  [#7649](https://github.com/bytecodealliance/wasmtime/pull/7649)
+  [#7712](https://github.com/bytecodealliance/wasmtime/pull/7712)
+
 ### Changed
 
+* Minor changes have been made to a number of WITs as they progressed to their
+  official 0.2.0 status.
+  [#7625](https://github.com/bytecodealliance/wasmtime/pull/7625)
+  [#7640](https://github.com/bytecodealliance/wasmtime/pull/7640)
+  [#7690](https://github.com/bytecodealliance/wasmtime/pull/7690)
+  [#7781](https://github.com/bytecodealliance/wasmtime/pull/7781)
+  [#7817](https://github.com/bytecodealliance/wasmtime/pull/7817)
+
+* The component model is now enabled by default.
+  [#7821](https://github.com/bytecodealliance/wasmtime/pull/7821)
+
+* The implementation of `memory.atomic.{wait,notify}` has been rewritten.
+  [#7629](https://github.com/bytecodealliance/wasmtime/pull/7629)
+
+* The `wasmtime_wasi::preview2::Table` type has been moved to
+  `wasmtime::component::ResourceTable`.
+  [#7655](https://github.com/bytecodealliance/wasmtime/pull/7655)
+
+* Creating a UDP stream now validates the address being sent to.
+  [#7648](https://github.com/bytecodealliance/wasmtime/pull/7648)
+
+* Defining resource types in `Linker<T>` now takes the type to define as a
+  runtime parameter.
+  [#7680](https://github.com/bytecodealliance/wasmtime/pull/7680)
+
+* Socket address checks can now be performed dynamically at runtime.
+  [#7662](https://github.com/bytecodealliance/wasmtime/pull/7662)
+
+* Wasmtime and Cranelift's MSRV is now 1.73.0.
+  [#7739](https://github.com/bytecodealliance/wasmtime/pull/7739)
+
+### Fixed
+
+* Bindings for WIT APIs where interfaces have multiple versions are now fixed by
+  putting the version in the generated binding names.
+  [#7656](https://github.com/bytecodealliance/wasmtime/pull/7656)
+
+* The preview1 `fd_{read,write}` APIs are now fixed when a shared memory is
+  used.
+  [#7755](https://github.com/bytecodealliance/wasmtime/pull/7755)
+
+* The preview1 `fd_{read,write}` APIs no longer leak an intermediate stream
+  created.
+  [#7819](https://github.com/bytecodealliance/wasmtime/pull/7819)
+
 --------------------------------------------------------------------------------
 
 ## 16.0.0
diff --git a/crates/wasi-http/src/lib.rs b/crates/wasi-http/src/lib.rs
index d331eb56b..e7218250a 100644
--- a/crates/wasi-http/src/lib.rs
+++ b/crates/wasi-http/src/lib.rs
@@ -11,9 +11,9 @@ pub mod bindings {
     wasmtime::component::bindgen!({
         path: "wit",
         interfaces: "
-            import wasi:http/incoming-handler@0.2.0-rc-2024-01-16;
-            import wasi:http/outgoing-handler@0.2.0-rc-2024-01-16;
-            import wasi:http/types@0.2.0-rc-2024-01-16;
+            import wasi:http/incoming-handler@0.2.0;
+            import wasi:http/outgoing-handler@0.2.0;
+            import wasi:http/types@0.2.0;
         ",
         tracing: true,
         async: false,
diff --git a/crates/wasi-http/wit/command-extended.wit b/crates/wasi-http/wit/command-extended.wit
index 2f1491ef9..4bff99e65 100644
--- a/crates/wasi-http/wit/command-extended.wit
+++ b/crates/wasi-http/wit/command-extended.wit
@@ -1,6 +1,6 @@
 // All of the same imports and exports available in the wasi:cli/command world
 // with addition of HTTP proxy related imports:
 world command-extended {
-  include wasi:cli/command@0.2.0-rc-2024-01-16;
-  import wasi:http/outgoing-handler@0.2.0-rc-2024-01-16;
+  include wasi:cli/command@0.2.0;
+  import wasi:http/outgoing-handler@0.2.0;
 }
diff --git a/crates/wasi-http/wit/deps/cli/command.wit b/crates/wasi-http/wit/deps/cli/command.wit
index a9889164f..d8005bd38 100644
--- a/crates/wasi-http/wit/deps/cli/command.wit
+++ b/crates/wasi-http/wit/deps/cli/command.wit
@@ -1,4 +1,4 @@
-package wasi:cli@0.2.0-rc-2024-01-16;
+package wasi:cli@0.2.0;
 
 world command {
   include imports;
diff --git a/crates/wasi-http/wit/deps/cli/imports.wit b/crates/wasi-http/wit/deps/cli/imports.wit
index 8ce1abec3..083b84a03 100644
--- a/crates/wasi-http/wit/deps/cli/imports.wit
+++ b/crates/wasi-http/wit/deps/cli/imports.wit
@@ -1,11 +1,11 @@
-package wasi:cli@0.2.0-rc-2024-01-16;
+package wasi:cli@0.2.0;
 
 world imports {
-  include wasi:clocks/imports@0.2.0-rc-2023-11-10;
-  include wasi:filesystem/imports@0.2.0-rc-2023-11-10;
-  include wasi:sockets/imports@0.2.0-rc-2024-01-16;
-  include wasi:random/imports@0.2.0-rc-2023-11-10;
-  include wasi:io/imports@0.2.0-rc-2023-11-10;
+  include wasi:clocks/imports@0.2.0;
+  include wasi:filesystem/imports@0.2.0;
+  include wasi:sockets/imports@0.2.0;
+  include wasi:random/imports@0.2.0;
+  include wasi:io/imports@0.2.0;
 
   import environment;
   import exit;
diff --git a/crates/wasi-http/wit/deps/cli/stdio.wit b/crates/wasi-http/wit/deps/cli/stdio.wit
index 1b653b6e2..31ef35b5a 100644
--- a/crates/wasi-http/wit/deps/cli/stdio.wit
+++ b/crates/wasi-http/wit/deps/cli/stdio.wit
@@ -1,17 +1,17 @@
 interface stdin {
-  use wasi:io/streams@0.2.0-rc-2023-11-10.{input-stream};
+  use wasi:io/streams@0.2.0.{input-stream};
 
   get-stdin: func() -> input-stream;
 }
 
 interface stdout {
-  use wasi:io/streams@0.2.0-rc-2023-11-10.{output-stream};
+  use wasi:io/streams@0.2.0.{output-stream};
 
   get-stdout: func() -> output-stream;
 }
 
 interface stderr {
-  use wasi:io/streams@0.2.0-rc-2023-11-10.{output-stream};
+  use wasi:io/streams@0.2.0.{output-stream};
 
   get-stderr: func() -> output-stream;
 }
diff --git a/crates/wasi-http/wit/deps/clocks/monotonic-clock.wit b/crates/wasi-http/wit/deps/clocks/monotonic-clock.wit
index 09ef32c36..4e4dc3a19 100644
--- a/crates/wasi-http/wit/deps/clocks/monotonic-clock.wit
+++ b/crates/wasi-http/wit/deps/clocks/monotonic-clock.wit
@@ -1,4 +1,4 @@
-package wasi:clocks@0.2.0-rc-2023-11-10;
+package wasi:clocks@0.2.0;
 /// WASI Monotonic Clock is a clock API intended to let users measure elapsed
 /// time.
 ///
@@ -10,7 +10,7 @@ package wasi:clocks@0.2.0-rc-2023-11-10;
 ///
 /// It is intended for measuring elapsed time.
 interface monotonic-clock {
-    use wasi:io/poll@0.2.0-rc-2023-11-10.{pollable};
+    use wasi:io/poll@0.2.0.{pollable};
 
     /// An instant in time, in nanoseconds. An instant is relative to an
     /// unspecified initial value, and can only be compared to instances from
diff --git a/crates/wasi-http/wit/deps/clocks/wall-clock.wit b/crates/wasi-http/wit/deps/clocks/wall-clock.wit
index 8abb9a0c0..440ca0f33 100644
--- a/crates/wasi-http/wit/deps/clocks/wall-clock.wit
+++ b/crates/wasi-http/wit/deps/clocks/wall-clock.wit
@@ -1,4 +1,4 @@
-package wasi:clocks@0.2.0-rc-2023-11-10;
+package wasi:clocks@0.2.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.
diff --git a/crates/wasi-http/wit/deps/clocks/world.wit b/crates/wasi-http/wit/deps/clocks/world.wit
index 8fa080f0e..c0224572a 100644
--- a/crates/wasi-http/wit/deps/clocks/world.wit
+++ b/crates/wasi-http/wit/deps/clocks/world.wit
@@ -1,4 +1,4 @@
-package wasi:clocks@0.2.0-rc-2023-11-10;
+package wasi:clocks@0.2.0;
 
 world imports {
     import monotonic-clock;
diff --git a/crates/wasi-http/wit/deps/filesystem/preopens.wit b/crates/wasi-http/wit/deps/filesystem/preopens.wit
index 95ec67843..da801f6d6 100644
--- a/crates/wasi-http/wit/deps/filesystem/preopens.wit
+++ b/crates/wasi-http/wit/deps/filesystem/preopens.wit
@@ -1,4 +1,4 @@
-package wasi:filesystem@0.2.0-rc-2023-11-10;
+package wasi:filesystem@0.2.0;
 
 interface preopens {
     use types.{descriptor};
diff --git a/crates/wasi-http/wit/deps/filesystem/types.wit b/crates/wasi-http/wit/deps/filesystem/types.wit
index 059722ab8..11108fcda 100644
--- a/crates/wasi-http/wit/deps/filesystem/types.wit
+++ b/crates/wasi-http/wit/deps/filesystem/types.wit
@@ -1,4 +1,4 @@
-package wasi:filesystem@0.2.0-rc-2023-11-10;
+package wasi:filesystem@0.2.0;
 /// 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.
@@ -24,8 +24,8 @@ package wasi:filesystem@0.2.0-rc-2023-11-10;
 ///
 /// [WASI filesystem path resolution]: https://github.com/WebAssembly/wasi-filesystem/blob/main/path-resolution.md
 interface types {
-    use wasi:io/streams@0.2.0-rc-2023-11-10.{input-stream, output-stream, error};
-    use wasi:clocks/wall-clock@0.2.0-rc-2023-11-10.{datetime};
+    use wasi:io/streams@0.2.0.{input-stream, output-stream, error};
+    use wasi:clocks/wall-clock@0.2.0.{datetime};
 
     /// File size or length of a region within a file.
     type filesize = u64;
diff --git a/crates/wasi-http/wit/deps/filesystem/world.wit b/crates/wasi-http/wit/deps/filesystem/world.wit
index 285e0bae9..663f57920 100644
--- a/crates/wasi-http/wit/deps/filesystem/world.wit
+++ b/crates/wasi-http/wit/deps/filesystem/world.wit
@@ -1,4 +1,4 @@
-package wasi:filesystem@0.2.0-rc-2023-11-10;
+package wasi:filesystem@0.2.0;
 
 world imports {
     import types;
diff --git a/crates/wasi-http/wit/deps/http/proxy.wit b/crates/wasi-http/wit/deps/http/proxy.wit
index 2b0ce4b8a..687c24d23 100644
--- a/crates/wasi-http/wit/deps/http/proxy.wit
+++ b/crates/wasi-http/wit/deps/http/proxy.wit
@@ -1,4 +1,4 @@
-package wasi:http@0.2.0-rc-2024-01-16;
+package wasi:http@0.2.0;
 
 /// The `wasi:http/proxy` world captures a widely-implementable intersection of
 /// hosts that includes HTTP forward and reverse proxies. Components targeting
@@ -6,19 +6,19 @@ package wasi:http@0.2.0-rc-2024-01-16;
 /// outgoing HTTP requests.
 world proxy {
   /// HTTP proxies have access to time and randomness.
-  include wasi:clocks/imports@0.2.0-rc-2023-11-10;
-  import wasi:random/random@0.2.0-rc-2023-11-10;
+  include wasi:clocks/imports@0.2.0;
+  import wasi:random/random@0.2.0;
 
   /// Proxies have standard output and error streams which are expected to
   /// terminate in a developer-facing console provided by the host.
-  import wasi:cli/stdout@0.2.0-rc-2024-01-16;
-  import wasi:cli/stderr@0.2.0-rc-2024-01-16;
+  import wasi:cli/stdout@0.2.0;
+  import wasi:cli/stderr@0.2.0;
 
   /// TODO: this is a temporary workaround until component tooling is able to
   /// gracefully handle the absence of stdin. Hosts must return an eof stream
   /// for this import, which is what wasi-libc + tooling will do automatically
   /// when this import is properly removed.
-  import wasi:cli/stdin@0.2.0-rc-2024-01-16;
+  import wasi:cli/stdin@0.2.0;
 
   /// This is the default handler to use when user code simply wants to make an
   /// HTTP request (e.g., via `fetch()`).
diff --git a/crates/wasi-http/wit/deps/http/types.wit b/crates/wasi-http/wit/deps/http/types.wit
index 0f698e769..755ac6a6b 100644
--- a/crates/wasi-http/wit/deps/http/types.wit
+++ b/crates/wasi-http/wit/deps/http/types.wit
@@ -2,10 +2,10 @@
 /// HTTP Requests and Responses, both incoming and outgoing, as well as
 /// their headers, trailers, and bodies.
 interface types {
-  use wasi:clocks/monotonic-clock@0.2.0-rc-2023-11-10.{duration};
-  use wasi:io/streams@0.2.0-rc-2023-11-10.{input-stream, output-stream};
-  use wasi:io/error@0.2.0-rc-2023-11-10.{error as io-error};
-  use wasi:io/poll@0.2.0-rc-2023-11-10.{pollable};
+  use wasi:clocks/monotonic-clock@0.2.0.{duration};
+  use wasi:io/streams@0.2.0.{input-stream, output-stream};
+  use wasi:io/error@0.2.0.{error as io-error};
+  use wasi:io/poll@0.2.0.{pollable};
 
   /// This type corresponds to HTTP standard Methods.
   variant method {
diff --git a/crates/wasi-http/wit/deps/io/error.wit b/crates/wasi-http/wit/deps/io/error.wit
index 31918acbb..22e5b6489 100644
--- a/crates/wasi-http/wit/deps/io/error.wit
+++ b/crates/wasi-http/wit/deps/io/error.wit
@@ -1,4 +1,4 @@
-package wasi:io@0.2.0-rc-2023-11-10;
+package wasi:io@0.2.0;
 
 
 interface error {
diff --git a/crates/wasi-http/wit/deps/io/poll.wit b/crates/wasi-http/wit/deps/io/poll.wit
index bddde3c19..c982f1af7 100644
--- a/crates/wasi-http/wit/deps/io/poll.wit
+++ b/crates/wasi-http/wit/deps/io/poll.wit
@@ -1,4 +1,4 @@
-package wasi:io@0.2.0-rc-2023-11-10;
+package wasi:io@0.2.0;
 
 /// A poll API intended to let users wait for I/O events on multiple handles
 /// at once.
diff --git a/crates/wasi-http/wit/deps/io/streams.wit b/crates/wasi-http/wit/deps/io/streams.wit
index e7e1b689a..c797e37ff 100644
--- a/crates/wasi-http/wit/deps/io/streams.wit
+++ b/crates/wasi-http/wit/deps/io/streams.wit
@@ -1,4 +1,4 @@
-package wasi:io@0.2.0-rc-2023-11-10;
+package wasi:io@0.2.0;
 
 /// WASI I/O is an I/O abstraction API which is currently focused on providing
 /// stream types.
diff --git a/crates/wasi-http/wit/deps/io/world.wit b/crates/wasi-http/wit/deps/io/world.wit
index 8243da2ee..5f0b43fe5 100644
--- a/crates/wasi-http/wit/deps/io/world.wit
+++ b/crates/wasi-http/wit/deps/io/world.wit
@@ -1,4 +1,4 @@
-package wasi:io@0.2.0-rc-2023-11-10;
+package wasi:io@0.2.0;
 
 world imports {
     import streams;
diff --git a/crates/wasi-http/wit/deps/random/insecure-seed.wit b/crates/wasi-http/wit/deps/random/insecure-seed.wit
index f76e87dad..47210ac6b 100644
--- a/crates/wasi-http/wit/deps/random/insecure-seed.wit
+++ b/crates/wasi-http/wit/deps/random/insecure-seed.wit
@@ -1,4 +1,4 @@
-package wasi:random@0.2.0-rc-2023-11-10;
+package wasi:random@0.2.0;
 /// The insecure-seed interface for seeding hash-map DoS resistance.
 ///
 /// It is intended to be portable at least between Unix-family platforms and
diff --git a/crates/wasi-http/wit/deps/random/insecure.wit b/crates/wasi-http/wit/deps/random/insecure.wit
index ec7b99737..c58f4ee85 100644
--- a/crates/wasi-http/wit/deps/random/insecure.wit
+++ b/crates/wasi-http/wit/deps/random/insecure.wit
@@ -1,4 +1,4 @@
-package wasi:random@0.2.0-rc-2023-11-10;
+package wasi:random@0.2.0;
 /// The insecure interface for insecure pseudo-random numbers.
 ///
 /// It is intended to be portable at least between Unix-family platforms and
diff --git a/crates/wasi-http/wit/deps/random/random.wit b/crates/wasi-http/wit/deps/random/random.wit
index 7a7dfa27a..0c017f093 100644
--- a/crates/wasi-http/wit/deps/random/random.wit
+++ b/crates/wasi-http/wit/deps/random/random.wit
@@ -1,4 +1,4 @@
-package wasi:random@0.2.0-rc-2023-11-10;
+package wasi:random@0.2.0;
 /// WASI Random is a random data API.
 ///
 /// It is intended to be portable at least between Unix-family platforms and
diff --git a/crates/wasi-http/wit/deps/random/world.wit b/crates/wasi-http/wit/deps/random/world.wit
index 49e5743b4..3da34914a 100644
--- a/crates/wasi-http/wit/deps/random/world.wit
+++ b/crates/wasi-http/wit/deps/random/world.wit
@@ -1,4 +1,4 @@
-package wasi:random@0.2.0-rc-2023-11-10;
+package wasi:random@0.2.0;
 
 world imports {
     import random;
diff --git a/crates/wasi-http/wit/deps/sockets/ip-name-lookup.wit b/crates/wasi-http/wit/deps/sockets/ip-name-lookup.wit
index 931ccf7e0..8e639ec59 100644
--- a/crates/wasi-http/wit/deps/sockets/ip-name-lookup.wit
+++ b/crates/wasi-http/wit/deps/sockets/ip-name-lookup.wit
@@ -1,6 +1,6 @@
 
 interface ip-name-lookup {
-    use wasi:io/poll@0.2.0-rc-2023-11-10.{pollable};
+    use wasi:io/poll@0.2.0.{pollable};
     use network.{network, error-code, ip-address};
 
 
diff --git a/crates/wasi-http/wit/deps/sockets/tcp.wit b/crates/wasi-http/wit/deps/sockets/tcp.wit
index e045a436a..fbe023b64 100644
--- a/crates/wasi-http/wit/deps/sockets/tcp.wit
+++ b/crates/wasi-http/wit/deps/sockets/tcp.wit
@@ -1,8 +1,8 @@
 
 interface tcp {
-    use wasi:io/streams@0.2.0-rc-2023-11-10.{input-stream, output-stream};
-    use wasi:io/poll@0.2.0-rc-2023-11-10.{pollable};
-    use wasi:clocks/monotonic-clock@0.2.0-rc-2023-11-10.{duration};
+    use wasi:io/streams@0.2.0.{input-stream, output-stream};
+    use wasi:io/poll@0.2.0.{pollable};
+    use wasi:clocks/monotonic-clock@0.2.0.{duration};
     use network.{network, error-code, ip-socket-address, ip-address-family};
 
     enum shutdown-type {
diff --git a/crates/wasi-http/wit/deps/sockets/udp.wit b/crates/wasi-http/wit/deps/sockets/udp.wit
index ae82b97fc..b9826a6a5 100644
--- a/crates/wasi-http/wit/deps/sockets/udp.wit
+++ b/crates/wasi-http/wit/deps/sockets/udp.wit
@@ -1,6 +1,6 @@
 
 interface udp {
-    use wasi:io/poll@0.2.0-rc-2023-11-10.{pollable};
+    use wasi:io/poll@0.2.0.{pollable};
     use network.{network, error-code, ip-socket-address, ip-address-family};
 
     /// A received datagram.
diff --git a/crates/wasi-http/wit/deps/sockets/world.wit b/crates/wasi-http/wit/deps/sockets/world.wit
index 8588cc6c1..f8bb92ae0 100644
--- a/crates/wasi-http/wit/deps/sockets/world.wit
+++ b/crates/wasi-http/wit/deps/sockets/world.wit
@@ -1,4 +1,4 @@
-package wasi:sockets@0.2.0-rc-2024-01-16;
+package wasi:sockets@0.2.0;
 
 world imports {
     import instance-network;
diff --git a/crates/wasi-preview1-component-adapter/src/descriptors.rs b/crates/wasi-preview1-component-adapter/src/descriptors.rs
index 23e0a45d4..52b2378c7 100644
--- a/crates/wasi-preview1-component-adapter/src/descriptors.rs
+++ b/crates/wasi-preview1-component-adapter/src/descriptors.rs
@@ -194,7 +194,7 @@ impl Descriptors {
 
     #[cfg(not(feature = "proxy"))]
     fn open_preopens(&self, import_alloc: &ImportAlloc, arena: &BumpArena) {
-        #[link(wasm_import_module = "wasi:filesystem/preopens@0.2.0-rc-2023-11-10")]
+        #[link(wasm_import_module = "wasi:filesystem/preopens@0.2.0")]
         #[allow(improper_ctypes)] // FIXME(bytecodealliance/wit-bindgen#684)
         extern "C" {
             #[link_name = "get-directories"]
diff --git a/crates/wasi-preview1-component-adapter/src/lib.rs b/crates/wasi-preview1-component-adapter/src/lib.rs
index bd1d94e40..0df1b5e1f 100644
--- a/crates/wasi-preview1-component-adapter/src/lib.rs
+++ b/crates/wasi-preview1-component-adapter/src/lib.rs
@@ -84,12 +84,12 @@ pub mod bindings {
             package wasmtime:adapter;
 
             world adapter {
-                import wasi:clocks/wall-clock@0.2.0-rc-2023-11-10;
-                import wasi:clocks/monotonic-clock@0.2.0-rc-2023-11-10;
-                import wasi:random/random@0.2.0-rc-2023-11-10;
-                import wasi:cli/stdout@0.2.0-rc-2024-01-16;
-                import wasi:cli/stderr@0.2.0-rc-2024-01-16;
-                import wasi:cli/stdin@0.2.0-rc-2024-01-16;
+                import wasi:clocks/wall-clock@0.2.0;
+                import wasi:clocks/monotonic-clock@0.2.0;
+                import wasi:random/random@0.2.0;
+                import wasi:cli/stdout@0.2.0;
+                import wasi:cli/stderr@0.2.0;
+                import wasi:cli/stdin@0.2.0;
             }
         "#,
         std_feature,
@@ -98,7 +98,7 @@ pub mod bindings {
     });
 }
 
-#[export_name = "wasi:cli/run@0.2.0-rc-2024-01-16#run"]
+#[export_name = "wasi:cli/run@0.2.0#run"]
 #[cfg(feature = "command")]
 pub unsafe extern "C" fn run() -> u32 {
     #[link(wasm_import_module = "__main_module__")]
@@ -1942,7 +1942,7 @@ pub unsafe extern "C" fn poll_oneoff(
             });
         }
 
-        #[link(wasm_import_module = "wasi:io/poll@0.2.0-rc-2023-11-10")]
+        #[link(wasm_import_module = "wasi:io/poll@0.2.0")]
         #[allow(improper_ctypes)] // FIXME(bytecodealliance/wit-bindgen#684)
         extern "C" {
             #[link_name = "poll"]
@@ -2665,7 +2665,7 @@ impl State {
     #[cfg(not(feature = "proxy"))]
     fn get_environment(&self) -> &[StrTuple] {
         if self.env_vars.get().is_none() {
-            #[link(wasm_import_module = "wasi:cli/environment@0.2.0-rc-2024-01-16")]
+            #[link(wasm_import_module = "wasi:cli/environment@0.2.0")]
             extern "C" {
                 #[link_name = "get-environment"]
                 fn get_environment_import(rval: *mut StrTupleList);
@@ -2690,7 +2690,7 @@ impl State {
     #[cfg(not(feature = "proxy"))]
     fn get_args(&self) -> &[WasmStr] {
         if self.args.get().is_none() {
-            #[link(wasm_import_module = "wasi:cli/environment@0.2.0-rc-2024-01-16")]
+            #[link(wasm_import_module = "wasi:cli/environment@0.2.0")]
             extern "C" {
                 #[link_name = "get-arguments"]
                 fn get_args_import(rval: *mut WasmStrList);
diff --git a/crates/wasi/src/preview2/mod.rs b/crates/wasi/src/preview2/mod.rs
index f7fc9004e..160875043 100644
--- a/crates/wasi/src/preview2/mod.rs
+++ b/crates/wasi/src/preview2/mod.rs
@@ -69,9 +69,9 @@ pub mod bindings {
             wasmtime::component::bindgen!({
                 path: "wit",
                 interfaces: "
-                    import wasi:io/poll@0.2.0-rc-2023-11-10;
-                    import wasi:io/streams@0.2.0-rc-2023-11-10;
-                    import wasi:filesystem/types@0.2.0-rc-2023-11-10;
+                    import wasi:io/poll@0.2.0;
+                    import wasi:io/streams@0.2.0;
+                    import wasi:filesystem/types@0.2.0;
                 ",
                 tracing: true,
                 trappable_error_type: {
diff --git a/crates/wasi/src/preview2/preview1.rs b/crates/wasi/src/preview2/preview1.rs
index 83da22771..c692bf0b3 100644
--- a/crates/wasi/src/preview2/preview1.rs
+++ b/crates/wasi/src/preview2/preview1.rs
@@ -1340,8 +1340,10 @@ impl<
                         .unwrap_or_else(types::Error::trap)
                 })?;
                 let read = blocking_mode
-                    .read(self, stream, buf.len().try_into()?)
-                    .await?;
+                    .read(self, stream.borrowed(), buf.len().try_into()?)
+                    .await;
+                streams::HostInputStream::drop(self, stream).map_err(|e| types::Error::trap(e))?;
+                let read = read?;
                 let n = read.len().try_into()?;
                 let pos = pos.checked_add(n).ok_or(types::Errno::Overflow)?;
                 position.store(pos, Ordering::Relaxed);
@@ -1398,9 +1400,10 @@ impl<
                         .unwrap_or_else(types::Error::trap)
                 })?;
                 let read = blocking_mode
-                    .read(self, stream, buf.len().try_into()?)
-                    .await?;
-                (buf, read)
+                    .read(self, stream.borrowed(), buf.len().try_into()?)
+                    .await;
+                streams::HostInputStream::drop(self, stream).map_err(|e| types::Error::trap(e))?;
+                (buf, read?)
             }
             Descriptor::Stdin { .. } => {
                 // NOTE: legacy implementation returns SPIPE here
@@ -1459,7 +1462,9 @@ impl<
                     })?;
                     (stream, pos)
                 };
-                let n = blocking_mode.write(self, stream, buf).await?;
+                let n = blocking_mode.write(self, stream.borrowed(), buf).await;
+                streams::HostOutputStream::drop(self, stream).map_err(|e| types::Error::trap(e))?;
+                let n = n?;
                 if append {
                     let len = self.stat(fd2).await?;
                     position.store(len.size, Ordering::Relaxed);
@@ -1512,7 +1517,9 @@ impl<
                         .context("failed to call `write-via-stream`")
                         .unwrap_or_else(types::Error::trap)
                 })?;
-                blocking_mode.write(self, stream, buf).await?
+                let result = blocking_mode.write(self, stream.borrowed(), buf).await;
+                streams::HostOutputStream::drop(self, stream).map_err(|e| types::Error::trap(e))?;
+                result?
             }
             Descriptor::Stdout { .. } | Descriptor::Stderr { .. } => {
                 // NOTE: legacy implementation returns SPIPE here
diff --git a/crates/wasi/wit/command-extended.wit b/crates/wasi/wit/command-extended.wit
index 2f1491ef9..4bff99e65 100644
--- a/crates/wasi/wit/command-extended.wit
+++ b/crates/wasi/wit/command-extended.wit
@@ -1,6 +1,6 @@
 // All of the same imports and exports available in the wasi:cli/command world
 // with addition of HTTP proxy related imports:
 world command-extended {
-  include wasi:cli/command@0.2.0-rc-2024-01-16;
-  import wasi:http/outgoing-handler@0.2.0-rc-2024-01-16;
+  include wasi:cli/command@0.2.0;
+  import wasi:http/outgoing-handler@0.2.0;
 }
diff --git a/crates/wasi/wit/deps/cli/command.wit b/crates/wasi/wit/deps/cli/command.wit
index a9889164f..d8005bd38 100644
--- a/crates/wasi/wit/deps/cli/command.wit
+++ b/crates/wasi/wit/deps/cli/command.wit
@@ -1,4 +1,4 @@
-package wasi:cli@0.2.0-rc-2024-01-16;
+package wasi:cli@0.2.0;
 
 world command {
   include imports;
diff --git a/crates/wasi/wit/deps/cli/imports.wit b/crates/wasi/wit/deps/cli/imports.wit
index 8ce1abec3..083b84a03 100644
--- a/crates/wasi/wit/deps/cli/imports.wit
+++ b/crates/wasi/wit/deps/cli/imports.wit
@@ -1,11 +1,11 @@
-package wasi:cli@0.2.0-rc-2024-01-16;
+package wasi:cli@0.2.0;
 
 world imports {
-  include wasi:clocks/imports@0.2.0-rc-2023-11-10;
-  include wasi:filesystem/imports@0.2.0-rc-2023-11-10;
-  include wasi:sockets/imports@0.2.0-rc-2024-01-16;
-  include wasi:random/imports@0.2.0-rc-2023-11-10;
-  include wasi:io/imports@0.2.0-rc-2023-11-10;
+  include wasi:clocks/imports@0.2.0;
+  include wasi:filesystem/imports@0.2.0;
+  include wasi:sockets/imports@0.2.0;
+  include wasi:random/imports@0.2.0;
+  include wasi:io/imports@0.2.0;
 
   import environment;
   import exit;
diff --git a/crates/wasi/wit/deps/cli/stdio.wit b/crates/wasi/wit/deps/cli/stdio.wit
index 1b653b6e2..31ef35b5a 100644
--- a/crates/wasi/wit/deps/cli/stdio.wit
+++ b/crates/wasi/wit/deps/cli/stdio.wit
@@ -1,17 +1,17 @@
 interface stdin {
-  use wasi:io/streams@0.2.0-rc-2023-11-10.{input-stream};
+  use wasi:io/streams@0.2.0.{input-stream};
 
   get-stdin: func() -> input-stream;
 }
 
 interface stdout {
-  use wasi:io/streams@0.2.0-rc-2023-11-10.{output-stream};
+  use wasi:io/streams@0.2.0.{output-stream};
 
   get-stdout: func() -> output-stream;
 }
 
 interface stderr {
-  use wasi:io/streams@0.2.0-rc-2023-11-10.{output-stream};
+  use wasi:io/streams@0.2.0.{output-stream};
 
   get-stderr: func() -> output-stream;
 }
diff --git a/crates/wasi/wit/deps/clocks/monotonic-clock.wit b/crates/wasi/wit/deps/clocks/monotonic-clock.wit
index 09ef32c36..4e4dc3a19 100644
--- a/crates/wasi/wit/deps/clocks/monotonic-clock.wit
+++ b/crates/wasi/wit/deps/clocks/monotonic-clock.wit
@@ -1,4 +1,4 @@
-package wasi:clocks@0.2.0-rc-2023-11-10;
+package wasi:clocks@0.2.0;
 /// WASI Monotonic Clock is a clock API intended to let users measure elapsed
 /// time.
 ///
@@ -10,7 +10,7 @@ package wasi:clocks@0.2.0-rc-2023-11-10;
 ///
 /// It is intended for measuring elapsed time.
 interface monotonic-clock {
-    use wasi:io/poll@0.2.0-rc-2023-11-10.{pollable};
+    use wasi:io/poll@0.2.0.{pollable};
 
     /// An instant in time, in nanoseconds. An instant is relative to an
     /// unspecified initial value, and can only be compared to instances from
diff --git a/crates/wasi/wit/deps/clocks/wall-clock.wit b/crates/wasi/wit/deps/clocks/wall-clock.wit
index 8abb9a0c0..440ca0f33 100644
--- a/crates/wasi/wit/deps/clocks/wall-clock.wit
+++ b/crates/wasi/wit/deps/clocks/wall-clock.wit
@@ -1,4 +1,4 @@
-package wasi:clocks@0.2.0-rc-2023-11-10;
+package wasi:clocks@0.2.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.
diff --git a/crates/wasi/wit/deps/clocks/world.wit b/crates/wasi/wit/deps/clocks/world.wit
index 8fa080f0e..c0224572a 100644
--- a/crates/wasi/wit/deps/clocks/world.wit
+++ b/crates/wasi/wit/deps/clocks/world.wit
@@ -1,4 +1,4 @@
-package wasi:clocks@0.2.0-rc-2023-11-10;
+package wasi:clocks@0.2.0;
 
 world imports {
     import monotonic-clock;
diff --git a/crates/wasi/wit/deps/filesystem/preopens.wit b/crates/wasi/wit/deps/filesystem/preopens.wit
index 95ec67843..da801f6d6 100644
--- a/crates/wasi/wit/deps/filesystem/preopens.wit
+++ b/crates/wasi/wit/deps/filesystem/preopens.wit
@@ -1,4 +1,4 @@
-package wasi:filesystem@0.2.0-rc-2023-11-10;
+package wasi:filesystem@0.2.0;
 
 interface preopens {
     use types.{descriptor};
diff --git a/crates/wasi/wit/deps/filesystem/types.wit b/crates/wasi/wit/deps/filesystem/types.wit
index 059722ab8..11108fcda 100644
--- a/crates/wasi/wit/deps/filesystem/types.wit
+++ b/crates/wasi/wit/deps/filesystem/types.wit
@@ -1,4 +1,4 @@
-package wasi:filesystem@0.2.0-rc-2023-11-10;
+package wasi:filesystem@0.2.0;
 /// 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.
@@ -24,8 +24,8 @@ package wasi:filesystem@0.2.0-rc-2023-11-10;
 ///
 /// [WASI filesystem path resolution]: https://github.com/WebAssembly/wasi-filesystem/blob/main/path-resolution.md
 interface types {
-    use wasi:io/streams@0.2.0-rc-2023-11-10.{input-stream, output-stream, error};
-    use wasi:clocks/wall-clock@0.2.0-rc-2023-11-10.{datetime};
+    use wasi:io/streams@0.2.0.{input-stream, output-stream, error};
+    use wasi:clocks/wall-clock@0.2.0.{datetime};
 
     /// File size or length of a region within a file.
     type filesize = u64;
diff --git a/crates/wasi/wit/deps/filesystem/world.wit b/crates/wasi/wit/deps/filesystem/world.wit
index 285e0bae9..663f57920 100644
--- a/crates/wasi/wit/deps/filesystem/world.wit
+++ b/crates/wasi/wit/deps/filesystem/world.wit
@@ -1,4 +1,4 @@
-package wasi:filesystem@0.2.0-rc-2023-11-10;
+package wasi:filesystem@0.2.0;
 
 world imports {
     import types;
diff --git a/crates/wasi/wit/deps/http/proxy.wit b/crates/wasi/wit/deps/http/proxy.wit
index 2b0ce4b8a..687c24d23 100644
--- a/crates/wasi/wit/deps/http/proxy.wit
+++ b/crates/wasi/wit/deps/http/proxy.wit
@@ -1,4 +1,4 @@
-package wasi:http@0.2.0-rc-2024-01-16;
+package wasi:http@0.2.0;
 
 /// The `wasi:http/proxy` world captures a widely-implementable intersection of
 /// hosts that includes HTTP forward and reverse proxies. Components targeting
@@ -6,19 +6,19 @@ package wasi:http@0.2.0-rc-2024-01-16;
 /// outgoing HTTP requests.
 world proxy {
   /// HTTP proxies have access to time and randomness.
-  include wasi:clocks/imports@0.2.0-rc-2023-11-10;
-  import wasi:random/random@0.2.0-rc-2023-11-10;
+  include wasi:clocks/imports@0.2.0;
+  import wasi:random/random@0.2.0;
 
   /// Proxies have standard output and error streams which are expected to
   /// terminate in a developer-facing console provided by the host.
-  import wasi:cli/stdout@0.2.0-rc-2024-01-16;
-  import wasi:cli/stderr@0.2.0-rc-2024-01-16;
+  import wasi:cli/stdout@0.2.0;
+  import wasi:cli/stderr@0.2.0;
 
   /// TODO: this is a temporary workaround until component tooling is able to
   /// gracefully handle the absence of stdin. Hosts must return an eof stream
   /// for this import, which is what wasi-libc + tooling will do automatically
   /// when this import is properly removed.
-  import wasi:cli/stdin@0.2.0-rc-2024-01-16;
+  import wasi:cli/stdin@0.2.0;
 
   /// This is the default handler to use when user code simply wants to make an
   /// HTTP request (e.g., via `fetch()`).
diff --git a/crates/wasi/wit/deps/http/types.wit b/crates/wasi/wit/deps/http/types.wit
index 0f698e769..755ac6a6b 100644
--- a/crates/wasi/wit/deps/http/types.wit
+++ b/crates/wasi/wit/deps/http/types.wit
@@ -2,10 +2,10 @@
 /// HTTP Requests and Responses, both incoming and outgoing, as well as
 /// their headers, trailers, and bodies.
 interface types {
-  use wasi:clocks/monotonic-clock@0.2.0-rc-2023-11-10.{duration};
-  use wasi:io/streams@0.2.0-rc-2023-11-10.{input-stream, output-stream};
-  use wasi:io/error@0.2.0-rc-2023-11-10.{error as io-error};
-  use wasi:io/poll@0.2.0-rc-2023-11-10.{pollable};
+  use wasi:clocks/monotonic-clock@0.2.0.{duration};
+  use wasi:io/streams@0.2.0.{input-stream, output-stream};
+  use wasi:io/error@0.2.0.{error as io-error};
+  use wasi:io/poll@0.2.0.{pollable};
 
   /// This type corresponds to HTTP standard Methods.
   variant method {
diff --git a/crates/wasi/wit/deps/io/error.wit b/crates/wasi/wit/deps/io/error.wit
index 31918acbb..22e5b6489 100644
--- a/crates/wasi/wit/deps/io/error.wit
+++ b/crates/wasi/wit/deps/io/error.wit
@@ -1,4 +1,4 @@
-package wasi:io@0.2.0-rc-2023-11-10;
+package wasi:io@0.2.0;
 
 
 interface error {
diff --git a/crates/wasi/wit/deps/io/poll.wit b/crates/wasi/wit/deps/io/poll.wit
index bddde3c19..c982f1af7 100644
--- a/crates/wasi/wit/deps/io/poll.wit
+++ b/crates/wasi/wit/deps/io/poll.wit
@@ -1,4 +1,4 @@
-package wasi:io@0.2.0-rc-2023-11-10;
+package wasi:io@0.2.0;
 
 /// A poll API intended to let users wait for I/O events on multiple handles
 /// at once.
diff --git a/crates/wasi/wit/deps/io/streams.wit b/crates/wasi/wit/deps/io/streams.wit
index e7e1b689a..c797e37ff 100644
--- a/crates/wasi/wit/deps/io/streams.wit
+++ b/crates/wasi/wit/deps/io/streams.wit
@@ -1,4 +1,4 @@
-package wasi:io@0.2.0-rc-2023-11-10;
+package wasi:io@0.2.0;
 
 /// WASI I/O is an I/O abstraction API which is currently focused on providing
 /// stream types.
diff --git a/crates/wasi/wit/deps/io/world.wit b/crates/wasi/wit/deps/io/world.wit
index 8243da2ee..5f0b43fe5 100644
--- a/crates/wasi/wit/deps/io/world.wit
+++ b/crates/wasi/wit/deps/io/world.wit
@@ -1,4 +1,4 @@
-package wasi:io@0.2.0-rc-2023-11-10;
+package wasi:io@0.2.0;
 
 world imports {
     import streams;
diff --git a/crates/wasi/wit/deps/random/insecure-seed.wit b/crates/wasi/wit/deps/random/insecure-seed.wit
index f76e87dad..47210ac6b 100644
--- a/crates/wasi/wit/deps/random/insecure-seed.wit
+++ b/crates/wasi/wit/deps/random/insecure-seed.wit
@@ -1,4 +1,4 @@
-package wasi:random@0.2.0-rc-2023-11-10;
+package wasi:random@0.2.0;
 /// The insecure-seed interface for seeding hash-map DoS resistance.
 ///
 /// It is intended to be portable at least between Unix-family platforms and
diff --git a/crates/wasi/wit/deps/random/insecure.wit b/crates/wasi/wit/deps/random/insecure.wit
index ec7b99737..c58f4ee85 100644
--- a/crates/wasi/wit/deps/random/insecure.wit
+++ b/crates/wasi/wit/deps/random/insecure.wit
@@ -1,4 +1,4 @@
-package wasi:random@0.2.0-rc-2023-11-10;
+package wasi:random@0.2.0;
 /// The insecure interface for insecure pseudo-random numbers.
 ///
 /// It is intended to be portable at least between Unix-family platforms and
diff --git a/crates/wasi/wit/deps/random/random.wit b/crates/wasi/wit/deps/random/random.wit
index 7a7dfa27a..0c017f093 100644
--- a/crates/wasi/wit/deps/random/random.wit
+++ b/crates/wasi/wit/deps/random/random.wit
@@ -1,4 +1,4 @@
-package wasi:random@0.2.0-rc-2023-11-10;
+package wasi:random@0.2.0;
 /// WASI Random is a random data API.
 ///
 /// It is intended to be portable at least between Unix-family platforms and
diff --git a/crates/wasi/wit/deps/random/world.wit b/crates/wasi/wit/deps/random/world.wit
index 49e5743b4..3da34914a 100644
--- a/crates/wasi/wit/deps/random/world.wit
+++ b/crates/wasi/wit/deps/random/world.wit
@@ -1,4 +1,4 @@
-package wasi:random@0.2.0-rc-2023-11-10;
+package wasi:random@0.2.0;
 
 world imports {
     import random;
diff --git a/crates/wasi/wit/deps/sockets/ip-name-lookup.wit b/crates/wasi/wit/deps/sockets/ip-name-lookup.wit
index 931ccf7e0..8e639ec59 100644
--- a/crates/wasi/wit/deps/sockets/ip-name-lookup.wit
+++ b/crates/wasi/wit/deps/sockets/ip-name-lookup.wit
@@ -1,6 +1,6 @@
 
 interface ip-name-lookup {
-    use wasi:io/poll@0.2.0-rc-2023-11-10.{pollable};
+    use wasi:io/poll@0.2.0.{pollable};
     use network.{network, error-code, ip-address};
 
 
diff --git a/crates/wasi/wit/deps/sockets/tcp.wit b/crates/wasi/wit/deps/sockets/tcp.wit
index e045a436a..fbe023b64 100644
--- a/crates/wasi/wit/deps/sockets/tcp.wit
+++ b/crates/wasi/wit/deps/sockets/tcp.wit
@@ -1,8 +1,8 @@
 
 interface tcp {
-    use wasi:io/streams@0.2.0-rc-2023-11-10.{input-stream, output-stream};
-    use wasi:io/poll@0.2.0-rc-2023-11-10.{pollable};
-    use wasi:clocks/monotonic-clock@0.2.0-rc-2023-11-10.{duration};
+    use wasi:io/streams@0.2.0.{input-stream, output-stream};
+    use wasi:io/poll@0.2.0.{pollable};
+    use wasi:clocks/monotonic-clock@0.2.0.{duration};
     use network.{network, error-code, ip-socket-address, ip-address-family};
 
     enum shutdown-type {
diff --git a/crates/wasi/wit/deps/sockets/udp.wit b/crates/wasi/wit/deps/sockets/udp.wit
index ae82b97fc..b9826a6a5 100644
--- a/crates/wasi/wit/deps/sockets/udp.wit
+++ b/crates/wasi/wit/deps/sockets/udp.wit
@@ -1,6 +1,6 @@
 
 interface udp {
-    use wasi:io/poll@0.2.0-rc-2023-11-10.{pollable};
+    use wasi:io/poll@0.2.0.{pollable};
     use network.{network, error-code, ip-socket-address, ip-address-family};
 
     /// A received datagram.
diff --git a/crates/wasi/wit/deps/sockets/world.wit b/crates/wasi/wit/deps/sockets/world.wit
index 8588cc6c1..f8bb92ae0 100644
--- a/crates/wasi/wit/deps/sockets/world.wit
+++ b/crates/wasi/wit/deps/sockets/world.wit
@@ -1,4 +1,4 @@
-package wasi:sockets@0.2.0-rc-2024-01-16;
+package wasi:sockets@0.2.0;
 
 world imports {
     import instance-network;
diff --git a/crates/wasmtime/src/config.rs b/crates/wasmtime/src/config.rs
index 2295ff7fd..5a4f37149 100644
--- a/crates/wasmtime/src/config.rs
+++ b/crates/wasmtime/src/config.rs
@@ -228,6 +228,8 @@ impl Config {
         ret.wasm_multi_value(true);
         ret.wasm_bulk_memory(true);
         ret.wasm_simd(true);
+        #[cfg(feature = "component-model")]
+        ret.wasm_component_model(true);
         ret.wasm_backtrace_details(WasmBacktraceDetails::Environment);
 
         // This is on-by-default in `wasmparser` since it's a stage 4+ proposal
diff --git a/src/common.rs b/src/common.rs
index 70782c0b3..2850639d0 100644
--- a/src/common.rs
+++ b/src/common.rs
@@ -107,7 +107,7 @@ impl RunCommon {
 
     #[cfg(feature = "component-model")]
     fn ensure_allow_components(&self) -> Result<()> {
-        if self.common.wasm.component_model != Some(true) {
+        if self.common.wasm.component_model == Some(false) {
             bail!("cannot execute a component without `--wasm component-model`");
         }
 


Test patch:
diff --git a/crates/test-programs/src/bin/preview1_path_open_lots.rs b/crates/test-programs/src/bin/preview1_path_open_lots.rs
new file mode 100644
index 000000000..df163f95c
--- /dev/null
+++ b/crates/test-programs/src/bin/preview1_path_open_lots.rs
@@ -0,0 +1,107 @@
+use std::{env, process};
+use test_programs::preview1::{create_file, open_scratch_directory};
+
+unsafe fn test_path_open_lots(dir_fd: wasi::Fd) {
+    create_file(dir_fd, "file");
+
+    for _ in 0..2000 {
+        let f_readonly = wasi::path_open(dir_fd, 0, "file", 0, wasi::RIGHTS_FD_READ, 0, 0)
+            .expect("open file readonly");
+
+        let buffer = &mut [0u8; 100];
+        let iovec = wasi::Iovec {
+            buf: buffer.as_mut_ptr(),
+            buf_len: buffer.len(),
+        };
+        let nread = wasi::fd_read(f_readonly, &[iovec]).expect("reading readonly file");
+        assert_eq!(nread, 0, "readonly file is empty");
+
+        wasi::fd_close(f_readonly).expect("close readonly");
+    }
+
+    for _ in 0..2000 {
+        let f_readonly = wasi::path_open(dir_fd, 0, "file", 0, wasi::RIGHTS_FD_READ, 0, 0)
+            .expect("open file readonly");
+
+        let buffer = &mut [0u8; 100];
+        let iovec = wasi::Iovec {
+            buf: buffer.as_mut_ptr(),
+            buf_len: buffer.len(),
+        };
+        let nread = wasi::fd_pread(f_readonly, &[iovec], 0).expect("reading readonly file");
+        assert_eq!(nread, 0, "readonly file is empty");
+
+        wasi::fd_close(f_readonly).expect("close readonly");
+    }
+
+    for _ in 0..2000 {
+        let f = wasi::path_open(
+            dir_fd,
+            0,
+            "file",
+            0,
+            wasi::RIGHTS_FD_READ | wasi::RIGHTS_FD_WRITE,
+            0,
+            0,
+        )
+        .unwrap();
+
+        let buffer = &[0u8; 100];
+        let ciovec = wasi::Ciovec {
+            buf: buffer.as_ptr(),
+            buf_len: buffer.len(),
+        };
+        let nwritten = wasi::fd_write(f, &[ciovec]).expect("write failed");
+        assert_eq!(nwritten, 100);
+
+        wasi::fd_close(f).unwrap();
+    }
+
+    for _ in 0..2000 {
+        let f = wasi::path_open(
+            dir_fd,
+            0,
+            "file",
+            0,
+            wasi::RIGHTS_FD_READ | wasi::RIGHTS_FD_WRITE,
+            0,
+            0,
+        )
+        .unwrap();
+
+        let buffer = &[0u8; 100];
+        let ciovec = wasi::Ciovec {
+            buf: buffer.as_ptr(),
+            buf_len: buffer.len(),
+        };
+        let nwritten = wasi::fd_pwrite(f, &[ciovec], 0).expect("write failed");
+        assert_eq!(nwritten, 100);
+
+        wasi::fd_close(f).unwrap();
+    }
+
+    wasi::path_unlink_file(dir_fd, "file").expect("removing a file");
+}
+
+fn main() {
+    let mut args = env::args();
+    let prog = args.next().unwrap();
+    let arg = if let Some(arg) = args.next() {
+        arg
+    } else {
+        eprintln!("usage: {} <scratch directory>", prog);
+        process::exit(1);
+    };
+
+    // Open scratch directory
+    let dir_fd = match open_scratch_directory(&arg) {
+        Ok(dir_fd) => dir_fd,
+        Err(err) => {
+            eprintln!("{}", err);
+            process::exit(1)
+        }
+    };
+
+    // Run the tests.
+    unsafe { test_path_open_lots(dir_fd) }
+}
diff --git a/crates/wasi-common/tests/all/async_.rs b/crates/wasi-common/tests/all/async_.rs
index c7fd0df5e..4622da8fa 100644
--- a/crates/wasi-common/tests/all/async_.rs
+++ b/crates/wasi-common/tests/all/async_.rs
@@ -283,3 +283,7 @@ async fn preview1_unicode_output() {
 async fn preview1_file_write() {
     run(PREVIEW1_FILE_WRITE, true).await.unwrap()
 }
+#[test_log::test(tokio::test(flavor = "multi_thread"))]
+async fn preview1_path_open_lots() {
+    run(PREVIEW1_PATH_OPEN_LOTS, true).await.unwrap()
+}
diff --git a/crates/wasi-common/tests/all/sync.rs b/crates/wasi-common/tests/all/sync.rs
index caa6cd21b..ce4d37c11 100644
--- a/crates/wasi-common/tests/all/sync.rs
+++ b/crates/wasi-common/tests/all/sync.rs
@@ -269,3 +269,7 @@ fn preview1_unicode_output() {
 fn preview1_file_write() {
     run(PREVIEW1_FILE_WRITE, true).unwrap()
 }
+#[test_log::test]
+fn preview1_path_open_lots() {
+    run(PREVIEW1_PATH_OPEN_LOTS, true).unwrap()
+}
diff --git a/crates/wasi-http/wit/test.wit b/crates/wasi-http/wit/test.wit
index 15294b4aa..f59039103 100644
--- a/crates/wasi-http/wit/test.wit
+++ b/crates/wasi-http/wit/test.wit
@@ -2,21 +2,21 @@ package wasmtime:wasi;
 
 // only used as part of `test-programs`
 world test-reactor {
-  include wasi:cli/imports@0.2.0-rc-2024-01-16;
+  include wasi:cli/imports@0.2.0;
 
   export add-strings: func(s: list<string>) -> u32;
   export get-strings: func() -> list<string>;
 
-  use wasi:io/streams@0.2.0-rc-2023-11-10.{output-stream};
+  use wasi:io/streams@0.2.0.{output-stream};
 
   export write-strings-to: func(o: output-stream) -> result;
 
-  use wasi:filesystem/types@0.2.0-rc-2023-11-10.{descriptor-stat};
+  use wasi:filesystem/types@0.2.0.{descriptor-stat};
   export pass-an-imported-record: func(d: descriptor-stat) -> string;
 }
 
 world test-command {
-  include wasi:cli/imports@0.2.0-rc-2024-01-16;
-  import wasi:http/types@0.2.0-rc-2024-01-16;
-  import wasi:http/outgoing-handler@0.2.0-rc-2024-01-16;
+  include wasi:cli/imports@0.2.0;
+  import wasi:http/types@0.2.0;
+  import wasi:http/outgoing-handler@0.2.0;
 }
diff --git a/crates/wasi/tests/all/async_.rs b/crates/wasi/tests/all/async_.rs
index f47997e0e..1aaabe0d5 100644
--- a/crates/wasi/tests/all/async_.rs
+++ b/crates/wasi/tests/all/async_.rs
@@ -281,6 +281,10 @@ async fn preview1_unicode_output() {
 async fn preview1_file_write() {
     run(PREVIEW1_FILE_WRITE_COMPONENT, false).await.unwrap()
 }
+#[test_log::test(tokio::test(flavor = "multi_thread"))]
+async fn preview1_path_open_lots() {
+    run(PREVIEW1_PATH_OPEN_LOTS_COMPONENT, false).await.unwrap()
+}
 
 #[test_log::test(tokio::test(flavor = "multi_thread"))]
 async fn preview2_sleep() {
diff --git a/crates/wasi/tests/all/preview1.rs b/crates/wasi/tests/all/preview1.rs
index 7acde9dd4..dcfcb0041 100644
--- a/crates/wasi/tests/all/preview1.rs
+++ b/crates/wasi/tests/all/preview1.rs
@@ -237,3 +237,7 @@ async fn preview1_unicode_output() {
 async fn preview1_file_write() {
     run(PREVIEW1_FILE_WRITE, true).await.unwrap()
 }
+#[test_log::test(tokio::test(flavor = "multi_thread"))]
+async fn preview1_path_open_lots() {
+    run(PREVIEW1_PATH_OPEN_LOTS, true).await.unwrap()
+}
diff --git a/crates/wasi/tests/all/sync.rs b/crates/wasi/tests/all/sync.rs
index ce0c2e161..c12454643 100644
--- a/crates/wasi/tests/all/sync.rs
+++ b/crates/wasi/tests/all/sync.rs
@@ -228,6 +228,10 @@ fn preview1_unicode_output() {
 fn preview1_file_write() {
     run(PREVIEW1_FILE_WRITE_COMPONENT, false).unwrap()
 }
+#[test_log::test]
+fn preview1_path_open_lots() {
+    run(PREVIEW1_PATH_OPEN_LOTS_COMPONENT, false).unwrap()
+}
 
 #[test_log::test]
 fn preview2_sleep() {
diff --git a/crates/wasi/wit/test.wit b/crates/wasi/wit/test.wit
index 15294b4aa..f59039103 100644
--- a/crates/wasi/wit/test.wit
+++ b/crates/wasi/wit/test.wit
@@ -2,21 +2,21 @@ package wasmtime:wasi;
 
 // only used as part of `test-programs`
 world test-reactor {
-  include wasi:cli/imports@0.2.0-rc-2024-01-16;
+  include wasi:cli/imports@0.2.0;
 
   export add-strings: func(s: list<string>) -> u32;
   export get-strings: func() -> list<string>;
 
-  use wasi:io/streams@0.2.0-rc-2023-11-10.{output-stream};
+  use wasi:io/streams@0.2.0.{output-stream};
 
   export write-strings-to: func(o: output-stream) -> result;
 
-  use wasi:filesystem/types@0.2.0-rc-2023-11-10.{descriptor-stat};
+  use wasi:filesystem/types@0.2.0.{descriptor-stat};
   export pass-an-imported-record: func(d: descriptor-stat) -> string;
 }
 
 world test-command {
-  include wasi:cli/imports@0.2.0-rc-2024-01-16;
-  import wasi:http/types@0.2.0-rc-2024-01-16;
-  import wasi:http/outgoing-handler@0.2.0-rc-2024-01-16;
+  include wasi:cli/imports@0.2.0;
+  import wasi:http/types@0.2.0;
+  import wasi:http/outgoing-handler@0.2.0;
 }
diff --git a/tests/all/cli_tests.rs b/tests/all/cli_tests.rs
index 8a7d08027..a6f40d49d 100644
--- a/tests/all/cli_tests.rs
+++ b/tests/all/cli_tests.rs
@@ -760,6 +760,7 @@ fn component_missing_feature() -> Result<()> {
     let wasm = build_wasm(path)?;
     let output = get_wasmtime_command()?
         .arg("-Ccache=n")
+        .arg("-Wcomponent-model=n")
         .arg(wasm.path())
         .output()?;
     assert!(!output.status.success());
@@ -772,6 +773,7 @@ fn component_missing_feature() -> Result<()> {
     // also tests with raw *.wat input
     let output = get_wasmtime_command()?
         .arg("-Ccache=n")
+        .arg("-Wcomponent-model=n")
         .arg(path)
         .output()?;
     assert!(!output.status.success());
@@ -784,6 +786,27 @@ fn component_missing_feature() -> Result<()> {
     Ok(())
 }
 
+#[test]
+#[cfg_attr(not(feature = "component-model"), ignore)]
+fn component_enabled_by_default() -> Result<()> {
+    let path = "tests/all/cli_tests/component-basic.wat";
+    let wasm = build_wasm(path)?;
+    let output = get_wasmtime_command()?
+        .arg("-Ccache=n")
+        .arg(wasm.path())
+        .output()?;
+    assert!(output.status.success());
+
+    // also tests with raw *.wat input
+    let output = get_wasmtime_command()?
+        .arg("-Ccache=n")
+        .arg(path)
+        .output()?;
+    assert!(output.status.success());
+
+    Ok(())
+}
+
 // If the text format is invalid then the filename should be mentioned in the
 // error message.
 #[test]
diff --git a/tests/all/cli_tests/component-basic.wat b/tests/all/cli_tests/component-basic.wat
index 99600f1f0..057ee944a 100644
--- a/tests/all/cli_tests/component-basic.wat
+++ b/tests/all/cli_tests/component-basic.wat
@@ -7,6 +7,6 @@
   (func $run (result (result))
     (canon lift (core func $i "run")))
 
-  (instance (export (interface "wasi:cli/run@0.2.0-rc-2024-01-16"))
+  (instance (export (interface "wasi:cli/run@0.2.0"))
     (export "run" (func $run)))
 )