extension: Update to wasm32-wasip2 target (#30953)

Ben Brandt created

Cleans things up now that wasm32-wasip2 is a supported target.

Before we merge, I will need to test against the current extensions to
make sure this is fine.

However, since our wit world isn't using any wasi package imports, this
shouldn't be a breaking change.

Release Notes:

- N/A

Change summary

Cargo.lock                                | 44 ----------------
Cargo.toml                                |  2 
crates/extension/Cargo.toml               |  2 
crates/extension/src/extension_builder.rs | 65 ++++++++++--------------
crates/extension_api/README.md            |  4 +
rust-toolchain.toml                       |  2 
tooling/workspace-hack/Cargo.toml         |  2 
7 files changed, 32 insertions(+), 89 deletions(-)

Detailed changes

Cargo.lock 🔗

@@ -5120,10 +5120,8 @@ dependencies = [
  "task",
  "toml 0.8.20",
  "util",
- "wasi-preview1-component-adapter-provider",
  "wasm-encoder 0.221.3",
  "wasmparser 0.221.3",
- "wit-component 0.221.3",
  "workspace-hack",
 ]
 
@@ -17397,12 +17395,6 @@ dependencies = [
  "wit-bindgen-rt 0.39.0",
 ]
 
-[[package]]
-name = "wasi-preview1-component-adapter-provider"
-version = "29.0.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dcd9f21bbde82ba59e415a8725e6ad0d0d7e9e460b1a3ccbca5bdee952c1a324"
-
 [[package]]
 name = "wasite"
 version = "0.1.0"
@@ -17525,22 +17517,6 @@ dependencies = [
  "wasmparser 0.201.0",
 ]
 
-[[package]]
-name = "wasm-metadata"
-version = "0.221.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "11f4ef50d17e103a88774cd4aa5d06bfb1ae44036a8f3f1325e0e9b3e3417ac4"
-dependencies = [
- "anyhow",
- "indexmap",
- "serde",
- "serde_derive",
- "serde_json",
- "spdx",
- "wasm-encoder 0.221.3",
- "wasmparser 0.221.3",
-]
-
 [[package]]
 name = "wasm-metadata"
 version = "0.227.1"
@@ -19037,25 +19013,6 @@ dependencies = [
  "wit-parser 0.201.0",
 ]
 
-[[package]]
-name = "wit-component"
-version = "0.221.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "66c55ca8772d2b270e28066caed50ce4e53a28c3ac10e01efbd90e5be31e448b"
-dependencies = [
- "anyhow",
- "bitflags 2.9.0",
- "indexmap",
- "log",
- "serde",
- "serde_derive",
- "serde_json",
- "wasm-encoder 0.221.3",
- "wasm-metadata 0.221.3",
- "wasmparser 0.221.3",
- "wit-parser 0.221.3",
-]
-
 [[package]]
 name = "wit-component"
 version = "0.227.1"
@@ -19362,7 +19319,6 @@ dependencies = [
  "unicode-properties",
  "url",
  "uuid",
- "wasm-encoder 0.221.3",
  "wasmparser 0.221.3",
  "wasmtime",
  "wasmtime-cranelift",

Cargo.toml 🔗

@@ -603,7 +603,6 @@ url = "2.2"
 urlencoding = "2.1.2"
 uuid = { version = "1.1.2", features = ["v4", "v5", "v7", "serde"] }
 walkdir = "2.5"
-wasi-preview1-component-adapter-provider = "29"
 wasm-encoder = "0.221"
 wasmparser = "0.221"
 wasmtime = { version = "29", default-features = false, features = [
@@ -617,7 +616,6 @@ wasmtime = { version = "29", default-features = false, features = [
 ] }
 wasmtime-wasi = "29"
 which = "6.0.0"
-wit-component = "0.221"
 workspace-hack = "0.1.0"
 zed_llm_client = "0.8.3"
 zstd = "0.11"

crates/extension/Cargo.toml 🔗

@@ -33,8 +33,6 @@ serde_json.workspace = true
 task.workspace = true
 toml.workspace = true
 util.workspace = true
-wasi-preview1-component-adapter-provider.workspace = true
 wasm-encoder.workspace = true
 wasmparser.workspace = true
-wit-component.workspace = true
 workspace-hack.workspace = true

crates/extension/src/extension_builder.rs 🔗

@@ -14,18 +14,11 @@ use std::{
     process::Stdio,
     sync::Arc,
 };
-use wasi_preview1_component_adapter_provider::WASI_SNAPSHOT_PREVIEW1_REACTOR_ADAPTER;
 use wasm_encoder::{ComponentSectionId, Encode as _, RawSection, Section as _};
 use wasmparser::Parser;
-use wit_component::ComponentEncoder;
 
-/// Currently, we compile with Rust's `wasm32-wasip1` target, which works with WASI `preview1`.
-/// But the WASM component model is based on WASI `preview2`. So we need an 'adapter' WASM
-/// module, which implements the `preview1` interface in terms of `preview2`.
-///
-/// Once Rust 1.78 is released, there will be a `wasm32-wasip2` target available, so we will
-/// not need the adapter anymore.
-const RUST_TARGET: &str = "wasm32-wasip1";
+/// Currently, we compile with Rust's `wasm32-wasip2` target, which works with WASI `preview2` and the component model.
+const RUST_TARGET: &str = "wasm32-wasip2";
 
 /// Compiling Tree-sitter parsers from C to WASM requires Clang 17, and a WASM build of libc
 /// and clang's runtime library. The `wasi-sdk` provides these binaries.
@@ -174,31 +167,18 @@ impl ExtensionBuilder {
             &cargo_toml
                 .package
                 .name
-                // The wasm32-wasip1 target normalizes `-` in package names to `_` in the resulting `.wasm` file.
+                // The wasm32-wasip2 target normalizes `-` in package names to `_` in the resulting `.wasm` file.
                 .replace('-', "_"),
         ]);
         wasm_path.set_extension("wasm");
 
-        let wasm_bytes = fs::read(&wasm_path)
-            .with_context(|| format!("failed to read output module `{}`", wasm_path.display()))?;
-
-        let mut encoder = ComponentEncoder::default()
-            .module(&wasm_bytes)?
-            .adapter(
-                "wasi_snapshot_preview1",
-                WASI_SNAPSHOT_PREVIEW1_REACTOR_ADAPTER,
-            )
-            .context("failed to load adapter module")?
-            .validate(true);
-
         log::info!(
             "encoding wasm component for extension {}",
             extension_dir.display()
         );
 
-        let component_bytes = encoder
-            .encode()
-            .context("failed to encode wasm component")?;
+        let component_bytes = fs::read(&wasm_path)
+            .with_context(|| format!("failed to read output module `{}`", wasm_path.display()))?;
 
         let component_bytes = self
             .strip_custom_sections(&component_bytes)
@@ -439,26 +419,34 @@ impl ExtensionBuilder {
     }
 
     // This was adapted from:
-    // https://github.com/bytecodealliance/wasm-tools/blob/1791a8f139722e9f8679a2bd3d8e423e55132b22/src/bin/wasm-tools/strip.rs
+    // https://github.com/bytecodealliance/wasm-tools/blob/e8809bb17fcf69aa8c85cd5e6db7cff5cf36b1de/src/bin/wasm-tools/strip.rs
     fn strip_custom_sections(&self, input: &Vec<u8>) -> Result<Vec<u8>> {
         use wasmparser::Payload::*;
 
-        let strip_custom_section = |name: &str| name.starts_with(".debug");
+        let strip_custom_section = |name: &str| {
+            // Default strip everything but:
+            // * the `name` section
+            // * any `component-type` sections
+            // * the `dylink.0` section
+            // * our custom version section
+            name != "name"
+                && !name.starts_with("component-type:")
+                && name != "dylink.0"
+                && name != "zed:api-version"
+        };
 
         let mut output = Vec::new();
         let mut stack = Vec::new();
 
-        for payload in Parser::new(0).parse_all(input) {
+        for payload in Parser::new(0).parse_all(&input) {
             let payload = payload?;
-            let component_header = wasm_encoder::Component::HEADER;
-            let module_header = wasm_encoder::Module::HEADER;
 
             // Track nesting depth, so that we don't mess with inner producer sections:
             match payload {
                 Version { encoding, .. } => {
                     output.extend_from_slice(match encoding {
-                        wasmparser::Encoding::Component => &component_header,
-                        wasmparser::Encoding::Module => &module_header,
+                        wasmparser::Encoding::Component => &wasm_encoder::Component::HEADER,
+                        wasmparser::Encoding::Module => &wasm_encoder::Module::HEADER,
                     });
                 }
                 ModuleSection { .. } | ComponentSection { .. } => {
@@ -470,7 +458,7 @@ impl ExtensionBuilder {
                         Some(c) => c,
                         None => break,
                     };
-                    if output.starts_with(&component_header) {
+                    if output.starts_with(&wasm_encoder::Component::HEADER) {
                         parent.push(ComponentSectionId::Component as u8);
                         output.encode(&mut parent);
                     } else {
@@ -482,12 +470,15 @@ impl ExtensionBuilder {
                 _ => {}
             }
 
-            if let CustomSection(c) = &payload {
-                if strip_custom_section(c.name()) {
-                    continue;
+            match &payload {
+                CustomSection(c) => {
+                    if strip_custom_section(c.name()) {
+                        continue;
+                    }
                 }
-            }
 
+                _ => {}
+            }
             if let Some((id, range)) = payload.as_section() {
                 RawSection {
                     id,

crates/extension_api/README.md 🔗

@@ -23,7 +23,7 @@ need to set your `crate-type` accordingly:
 
 ```toml
 [dependencies]
-zed_extension_api = "0.5.0"
+zed_extension_api = "0.6.0"
 
 [lib]
 crate-type = ["cdylib"]
@@ -51,6 +51,8 @@ zed::register_extension!(MyExtension);
 
 To run your extension in Zed as you're developing it:
 
+- Make sure you have [Rust installed](https://www.rust-lang.org/learn/get-started)
+- Have the `wasm32-wasip2` target installed (`rustup target add wasm32-wasip2`)
 - Open the extensions view using the `zed: extensions` action in the command palette.
 - Click the `Install Dev Extension` button in the top right
 - Choose the path to your extension directory.

rust-toolchain.toml 🔗

@@ -7,6 +7,6 @@ targets = [
     "aarch64-apple-darwin",
     "x86_64-unknown-linux-gnu",
     "x86_64-pc-windows-msvc",
-    "wasm32-wasip1", # extensions
+    "wasm32-wasip2", # extensions
     "x86_64-unknown-linux-musl", # remote server
 ]

tooling/workspace-hack/Cargo.toml 🔗

@@ -134,7 +134,6 @@ unicode-normalization = { version = "0.1" }
 unicode-properties = { version = "0.1" }
 url = { version = "2", features = ["serde"] }
 uuid = { version = "1", features = ["serde", "v4", "v5", "v7"] }
-wasm-encoder = { version = "0.221", features = ["wasmparser"] }
 wasmparser = { version = "0.221" }
 wasmtime = { version = "29", default-features = false, features = ["async", "component-model", "cranelift", "demangle", "gc-drc", "incremental-cache", "parallel-compilation"] }
 wasmtime-cranelift = { version = "29", default-features = false, features = ["component-model", "gc-drc", "incremental-cache"] }
@@ -273,7 +272,6 @@ unicode-normalization = { version = "0.1" }
 unicode-properties = { version = "0.1" }
 url = { version = "2", features = ["serde"] }
 uuid = { version = "1", features = ["serde", "v4", "v5", "v7"] }
-wasm-encoder = { version = "0.221", features = ["wasmparser"] }
 wasmparser = { version = "0.221" }
 wasmtime = { version = "29", default-features = false, features = ["async", "component-model", "cranelift", "demangle", "gc-drc", "incremental-cache", "parallel-compilation"] }
 wasmtime-cranelift = { version = "29", default-features = false, features = ["component-model", "gc-drc", "incremental-cache"] }