From d3d2d2c15e50947c6b3fc7ed05770935e57652d3 Mon Sep 17 00:00:00 2001 From: Daniel Macovei Date: Fri, 12 Jul 2024 13:04:31 -0500 Subject: [PATCH] fix interfaces test assertion --- crates/wit-component/src/encoding/wit/v2.rs | 26 ++++--- crates/wit-component/tests/interfaces.rs | 4 +- crates/wit-parser/src/decoding.rs | 78 ++++++++++++--------- crates/wit-parser/src/metadata.rs | 2 +- 4 files changed, 63 insertions(+), 47 deletions(-) diff --git a/crates/wit-component/src/encoding/wit/v2.rs b/crates/wit-component/src/encoding/wit/v2.rs index 2723f00511..df6a155208 100644 --- a/crates/wit-component/src/encoding/wit/v2.rs +++ b/crates/wit-component/src/encoding/wit/v2.rs @@ -64,6 +64,14 @@ impl Encoder<'_> { self.encode_package(&mut names, pkg, None)?; } } + if self.packages.len() == 1 { + // let pkg = self.packages[0]; + let package_metadata = PackageMetadata::extract(self.resolve, self.packages[0]); + self.component.custom_section(&CustomSection { + name: PackageMetadata::SECTION_NAME.into(), + data: package_metadata.encode()?.into(), + }); + } let mut final_names = ComponentNameSection::new(); final_names.components(&names); self.component.names(&final_names); @@ -86,7 +94,7 @@ impl Encoder<'_> { }); } - for (name, &id) in self.resolve.packages[*pkg].interfaces.iter() { + for (name, &id) in package.interfaces.iter() { if let Some(ref mut sub) = sub_encoder { let component_ty = sub.encode_interface(id, pkg)?; let ty = sub.component.type_component(&component_ty); @@ -99,7 +107,7 @@ impl Encoder<'_> { .export(name.as_ref(), ComponentExportKind::Type, ty, None); } } - for (name, &world) in self.resolve.packages[*pkg].worlds.iter() { + for (name, &world) in package.worlds.iter() { if let Some(ref mut sub) = sub_encoder { // Encode the `world` directly as a component, then create a wrapper // component that exports that component. @@ -120,20 +128,16 @@ impl Encoder<'_> { let world = &self.resolve.worlds[world]; let mut wrapper = ComponentType::new(); wrapper.ty().component(&component_ty); - let pkg = &self.resolve.packages[world.package.unwrap()]; - wrapper.export(&pkg.name.interface_id(name), ComponentTypeRef::Component(0)); + let package = &self.resolve.packages[world.package.unwrap()]; + wrapper.export( + &package.name.interface_id(name), + ComponentTypeRef::Component(0), + ); let ty = self.component.type_component(&wrapper); self.component .export(name.as_ref(), ComponentExportKind::Type, ty, None); } } - if sub_encoder.is_none() { - let package_metadata = PackageMetadata::extract(self.resolve, *pkg); - self.component.custom_section(&CustomSection { - name: PackageMetadata::SECTION_NAME.into(), - data: package_metadata.encode()?.into(), - }); - } if let Some(sub_encoder) = sub_encoder { let sub = self.component.component(sub_encoder.component); names.append(sub, &package.name.to_string()); diff --git a/crates/wit-component/tests/interfaces.rs b/crates/wit-component/tests/interfaces.rs index 70ab329f80..df857ebb96 100644 --- a/crates/wit-component/tests/interfaces.rs +++ b/crates/wit-component/tests/interfaces.rs @@ -72,14 +72,14 @@ fn run_test(path: &Path, is_dir: bool) -> Result<()> { // this package's documents and assert they all match the expectations. let decoded = wit_component::decode(&wasm)?; - let decoded_package = decoded.packages()[0]; + let decoded_package = decoded.packages(); let resolve = decoded.resolve(); assert_print(resolve, decoded.packages(), path, is_dir)?; // Finally convert the decoded package to wasm again and make sure it // matches the prior wasm. - let wasm2 = wit_component::encode(Some(true), resolve, &[decoded_package])?; + let wasm2 = wit_component::encode(Some(true), resolve, &decoded_package)?; if wasm != wasm2 { let wat2 = wasmprinter::print_bytes(&wasm)?; assert_eq!(wat, wat2, "document did not roundtrip correctly"); diff --git a/crates/wit-parser/src/decoding.rs b/crates/wit-parser/src/decoding.rs index 51385b27d0..801b556402 100644 --- a/crates/wit-parser/src/decoding.rs +++ b/crates/wit-parser/src/decoding.rs @@ -354,9 +354,11 @@ impl ComponentInfo { let mut pkg_name = None; let mut pkg_names = Vec::new(); + let mut interfaces = IndexMap::new(); + let mut worlds = IndexMap::new(); let mut fields = PackageFields { - interfaces: &mut IndexMap::new(), - worlds: &mut IndexMap::new(), + interfaces: &mut interfaces, + worlds: &mut worlds, }; let mut pkg_ids: Vec = Vec::new(); let mut implicit = None; @@ -413,11 +415,18 @@ impl ComponentInfo { let pkg = Package { name, docs: Docs::default(), - interfaces: fields.interfaces.clone(), - worlds: fields.worlds.clone(), + interfaces: interfaces.clone(), + worlds, }; - let (resolve, package) = decoder.finish(pkg); + let (mut resolve, package) = decoder.finish(pkg); implicit = Some(package); + // For now this is a sufficient condition to know that we're working with + // an implicit package declaration. This will need to be reworked when + // mixed package declarations are supported + // if let Some(package) = implicit { + if let Some(package_metadata) = &self.package_metadata { + package_metadata.inject(&mut resolve, package)?; + } resolve } else { Resolve::new() @@ -425,8 +434,12 @@ impl ComponentInfo { for explicit in &self.explicit { let mut cur_decoder = WitPackageDecoder::new(explicit.types.as_ref().unwrap()); - fields.interfaces.clear(); - fields.worlds.clear(); + let mut interfaces = IndexMap::new(); + let mut worlds = IndexMap::new(); + let mut fields = PackageFields { + interfaces: &mut interfaces, + worlds: &mut worlds, + }; pkg_name = None; for (_, item) in explicit.externs.iter() { let export = match item { @@ -469,6 +482,7 @@ impl ComponentInfo { } _ => unreachable!(), }; + if let Some(pkg_name) = pkg_name.as_ref() { // TODO: when we have fully switched to the v2 format, we should switch to parsing // multiple wit documents instead of bailing. @@ -505,15 +519,15 @@ impl ComponentInfo { Package { name: name.clone(), docs: Docs::default(), - interfaces: fields.interfaces.clone(), - worlds: fields.worlds.clone(), + interfaces, + worlds, } } else { Package { name: explicit.name.as_ref().unwrap().clone(), docs: Docs::default(), - interfaces: fields.interfaces.clone(), - worlds: fields.worlds.clone(), + interfaces, + worlds, } }; let (cur_resolve, _) = cur_decoder.finish(pkg); @@ -530,14 +544,7 @@ impl ComponentInfo { } } } - // For now this is a sufficient condition to know that we're working with - // an implicit package declaration. This will need to be reworked when - // mixed package declarations are supported - if let Some(package) = implicit { - if let Some(package_metadata) = &self.package_metadata { - package_metadata.inject(&mut resolve, package)?; - } - } + let packages = if let Some(package) = implicit { vec![package] } else { @@ -733,15 +740,18 @@ pub fn decode_world(wasm: &[u8]) -> Result<(Resolve, WorldId)> { types::ComponentEntityType::Component(ty) => ty, _ => unreachable!(), }; - let mut fields = PackageFields { - interfaces: &mut interfaces, - worlds: &mut worlds, - }; - let name = decoder.decode_world(name, &types[ty], &mut fields)?; + let name = decoder.decode_world( + name, + &types[ty], + &mut PackageFields { + interfaces: &mut interfaces, + worlds: &mut worlds, + }, + )?; let (resolve, pkg) = decoder.finish(Package { name, - interfaces: fields.interfaces.clone(), - worlds: fields.worlds.clone(), + interfaces, + worlds, docs: Default::default(), }); // The package decoded here should only have a single world so extract that @@ -839,7 +849,7 @@ impl WitPackageDecoder<'_> { _ => bail!("component export `{name}` is not an instance or component"), } } - Ok(package.clone()) + Ok(package) } fn decode_interface<'a>( @@ -847,7 +857,7 @@ impl WitPackageDecoder<'_> { name: &str, imports: &wasmparser::collections::IndexMap, ty: &types::ComponentInstanceType, - fields: &mut PackageFields, + fields: &mut PackageFields<'a>, ) -> Result { let component_name = self .parse_component_name(name) @@ -876,7 +886,7 @@ impl WitPackageDecoder<'_> { &mut self, name: &str, ty: &types::ComponentType, - fields: &mut PackageFields, + fields: &mut PackageFields<'a>, ) -> Result { let kebab_name = self .parse_component_name(name) @@ -896,7 +906,7 @@ impl WitPackageDecoder<'_> { &mut self, name: &str, world: WorldId, - package: &mut PackageFields, + package: &mut PackageFields<'a>, ) -> Result<()> { log::debug!("decoding component import `{name}`"); let ty = self.types.component_entity_type_of_import(name).unwrap(); @@ -946,7 +956,7 @@ impl WitPackageDecoder<'_> { &mut self, export: &DecodingExport, world: WorldId, - package: &mut PackageFields, + package: &mut PackageFields<'a>, ) -> Result<()> { let name = &export.name; log::debug!("decoding component export `{name}`"); @@ -1190,7 +1200,7 @@ impl WitPackageDecoder<'_> { &mut self, name: &str, ty: &types::ComponentInstanceType, - package: &mut PackageFields, + package: &mut PackageFields<'a>, ) -> Result<(WorldKey, InterfaceId)> { // If this interface's name is already known then that means this is an // interface that's both imported and exported. Use `register_import` @@ -1331,7 +1341,7 @@ impl WitPackageDecoder<'_> { &mut self, name: &str, ty: &types::ComponentType, - package: &mut PackageFields, + package: &mut PackageFields<'a>, ) -> Result { let name = self .extract_interface_name_from_component_name(name)? @@ -1696,6 +1706,7 @@ impl WitPackageDecoder<'_> { for i in 0..self.foreign_packages.len() { self.visit_package(i, &mut order); } + // Using the topological ordering create a temporary map from // index-in-`foreign_packages` to index-in-`order` let mut idx_to_pos = vec![0; self.foreign_packages.len()]; @@ -1715,6 +1726,7 @@ impl WitPackageDecoder<'_> { for (_idx, (_url, pkg)) in deps { self.insert_package(pkg); } + let id = self.insert_package(package); assert!(self.resolve.worlds.iter().all(|(_, w)| w.package.is_some())); assert!(self diff --git a/crates/wit-parser/src/metadata.rs b/crates/wit-parser/src/metadata.rs index 78554a3ad0..a9a6967d88 100644 --- a/crates/wit-parser/src/metadata.rs +++ b/crates/wit-parser/src/metadata.rs @@ -530,7 +530,7 @@ impl InterfaceMetadata { fn extract(resolve: &Resolve, id: InterfaceId) -> Self { let interface = &resolve.interfaces[id]; - let funcs = interface + let funcs: IndexMap = interface .functions .iter() .map(|(name, func)| (name.to_string(), FunctionMetadata::extract(func)))