Skip to content

Commit

Permalink
Test wasm-tools component wit on core modules
Browse files Browse the repository at this point in the history
Also cause it to return an error if the input is a core wasm module with
zero `component-type` custom sections.

Closes bytecodealliance#1673
  • Loading branch information
alexcrichton committed Aug 9, 2024
1 parent d19cf14 commit 26a655f
Show file tree
Hide file tree
Showing 7 changed files with 51 additions and 8 deletions.
6 changes: 4 additions & 2 deletions crates/wit-component/src/encoding.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1922,6 +1922,7 @@ impl ComponentEncoder {
/// core module.
pub fn module(mut self, module: &[u8]) -> Result<Self> {
let (wasm, metadata) = metadata::decode(module)?;
let wasm = wasm.as_deref().unwrap_or(module);
let world = self
.metadata
.merge(metadata)
Expand All @@ -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)
}
Expand Down Expand Up @@ -1986,6 +1987,7 @@ impl ComponentEncoder {
library_info: Option<LibraryInfo>,
) -> Result<Self> {
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.
//
Expand Down Expand Up @@ -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,
Expand Down
17 changes: 12 additions & 5 deletions crates/wit-component/src/metadata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ pub struct ModuleMetadata {
pub export_encodings: IndexMap<String, StringEncoding>,
}

/// 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.
///
Expand All @@ -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<u8>, 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<Vec<u8>>, 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 {
Expand All @@ -144,6 +146,7 @@ pub fn decode(wasm: &[u8]) -> Result<(Vec<u8>, 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")
Expand All @@ -159,7 +162,11 @@ pub fn decode(wasm: &[u8]) -> Result<(Vec<u8>, 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.
Expand Down
10 changes: 9 additions & 1 deletion src/bin/wasm-tools/component.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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))
}
}
Expand Down
3 changes: 3 additions & 0 deletions tests/cli/component-wit-empty-core-module.wat
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
;; FAIL: component wit %

(module)
1 change: 1 addition & 0 deletions tests/cli/component-wit-empty-core-module.wat.stderr
Original file line number Diff line number Diff line change
@@ -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?
8 changes: 8 additions & 0 deletions tests/cli/component-wit-of-core-module.wit
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// RUN: component embed --dummy % | component wit

package a:b;

world foo {
import x: func();
export y: func();
}
14 changes: 14 additions & 0 deletions tests/cli/component-wit-of-core-module.wit.stdout
Original file line number Diff line number Diff line change
@@ -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();
}
}

0 comments on commit 26a655f

Please sign in to comment.