Repository: bytecodealliance/wasmtime
Pull request #7407 (2023-10-30 18:22:30)

Update wasm-tools crates
This commit updates the wasm-tools family of crate for a number of notable updates:

* bytecodealliance/wasm-tools#1257 - wasmparser's ID-based infrastructure has been refactored to have more precise types for each ID rather than one all-purpose `TypeId`.
* bytecodealliance/wasm-tools#1262 - the implementation of "implementation imports" for the component model which both updates the binary format in addition to adding more syntactic forms of imports.
* bytecodealliance/wasm-tools#1260 - a new encoding scheme for component information for `wit-component` in objects (not used by Wasmtime but used by bindings generators).

Translation for components needed to be updated to account for the first change, but otherwise this was a straightforward update.

<!--
Please make sure you include the following information:

- If this work has been discussed elsewhere, please include a link to that
  conversation. If it was discussed in an issue, just mention "issue #...".

- Explain why this change is needed. If the details are in an issue already,
  this can be brief.

Our development process is documented in the Wasmtime book:
https://docs.wasmtime.dev/contributing-development-process.html

Please ensure all communication follows the code of conduct:
https://github.com/bytecodealliance/wasmtime/blob/main/CODE_OF_CONDUCT.md
-->



Patch:
diff --git a/.github/actions/github-release/main.js b/.github/actions/github-release/main.js
index d61b24ed5..bcf4f75b4 100644
--- a/.github/actions/github-release/main.js
+++ b/.github/actions/github-release/main.js
@@ -91,13 +91,25 @@ async function runOnce() {
   } catch (e) {
     console.log("ERROR: ", JSON.stringify(e, null, 2));
     core.info(`creating a release`);
+
+    const releaseNotes = fs.readFileSync('RELEASES.md').toString();
+    let notes = null;
+    const opts = {
+      owner,
+      repo,
+      tag_name: name,
+      prerelease: name === 'dev',
+    };
+    if (name !== 'dev') {
+      for (let x of releaseNotes.split(/^---+$/m)) {
+        if (x.indexOf(name.substring(1)) == -1)
+          continue;
+        opts.body = x;
+        break;
+      }
+    }
     try {
-      release = await octokit.rest.repos.createRelease({
-        owner,
-        repo,
-        tag_name: name,
-        prerelease: name === 'dev',
-      });
+      release = await octokit.rest.repos.createRelease(opts);
     } catch(e) {
       console.log("ERROR: ", JSON.stringify(e, null, 2));
       core.info(`fetching one more time`);
diff --git a/Cargo.lock b/Cargo.lock
index e8403c460..983eb0681 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -3101,18 +3101,18 @@ checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1"
 
 [[package]]
 name = "wasm-encoder"
-version = "0.35.0"
+version = "0.36.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9ca90ba1b5b0a70d3d49473c5579951f3bddc78d47b59256d2f9d4922b150aca"
+checksum = "53ae0be20bf87918df4fa831bfbbd0b491d24aee407ed86360eae4c2c5608d38"
 dependencies = [
  "leb128",
 ]
 
 [[package]]
 name = "wasm-metadata"
-version = "0.10.9"
+version = "0.10.10"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "14abc161bfda5b519aa229758b68f2a52b45a12b993808665c857d1a9a00223c"
+checksum = "5621910462c61a8efc3248fdfb1739bf649bb335b0df935c27b340418105f9d8"
 dependencies = [
  "anyhow",
  "indexmap 2.0.0",
@@ -3126,9 +3126,9 @@ dependencies = [
 
 [[package]]
 name = "wasm-mutate"
-version = "0.2.38"
+version = "0.2.39"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7b1e04b0c049b0a0c42dd108a56c5c92500076747363d3bf1e83e7f0f8b4dfe4"
+checksum = "b39266e421acd09370e738fc042a5224d0014036ed919e68f1dd9a98a9b28f5a"
 dependencies = [
  "egg",
  "log",
@@ -3140,9 +3140,9 @@ dependencies = [
 
 [[package]]
 name = "wasm-smith"
-version = "0.12.21"
+version = "0.12.22"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fef779c243bbf04d9f03333c2cb50b98047c6dcc2a1db0cc7d0691e4135064b4"
+checksum = "39217efc459328aa5a29a5bbf792e76f1ae7ebeedbf8878f8320b6a0a6544b06"
 dependencies = [
  "arbitrary",
  "flagset",
@@ -3192,9 +3192,9 @@ dependencies = [
 
 [[package]]
 name = "wasmparser"
-version = "0.115.0"
+version = "0.116.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e06c0641a4add879ba71ccb3a1e4278fd546f76f1eafb21d8f7b07733b547cd5"
+checksum = "53290b1276c5c2d47d694fb1a920538c01f51690e7e261acbe1d10c5fc306ea1"
 dependencies = [
  "indexmap 2.0.0",
  "semver",
@@ -3211,9 +3211,9 @@ dependencies = [
 
 [[package]]
 name = "wasmprinter"
-version = "0.2.70"
+version = "0.2.71"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e74458a9bc5cc9c7108abfa0fe4dc88d5abf1f3baf194df3264985f17d559b5e"
+checksum = "8f98260aa20f939518bcec1fac32c78898d5c68872e7363a4651f21f791b6c7e"
 dependencies = [
  "anyhow",
  "wasmparser",
@@ -3388,7 +3388,7 @@ dependencies = [
  "wasmtime-wasi-nn",
  "wasmtime-wasi-threads",
  "wasmtime-wast",
- "wast 66.0.2",
+ "wast 67.0.0",
  "wat",
  "windows-sys",
 ]
@@ -3774,7 +3774,7 @@ dependencies = [
  "anyhow",
  "log",
  "wasmtime",
- "wast 66.0.2",
+ "wast 67.0.0",
 ]
 
 [[package]]
@@ -3817,9 +3817,9 @@ dependencies = [
 
 [[package]]
 name = "wast"
-version = "66.0.2"
+version = "67.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "93cb43b0ac6dd156f2c375735ccfd72b012a7c0a6e6d09503499b8d3cb6e6072"
+checksum = "36c2933efd77ff2398b83817a98984ffe4b67aefd9aa1d2c8e68e19b553f1c38"
 dependencies = [
  "leb128",
  "memchr",
@@ -3829,11 +3829,11 @@ dependencies = [
 
 [[package]]
 name = "wat"
-version = "1.0.77"
+version = "1.0.78"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e367582095d2903caeeea9acbb140e1db9c7677001efa4347c3687fd34fe7072"
+checksum = "c02905d13751dcb18f4e19f489d37a1bf139f519feaeef28d072a41a78e69a74"
 dependencies = [
- "wast 66.0.2",
+ "wast 67.0.0",
 ]
 
 [[package]]
@@ -4089,9 +4089,9 @@ dependencies = [
 
 [[package]]
 name = "wit-bindgen"
-version = "0.13.0"
+version = "0.13.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c7d92ce0ca6b6074059413a9581a637550c3a740581c854f9847ec293c8aed71"
+checksum = "38726c54a5d7c03cac28a2a8de1006cfe40397ddf6def3f836189033a413bc08"
 dependencies = [
  "bitflags 2.4.1",
  "wit-bindgen-rust-macro",
@@ -4099,9 +4099,9 @@ dependencies = [
 
 [[package]]
 name = "wit-bindgen-core"
-version = "0.13.0"
+version = "0.13.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "565b945ae074886071eccf9cdaf8ccd7b959c2b0d624095bea5fe62003e8b3e0"
+checksum = "c8bf1fddccaff31a1ad57432d8bfb7027a7e552969b6c68d6d8820dcf5c2371f"
 dependencies = [
  "anyhow",
  "wit-component",
@@ -4110,9 +4110,9 @@ dependencies = [
 
 [[package]]
 name = "wit-bindgen-rust"
-version = "0.13.0"
+version = "0.13.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5695ff4e41873ed9ce56d2787e6b5772bdad9e70e2c1d2d160621d1762257f4f"
+checksum = "0e7200e565124801e01b7b5ddafc559e1da1b2e1bed5364d669cd1d96fb88722"
 dependencies = [
  "anyhow",
  "heck",
@@ -4123,9 +4123,9 @@ dependencies = [
 
 [[package]]
 name = "wit-bindgen-rust-macro"
-version = "0.13.0"
+version = "0.13.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a91835ea4231da1fe7971679d505ba14be7826e192b6357f08465866ef482e08"
+checksum = "4ae33920ad8119fe72cf59eb00f127c0b256a236b9de029a1a10397b1f38bdbd"
 dependencies = [
  "anyhow",
  "proc-macro2",
@@ -4138,9 +4138,9 @@ dependencies = [
 
 [[package]]
 name = "wit-component"
-version = "0.16.0"
+version = "0.17.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e87488b57a08e2cbbd076b325acbe7f8666965af174d69d5929cd373bd54547f"
+checksum = "480cc1a078b305c1b8510f7c455c76cbd008ee49935f3a6c5fd5e937d8d95b1e"
 dependencies = [
  "anyhow",
  "bitflags 2.4.1",
@@ -4157,9 +4157,9 @@ dependencies = [
 
 [[package]]
 name = "wit-parser"
-version = "0.12.1"
+version = "0.12.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f6ace9943d89bbf3dbbc71b966da0e7302057b311f36a4ac3d65ddfef17b52cf"
+checksum = "43771ee863a16ec4ecf9da0fc65c3bbd4a1235c8e3da5f094b562894843dfa76"
 dependencies = [
  "anyhow",
  "id-arena",
diff --git a/Cargo.toml b/Cargo.toml
index 167a46a65..ee34a6039 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -209,18 +209,18 @@ io-extras = "0.18.0"
 rustix = "0.38.8"
 is-terminal = "0.4.0"
 # wit-bindgen:
-wit-bindgen = { version = "0.13.0", default-features = false }
+wit-bindgen = { version = "0.13.1", default-features = false }
 
 # wasm-tools family:
-wasmparser = "0.115.0"
-wat = "1.0.77"
-wast = "66.0.2"
-wasmprinter = "0.2.70"
-wasm-encoder = "0.35.0"
-wasm-smith = "0.12.21"
-wasm-mutate = "0.2.38"
-wit-parser = "0.12.1"
-wit-component = "0.16.0"
+wasmparser = "0.116.0"
+wat = "1.0.78"
+wast = "67.0.0"
+wasmprinter = "0.2.71"
+wasm-encoder = "0.36.1"
+wasm-smith = "0.12.22"
+wasm-mutate = "0.2.39"
+wit-parser = "0.12.2"
+wit-component = "0.17.0"
 
 # Non-Bytecode Alliance maintained dependencies:
 # --------------------------
diff --git a/crates/environ/examples/factc.rs b/crates/environ/examples/factc.rs
index 6dfb7136e..0416b1613 100644
--- a/crates/environ/examples/factc.rs
+++ b/crates/environ/examples/factc.rs
@@ -129,13 +129,11 @@ impl Factc {
             .context("failed to validate input wasm")?;
         let wasm_types = wasm_types.as_ref();
         for i in 0..wasm_types.component_type_count() {
-            let ty = wasm_types.component_type_at(i);
-            let ty = match &wasm_types[ty] {
-                wasmparser::types::Type::ComponentFunc(_) => {
-                    types.convert_component_func_type(wasm_types, ty)?
-                }
+            let ty = match wasm_types.component_any_type_at(i) {
+                wasmparser::types::ComponentAnyTypeId::Func(id) => id,
                 _ => continue,
             };
+            let ty = types.convert_component_func_type(wasm_types, ty)?;
             adapters.push(Adapter {
                 lift_ty: ty,
                 lower_ty: ty,
diff --git a/crates/environ/src/component/translate.rs b/crates/environ/src/component/translate.rs
index 77e75ed45..df404bd5a 100644
--- a/crates/environ/src/component/translate.rs
+++ b/crates/environ/src/component/translate.rs
@@ -8,8 +8,10 @@ use anyhow::{bail, Result};
 use indexmap::IndexMap;
 use std::collections::HashMap;
 use std::mem;
-use wasmparser::types::{ComponentEntityType, TypeId, Types};
-use wasmparser::{Chunk, ComponentExternName, Encoding, Parser, Payload, Validator};
+use wasmparser::types::{
+    AliasableResourceId, ComponentEntityType, ComponentFuncTypeId, ComponentInstanceTypeId, Types,
+};
+use wasmparser::{Chunk, ComponentImportName, Encoding, Parser, Payload, Validator};
 
 mod adapt;
 pub use self::adapt::*;
@@ -165,22 +167,22 @@ struct Translation<'data> {
 #[allow(missing_docs)]
 enum LocalInitializer<'data> {
     // imports
-    Import(ComponentExternName<'data>, ComponentEntityType),
+    Import(ComponentImportName<'data>, ComponentEntityType),
 
     // canonical function sections
     Lower {
         func: ComponentFuncIndex,
-        lower_ty: TypeId,
+        lower_ty: ComponentFuncTypeId,
         canonical_abi: SignatureIndex,
         options: LocalCanonicalOptions,
     },
-    Lift(TypeId, FuncIndex, LocalCanonicalOptions),
+    Lift(ComponentFuncTypeId, FuncIndex, LocalCanonicalOptions),
 
     // resources
-    Resource(TypeId, WasmType, Option<FuncIndex>),
-    ResourceNew(TypeId, SignatureIndex),
-    ResourceRep(TypeId, SignatureIndex),
-    ResourceDrop(TypeId, SignatureIndex),
+    Resource(AliasableResourceId, WasmType, Option<FuncIndex>),
+    ResourceNew(AliasableResourceId, SignatureIndex),
+    ResourceRep(AliasableResourceId, SignatureIndex),
+    ResourceDrop(AliasableResourceId, SignatureIndex),
 
     // core wasm modules
     ModuleStatic(StaticModuleIndex),
@@ -193,7 +195,11 @@ enum LocalInitializer<'data> {
     ComponentStatic(StaticComponentIndex, ClosedOverVars),
 
     // component instances
-    ComponentInstantiate(ComponentIndex, HashMap<&'data str, ComponentItem>, TypeId),
+    ComponentInstantiate(
+        ComponentIndex,
+        HashMap<&'data str, ComponentItem>,
+        ComponentInstanceTypeId,
+    ),
     ComponentSynthetic(HashMap<&'data str, ComponentItem>),
 
     // alias section
@@ -414,7 +420,9 @@ impl<'a, 'data> Translator<'a, 'data> {
                     match ty? {
                         wasmparser::ComponentType::Resource { rep, dtor } => {
                             let rep = self.types.convert_valtype(rep);
-                            let id = types.component_type_at(component_type_index);
+                            let id = types
+                                .component_any_type_at(component_type_index)
+                                .unwrap_resource();
                             let dtor = dtor.map(FuncIndex::from_u32);
                             self.result
                                 .initializers
@@ -444,7 +452,7 @@ impl<'a, 'data> Translator<'a, 'data> {
                     let import = import?;
                     let types = self.validator.types(0).unwrap();
                     let ty = types
-                        .component_entity_type_of_import(import.name.as_str())
+                        .component_entity_type_of_import(import.name.0)
                         .unwrap();
                     self.result
                         .initializers
@@ -465,7 +473,7 @@ impl<'a, 'data> Translator<'a, 'data> {
                             core_func_index,
                             options,
                         } => {
-                            let ty = types.component_type_at(type_index);
+                            let ty = types.component_any_type_at(type_index).unwrap_func();
                             let func = FuncIndex::from_u32(core_func_index);
                             let options = self.canonical_options(&options);
                             LocalInitializer::Lift(ty, func, options)
@@ -488,19 +496,19 @@ impl<'a, 'data> Translator<'a, 'data> {
                             }
                         }
                         wasmparser::CanonicalFunction::ResourceNew { resource } => {
-                            let resource = types.component_type_at(resource);
+                            let resource = types.component_any_type_at(resource).unwrap_resource();
                             let ty = self.core_func_signature(core_func_index);
                             core_func_index += 1;
                             LocalInitializer::ResourceNew(resource, ty)
                         }
                         wasmparser::CanonicalFunction::ResourceDrop { resource } => {
-                            let resource = types.component_type_at(resource);
+                            let resource = types.component_any_type_at(resource).unwrap_resource();
                             let ty = self.core_func_signature(core_func_index);
                             core_func_index += 1;
                             LocalInitializer::ResourceDrop(resource, ty)
                         }
                         wasmparser::CanonicalFunction::ResourceRep { resource } => {
-                            let resource = types.component_type_at(resource);
+                            let resource = types.component_any_type_at(resource).unwrap_resource();
                             let ty = self.core_func_signature(core_func_index);
                             core_func_index += 1;
                             LocalInitializer::ResourceRep(resource, ty)
@@ -602,7 +610,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.as_str(), item);
+                    let prev = self.result.exports.insert(export.name.0, item);
                     assert!(prev.is_none());
                     self.result
                         .initializers
@@ -722,7 +730,7 @@ impl<'a, 'data> Translator<'a, 'data> {
         &mut self,
         component: ComponentIndex,
         raw_args: &[wasmparser::ComponentInstantiationArg<'data>],
-        ty: TypeId,
+        ty: ComponentInstanceTypeId,
     ) -> Result<LocalInitializer<'data>> {
         let mut args = HashMap::with_capacity(raw_args.len());
         for arg in raw_args {
@@ -742,7 +750,7 @@ impl<'a, 'data> Translator<'a, 'data> {
         let mut map = HashMap::with_capacity(exports.len());
         for export in exports {
             let idx = self.kind_to_item(export.kind, export.index)?;
-            map.insert(export.name.as_str(), idx);
+            map.insert(export.name.0, idx);
         }
 
         Ok(LocalInitializer::ComponentSynthetic(map))
@@ -775,7 +783,7 @@ impl<'a, 'data> Translator<'a, 'data> {
             }
             wasmparser::ComponentExternalKind::Type => {
                 let types = self.validator.types(0).unwrap();
-                let ty = types.component_type_at(index);
+                let ty = types.component_any_type_at(index);
                 ComponentItem::Type(ty)
             }
         })
@@ -883,7 +891,7 @@ impl<'a, 'data> Translator<'a, 'data> {
 
     fn core_func_signature(&mut self, idx: u32) -> SignatureIndex {
         let types = self.validator.types(0).unwrap();
-        let id = types.function_at(idx);
+        let id = types.core_function_at(idx);
         let ty = types[id].unwrap_func();
         let ty = self.types.convert_func_type(ty);
         self.types.module_types_builder().wasm_func_type(ty)
diff --git a/crates/environ/src/component/translate/inline.rs b/crates/environ/src/component/translate/inline.rs
index dc75a404c..629eee693 100644
--- a/crates/environ/src/component/translate/inline.rs
+++ b/crates/environ/src/component/translate/inline.rs
@@ -50,6 +50,7 @@ use crate::component::translate::*;
 use crate::{EntityType, PrimaryMap};
 use indexmap::IndexMap;
 use std::borrow::Cow;
+use wasmparser::types::{ComponentAnyTypeId, ComponentEntityType, ComponentInstanceTypeId};
 
 pub(super) fn run(
     types: &mut ComponentTypesBuilder,
@@ -114,12 +115,9 @@ pub(super) fn run(
         if let TypeDef::Interface(_) = ty {
             continue;
         }
-        let index = inliner
-            .result
-            .import_types
-            .push((name.as_str().to_string(), ty));
+        let index = inliner.result.import_types.push((name.0.to_string(), ty));
         let path = ImportPath::root(index);
-        args.insert(name.as_str(), ComponentItemDef::from_import(path, ty)?);
+        args.insert(name.0, ComponentItemDef::from_import(path, ty)?);
     }
 
     // This will run the inliner to completion after being seeded with the
@@ -220,7 +218,7 @@ struct InlinerFrame<'a> {
     /// register resource types after instantiation has completed.
     ///
     /// This is `Some` for all subcomponents and `None` for the root component.
-    instance_ty: Option<TypeId>,
+    instance_ty: Option<ComponentInstanceTypeId>,
 }
 
 /// "Closure state" for a component which is resolved from the `ClosedOverVars`
@@ -431,7 +429,7 @@ impl<'a> Inliner<'a> {
             // was provided as an import at the instantiation-site to what was
             // needed during the component's instantiation.
             Import(name, ty) => {
-                let arg = match frame.args.get(name.as_str()) {
+                let arg = match frame.args.get(name.0) {
                     Some(arg) => arg,
 
                     // Not all arguments need to be provided for instantiation,
@@ -447,12 +445,11 @@ impl<'a> Inliner<'a> {
                     // skipped.
                     None => {
                         match ty {
-                            ComponentEntityType::Type { created, .. } => {
-                                match frame.translation.types_ref()[*created] {
-                                    wasmparser::types::Type::Resource(_) => unreachable!(),
-                                    _ => {}
-                                }
-                            }
+                            ComponentEntityType::Type {
+                                created: ComponentAnyTypeId::Resource(_),
+                                ..
+                            } => unreachable!(),
+                            ComponentEntityType::Type { .. } => {}
                             _ => unreachable!(),
                         }
                         return Ok(None);
@@ -643,16 +640,14 @@ impl<'a> Inliner<'a> {
                 // intended, though, since `ty` can't be referred to outside of
                 // this component.
                 let idx = self.result.resource_index(idx);
-                types
-                    .resources_mut()
-                    .register_resource(frame.translation.types_ref(), *ty, idx);
+                types.resources_mut().register_resource(ty.resource(), idx);
             }
 
             // Resource-related intrinsics are generally all the same.
             // Wasmparser type information is converted to wasmtime type
             // information and then new entries for each intrinsic are recorded.
             ResourceNew(id, ty) => {
-                let id = types.resource_id(frame.translation.types_ref(), *id);
+                let id = types.resource_id(id.resource());
                 let index = self
                     .result
                     .trampolines
@@ -660,7 +655,7 @@ impl<'a> Inliner<'a> {
                 frame.funcs.push(dfg::CoreDef::Trampoline(index));
             }
             ResourceRep(id, ty) => {
-                let id = types.resource_id(frame.translation.types_ref(), *id);
+                let id = types.resource_id(id.resource());
                 let index = self
                     .result
                     .trampolines
@@ -668,7 +663,7 @@ impl<'a> Inliner<'a> {
                 frame.funcs.push(dfg::CoreDef::Trampoline(index));
             }
             ResourceDrop(id, ty) => {
-                let id = types.resource_id(frame.translation.types_ref(), *id);
+                let id = types.resource_id(id.resource());
                 let index = self
                     .result
                     .trampolines
@@ -1105,7 +1100,7 @@ impl<'a> InlinerFrame<'a> {
         translation: &'a Translation<'a>,
         closure: ComponentClosure<'a>,
         args: HashMap<&'a str, ComponentItemDef<'a>>,
-        instance_ty: Option<TypeId>,
+        instance_ty: Option<ComponentInstanceTypeId>,
     ) -> Self {
         // FIXME: should iterate over the initializers of `translation` and
         // calculate the size of each index space to use `with_capacity` for
@@ -1229,7 +1224,7 @@ impl<'a> InlinerFrame<'a> {
     fn finish_instantiate(
         &mut self,
         def: ComponentInstanceDef<'a>,
-        ty: TypeId,
+        ty: ComponentInstanceTypeId,
         types: &mut ComponentTypesBuilder,
     ) {
         let (resources, types) = types.resources_mut_and_types();
@@ -1237,7 +1232,7 @@ impl<'a> InlinerFrame<'a> {
         let arg = ComponentItemDef::Instance(def);
         resources.register_component_entity_type(
             &self.translation.types_ref(),
-            wasmparser::types::ComponentEntityType::Instance(ty),
+            ComponentEntityType::Instance(ty),
             &mut path,
             &mut |path| arg.lookup_resource(path, types),
         );
diff --git a/crates/environ/src/component/types.rs b/crates/environ/src/component/types.rs
index db751bc2e..ecf38d4b1 100644
--- a/crates/environ/src/component/types.rs
+++ b/crates/environ/src/component/types.rs
@@ -230,7 +230,7 @@ pub enum ComponentItem {
     Module(ModuleIndex),
     Component(ComponentIndex),
     ComponentInstance(ComponentInstanceIndex),
-    Type(wasmparser::types::TypeId),
+    Type(types::ComponentAnyTypeId),
 }
 
 /// Runtime information about the type information contained within a component.
@@ -440,9 +440,9 @@ impl ComponentTypesBuilder {
     pub fn convert_component_func_type(
         &mut self,
         types: types::TypesRef<'_>,
-        id: types::TypeId,
+        id: types::ComponentFuncTypeId,
     ) -> Result<TypeFuncIndex> {
-        let ty = types[id].unwrap_component_func();
+        let ty = &types[id];
         let params = ty
             .params
             .iter()
@@ -480,9 +480,13 @@ impl ComponentTypesBuilder {
             types::ComponentEntityType::Func(id) => {
                 TypeDef::ComponentFunc(self.convert_component_func_type(types, id)?)
             }
-            types::ComponentEntityType::Type { created, .. } => match types[created] {
-                types::Type::Defined(_) => TypeDef::Interface(self.defined_type(types, created)?),
-                types::Type::Resource(_) => TypeDef::Resource(self.resource_id(types, created)),
+            types::ComponentEntityType::Type { created, .. } => match created {
+                types::ComponentAnyTypeId::Defined(id) => {
+                    TypeDef::Interface(self.defined_type(types, id)?)
+                }
+                types::ComponentAnyTypeId::Resource(id) => {
+                    TypeDef::Resource(self.resource_id(id.resource()))
+                }
                 _ => bail!("unsupported type export"),
             },
             types::ComponentEntityType::Value(_) => bail!("values not supported"),
@@ -493,31 +497,33 @@ impl ComponentTypesBuilder {
     pub fn convert_type(
         &mut self,
         types: types::TypesRef<'_>,
-        id: types::TypeId,
+        id: types::ComponentAnyTypeId,
     ) -> Result<TypeDef> {
-        Ok(match &types[id] {
-            types::Type::Defined(_) => TypeDef::Interface(self.defined_type(types, id)?),
-            types::Type::Module(_) => TypeDef::Module(self.convert_module(types, id)?),
-            types::Type::Component(_) => TypeDef::Component(self.convert_component(types, id)?),
-            types::Type::ComponentInstance(_) => {
+        Ok(match id {
+            types::ComponentAnyTypeId::Defined(id) => {
+                TypeDef::Interface(self.defined_type(types, id)?)
+            }
+            types::ComponentAnyTypeId::Component(id) => {
+                TypeDef::Component(self.convert_component(types, id)?)
+            }
+            types::ComponentAnyTypeId::Instance(id) => {
                 TypeDef::ComponentInstance(self.convert_instance(types, id)?)
             }
-            types::Type::ComponentFunc(_) => {
+            types::ComponentAnyTypeId::Func(id) => {
                 TypeDef::ComponentFunc(self.convert_component_func_type(types, id)?)
             }
-            types::Type::Instance(_) | types::Type::Sub(_) => {
-                unreachable!()
+            types::ComponentAnyTypeId::Resource(id) => {
+                TypeDef::Resource(self.resource_id(id.resource()))
             }
-            types::Type::Resource(_) => TypeDef::Resource(self.resource_id(types, id)),
         })
     }
 
     fn convert_component(
         &mut self,
         types: types::TypesRef<'_>,
-        id: types::TypeId,
+        id: types::ComponentTypeId,
     ) -> Result<TypeComponentIndex> {
-        let ty = types[id].unwrap_component();
+        let ty = &types[id];
         let mut result = TypeComponent::default();
         for (name, ty) in ty.imports.iter() {
             result.imports.insert(
@@ -537,9 +543,9 @@ impl ComponentTypesBuilder {
     fn convert_instance(
         &mut self,
         types: types::TypesRef<'_>,
-        id: types::TypeId,
+        id: types::ComponentInstanceTypeId,
     ) -> Result<TypeComponentInstanceIndex> {
-        let ty = types[id].unwrap_component_instance();
+        let ty = &types[id];
         let mut result = TypeComponentInstance::default();
         for (name, ty) in ty.exports.iter() {
             result.exports.insert(
@@ -553,9 +559,9 @@ impl ComponentTypesBuilder {
     fn convert_module(
         &mut self,
         types: types::TypesRef<'_>,
-        id: types::TypeId,
+        id: types::ComponentCoreModuleTypeId,
     ) -> Result<TypeModuleIndex> {
-        let ty = &types[id].unwrap_module();
+        let ty = &types[id];
         let mut result = TypeModule::default();
         for ((module, field), ty) in ty.imports.iter() {
             result.imports.insert(
@@ -592,9 +598,9 @@ impl ComponentTypesBuilder {
     fn defined_type(
         &mut self,
         types: types::TypesRef<'_>,
-        id: types::TypeId,
+        id: types::ComponentDefinedTypeId,
     ) -> Result<InterfaceType> {
-        let ret = match types[id].unwrap_defined() {
+        let ret = match &types[id] {
             types::ComponentDefinedType::Primitive(ty) => ty.into(),
             types::ComponentDefinedType::Record(e) => {
                 InterfaceType::Record(self.record_type(types, e)?)
@@ -614,9 +620,11 @@ impl ComponentTypesBuilder {
             types::ComponentDefinedType::Result { ok, err } => {
                 InterfaceType::Result(self.result_type(types, ok, err)?)
             }
-            types::ComponentDefinedType::Own(r) => InterfaceType::Own(self.resource_id(types, *r)),
+            types::ComponentDefinedType::Own(r) => {
+                InterfaceType::Own(self.resource_id(r.resource()))
+            }
             types::ComponentDefinedType::Borrow(r) => {
-                InterfaceType::Borrow(self.resource_id(types, *r))
+                InterfaceType::Borrow(self.resource_id(r.resource()))
             }
         };
         let info = self.type_information(&ret);
@@ -768,12 +776,7 @@ impl ComponentTypesBuilder {
 
     /// Converts a wasmparser `id`, which must point to a resource, to its
     /// corresponding `TypeResourceTableIndex`.
-    pub fn resource_id(
-        &mut self,
-        types: types::TypesRef<'_>,
-        id: types::TypeId,
-    ) -> TypeResourceTableIndex {
-        let id = types[id].unwrap_resource();
+    pub fn resource_id(&mut self, id: types::ResourceId) -> TypeResourceTableIndex {
         self.resources.convert(id, &mut self.component_types)
     }
 
diff --git a/crates/environ/src/component/types/resources.rs b/crates/environ/src/component/types/resources.rs
index 22a99d62f..21d42b20e 100644
--- a/crates/environ/src/component/types/resources.rs
+++ b/crates/environ/src/component/types/resources.rs
@@ -186,13 +186,12 @@ impl ResourcesBuilder {
             // with the current path and that's inserted in to
             // `resource_id_to_resource_index` if the resource hasn't been seen
             // yet.
-            types::ComponentEntityType::Type { created, .. } => {
-                let id = match types[created] {
-                    types::Type::Resource(id) => id,
-                    _ => return,
-                };
+            types::ComponentEntityType::Type {
+                created: types::ComponentAnyTypeId::Resource(id),
+                ..
+            } => {
                 self.resource_id_to_resource_index
-                    .entry(id)
+                    .entry(id.resource())
                     .or_insert_with(|| register(path));
             }
 
@@ -200,7 +199,7 @@ impl ResourcesBuilder {
             // all instance exports are walked here. Note the management of
             // `path` which is used for the recursive invocation of this method.
             types::ComponentEntityType::Instance(id) => {
-                let ty = types[id].unwrap_component_instance();
+                let ty = &types[id];
                 for (name, ty) in ty.exports.iter() {
                     path.push(name);
                     self.register_component_entity_type(types, *ty, path, register);
@@ -211,6 +210,7 @@ impl ResourcesBuilder {
             // None of these items can introduce a new component type, so
             // there's no need to recurse over these.
             types::ComponentEntityType::Func(_)
+            | types::ComponentEntityType::Type { .. }
             | types::ComponentEntityType::Module(_)
             | types::ComponentEntityType::Component(_)
             | types::ComponentEntityType::Value(_) => {}
@@ -221,13 +221,7 @@ impl ResourcesBuilder {
     /// defined by the `ty` provided.
     ///
     /// This is used when a local resource is defined within a component for example.
-    pub fn register_resource(
-        &mut self,
-        types: types::TypesRef<'_>,
-        id: types::TypeId,
-        ty: ResourceIndex,
-    ) {
-        let id = types[id].unwrap_resource();
+    pub fn register_resource(&mut self, id: types::ResourceId, ty: ResourceIndex) {
         let prev = self.resource_id_to_resource_index.insert(id, ty);
         assert!(prev.is_none());
     }
diff --git a/crates/types/src/lib.rs b/crates/types/src/lib.rs
index 125be22ce..2719e6df9 100644
--- a/crates/types/src/lib.rs
+++ b/crates/types/src/lib.rs
@@ -483,7 +483,7 @@ pub trait TypeConvert {
         match ty {
             wasmparser::HeapType::Func => WasmHeapType::Func,
             wasmparser::HeapType::Extern => WasmHeapType::Extern,
-            wasmparser::HeapType::Indexed(i) => self.lookup_heap_type(TypeIndex::from_u32(i)),
+            wasmparser::HeapType::Concrete(i) => self.lookup_heap_type(TypeIndex::from_u32(i)),
 
             wasmparser::HeapType::Any
             | wasmparser::HeapType::None
diff --git a/crates/wasi-http/src/http_impl.rs b/crates/wasi-http/src/http_impl.rs
index d9e25a4ce..f77575c9c 100644
--- a/crates/wasi-http/src/http_impl.rs
+++ b/crates/wasi-http/src/http_impl.rs
@@ -65,15 +65,22 @@ impl<T: WasiHttpView> outgoing_handler::Host for T {
             }
         };
 
-        let authority = if req.authority.find(':').is_some() {
-            req.authority.clone()
+        let authority = if let Some(authority) = req.authority {
+            if authority.find(':').is_some() {
+                authority
+            } else {
+                format!("{}:{port}", authority)
+            }
         } else {
-            format!("{}:{port}", req.authority)
+            String::new()
         };
 
         let mut builder = hyper::Request::builder()
             .method(method)
-            .uri(format!("{scheme}{authority}{}", req.path_with_query))
+            .uri(format!(
+                "{scheme}{authority}{}",
+                req.path_with_query.as_ref().map_or("", String::as_ref)
+            ))
             .header(hyper::header::HOST, &authority);
 
         for (k, v) in req.headers.iter() {
diff --git a/crates/wasi-http/src/types.rs b/crates/wasi-http/src/types.rs
index 76530811c..50119b989 100644
--- a/crates/wasi-http/src/types.rs
+++ b/crates/wasi-http/src/types.rs
@@ -193,6 +193,51 @@ fn invalid_url(e: std::io::Error) -> anyhow::Error {
     ))
 }
 
+impl From<http::Method> for types::Method {
+    fn from(method: http::Method) -> Self {
+        if method == http::Method::GET {
+            types::Method::Get
+        } else if method == hyper::Method::HEAD {
+            types::Method::Head
+        } else if method == hyper::Method::POST {
+            types::Method::Post
+        } else if method == hyper::Method::PUT {
+            types::Method::Put
+        } else if method == hyper::Method::DELETE {
+            types::Method::Delete
+        } else if method == hyper::Method::CONNECT {
+            types::Method::Connect
+        } else if method == hyper::Method::OPTIONS {
+            types::Method::Options
+        } else if method == hyper::Method::TRACE {
+            types::Method::Trace
+        } else if method == hyper::Method::PATCH {
+            types::Method::Patch
+        } else {
+            types::Method::Other(method.to_string())
+        }
+    }
+}
+
+impl TryInto<http::Method> for types::Method {
+    type Error = http::method::InvalidMethod;
+
+    fn try_into(self) -> Result<http::Method, Self::Error> {
+        match self {
+            Method::Get => Ok(http::Method::GET),
+            Method::Head => Ok(http::Method::HEAD),
+            Method::Post => Ok(http::Method::POST),
+            Method::Put => Ok(http::Method::PUT),
+            Method::Delete => Ok(http::Method::DELETE),
+            Method::Connect => Ok(http::Method::CONNECT),
+            Method::Options => Ok(http::Method::OPTIONS),
+            Method::Trace => Ok(http::Method::TRACE),
+            Method::Patch => Ok(http::Method::PATCH),
+            Method::Other(s) => http::Method::from_bytes(s.as_bytes()),
+        }
+    }
+}
+
 pub struct HostIncomingRequest {
     pub parts: http::request::Parts,
     pub body: Option<HostIncomingBodyBuilder>,
@@ -206,8 +251,8 @@ pub struct HostResponseOutparam {
 pub struct HostOutgoingRequest {
     pub method: Method,
     pub scheme: Option<Scheme>,
-    pub path_with_query: String,
-    pub authority: String,
+    pub path_with_query: Option<String>,
+    pub authority: Option<String>,
     pub headers: FieldMap,
     pub body: Option<HyperOutgoingBody>,
 }
diff --git a/crates/wasi-http/src/types_impl.rs b/crates/wasi-http/src/types_impl.rs
index dbaa54969..d1c8eabb6 100644
--- a/crates/wasi-http/src/types_impl.rs
+++ b/crates/wasi-http/src/types_impl.rs
@@ -1,4 +1,4 @@
-use crate::bindings::http::types::{Error, Headers, Method, Scheme, StatusCode, Trailers};
+use crate::bindings::http::types::{self, Error, Headers, Method, Scheme, StatusCode, Trailers};
 use crate::body::{FinishMessage, HostFutureTrailers, HostFutureTrailersState};
 use crate::types::{HostIncomingRequest, HostOutgoingResponse};
 use crate::WasiHttpView;
@@ -19,6 +19,19 @@ use wasmtime_wasi::preview2::{
 
 impl<T: WasiHttpView> crate::bindings::http::types::Host for T {}
 
+/// Take ownership of the underlying [`FieldMap`] associated with this fields resource. If the
+/// fields resource references another fields, the returned [`FieldMap`] will be cloned.
+fn move_fields(table: &mut Table, id: Resource<HostFields>) -> wasmtime::Result<FieldMap> {
+    match table.delete(id)? {
+        HostFields::Ref { parent, get_fields } => {
+            let entry = table.get_any_mut(parent)?;
+            Ok(get_fields(entry).clone())
+        }
+
+        HostFields::Owned { fields } => Ok(fields),
+    }
+}
+
 fn get_fields_mut<'a>(
     table: &'a mut Table,
     id: &Resource<HostFields>,
@@ -145,29 +158,8 @@ impl<T: WasiHttpView> crate::bindings::http::types::HostFields for T {
 
 impl<T: WasiHttpView> crate::bindings::http::types::HostIncomingRequest for T {
     fn method(&mut self, id: Resource<HostIncomingRequest>) -> wasmtime::Result<Method> {
-        let method = self.table().get(&id)?.parts.method.as_ref();
-
-        if method == hyper::Method::GET {
-            Ok(Method::Get)
-        } else if method == hyper::Method::HEAD {
-            Ok(Method::Head)
-        } else if method == hyper::Method::POST {
-            Ok(Method::Post)
-        } else if method == hyper::Method::PUT {
-            Ok(Method::Put)
-        } else if method == hyper::Method::DELETE {
-            Ok(Method::Delete)
-        } else if method == hyper::Method::CONNECT {
-            Ok(Method::Connect)
-        } else if method == hyper::Method::OPTIONS {
-            Ok(Method::Options)
-        } else if method == hyper::Method::TRACE {
-            Ok(Method::Trace)
-        } else if method == hyper::Method::PATCH {
-            Ok(Method::Patch)
-        } else {
-            Ok(Method::Other(method.to_owned()))
-        }
+        let method = self.table().get(&id)?.parts.method.clone();
+        Ok(method.into())
     }
     fn path_with_query(
         &mut self,
@@ -258,11 +250,12 @@ impl<T: WasiHttpView> crate::bindings::http::types::HostOutgoingRequest for T {
         authority: Option<String>,
         headers: Resource<Headers>,
     ) -> wasmtime::Result<Resource<HostOutgoingRequest>> {
-        let headers = get_fields_mut(self.table(), &headers)?.clone();
+        let headers = move_fields(self.table(), headers)?;
+
         self.table()
             .push(HostOutgoingRequest {
-                path_with_query: path_with_query.unwrap_or("".to_string()),
-                authority: authority.unwrap_or("".to_string()),
+                path_with_query,
+                authority,
                 method,
                 headers,
                 scheme,
@@ -271,7 +264,7 @@ impl<T: WasiHttpView> crate::bindings::http::types::HostOutgoingRequest for T {
             .context("[new_outgoing_request] pushing request")
     }
 
-    fn write(
+    fn body(
         &mut self,
         request: Resource<HostOutgoingRequest>,
     ) -> wasmtime::Result<Result<Resource<HostOutgoingBody>, ()>> {
@@ -299,6 +292,97 @@ impl<T: WasiHttpView> crate::bindings::http::types::HostOutgoingRequest for T {
         let _ = self.table().delete(request)?;
         Ok(())
     }
+
+    fn method(
+        &mut self,
+        request: wasmtime::component::Resource<types::OutgoingRequest>,
+    ) -> wasmtime::Result<Method> {
+        Ok(self.table().get(&request)?.method.clone().try_into()?)
+    }
+
+    fn set_method(
+        &mut self,
+        request: wasmtime::component::Resource<types::OutgoingRequest>,
+        method: Method,
+    ) -> wasmtime::Result<()> {
+        self.table().get_mut(&request)?.method = method.into();
+        Ok(())
+    }
+
+    fn path_with_query(
+        &mut self,
+        request: wasmtime::component::Resource<types::OutgoingRequest>,
+    ) -> wasmtime::Result<Option<String>> {
+        Ok(self.table().get(&request)?.path_with_query.clone())
+    }
+
+    fn set_path_with_query(
+        &mut self,
+        request: wasmtime::component::Resource<types::OutgoingRequest>,
+        path_with_query: Option<String>,
+    ) -> wasmtime::Result<()> {
+        self.table().get_mut(&request)?.path_with_query = path_with_query;
+        Ok(())
+    }
+
+    fn scheme(
+        &mut self,
+        request: wasmtime::component::Resource<types::OutgoingRequest>,
+    ) -> wasmtime::Result<Option<Scheme>> {
+        Ok(self.table().get(&request)?.scheme.clone())
+    }
+
+    fn set_scheme(
+        &mut self,
+        request: wasmtime::component::Resource<types::OutgoingRequest>,
+        scheme: Option<Scheme>,
+    ) -> wasmtime::Result<()> {
+        self.table().get_mut(&request)?.scheme = scheme;
+        Ok(())
+    }
+
+    fn authority(
+        &mut self,
+        request: wasmtime::component::Resource<types::OutgoingRequest>,
+    ) -> wasmtime::Result<Option<String>> {
+        Ok(self.table().get(&request)?.authority.clone())
+    }
+
+    fn set_authority(
+        &mut self,
+        request: wasmtime::component::Resource<types::OutgoingRequest>,
+        authority: Option<String>,
+    ) -> wasmtime::Result<()> {
+        self.table().get_mut(&request)?.authority = authority;
+        Ok(())
+    }
+
+    fn headers(
+        &mut self,
+        request: wasmtime::component::Resource<types::OutgoingRequest>,
+    ) -> wasmtime::Result<wasmtime::component::Resource<Headers>> {
+        let _ = self
+            .table()
+            .get(&request)
+            .context("[outgoing_request_headers] getting request")?;
+
+        fn get_fields(elem: &mut dyn Any) -> &mut FieldMap {
+            &mut elem
+                .downcast_mut::<types::OutgoingRequest>()
+                .unwrap()
+                .headers
+        }
+
+        let id = self.table().push_child(
+            HostFields::Ref {
+                parent: request.rep(),
+                get_fields,
+            },
+            &request,
+        )?;
+
+        Ok(id)
+    }
 }
 
 impl<T: WasiHttpView> crate::bindings::http::types::HostResponseOutparam for T {
@@ -470,7 +554,7 @@ impl<T: WasiHttpView> crate::bindings::http::types::HostOutgoingResponse for T {
         status: StatusCode,
         headers: Resource<Headers>,
     ) -> wasmtime::Result<Resource<HostOutgoingResponse>> {
-        let fields = get_fields_mut(self.table(), &headers)?.clone();
+        let fields = move_fields(self.table(), headers)?;
 
         let id = self.table().push(HostOutgoingResponse {
             status,
@@ -481,7 +565,7 @@ impl<T: WasiHttpView> crate::bindings::http::types::HostOutgoingResponse for T {
         Ok(id)
     }
 
-    fn write(
+    fn body(
         &mut self,
         id: Resource<HostOutgoingResponse>,
     ) -> wasmtime::Result<Result<Resource<HostOutgoingBody>, ()>> {
@@ -500,6 +584,43 @@ impl<T: WasiHttpView> crate::bindings::http::types::HostOutgoingResponse for T {
         Ok(Ok(id))
     }
 
+    fn status_code(
+        &mut self,
+        id: Resource<HostOutgoingResponse>,
+    ) -> wasmtime::Result<types::StatusCode> {
+        Ok(self.table().get(&id)?.status)
+    }
+
+    fn set_status_code(
+        &mut self,
+        id: Resource<HostOutgoingResponse>,
+        status: types::StatusCode,
+    ) -> wasmtime::Result<()> {
+        self.table().get_mut(&id)?.status = status;
+        Ok(())
+    }
+
+    fn headers(
+        &mut self,
+        id: Resource<HostOutgoingResponse>,
+    ) -> wasmtime::Result<Resource<types::Headers>> {
+        // Trap if the outgoing-response doesn't exist.
+        let _ = self.table().get(&id)?;
+
+        fn get_fields(elem: &mut dyn Any) -> &mut FieldMap {
+            let resp = elem.downcast_mut::<HostOutgoingResponse>().unwrap();
+            &mut resp.headers
+        }
+
+        Ok(self.table().push_child(
+            HostFields::Ref {
+                parent: id.rep(),
+                get_fields,
+            },
+            &id,
+        )?)
+    }
+
     fn drop(&mut self, id: Resource<HostOutgoingResponse>) -> wasmtime::Result<()> {
         let _ = self.table().delete(id)?;
         Ok(())
diff --git a/crates/wasi-http/wit/deps/http/types.wit b/crates/wasi-http/wit/deps/http/types.wit
index 343d32220..9cace67ab 100644
--- a/crates/wasi-http/wit/deps/http/types.wit
+++ b/crates/wasi-http/wit/deps/http/types.wit
@@ -127,17 +127,73 @@ interface types {
   resource outgoing-request {
 
     /// Construct a new `outgoing-request`.
+    ///
+    /// * `method` represents the HTTP Method for the Request.
+    /// * `path-with-query` is the combination of the HTTP Path and Query for
+    ///    the Request. When `none`, this represents an empty Path and empty
+    ///    Query.
+    /// * `scheme` is the HTTP Related Scheme for the Request. When `none`,
+    ///    the implementation may choose an appropriate default scheme.
+    /// * `authority` is the HTTP Authority for the Request. A value of `none`
+    ///    may be used with Related Schemes which do not require an Authority.
+    ///    The HTTP and HTTPS schemes always require an authority.
+    /// * `headers` is the HTTP Headers for the Request.
+    ///
+    /// It is possible to construct, or manipulate with the accessor functions
+    /// below, an `outgoing-request` with an invalid combination of `scheme`
+    /// and `authority`, or `headers` which are not permitted to be sent.
+    /// It is the obligation of the `outgoing-handler.handle` implementation
+    /// to reject invalid constructions of `outgoing-request`.
     constructor(
       method: method,
       path-with-query: option<string>,
       scheme: option<scheme>,
       authority: option<string>,
-      headers: borrow<headers>
+      headers: headers
     );
 
-    /// Will return the outgoing-body child at most once. If called more than
-    /// once, subsequent calls will return error.
-    write: func() -> result<outgoing-body>;
+    /// Returns the resource corresponding to the outgoing Body for this
+    /// Request.
+    ///
+    /// Returns success on the first call: the `outgoing-body` resource for
+    /// this `outgoing-response` can be retrieved at most once. Subsequent
+    /// calls will return error.
+    body: func() -> result<outgoing-body>;
+
+    /// Get the Method for the Request.
+    method: func() -> method;
+    /// Set the Method for the Request.
+    set-method: func(method: method);
+
+    /// Get the combination of the HTTP Path and Query for the Request.
+    /// When `none`, this represents an empty Path and empty Query.
+    path-with-query: func() -> option<string>;
+    /// Set the combination of the HTTP Path and Query for the Request.
+    /// When `none`, this represents an empty Path and empty Query.
+    set-path-with-query: func(path-with-query: option<string>);
+
+    /// Get the HTTP Related Scheme for the Request. When `none`, the
+    /// implementation may choose an appropriate default scheme.
+    scheme: func() -> option<scheme>;
+    /// Set the HTTP Related Scheme for the Request. When `none`, the
+    /// implementation may choose an appropriate default scheme.
+    set-scheme: func(scheme: option<scheme>);
+
+    /// Get the HTTP Authority for the Request. A value of `none` may be used
+    /// with Related Schemes which do not require an Authority. The HTTP and
+    /// HTTPS schemes always require an authority.
+    authority: func() -> option<string>;
+    /// Set the HTTP Authority for the Request. A value of `none` may be used
+    /// with Related Schemes which do not require an Authority. The HTTP and
+    /// HTTPS schemes always require an authority.
+    set-authority: func(authority: option<string>);
+
+    /// Get the headers associated with the Request.
+    ///
+    /// This headers resource is a child: it must be dropped before the parent
+    /// `outgoing-request` is dropped, or its ownership is transfered to
+    /// another component by e.g. `outgoing-handler.handle`.
+    headers: func() -> headers;
   }
 
   /// Parameters for making an HTTP Request. Each of these parameters is an
@@ -176,6 +232,9 @@ interface types {
     /// This method consumes the `response-outparam` to ensure that it is
     /// called at most once. If it is never called, the implementation
     /// will respond with an error.
+    ///
+    /// The user may provide an `error` to `response` to allow the
+    /// implementation determine how to respond with an HTTP error response.
     set: static func(
       param: response-outparam,
       response: result<outgoing-response, error>,
@@ -260,16 +319,29 @@ interface types {
   resource outgoing-response {
 
     /// Construct an `outgoing-response`.
-    constructor(status-code: status-code, headers: borrow<headers>);
+    ///
+    /// * `status-code` is the HTTP Status Code for the Response.
+    /// * `headers` is the HTTP Headers for the Response.
+    constructor(status-code: status-code, headers: headers);
+
+    /// Get the HTTP Status Code for the Response.
+    status-code: func() -> status-code;
+    /// Set the HTTP Status Code for the Response.
+    set-status-code: func(status-code: status-code);
+
+    /// Get the headers associated with the Request.
+    ///
+    /// This headers resource is a child: it must be dropped before the parent
+    /// `outgoing-request` is dropped, or its ownership is transfered to
+    /// another component by e.g. `outgoing-handler.handle`.
+    headers: func() -> headers;
 
     /// Returns the resource corresponding to the outgoing Body for this Response.
     ///
     /// Returns success on the first call: the `outgoing-body` resource for
-    /// this `outgoing-response` can be retrieved at most once. Sunsequent
+    /// this `outgoing-response` can be retrieved at most once. Subsequent
     /// calls will return error.
-    ///
-    /// FIXME: rename this method to `body`.
-    write: func() -> result<outgoing-body>;
+    body: func() -> result<outgoing-body>;
   }
 
   /// Represents an outgoing HTTP Request or Response's Body.
diff --git a/crates/wasi/wit/deps/http/types.wit b/crates/wasi/wit/deps/http/types.wit
index 343d32220..9cace67ab 100644
--- a/crates/wasi/wit/deps/http/types.wit
+++ b/crates/wasi/wit/deps/http/types.wit
@@ -127,17 +127,73 @@ interface types {
   resource outgoing-request {
 
     /// Construct a new `outgoing-request`.
+    ///
+    /// * `method` represents the HTTP Method for the Request.
+    /// * `path-with-query` is the combination of the HTTP Path and Query for
+    ///    the Request. When `none`, this represents an empty Path and empty
+    ///    Query.
+    /// * `scheme` is the HTTP Related Scheme for the Request. When `none`,
+    ///    the implementation may choose an appropriate default scheme.
+    /// * `authority` is the HTTP Authority for the Request. A value of `none`
+    ///    may be used with Related Schemes which do not require an Authority.
+    ///    The HTTP and HTTPS schemes always require an authority.
+    /// * `headers` is the HTTP Headers for the Request.
+    ///
+    /// It is possible to construct, or manipulate with the accessor functions
+    /// below, an `outgoing-request` with an invalid combination of `scheme`
+    /// and `authority`, or `headers` which are not permitted to be sent.
+    /// It is the obligation of the `outgoing-handler.handle` implementation
+    /// to reject invalid constructions of `outgoing-request`.
     constructor(
       method: method,
       path-with-query: option<string>,
       scheme: option<scheme>,
       authority: option<string>,
-      headers: borrow<headers>
+      headers: headers
     );
 
-    /// Will return the outgoing-body child at most once. If called more than
-    /// once, subsequent calls will return error.
-    write: func() -> result<outgoing-body>;
+    /// Returns the resource corresponding to the outgoing Body for this
+    /// Request.
+    ///
+    /// Returns success on the first call: the `outgoing-body` resource for
+    /// this `outgoing-response` can be retrieved at most once. Subsequent
+    /// calls will return error.
+    body: func() -> result<outgoing-body>;
+
+    /// Get the Method for the Request.
+    method: func() -> method;
+    /// Set the Method for the Request.
+    set-method: func(method: method);
+
+    /// Get the combination of the HTTP Path and Query for the Request.
+    /// When `none`, this represents an empty Path and empty Query.
+    path-with-query: func() -> option<string>;
+    /// Set the combination of the HTTP Path and Query for the Request.
+    /// When `none`, this represents an empty Path and empty Query.
+    set-path-with-query: func(path-with-query: option<string>);
+
+    /// Get the HTTP Related Scheme for the Request. When `none`, the
+    /// implementation may choose an appropriate default scheme.
+    scheme: func() -> option<scheme>;
+    /// Set the HTTP Related Scheme for the Request. When `none`, the
+    /// implementation may choose an appropriate default scheme.
+    set-scheme: func(scheme: option<scheme>);
+
+    /// Get the HTTP Authority for the Request. A value of `none` may be used
+    /// with Related Schemes which do not require an Authority. The HTTP and
+    /// HTTPS schemes always require an authority.
+    authority: func() -> option<string>;
+    /// Set the HTTP Authority for the Request. A value of `none` may be used
+    /// with Related Schemes which do not require an Authority. The HTTP and
+    /// HTTPS schemes always require an authority.
+    set-authority: func(authority: option<string>);
+
+    /// Get the headers associated with the Request.
+    ///
+    /// This headers resource is a child: it must be dropped before the parent
+    /// `outgoing-request` is dropped, or its ownership is transfered to
+    /// another component by e.g. `outgoing-handler.handle`.
+    headers: func() -> headers;
   }
 
   /// Parameters for making an HTTP Request. Each of these parameters is an
@@ -176,6 +232,9 @@ interface types {
     /// This method consumes the `response-outparam` to ensure that it is
     /// called at most once. If it is never called, the implementation
     /// will respond with an error.
+    ///
+    /// The user may provide an `error` to `response` to allow the
+    /// implementation determine how to respond with an HTTP error response.
     set: static func(
       param: response-outparam,
       response: result<outgoing-response, error>,
@@ -260,16 +319,29 @@ interface types {
   resource outgoing-response {
 
     /// Construct an `outgoing-response`.
-    constructor(status-code: status-code, headers: borrow<headers>);
+    ///
+    /// * `status-code` is the HTTP Status Code for the Response.
+    /// * `headers` is the HTTP Headers for the Response.
+    constructor(status-code: status-code, headers: headers);
+
+    /// Get the HTTP Status Code for the Response.
+    status-code: func() -> status-code;
+    /// Set the HTTP Status Code for the Response.
+    set-status-code: func(status-code: status-code);
+
+    /// Get the headers associated with the Request.
+    ///
+    /// This headers resource is a child: it must be dropped before the parent
+    /// `outgoing-request` is dropped, or its ownership is transfered to
+    /// another component by e.g. `outgoing-handler.handle`.
+    headers: func() -> headers;
 
     /// Returns the resource corresponding to the outgoing Body for this Response.
     ///
     /// Returns success on the first call: the `outgoing-body` resource for
-    /// this `outgoing-response` can be retrieved at most once. Sunsequent
+    /// this `outgoing-response` can be retrieved at most once. Subsequent
     /// calls will return error.
-    ///
-    /// FIXME: rename this method to `body`.
-    write: func() -> result<outgoing-body>;
+    body: func() -> result<outgoing-body>;
   }
 
   /// Represents an outgoing HTTP Request or Response's Body.
diff --git a/supply-chain/audits.toml b/supply-chain/audits.toml
index 8c06bd9ea..907ccc4b2 100644
--- a/supply-chain/audits.toml
+++ b/supply-chain/audits.toml
@@ -1515,6 +1515,12 @@ criteria = "safe-to-deploy"
 delta = "0.2.146 -> 0.2.147"
 notes = "Only new type definitions and updating others for some platforms, no major changes"
 
+[[audits.libc]]
+who = "Alex Crichton <alex@alexcrichton.com>"
+criteria = "safe-to-deploy"
+delta = "0.2.148 -> 0.2.149"
+notes = "Lots of new functions and constants for new platforms and nothing out of the ordinary for what one would expect of the `libc` crate."
+
 [[audits.libfuzzer-sys]]
 who = "Nick Fitzgerald <fitzgen@gmail.com>"
 criteria = "safe-to-run"
diff --git a/supply-chain/imports.lock b/supply-chain/imports.lock
index 1114abac6..eec621f33 100644
--- a/supply-chain/imports.lock
+++ b/supply-chain/imports.lock
@@ -845,6 +845,13 @@ user-id = 1
 user-login = "alexcrichton"
 user-name = "Alex Crichton"
 
+[[publisher.wasm-encoder]]
+version = "0.36.1"
+when = "2023-10-30"
+user-id = 1
+user-login = "alexcrichton"
+user-name = "Alex Crichton"
+
 [[publisher.wasm-metadata]]
 version = "0.10.9"
 when = "2023-10-14"
@@ -852,6 +859,13 @@ user-id = 1
 user-login = "alexcrichton"
 user-name = "Alex Crichton"
 
+[[publisher.wasm-metadata]]
+version = "0.10.10"
+when = "2023-10-30"
+user-id = 1
+user-login = "alexcrichton"
+user-name = "Alex Crichton"
+
 [[publisher.wasm-mutate]]
 version = "0.2.38"
 when = "2023-10-14"
@@ -859,6 +873,13 @@ user-id = 1
 user-login = "alexcrichton"
 user-name = "Alex Crichton"
 
+[[publisher.wasm-mutate]]
+version = "0.2.39"
+when = "2023-10-30"
+user-id = 1
+user-login = "alexcrichton"
+user-name = "Alex Crichton"
+
 [[publisher.wasm-smith]]
 version = "0.12.21"
 when = "2023-10-14"
@@ -866,6 +887,13 @@ user-id = 1
 user-login = "alexcrichton"
 user-name = "Alex Crichton"
 
+[[publisher.wasm-smith]]
+version = "0.12.22"
+when = "2023-10-30"
+user-id = 1
+user-login = "alexcrichton"
+user-name = "Alex Crichton"
+
 [[publisher.wasmparser]]
 version = "0.115.0"
 when = "2023-10-14"
@@ -873,6 +901,13 @@ user-id = 1
 user-login = "alexcrichton"
 user-name = "Alex Crichton"
 
+[[publisher.wasmparser]]
+version = "0.116.0"
+when = "2023-10-30"
+user-id = 1
+user-login = "alexcrichton"
+user-name = "Alex Crichton"
+
 [[publisher.wasmprinter]]
 version = "0.2.70"
 when = "2023-10-14"
@@ -880,6 +915,13 @@ user-id = 1
 user-login = "alexcrichton"
 user-name = "Alex Crichton"
 
+[[publisher.wasmprinter]]
+version = "0.2.71"
+when = "2023-10-30"
+user-id = 1
+user-login = "alexcrichton"
+user-name = "Alex Crichton"
+
 [[publisher.wasmtime]]
 version = "14.0.2"
 when = "2023-10-26"
@@ -1037,6 +1079,13 @@ user-id = 1
 user-login = "alexcrichton"
 user-name = "Alex Crichton"
 
+[[publisher.wast]]
+version = "67.0.0"
+when = "2023-10-30"
+user-id = 1
+user-login = "alexcrichton"
+user-name = "Alex Crichton"
+
 [[publisher.wat]]
 version = "1.0.77"
 when = "2023-10-14"
@@ -1044,6 +1093,13 @@ user-id = 1
 user-login = "alexcrichton"
 user-name = "Alex Crichton"
 
+[[publisher.wat]]
+version = "1.0.78"
+when = "2023-10-30"
+user-id = 1
+user-login = "alexcrichton"
+user-name = "Alex Crichton"
+
 [[publisher.wiggle]]
 version = "14.0.2"
 when = "2023-10-26"
@@ -1159,6 +1215,13 @@ user-id = 1
 user-login = "alexcrichton"
 user-name = "Alex Crichton"
 
+[[publisher.wit-bindgen]]
+version = "0.13.1"
+when = "2023-10-30"
+user-id = 1
+user-login = "alexcrichton"
+user-name = "Alex Crichton"
+
 [[publisher.wit-bindgen-core]]
 version = "0.13.0"
 when = "2023-10-18"
@@ -1166,6 +1229,13 @@ user-id = 1
 user-login = "alexcrichton"
 user-name = "Alex Crichton"
 
+[[publisher.wit-bindgen-core]]
+version = "0.13.1"
+when = "2023-10-30"
+user-id = 1
+user-login = "alexcrichton"
+user-name = "Alex Crichton"
+
 [[publisher.wit-bindgen-rust]]
 version = "0.13.0"
 when = "2023-10-18"
@@ -1173,6 +1243,13 @@ user-id = 1
 user-login = "alexcrichton"
 user-name = "Alex Crichton"
 
+[[publisher.wit-bindgen-rust]]
+version = "0.13.2"
+when = "2023-10-30"
+user-id = 1
+user-login = "alexcrichton"
+user-name = "Alex Crichton"
+
 [[publisher.wit-bindgen-rust-macro]]
 version = "0.13.0"
 when = "2023-10-18"
@@ -1180,6 +1257,13 @@ user-id = 1
 user-login = "alexcrichton"
 user-name = "Alex Crichton"
 
+[[publisher.wit-bindgen-rust-macro]]
+version = "0.13.1"
+when = "2023-10-30"
+user-id = 1
+user-login = "alexcrichton"
+user-name = "Alex Crichton"
+
 [[publisher.wit-component]]
 version = "0.16.0"
 when = "2023-10-18"
@@ -1187,6 +1271,13 @@ user-id = 1
 user-login = "alexcrichton"
 user-name = "Alex Crichton"
 
+[[publisher.wit-component]]
+version = "0.17.0"
+when = "2023-10-30"
+user-id = 1
+user-login = "alexcrichton"
+user-name = "Alex Crichton"
+
 [[publisher.wit-parser]]
 version = "0.12.1"
 when = "2023-10-18"
@@ -1194,6 +1285,13 @@ user-id = 1
 user-login = "alexcrichton"
 user-name = "Alex Crichton"
 
+[[publisher.wit-parser]]
+version = "0.12.2"
+when = "2023-10-30"
+user-id = 1
+user-login = "alexcrichton"
+user-name = "Alex Crichton"
+
 [[audits.embark-studios.wildcard-audits.spdx]]
 who = "Jake Shadle <opensource@embark-studios.com>"
 criteria = "safe-to-deploy"
@@ -1552,13 +1650,6 @@ criteria = "safe-to-deploy"
 delta = "0.2.147 -> 0.2.148"
 aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml"
 
-[[audits.mozilla.audits.libc]]
-who = "Jan-Erik Rediger <jrediger@mozilla.com>"
-criteria = "safe-to-deploy"
-delta = "0.2.148 -> 0.2.149"
-notes = "New defintions for a new target we don't use"
-aggregated-from = "https://raw.githubusercontent.com/mozilla/glean/main/supply-chain/audits.toml"
-
 [[audits.mozilla.audits.log]]
 who = "Mike Hommey <mh+mozilla@glandium.org>"
 criteria = "safe-to-deploy"
diff --git a/winch/codegen/src/codegen/env.rs b/winch/codegen/src/codegen/env.rs
index 9d5f6e10e..3d118cab1 100644
--- a/winch/codegen/src/codegen/env.rs
+++ b/winch/codegen/src/codegen/env.rs
@@ -107,7 +107,7 @@ impl<'a, 'translation, 'data, P: PtrSize> FuncEnv<'a, 'translation, 'data, P> {
     /// Resolves a function [`Callee`] from an index.
     pub fn callee_from_index(&self, idx: FuncIndex) -> Callee {
         let types = &self.translation.get_types();
-        let ty = types[types.function_at(idx.as_u32())].unwrap_func();
+        let ty = types[types.core_function_at(idx.as_u32())].unwrap_func();
         let ty = self.translation.module.convert_func_type(ty);
         let import = self.translation.module.is_imported_function(idx);
 
diff --git a/winch/src/compile.rs b/winch/src/compile.rs
index ebf606108..3890371ba 100644
--- a/winch/src/compile.rs
+++ b/winch/src/compile.rs
@@ -54,7 +54,7 @@ fn compile(
 ) -> Result<()> {
     let index = translation.module.func_index(f.0);
     let types = &translation.get_types();
-    let sig = types[types.function_at(index.as_u32())].unwrap_func();
+    let sig = types[types.core_function_at(index.as_u32())].unwrap_func();
     let sig = translation.module.convert_func_type(sig);
     let FunctionBodyData { body, validator } = f.1;
     let vmoffsets = VMOffsets::new(isa.pointer_bytes(), &translation.module);


Test patch:
diff --git a/crates/test-programs/src/bin/api_proxy.rs b/crates/test-programs/src/bin/api_proxy.rs
index 6798d4e30..ae75c1d3b 100644
--- a/crates/test-programs/src/bin/api_proxy.rs
+++ b/crates/test-programs/src/bin/api_proxy.rs
@@ -17,8 +17,8 @@ struct T;
 impl bindings::exports::wasi::http::incoming_handler::Guest for T {
     fn handle(_request: IncomingRequest, outparam: ResponseOutparam) {
         let hdrs = bindings::wasi::http::types::Headers::new(&[]);
-        let resp = bindings::wasi::http::types::OutgoingResponse::new(200, &hdrs);
-        let body = resp.write().expect("outgoing response");
+        let resp = bindings::wasi::http::types::OutgoingResponse::new(200, hdrs);
+        let body = resp.body().expect("outgoing response");
 
         bindings::wasi::http::types::ResponseOutparam::set(outparam, Ok(resp));
 
diff --git a/crates/test-programs/src/bin/api_proxy_streaming.rs b/crates/test-programs/src/bin/api_proxy_streaming.rs
index f4978ac17..e63223058 100644
--- a/crates/test-programs/src/bin/api_proxy_streaming.rs
+++ b/crates/test-programs/src/bin/api_proxy_streaming.rs
@@ -51,11 +51,11 @@ async fn handle_request(request: IncomingRequest, response_out: ResponseOutparam
 
             let response = OutgoingResponse::new(
                 200,
-                &Fields::new(&[("content-type".to_string(), b"text/plain".to_vec())]),
+                Fields::new(&[("content-type".to_string(), b"text/plain".to_vec())]),
             );
 
             let mut body =
-                executor::outgoing_body(response.write().expect("response should be writable"));
+                executor::outgoing_body(response.body().expect("response should be writable"));
 
             ResponseOutparam::set(response_out, Ok(response));
 
@@ -75,7 +75,7 @@ async fn handle_request(request: IncomingRequest, response_out: ResponseOutparam
         (Method::Post, Some("/echo")) => {
             let response = OutgoingResponse::new(
                 200,
-                &Fields::new(
+                Fields::new(
                     &headers
                         .into_iter()
                         .filter_map(|(k, v)| (k == "content-type").then_some((k, v)))
@@ -84,7 +84,7 @@ async fn handle_request(request: IncomingRequest, response_out: ResponseOutparam
             );
 
             let mut body =
-                executor::outgoing_body(response.write().expect("response should be writable"));
+                executor::outgoing_body(response.body().expect("response should be writable"));
 
             ResponseOutparam::set(response_out, Ok(response));
 
@@ -108,9 +108,9 @@ async fn handle_request(request: IncomingRequest, response_out: ResponseOutparam
         }
 
         _ => {
-            let response = OutgoingResponse::new(405, &Fields::new(&[]));
+            let response = OutgoingResponse::new(405, Fields::new(&[]));
 
-            let body = response.write().expect("response should be writable");
+            let body = response.body().expect("response should be writable");
 
             ResponseOutparam::set(response_out, Ok(response));
 
@@ -137,7 +137,7 @@ async fn hash(url: &Url) -> Result<String> {
                 String::new()
             }
         )),
-        &Fields::new(&[]),
+        Fields::new(&[]),
     );
 
     let response = executor::outgoing_request_send(request).await?;
diff --git a/crates/test-programs/src/bin/http_outbound_request_response_build.rs b/crates/test-programs/src/bin/http_outbound_request_response_build.rs
index b377b4a47..d9a29822d 100644
--- a/crates/test-programs/src/bin/http_outbound_request_response_build.rs
+++ b/crates/test-programs/src/bin/http_outbound_request_response_build.rs
@@ -12,9 +12,9 @@ fn main() {
             None,
             Some(&http_types::Scheme::Https),
             Some("www.example.com"),
-            &headers,
+            headers,
         );
-        let outgoing_body = request.write().unwrap();
+        let outgoing_body = request.body().unwrap();
         let request_body = outgoing_body.write().unwrap();
         request_body
             .blocking_write_and_flush("request-body".as_bytes())
@@ -25,8 +25,8 @@ fn main() {
             "Content-Type".to_string(),
             "application/text".to_string().into_bytes(),
         )]);
-        let response = http_types::OutgoingResponse::new(200, &headers);
-        let outgoing_body = response.write().unwrap();
+        let response = http_types::OutgoingResponse::new(200, headers);
+        let outgoing_body = response.body().unwrap();
         let response_body = outgoing_body.write().unwrap();
         response_body
             .blocking_write_and_flush("response-body".as_bytes())
diff --git a/crates/test-programs/src/http.rs b/crates/test-programs/src/http.rs
index e87347cb5..f065b45ee 100644
--- a/crates/test-programs/src/http.rs
+++ b/crates/test-programs/src/http.rs
@@ -58,11 +58,11 @@ pub fn request(
         Some(path_with_query),
         Some(&scheme),
         Some(authority),
-        &headers,
+        headers,
     );
 
     let outgoing_body = request
-        .write()
+        .body()
         .map_err(|_| anyhow!("outgoing request write failed"))?;
 
     if let Some(mut buf) = body {
diff --git a/winch/filetests/src/lib.rs b/winch/filetests/src/lib.rs
index aabcab240..e9593cff3 100644
--- a/winch/filetests/src/lib.rs
+++ b/winch/filetests/src/lib.rs
@@ -156,7 +156,7 @@ mod test {
         let types = &translation.get_types();
 
         let index = module.func_index(f.0);
-        let sig = types[types.function_at(index.as_u32())].unwrap_func();
+        let sig = types[types.core_function_at(index.as_u32())].unwrap_func();
         let sig = translation.module.convert_func_type(&sig);
 
         let vmoffsets = VMOffsets::new(isa.pointer_bytes(), &translation.module);