From 26a655f781250b28c43d1c58d48545e3cfad0d27 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Fri, 9 Aug 2024 12:11:15 -0700 Subject: [PATCH] Test `wasm-tools component wit` on core modules Also cause it to return an error if the input is a core wasm module with zero `component-type` custom sections. Closes #1673 --- crates/wit-component/src/encoding.rs | 6 ++++-- crates/wit-component/src/metadata.rs | 17 ++++++++++++----- src/bin/wasm-tools/component.rs | 10 +++++++++- tests/cli/component-wit-empty-core-module.wat | 3 +++ .../component-wit-empty-core-module.wat.stderr | 1 + tests/cli/component-wit-of-core-module.wit | 8 ++++++++ .../cli/component-wit-of-core-module.wit.stdout | 14 ++++++++++++++ 7 files changed, 51 insertions(+), 8 deletions(-) create mode 100644 tests/cli/component-wit-empty-core-module.wat create mode 100644 tests/cli/component-wit-empty-core-module.wat.stderr create mode 100644 tests/cli/component-wit-of-core-module.wit create mode 100644 tests/cli/component-wit-of-core-module.wit.stdout diff --git a/crates/wit-component/src/encoding.rs b/crates/wit-component/src/encoding.rs index 40c5078657..7c44f2cfb0 100644 --- a/crates/wit-component/src/encoding.rs +++ b/crates/wit-component/src/encoding.rs @@ -1922,6 +1922,7 @@ impl ComponentEncoder { /// core module. pub fn module(mut self, module: &[u8]) -> Result { let (wasm, metadata) = metadata::decode(module)?; + let wasm = wasm.as_deref().unwrap_or(module); let world = self .metadata .merge(metadata) @@ -1931,7 +1932,7 @@ impl ComponentEncoder { self.module = if let Some(producers) = &self.metadata.producers { producers.add_to_wasm(&wasm)? } else { - wasm + wasm.to_vec() }; Ok(self) } @@ -1986,6 +1987,7 @@ impl ComponentEncoder { library_info: Option, ) -> Result { let (wasm, metadata) = metadata::decode(bytes)?; + let wasm = wasm.as_deref().unwrap_or(bytes); // Merge the adapter's document into our own document to have one large // document, and then afterwards merge worlds as well. // @@ -2041,7 +2043,7 @@ impl ComponentEncoder { self.adapters.insert( name.to_string(), Adapter { - wasm, + wasm: wasm.to_vec(), metadata: metadata.metadata, required_exports: exports, library_info, diff --git a/crates/wit-component/src/metadata.rs b/crates/wit-component/src/metadata.rs index 982b11f7dc..f436794c68 100644 --- a/crates/wit-component/src/metadata.rs +++ b/crates/wit-component/src/metadata.rs @@ -119,7 +119,7 @@ pub struct ModuleMetadata { pub export_encodings: IndexMap, } -/// This function will parse the `wasm` binary given as input and return a +/// This function will parse the core `wasm` binary given as input and return a /// [`Bindgen`] which extracts the custom sections describing component-level /// types from within the binary itself. /// @@ -130,12 +130,14 @@ pub struct ModuleMetadata { /// /// This will return an error if `wasm` is not a valid WebAssembly module. /// -/// Note that a "stripped" binary where `component-type` sections are removed -/// is returned as well to embed within a component. -pub fn decode(wasm: &[u8]) -> Result<(Vec, Bindgen)> { +/// If a `component-type` custom section was found then a new binary is +/// optionally returned with the custom sections stripped out. If no +/// `component-type` custom sections are found then `None` is returned. +pub fn decode(wasm: &[u8]) -> Result<(Option>, Bindgen)> { let mut ret = Bindgen::default(); let mut new_module = wasm_encoder::Module::new(); + let mut found_custom = false; for payload in wasmparser::Parser::new(0).parse_all(wasm) { let payload = payload.context("decoding item in module")?; match payload { @@ -144,6 +146,7 @@ pub fn decode(wasm: &[u8]) -> Result<(Vec, Bindgen)> { .with_context(|| format!("decoding custom section {}", cs.name()))?; ret.merge(data) .with_context(|| format!("updating metadata for section {}", cs.name()))?; + found_custom = true; } wasmparser::Payload::Version { encoding, .. } if encoding != Encoding::Module => { bail!("decoding a component is not supported") @@ -159,7 +162,11 @@ pub fn decode(wasm: &[u8]) -> Result<(Vec, Bindgen)> { } } - Ok((new_module.finish(), ret)) + if found_custom { + Ok((Some(new_module.finish()), ret)) + } else { + Ok((None, ret)) + } } /// Creates a `component-type*` custom section to be decoded by `decode` above. diff --git a/src/bin/wasm-tools/component.rs b/src/bin/wasm-tools/component.rs index a5c01c6c88..b7dbafdd59 100644 --- a/src/bin/wasm-tools/component.rs +++ b/src/bin/wasm-tools/component.rs @@ -574,7 +574,15 @@ impl WitOpts { if wasmparser::Parser::is_component(&input) { wit_component::decode(&input) } else { - let (_wasm, bindgen) = wit_component::metadata::decode(&input)?; + let (wasm, bindgen) = wit_component::metadata::decode(&input)?; + if wasm.is_none() { + bail!( + "input is a core wasm module with no `component-type*` \ + custom sections meaning that there is not WIT information; \ + is the information not embedded or is this supposed \ + to be a component?" + ) + } Ok(DecodedWasm::Component(bindgen.resolve, bindgen.world)) } } diff --git a/tests/cli/component-wit-empty-core-module.wat b/tests/cli/component-wit-empty-core-module.wat new file mode 100644 index 0000000000..809a84b04f --- /dev/null +++ b/tests/cli/component-wit-empty-core-module.wat @@ -0,0 +1,3 @@ +;; FAIL: component wit % + +(module) diff --git a/tests/cli/component-wit-empty-core-module.wat.stderr b/tests/cli/component-wit-empty-core-module.wat.stderr new file mode 100644 index 0000000000..a9d473a972 --- /dev/null +++ b/tests/cli/component-wit-empty-core-module.wat.stderr @@ -0,0 +1 @@ +error: input is a core wasm module with no `component-type*` custom sections meaning that there is not WIT information; is the information not embedded or is this supposed to be a component? diff --git a/tests/cli/component-wit-of-core-module.wit b/tests/cli/component-wit-of-core-module.wit new file mode 100644 index 0000000000..c4f7bf590d --- /dev/null +++ b/tests/cli/component-wit-of-core-module.wit @@ -0,0 +1,8 @@ +// RUN: component embed --dummy % | component wit + +package a:b; + +world foo { + import x: func(); + export y: func(); +} diff --git a/tests/cli/component-wit-of-core-module.wit.stdout b/tests/cli/component-wit-of-core-module.wit.stdout new file mode 100644 index 0000000000..6321454f2d --- /dev/null +++ b/tests/cli/component-wit-of-core-module.wit.stdout @@ -0,0 +1,14 @@ +package root:root; + +world root { + import x: func(); + + export y: func(); +} +package a:b { + world foo { + import x: func(); + + export y: func(); + } +}