1use crate::StringEncoding;
75use crate::metadata::{self, Bindgen, ModuleMetadata};
76use crate::validation::{
77 Export, ExportMap, Import, ImportInstance, ImportMap, PayloadInfo, PayloadType,
78};
79use anyhow::{Context, Result, anyhow, bail};
80use indexmap::{IndexMap, IndexSet};
81use std::borrow::Cow;
82use std::collections::HashMap;
83use std::hash::Hash;
84use std::mem;
85use wasm_encoder::*;
86use wasmparser::{Validator, WasmFeatures};
87use wit_parser::{
88 Function, FunctionKind, InterfaceId, LiveTypes, Param, Resolve, Stability, Type, TypeDefKind,
89 TypeId, TypeOwner, WorldItem, WorldKey,
90 abi::{AbiVariant, WasmSignature, WasmType},
91};
92
93const INDIRECT_TABLE_NAME: &str = "$imports";
94
95mod wit;
96pub use wit::{encode, encode_world};
97
98mod types;
99use types::{InstanceTypeEncoder, RootTypeEncoder, TypeEncodingMaps, ValtypeEncoder};
100mod world;
101use world::{ComponentWorld, ImportedInterface, Lowering};
102
103mod dedupe;
104pub(crate) use dedupe::ModuleImportMap;
105use wasm_metadata::AddMetadataField;
106
107fn to_val_type(ty: &WasmType) -> ValType {
108 match ty {
109 WasmType::I32 => ValType::I32,
110 WasmType::I64 => ValType::I64,
111 WasmType::F32 => ValType::F32,
112 WasmType::F64 => ValType::F64,
113 WasmType::Pointer => ValType::I32,
114 WasmType::PointerOrI64 => ValType::I64,
115 WasmType::Length => ValType::I32,
116 }
117}
118
119fn import_func_name(f: &Function) -> String {
120 match f.kind {
121 FunctionKind::Freestanding | FunctionKind::AsyncFreestanding => {
122 format!("import-func-{}", f.item_name())
123 }
124
125 FunctionKind::Method(_)
133 | FunctionKind::AsyncMethod(_)
134 | FunctionKind::Static(_)
135 | FunctionKind::AsyncStatic(_)
136 | FunctionKind::Constructor(_) => {
137 format!(
138 "import-{}",
139 f.name.replace('[', "").replace([']', '.', ' '], "-")
140 )
141 }
142 }
143}
144
145bitflags::bitflags! {
146 #[derive(Copy, Clone, Debug)]
149 pub struct RequiredOptions: u8 {
150 const MEMORY = 1 << 0;
153 const REALLOC = 1 << 1;
156 const STRING_ENCODING = 1 << 2;
159 const ASYNC = 1 << 3;
160 }
161}
162
163impl RequiredOptions {
164 fn for_import(resolve: &Resolve, func: &Function, abi: AbiVariant) -> RequiredOptions {
165 let sig = resolve.wasm_signature(abi, func);
166 let mut ret = RequiredOptions::empty();
167 ret.add_lift(TypeContents::for_types(
169 resolve,
170 func.params.iter().map(|p| &p.ty),
171 ));
172 ret.add_lower(TypeContents::for_types(resolve, &func.result));
173
174 if sig.retptr || sig.indirect_params {
177 ret |= RequiredOptions::MEMORY;
178 }
179 if abi == AbiVariant::GuestImportAsync {
180 ret |= RequiredOptions::ASYNC;
181 }
182 ret
183 }
184
185 fn for_export(resolve: &Resolve, func: &Function, abi: AbiVariant) -> RequiredOptions {
186 let sig = resolve.wasm_signature(abi, func);
187 let mut ret = RequiredOptions::empty();
188 ret.add_lower(TypeContents::for_types(
190 resolve,
191 func.params.iter().map(|p| &p.ty),
192 ));
193 ret.add_lift(TypeContents::for_types(resolve, &func.result));
194
195 if sig.retptr || sig.indirect_params {
199 ret |= RequiredOptions::MEMORY;
200 if sig.indirect_params {
201 ret |= RequiredOptions::REALLOC;
202 }
203 }
204 if let AbiVariant::GuestExportAsync | AbiVariant::GuestExportAsyncStackful = abi {
205 ret |= RequiredOptions::ASYNC;
206 ret |= task_return_options_and_type(resolve, func).0;
207 }
208 ret
209 }
210
211 fn add_lower(&mut self, types: TypeContents) {
212 if types.contains(TypeContents::NEEDS_MEMORY) {
216 *self |= RequiredOptions::MEMORY | RequiredOptions::REALLOC;
217 }
218 if types.contains(TypeContents::STRING) {
219 *self |= RequiredOptions::MEMORY
220 | RequiredOptions::STRING_ENCODING
221 | RequiredOptions::REALLOC;
222 }
223 }
224
225 fn add_lift(&mut self, types: TypeContents) {
226 if types.contains(TypeContents::NEEDS_MEMORY) {
230 *self |= RequiredOptions::MEMORY;
231 }
232 if types.contains(TypeContents::STRING) {
233 *self |= RequiredOptions::MEMORY | RequiredOptions::STRING_ENCODING;
234 }
235 }
236
237 fn into_iter(
238 self,
239 encoding: StringEncoding,
240 memory_index: Option<u32>,
241 realloc_index: Option<u32>,
242 ) -> Result<impl ExactSizeIterator<Item = CanonicalOption>> {
243 #[derive(Default)]
244 struct Iter {
245 options: [Option<CanonicalOption>; 5],
246 current: usize,
247 count: usize,
248 }
249
250 impl Iter {
251 fn push(&mut self, option: CanonicalOption) {
252 assert!(self.count < self.options.len());
253 self.options[self.count] = Some(option);
254 self.count += 1;
255 }
256 }
257
258 impl Iterator for Iter {
259 type Item = CanonicalOption;
260
261 fn next(&mut self) -> Option<Self::Item> {
262 if self.current == self.count {
263 return None;
264 }
265 let option = self.options[self.current];
266 self.current += 1;
267 option
268 }
269
270 fn size_hint(&self) -> (usize, Option<usize>) {
271 (self.count - self.current, Some(self.count - self.current))
272 }
273 }
274
275 impl ExactSizeIterator for Iter {}
276
277 let mut iter = Iter::default();
278
279 if self.contains(RequiredOptions::MEMORY) {
280 iter.push(CanonicalOption::Memory(memory_index.ok_or_else(|| {
281 anyhow!("module does not export a memory named `memory`")
282 })?));
283 }
284
285 if self.contains(RequiredOptions::REALLOC) {
286 iter.push(CanonicalOption::Realloc(realloc_index.ok_or_else(
287 || anyhow!("module does not export a function named `cabi_realloc`"),
288 )?));
289 }
290
291 if self.contains(RequiredOptions::STRING_ENCODING) {
292 iter.push(encoding.into());
293 }
294
295 if self.contains(RequiredOptions::ASYNC) {
296 iter.push(CanonicalOption::Async);
297 }
298
299 Ok(iter)
300 }
301}
302
303bitflags::bitflags! {
304 struct TypeContents: u8 {
307 const STRING = 1 << 0;
308 const NEEDS_MEMORY = 1 << 1;
309 }
310}
311
312impl TypeContents {
313 fn for_types<'a>(resolve: &Resolve, types: impl IntoIterator<Item = &'a Type>) -> Self {
314 let mut cur = TypeContents::empty();
315 for ty in types {
316 cur |= Self::for_type(resolve, ty);
317 }
318 cur
319 }
320
321 fn for_optional_types<'a>(
322 resolve: &Resolve,
323 types: impl Iterator<Item = Option<&'a Type>>,
324 ) -> Self {
325 Self::for_types(resolve, types.flatten())
326 }
327
328 fn for_optional_type(resolve: &Resolve, ty: Option<&Type>) -> Self {
329 match ty {
330 Some(ty) => Self::for_type(resolve, ty),
331 None => Self::empty(),
332 }
333 }
334
335 fn for_type(resolve: &Resolve, ty: &Type) -> Self {
336 match ty {
337 Type::Id(id) => match &resolve.types[*id].kind {
338 TypeDefKind::Handle(h) => match h {
339 wit_parser::Handle::Own(_) => Self::empty(),
340 wit_parser::Handle::Borrow(_) => Self::empty(),
341 },
342 TypeDefKind::Resource => Self::empty(),
343 TypeDefKind::Record(r) => Self::for_types(resolve, r.fields.iter().map(|f| &f.ty)),
344 TypeDefKind::Tuple(t) => Self::for_types(resolve, t.types.iter()),
345 TypeDefKind::Flags(_) => Self::empty(),
346 TypeDefKind::Option(t) => Self::for_type(resolve, t),
347 TypeDefKind::Result(r) => {
348 Self::for_optional_type(resolve, r.ok.as_ref())
349 | Self::for_optional_type(resolve, r.err.as_ref())
350 }
351 TypeDefKind::Variant(v) => {
352 Self::for_optional_types(resolve, v.cases.iter().map(|c| c.ty.as_ref()))
353 }
354 TypeDefKind::Enum(_) => Self::empty(),
355 TypeDefKind::List(t) => Self::for_type(resolve, t) | Self::NEEDS_MEMORY,
356 TypeDefKind::Map(k, v) => {
357 Self::for_type(resolve, k) | Self::for_type(resolve, v) | Self::NEEDS_MEMORY
358 }
359 TypeDefKind::FixedLengthList(t, _elements) => Self::for_type(resolve, t),
360 TypeDefKind::Type(t) => Self::for_type(resolve, t),
361 TypeDefKind::Future(_) => Self::empty(),
362 TypeDefKind::Stream(_) => Self::empty(),
363 TypeDefKind::Unknown => unreachable!(),
364 },
365 Type::String => Self::STRING,
366 _ => Self::empty(),
367 }
368 }
369}
370
371pub struct EncodingState<'a> {
373 component: ComponentBuilder,
375 module_index: Option<u32>,
379 instance_index: Option<u32>,
383 memory_index: Option<u32>,
387 shim_instance_index: Option<u32>,
391 fixups_module_index: Option<u32>,
395
396 adapter_modules: IndexMap<&'a str, u32>,
399 adapter_instances: IndexMap<&'a str, u32>,
401
402 instances: IndexMap<InterfaceId, u32>,
404 imported_funcs: IndexMap<String, u32>,
405
406 type_encoding_maps: TypeEncodingMaps<'a>,
411
412 aliased_core_items: HashMap<(u32, String), u32>,
418
419 info: &'a ComponentWorld<'a>,
421
422 export_task_initialization_wrappers: HashMap<String, u32>,
425}
426
427impl<'a> EncodingState<'a> {
428 fn encode_core_modules(&mut self) {
429 assert!(self.module_index.is_none());
430 let idx = self
431 .component
432 .core_module_raw(Some("main"), &self.info.encoder.module);
433 self.module_index = Some(idx);
434
435 for (name, adapter) in self.info.adapters.iter() {
436 let debug_name = if adapter.library_info.is_some() {
437 name.to_string()
438 } else {
439 format!("wit-component:adapter:{name}")
440 };
441 let idx = if self.info.encoder.debug_names {
442 let mut add_meta = wasm_metadata::AddMetadata::default();
443 add_meta.name = AddMetadataField::Set(debug_name.clone());
444 let wasm = add_meta
445 .to_wasm(&adapter.wasm)
446 .expect("core wasm can get name added");
447 self.component.core_module_raw(Some(&debug_name), &wasm)
448 } else {
449 self.component
450 .core_module_raw(Some(&debug_name), &adapter.wasm)
451 };
452 let prev = self.adapter_modules.insert(name, idx);
453 assert!(prev.is_none());
454 }
455 }
456
457 fn root_import_type_encoder(
458 &mut self,
459 interface: Option<InterfaceId>,
460 ) -> RootTypeEncoder<'_, 'a> {
461 RootTypeEncoder {
462 state: self,
463 interface,
464 import_types: true,
465 }
466 }
467
468 fn root_export_type_encoder(
469 &mut self,
470 interface: Option<InterfaceId>,
471 ) -> RootTypeEncoder<'_, 'a> {
472 RootTypeEncoder {
473 state: self,
474 interface,
475 import_types: false,
476 }
477 }
478
479 fn instance_type_encoder(&mut self, interface: InterfaceId) -> InstanceTypeEncoder<'_, 'a> {
480 InstanceTypeEncoder {
481 state: self,
482 interface,
483 type_encoding_maps: Default::default(),
484 ty: Default::default(),
485 }
486 }
487
488 fn encode_imports(&mut self, name_map: &HashMap<String, String>) -> Result<()> {
489 let mut has_funcs = false;
490 for (name, info) in self.info.import_map.iter() {
491 match name {
492 Some(name) => {
493 self.encode_interface_import(name_map.get(name).unwrap_or(name), info)?
494 }
495 None => has_funcs = true,
496 }
497 }
498
499 let resolve = &self.info.encoder.metadata.resolve;
500 let world = &resolve.worlds[self.info.encoder.metadata.world];
501
502 for (_name, item) in world.imports.iter() {
505 if let WorldItem::Type { id, .. } = item {
506 self.root_import_type_encoder(None)
507 .encode_valtype(resolve, &Type::Id(*id))?;
508 }
509 }
510
511 if has_funcs {
512 let info = &self.info.import_map[&None];
513 self.encode_root_import_funcs(info)?;
514 }
515 Ok(())
516 }
517
518 fn encode_interface_import(&mut self, name: &str, info: &ImportedInterface) -> Result<()> {
519 let resolve = &self.info.encoder.metadata.resolve;
520 let interface_id = info.interface.as_ref().unwrap();
521 let interface_id = *interface_id;
522 let interface = &resolve.interfaces[interface_id];
523 log::trace!("encoding imports for `{name}` as {interface_id:?}");
524 let mut encoder = self.instance_type_encoder(interface_id);
525
526 if let Some(live) = encoder.state.info.live_type_imports.get(&interface_id) {
528 for ty in live {
529 log::trace!(
530 "encoding extra type {ty:?} name={:?}",
531 resolve.types[*ty].name
532 );
533 encoder.encode_valtype(resolve, &Type::Id(*ty))?;
534 }
535 }
536
537 for (_, func) in interface.functions.iter() {
540 if !(info
541 .lowerings
542 .contains_key(&(func.name.clone(), AbiVariant::GuestImport))
543 || info
544 .lowerings
545 .contains_key(&(func.name.clone(), AbiVariant::GuestImportAsync)))
546 {
547 continue;
548 }
549 log::trace!("encoding function type for `{}`", func.name);
550 let idx = encoder.encode_func_type(resolve, func)?;
551
552 encoder.ty.export(
553 crate::encoding::types::extern_name(&func.name, func.external_id.as_deref()),
554 ComponentTypeRef::Func(idx),
555 );
556 }
557
558 let ty = encoder.ty;
559 if ty.is_empty() {
562 return Ok(());
563 }
564 let instance_type_idx = self
565 .component
566 .type_instance(Some(&format!("ty-{name}")), &ty);
567 let instance_idx = self.component.import(
568 wasm_encoder::ComponentExternName {
569 name: name.into(),
570 implements: info.implements.as_deref().map(|s| s.into()),
571 external_id: info.external_id.as_deref().map(|s| s.into()),
572 version_suffix: None,
573 },
574 ComponentTypeRef::Instance(instance_type_idx),
575 );
576 let prev = self.instances.insert(interface_id, instance_idx);
577 assert!(prev.is_none());
578 Ok(())
579 }
580
581 fn encode_root_import_funcs(&mut self, info: &ImportedInterface) -> Result<()> {
582 let resolve = &self.info.encoder.metadata.resolve;
583 let world = self.info.encoder.metadata.world;
584 for (name, item) in resolve.worlds[world].imports.iter() {
585 let func = match item {
586 WorldItem::Function(f) => f,
587 WorldItem::Interface { .. } | WorldItem::Type { .. } => continue,
588 };
589 let name = resolve.name_world_key(name);
590 if !(info
591 .lowerings
592 .contains_key(&(name.clone(), AbiVariant::GuestImport))
593 || info
594 .lowerings
595 .contains_key(&(name.clone(), AbiVariant::GuestImportAsync)))
596 {
597 continue;
598 }
599 log::trace!("encoding function type for `{}`", func.name);
600 let idx = self
601 .root_import_type_encoder(None)
602 .encode_func_type(resolve, func)?;
603 let func_idx = self.component.import(
604 crate::encoding::types::extern_name(name.as_str(), func.external_id.as_deref()),
605 ComponentTypeRef::Func(idx),
606 );
607 let prev = self.imported_funcs.insert(name, func_idx);
608 assert!(prev.is_none());
609 }
610 Ok(())
611 }
612
613 fn alias_instance_type_export(&mut self, interface: InterfaceId, id: TypeId) -> u32 {
614 let ty = &self.info.encoder.metadata.resolve.types[id];
615 let name = ty.name.as_ref().expect("type must have a name");
616 let instance = self.instances[&interface];
617 self.component
618 .alias_export(instance, name, ComponentExportKind::Type)
619 }
620
621 fn encode_core_instantiation(&mut self) -> Result<()> {
622 let shims = self.encode_shim_instantiation()?;
624
625 self.declare_types_for_imported_intrinsics(&shims)?;
629
630 self.instantiate_main_module(&shims)?;
634
635 self.create_export_task_initialization_wrappers()?;
638
639 let (before, after) = self
642 .info
643 .adapters
644 .iter()
645 .partition::<Vec<_>, _>(|(_, adapter)| {
646 !matches!(
647 adapter.library_info,
648 Some(LibraryInfo {
649 instantiate_after_shims: true,
650 ..
651 })
652 )
653 });
654
655 for (name, _adapter) in before {
656 self.instantiate_adapter_module(&shims, name)?;
657 }
658
659 self.encode_indirect_lowerings(&shims)?;
662
663 for (name, _adapter) in after {
664 self.instantiate_adapter_module(&shims, name)?;
665 }
666
667 self.encode_initialize_with_start()?;
668
669 Ok(())
670 }
671
672 fn lookup_resource_index(&mut self, id: TypeId) -> u32 {
673 let resolve = &self.info.encoder.metadata.resolve;
674 let ty = &resolve.types[id];
675 match ty.owner {
676 TypeOwner::World(_) => self.type_encoding_maps.id_to_index[&id],
680 TypeOwner::Interface(i) => {
681 let instance = self.instances[&i];
682 let name = ty.name.as_ref().expect("resources must be named");
683 self.component
684 .alias_export(instance, name, ComponentExportKind::Type)
685 }
686 TypeOwner::None => panic!("resources must have an owner"),
687 }
688 }
689
690 fn encode_exports(&mut self, module: CustomModule) -> Result<()> {
691 let resolve = &self.info.encoder.metadata.resolve;
692 let exports = match module {
693 CustomModule::Main => &self.info.encoder.main_module_exports,
694 CustomModule::Adapter(name) => &self.info.encoder.adapters[name].required_exports,
695 };
696
697 if exports.is_empty() {
698 return Ok(());
699 }
700
701 let mut interface_func_core_names = IndexMap::new();
702 let mut world_func_core_names = IndexMap::new();
703 for (core_name, export) in self.info.exports_for(module).iter() {
704 match export {
705 Export::WorldFunc(_, name, _) => {
706 let prev = world_func_core_names.insert(name, core_name);
707 assert!(prev.is_none());
708 }
709 Export::InterfaceFunc(key, _, name, _) => {
710 let prev = interface_func_core_names
711 .entry(key)
712 .or_insert(IndexMap::new())
713 .insert(name.as_str(), core_name);
714 assert!(prev.is_none());
715 }
716 Export::WorldFuncCallback(..)
717 | Export::InterfaceFuncCallback(..)
718 | Export::WorldFuncPostReturn(..)
719 | Export::InterfaceFuncPostReturn(..)
720 | Export::ResourceDtor(..)
721 | Export::Memory
722 | Export::GeneralPurposeRealloc
723 | Export::GeneralPurposeExportRealloc
724 | Export::GeneralPurposeImportRealloc
725 | Export::Initialize
726 | Export::ReallocForAdapter
727 | Export::IndirectFunctionTable
728 | Export::WasmInitTask
729 | Export::WasmInitAsyncTask => continue,
730 }
731 }
732
733 let world = &resolve.worlds[self.info.encoder.metadata.world];
734
735 for export_name in exports {
736 let export_string = resolve.name_world_key(export_name);
737 match &world.exports[export_name] {
738 WorldItem::Function(func) => {
739 let ty = self
740 .root_import_type_encoder(None)
741 .encode_func_type(resolve, func)?;
742 let core_name = world_func_core_names[&func.name];
743 let idx = self.encode_lift(module, &core_name, export_name, func, ty)?;
744 self.component.export(
745 crate::encoding::types::extern_name(
746 &export_string,
747 func.external_id.as_deref(),
748 ),
749 ComponentExportKind::Func,
750 idx,
751 None,
752 );
753 }
754 item @ WorldItem::Interface { id, .. } => {
755 let core_names = interface_func_core_names.get(export_name);
756 self.encode_interface_export(
757 &export_string,
758 module,
759 export_name,
760 item,
761 *id,
762 core_names,
763 )?;
764 }
765 WorldItem::Type { .. } => unreachable!(),
766 }
767 }
768
769 Ok(())
770 }
771
772 fn encode_interface_export(
773 &mut self,
774 export_name: &str,
775 module: CustomModule<'_>,
776 key: &WorldKey,
777 item: &WorldItem,
778 export: InterfaceId,
779 interface_func_core_names: Option<&IndexMap<&str, &str>>,
780 ) -> Result<()> {
781 log::trace!("encode interface export `{export_name}`");
782 let resolve = &self.info.encoder.metadata.resolve;
783
784 let mut imports = Vec::new();
791 let mut root = self.root_export_type_encoder(Some(export));
792 for (_, func) in &resolve.interfaces[export].functions {
793 let core_name = interface_func_core_names.unwrap()[func.name.as_str()];
794 let ty = root.encode_func_type(resolve, func)?;
795 let func_index = root.state.encode_lift(module, &core_name, key, func, ty)?;
796 imports.push((
797 import_func_name(func),
798 ComponentExportKind::Func,
799 func_index,
800 ));
801 }
802
803 let mut nested = NestedComponentTypeEncoder {
807 component: ComponentBuilder::default(),
808 type_encoding_maps: Default::default(),
809 export_types: false,
810 interface: export,
811 state: self,
812 imports: IndexMap::new(),
813 };
814
815 let mut types_to_import = LiveTypes::default();
825 types_to_import.add_interface(resolve, export);
826 let exports_used = &nested.state.info.exports_used[&export];
827 for ty in types_to_import.iter() {
828 if let TypeOwner::Interface(owner) = resolve.types[ty].owner {
829 if owner == export {
830 continue;
833 }
834
835 let mut encoder = if exports_used.contains(&owner) {
838 nested.state.root_export_type_encoder(Some(export))
839 } else {
840 nested.state.root_import_type_encoder(Some(export))
841 };
842 encoder.encode_valtype(resolve, &Type::Id(ty))?;
843
844 nested.interface = owner;
848 nested.encode_valtype(resolve, &Type::Id(ty))?;
849 }
850 }
851 nested.interface = export;
852
853 let imported_type_maps = nested.type_encoding_maps.clone();
857
858 let mut resources = HashMap::new();
864 for (_name, ty) in resolve.interfaces[export].types.iter() {
865 if !matches!(resolve.types[*ty].kind, TypeDefKind::Resource) {
866 continue;
867 }
868 let idx = match nested.encode_valtype(resolve, &Type::Id(*ty))? {
869 ComponentValType::Type(idx) => idx,
870 _ => unreachable!(),
871 };
872 resources.insert(*ty, idx);
873 }
874
875 for (_, func) in resolve.interfaces[export].functions.iter() {
879 let ty = nested.encode_func_type(resolve, func)?;
880 nested
881 .component
882 .import(&import_func_name(func), ComponentTypeRef::Func(ty));
883 }
884
885 let reverse_map = nested
892 .type_encoding_maps
893 .id_to_index
894 .drain()
895 .map(|p| (p.1, p.0))
896 .collect::<HashMap<_, _>>();
897 nested.type_encoding_maps.def_to_index.clear();
898 for (name, idx) in nested.imports.drain(..) {
899 let id = reverse_map[&idx];
900 let idx = nested.state.type_encoding_maps.id_to_index[&id];
901 imports.push((name, ComponentExportKind::Type, idx))
902 }
903
904 nested.type_encoding_maps = imported_type_maps;
909
910 nested.export_types = true;
917 nested.type_encoding_maps.func_type_map.clear();
918
919 for (_, id) in resolve.interfaces[export].types.iter() {
925 let ty = &resolve.types[*id];
926 match ty.kind {
927 TypeDefKind::Resource => {
928 let idx = nested.component.export(
929 crate::encoding::types::extern_name(
930 ty.name.as_ref().expect("resources must be named"),
931 ty.external_id.as_deref(),
932 ),
933 ComponentExportKind::Type,
934 resources[id],
935 None,
936 );
937 nested.type_encoding_maps.id_to_index.insert(*id, idx);
938 }
939 _ => {
940 nested.encode_valtype(resolve, &Type::Id(*id))?;
941 }
942 }
943 }
944
945 for (i, (_, func)) in resolve.interfaces[export].functions.iter().enumerate() {
946 let ty = nested.encode_func_type(resolve, func)?;
947 nested.component.export(
948 crate::encoding::types::extern_name(&func.name, func.external_id.as_deref()),
949 ComponentExportKind::Func,
950 i as u32,
951 Some(ComponentTypeRef::Func(ty)),
952 );
953 }
954
955 let component = nested.component;
959 let component_index = self
960 .component
961 .component(Some(&format!("{export_name}-shim-component")), component);
962 let instance_index = self.component.instantiate(
963 Some(&format!("{export_name}-shim-instance")),
964 component_index,
965 imports,
966 );
967 let idx = self.component.export(
968 wasm_encoder::ComponentExternName {
969 name: export_name.into(),
970 implements: resolve.implements_value(key, item).map(|s| s.into()),
971 external_id: resolve.external_id_value(key, item).map(|s| s.into()),
972 version_suffix: None,
973 },
974 ComponentExportKind::Instance,
975 instance_index,
976 None,
977 );
978 let prev = self.instances.insert(export, idx);
979 assert!(prev.is_none());
980
981 for (_name, id) in resolve.interfaces[export].types.iter() {
989 self.type_encoding_maps.id_to_index.remove(id);
990 self.type_encoding_maps
991 .def_to_index
992 .remove(&resolve.types[*id].kind);
993 }
994
995 return Ok(());
996
997 struct NestedComponentTypeEncoder<'state, 'a> {
998 component: ComponentBuilder,
999 type_encoding_maps: TypeEncodingMaps<'a>,
1000 export_types: bool,
1001 interface: InterfaceId,
1002 state: &'state mut EncodingState<'a>,
1003 imports: IndexMap<String, u32>,
1004 }
1005
1006 impl<'a> ValtypeEncoder<'a> for NestedComponentTypeEncoder<'_, 'a> {
1007 fn defined_type(&mut self) -> (u32, ComponentDefinedTypeEncoder<'_>) {
1008 self.component.type_defined(None)
1009 }
1010 fn define_function_type(&mut self) -> (u32, ComponentFuncTypeEncoder<'_>) {
1011 self.component.type_function(None)
1012 }
1013 fn export_type(
1014 &mut self,
1015 idx: u32,
1016 name: wasm_encoder::ComponentExternName<'a>,
1017 ) -> Option<u32> {
1018 if self.export_types {
1019 Some(
1020 self.component
1021 .export(name, ComponentExportKind::Type, idx, None),
1022 )
1023 } else {
1024 let name = self.unique_import_name(&name.name);
1025 let ret = self
1026 .component
1027 .import(&name, ComponentTypeRef::Type(TypeBounds::Eq(idx)));
1028 self.imports.insert(name, ret);
1029 Some(ret)
1030 }
1031 }
1032 fn export_resource(&mut self, name: wasm_encoder::ComponentExternName<'a>) -> u32 {
1033 if self.export_types {
1034 panic!("resources should already be exported")
1035 } else {
1036 let name = self.unique_import_name(&name.name);
1037 let ret = self
1038 .component
1039 .import(&name, ComponentTypeRef::Type(TypeBounds::SubResource));
1040 self.imports.insert(name, ret);
1041 ret
1042 }
1043 }
1044 fn import_type(&mut self, _: InterfaceId, _id: TypeId) -> u32 {
1045 unreachable!()
1046 }
1047 fn type_encoding_maps(&mut self) -> &mut TypeEncodingMaps<'a> {
1048 &mut self.type_encoding_maps
1049 }
1050 fn interface(&self) -> Option<InterfaceId> {
1051 Some(self.interface)
1052 }
1053 }
1054
1055 impl NestedComponentTypeEncoder<'_, '_> {
1056 fn unique_import_name(&mut self, name: &str) -> String {
1057 let mut name = format!("import-type-{name}");
1058 let mut n = 0;
1059 while self.imports.contains_key(&name) {
1060 name = format!("{name}{n}");
1061 n += 1;
1062 }
1063 name
1064 }
1065 }
1066 }
1067
1068 fn encode_lift(
1069 &mut self,
1070 module: CustomModule<'_>,
1071 core_name: &str,
1072 key: &WorldKey,
1073 func: &Function,
1074 ty: u32,
1075 ) -> Result<u32> {
1076 let resolve = &self.info.encoder.metadata.resolve;
1077 let metadata = self.info.module_metadata_for(module);
1078 let instance_index = self.instance_for(module);
1079 let core_func_index =
1082 if let Some(&wrapper_idx) = self.export_task_initialization_wrappers.get(core_name) {
1083 wrapper_idx
1084 } else {
1085 self.core_alias_export(Some(core_name), instance_index, core_name, ExportKind::Func)
1086 };
1087 let exports = self.info.exports_for(module);
1088
1089 let options = RequiredOptions::for_export(
1090 resolve,
1091 func,
1092 exports
1093 .abi(key, func)
1094 .ok_or_else(|| anyhow!("no ABI found for {}", func.name))?,
1095 );
1096
1097 let encoding = metadata
1098 .export_encodings
1099 .get(resolve, key, &func.name)
1100 .unwrap();
1101 let exports = self.info.exports_for(module);
1102 let realloc_index = exports
1103 .export_realloc_for(key, &func.name)
1104 .map(|name| self.core_alias_export(Some(name), instance_index, name, ExportKind::Func));
1105 let mut options = options
1106 .into_iter(encoding, self.memory_index, realloc_index)?
1107 .collect::<Vec<_>>();
1108
1109 if let Some(post_return) = exports.post_return(key, func) {
1110 let post_return = self.core_alias_export(
1111 Some(post_return),
1112 instance_index,
1113 post_return,
1114 ExportKind::Func,
1115 );
1116 options.push(CanonicalOption::PostReturn(post_return));
1117 }
1118 if let Some(callback) = exports.callback(key, func) {
1119 let callback =
1120 self.core_alias_export(Some(callback), instance_index, callback, ExportKind::Func);
1121 options.push(CanonicalOption::Callback(callback));
1122 }
1123 let func_index = self
1124 .component
1125 .lift_func(Some(&func.name), core_func_index, ty, options);
1126 Ok(func_index)
1127 }
1128
1129 fn encode_shim_instantiation(&mut self) -> Result<Shims<'a>> {
1130 let mut ret = Shims::default();
1131
1132 ret.append_indirect(self.info, CustomModule::Main)
1133 .context("failed to register indirect shims for main module")?;
1134
1135 for (adapter_name, _adapter) in self.info.adapters.iter() {
1139 ret.append_indirect(self.info, CustomModule::Adapter(adapter_name))
1140 .with_context(|| {
1141 format!("failed to register indirect shims for adapter {adapter_name}")
1142 })?;
1143 }
1144
1145 if ret.shims.is_empty() {
1146 return Ok(ret);
1147 }
1148
1149 assert!(self.shim_instance_index.is_none());
1150 assert!(self.fixups_module_index.is_none());
1151
1152 let mut types = TypeSection::new();
1161 let mut tables = TableSection::new();
1162 let mut functions = FunctionSection::new();
1163 let mut exports = ExportSection::new();
1164 let mut code = CodeSection::new();
1165 let mut sigs = IndexMap::new();
1166 let mut imports_section = ImportSection::new();
1167 let mut elements = ElementSection::new();
1168 let mut func_indexes = Vec::new();
1169 let mut func_names = NameMap::new();
1170
1171 for (i, shim) in ret.shims.values().enumerate() {
1172 let i = i as u32;
1173 let type_index = *sigs.entry(&shim.sig).or_insert_with(|| {
1174 let index = types.len();
1175 types.ty().function(
1176 shim.sig.params.iter().map(to_val_type),
1177 shim.sig.results.iter().map(to_val_type),
1178 );
1179 index
1180 });
1181
1182 functions.function(type_index);
1183 Self::encode_shim_function(type_index, i, &mut code, shim.sig.params.len() as u32);
1184 exports.export(&shim.name, ExportKind::Func, i);
1185
1186 imports_section.import("", &shim.name, EntityType::Function(type_index));
1187 func_indexes.push(i);
1188 func_names.append(i, &shim.debug_name);
1189 }
1190 let mut names = NameSection::new();
1191 names.module("wit-component:shim");
1192 names.functions(&func_names);
1193
1194 let table_type = TableType {
1195 element_type: RefType::FUNCREF,
1196 minimum: ret.shims.len() as u64,
1197 maximum: Some(ret.shims.len() as u64),
1198 table64: false,
1199 shared: false,
1200 };
1201
1202 tables.table(table_type);
1203
1204 exports.export(INDIRECT_TABLE_NAME, ExportKind::Table, 0);
1205 imports_section.import("", INDIRECT_TABLE_NAME, table_type);
1206
1207 elements.active(
1208 None,
1209 &ConstExpr::i32_const(0),
1210 Elements::Functions(func_indexes.into()),
1211 );
1212
1213 let mut shim = Module::new();
1214 shim.section(&types);
1215 shim.section(&functions);
1216 shim.section(&tables);
1217 shim.section(&exports);
1218 shim.section(&code);
1219 shim.section(&RawCustomSection(
1220 &crate::base_producers().raw_custom_section(),
1221 ));
1222 if self.info.encoder.debug_names {
1223 shim.section(&names);
1224 }
1225
1226 let mut fixups = Module::default();
1227 fixups.section(&types);
1228 fixups.section(&imports_section);
1229 fixups.section(&elements);
1230 fixups.section(&RawCustomSection(
1231 &crate::base_producers().raw_custom_section(),
1232 ));
1233
1234 if self.info.encoder.debug_names {
1235 let mut names = NameSection::new();
1236 names.module("wit-component:fixups");
1237 fixups.section(&names);
1238 }
1239
1240 let shim_module_index = self
1241 .component
1242 .core_module(Some("wit-component-shim-module"), &shim);
1243 let fixup_index = self
1244 .component
1245 .core_module(Some("wit-component-fixup"), &fixups);
1246 self.fixups_module_index = Some(fixup_index);
1247 let shim_instance = self.component.core_instantiate(
1248 Some("wit-component-shim-instance"),
1249 shim_module_index,
1250 [],
1251 );
1252 self.shim_instance_index = Some(shim_instance);
1253
1254 return Ok(ret);
1255 }
1256
1257 fn encode_shim_function(
1258 type_index: u32,
1259 func_index: u32,
1260 code: &mut CodeSection,
1261 param_count: u32,
1262 ) {
1263 let mut func = wasm_encoder::Function::new(std::iter::empty());
1264 for i in 0..param_count {
1265 func.instructions().local_get(i);
1266 }
1267 func.instructions().i32_const(func_index as i32);
1268 func.instructions().call_indirect(0, type_index);
1269 func.instructions().end();
1270 code.function(&func);
1271 }
1272
1273 fn encode_indirect_lowerings(&mut self, shims: &Shims<'_>) -> Result<()> {
1274 if shims.shims.is_empty() {
1275 return Ok(());
1276 }
1277
1278 let shim_instance_index = self
1279 .shim_instance_index
1280 .expect("must have an instantiated shim");
1281
1282 let table_index = self.core_alias_export(
1283 Some("shim table"),
1284 shim_instance_index,
1285 INDIRECT_TABLE_NAME,
1286 ExportKind::Table,
1287 );
1288
1289 let resolve = &self.info.encoder.metadata.resolve;
1290
1291 let mut exports = Vec::new();
1292 exports.push((INDIRECT_TABLE_NAME, ExportKind::Table, table_index));
1293
1294 for shim in shims.shims.values() {
1295 let core_func_index = match &shim.kind {
1296 ShimKind::IndirectLowering {
1303 interface,
1304 index,
1305 realloc,
1306 encoding,
1307 } => {
1308 let interface = &self.info.import_map[interface];
1309 let ((name, _), _) = interface.lowerings.get_index(*index).unwrap();
1310 let func_index = match &interface.interface {
1311 Some(interface_id) => {
1312 let instance_index = self.instances[interface_id];
1313 self.component.alias_export(
1314 instance_index,
1315 name,
1316 ComponentExportKind::Func,
1317 )
1318 }
1319 None => self.imported_funcs[name],
1320 };
1321
1322 let realloc = self
1323 .info
1324 .exports_for(*realloc)
1325 .import_realloc_for(interface.interface, name)
1326 .map(|name| {
1327 let instance = self.instance_for(*realloc);
1328 self.core_alias_export(
1329 Some("realloc"),
1330 instance,
1331 name,
1332 ExportKind::Func,
1333 )
1334 });
1335
1336 self.component.lower_func(
1337 Some(&shim.debug_name),
1338 func_index,
1339 shim.options
1340 .into_iter(*encoding, self.memory_index, realloc)?,
1341 )
1342 }
1343
1344 ShimKind::Adapter { adapter, func } => self.core_alias_export(
1349 Some(func),
1350 self.adapter_instances[adapter],
1351 func,
1352 ExportKind::Func,
1353 ),
1354
1355 ShimKind::ResourceDtor { module, export } => self.core_alias_export(
1360 Some(export),
1361 self.instance_for(*module),
1362 export,
1363 ExportKind::Func,
1364 ),
1365
1366 ShimKind::PayloadFunc {
1367 for_module,
1368 info,
1369 kind,
1370 } => {
1371 let metadata = self.info.module_metadata_for(*for_module);
1372 let exports = self.info.exports_for(*for_module);
1373 let instance_index = self.instance_for(*for_module);
1374 let (encoding, realloc) = match &info.ty {
1375 PayloadType::Type { function, .. } => {
1376 if info.imported {
1377 (
1378 metadata.import_encodings.get(resolve, &info.key, function),
1379 exports.import_realloc_for(info.interface, function),
1380 )
1381 } else {
1382 (
1383 metadata.export_encodings.get(resolve, &info.key, function),
1384 exports.export_realloc_for(&info.key, function),
1385 )
1386 }
1387 }
1388 PayloadType::UnitFuture | PayloadType::UnitStream => (None, None),
1389 };
1390 let encoding = encoding.unwrap_or(StringEncoding::UTF8);
1391 let realloc_index = realloc.map(|name| {
1392 self.core_alias_export(
1393 Some("realloc"),
1394 instance_index,
1395 name,
1396 ExportKind::Func,
1397 )
1398 });
1399 let type_index = self.payload_type_index(info)?;
1400 let options =
1401 shim.options
1402 .into_iter(encoding, self.memory_index, realloc_index)?;
1403
1404 match kind {
1405 PayloadFuncKind::FutureWrite => {
1406 self.component.future_write(type_index, options)
1407 }
1408 PayloadFuncKind::FutureRead => {
1409 self.component.future_read(type_index, options)
1410 }
1411 PayloadFuncKind::StreamWrite => {
1412 self.component.stream_write(type_index, options)
1413 }
1414 PayloadFuncKind::StreamRead => {
1415 self.component.stream_read(type_index, options)
1416 }
1417 }
1418 }
1419
1420 ShimKind::WaitableSetWait { cancellable } => self
1421 .component
1422 .waitable_set_wait(*cancellable, self.memory_index.unwrap()),
1423 ShimKind::WaitableSetPoll { cancellable } => self
1424 .component
1425 .waitable_set_poll(*cancellable, self.memory_index.unwrap()),
1426 ShimKind::ErrorContextNew { encoding } => self.component.error_context_new(
1427 shim.options.into_iter(*encoding, self.memory_index, None)?,
1428 ),
1429 ShimKind::ErrorContextDebugMessage {
1430 for_module,
1431 encoding,
1432 } => {
1433 let instance_index = self.instance_for(*for_module);
1434 let realloc = self.info.exports_for(*for_module).import_realloc_fallback();
1435 let realloc_index = realloc.map(|r| {
1436 self.core_alias_export(Some("realloc"), instance_index, r, ExportKind::Func)
1437 });
1438
1439 self.component
1440 .error_context_debug_message(shim.options.into_iter(
1441 *encoding,
1442 self.memory_index,
1443 realloc_index,
1444 )?)
1445 }
1446 ShimKind::TaskReturn {
1447 interface,
1448 func,
1449 result,
1450 encoding,
1451 for_module,
1452 } => {
1453 let mut encoder = if interface.is_none() {
1456 self.root_import_type_encoder(*interface)
1457 } else {
1458 self.root_export_type_encoder(*interface)
1459 };
1460 let result = match result {
1461 Some(ty) => Some(encoder.encode_valtype(resolve, ty)?),
1462 None => None,
1463 };
1464
1465 let exports = self.info.exports_for(*for_module);
1466 let realloc = exports.import_realloc_for(*interface, func);
1467
1468 let instance_index = self.instance_for(*for_module);
1469 let realloc_index = realloc.map(|r| {
1470 self.core_alias_export(Some("realloc"), instance_index, r, ExportKind::Func)
1471 });
1472 let options =
1473 shim.options
1474 .into_iter(*encoding, self.memory_index, realloc_index)?;
1475 self.component.task_return(result, options)
1476 }
1477 ShimKind::ThreadNewIndirect {
1478 for_module,
1479 func_ty,
1480 } => {
1481 let (func_ty_idx, f) = self.component.core_type(Some("thread-start"));
1483 f.core().func_type(func_ty);
1484
1485 let exports = self.info.exports_for(*for_module);
1488 let instance_index = self.instance_for(*for_module);
1489 let table_idx = exports.indirect_function_table().map(|table| {
1490 self.core_alias_export(
1491 Some("indirect-function-table"),
1492 instance_index,
1493 table,
1494 ExportKind::Table,
1495 )
1496 }).ok_or_else(|| {
1497 anyhow!(
1498 "table __indirect_function_table must be an exported funcref table for thread.new-indirect"
1499 )
1500 })?;
1501
1502 self.component.thread_new_indirect(func_ty_idx, table_idx)
1503 }
1504 };
1505
1506 exports.push((shim.name.as_str(), ExportKind::Func, core_func_index));
1507 }
1508
1509 let instance_index = self
1510 .component
1511 .core_instantiate_exports(Some("fixup-args"), exports);
1512 self.component.core_instantiate(
1513 Some("fixup"),
1514 self.fixups_module_index.expect("must have fixup module"),
1515 [("", ModuleArg::Instance(instance_index))],
1516 );
1517 Ok(())
1518 }
1519
1520 fn payload_type_index(&mut self, info: &PayloadInfo) -> Result<u32> {
1528 let resolve = &self.info.encoder.metadata.resolve;
1529 let mut encoder = if info.imported || info.interface.is_none() {
1545 self.root_import_type_encoder(None)
1546 } else {
1547 self.root_export_type_encoder(info.interface)
1548 };
1549 match info.ty {
1550 PayloadType::Type { id, .. } => match encoder.encode_valtype(resolve, &Type::Id(id))? {
1551 ComponentValType::Type(index) => Ok(index),
1552 ComponentValType::Primitive(_) => unreachable!(),
1553 },
1554 PayloadType::UnitFuture => Ok(encoder.encode_unit_future()),
1555 PayloadType::UnitStream => Ok(encoder.encode_unit_stream()),
1556 }
1557 }
1558
1559 fn declare_types_for_imported_intrinsics(&mut self, shims: &Shims<'_>) -> Result<()> {
1566 let resolve = &self.info.encoder.metadata.resolve;
1567 let world = &resolve.worlds[self.info.encoder.metadata.world];
1568
1569 let main_module_keys = self.info.encoder.main_module_exports.iter();
1572 let main_module_keys = main_module_keys.map(|key| (CustomModule::Main, key));
1573 let adapter_keys = self.info.encoder.adapters.iter().flat_map(|(name, info)| {
1574 info.required_exports
1575 .iter()
1576 .map(move |key| (CustomModule::Adapter(name), key))
1577 });
1578 for (for_module, key) in main_module_keys.chain(adapter_keys) {
1579 let id = match &world.exports[key] {
1580 WorldItem::Interface { id, .. } => *id,
1581 WorldItem::Type { .. } => unreachable!(),
1582 WorldItem::Function(_) => continue,
1583 };
1584
1585 for ty in resolve.interfaces[id].types.values() {
1586 let def = &resolve.types[*ty];
1587 match &def.kind {
1588 TypeDefKind::Resource => {
1592 let exports = self.info.exports_for(for_module);
1595 let dtor = exports.resource_dtor(*ty).map(|name| {
1596 let shim = &shims.shims[&ShimKind::ResourceDtor {
1597 module: for_module,
1598 export: name,
1599 }];
1600 let index = self.shim_instance_index.unwrap();
1601 self.core_alias_export(
1602 Some(&shim.debug_name),
1603 index,
1604 &shim.name,
1605 ExportKind::Func,
1606 )
1607 });
1608
1609 let resource_idx = self.component.type_resource(
1613 Some(def.name.as_ref().unwrap()),
1614 ValType::I32,
1615 dtor,
1616 );
1617 let prev = self
1618 .type_encoding_maps
1619 .id_to_index
1620 .insert(*ty, resource_idx);
1621 assert!(prev.is_none());
1622 }
1623 _other => {
1624 self.root_export_type_encoder(Some(id))
1625 .encode_valtype(resolve, &Type::Id(*ty))?;
1626 }
1627 }
1628 }
1629 }
1630 Ok(())
1631 }
1632
1633 fn instantiate_main_module(&mut self, shims: &Shims<'_>) -> Result<()> {
1636 assert!(self.instance_index.is_none());
1637
1638 let instance_index = self.instantiate_core_module(shims, CustomModule::Main)?;
1639
1640 if let Some(memory) = self.info.info.exports.memory() {
1641 self.memory_index = Some(self.core_alias_export(
1642 Some("memory"),
1643 instance_index,
1644 memory,
1645 ExportKind::Memory,
1646 ));
1647 }
1648
1649 self.instance_index = Some(instance_index);
1650 Ok(())
1651 }
1652
1653 fn instantiate_adapter_module(&mut self, shims: &Shims<'_>, name: &'a str) -> Result<()> {
1656 let instance = self.instantiate_core_module(shims, CustomModule::Adapter(name))?;
1657 self.adapter_instances.insert(name, instance);
1658 Ok(())
1659 }
1660
1661 fn instantiate_core_module(
1668 &mut self,
1669 shims: &Shims,
1670 for_module: CustomModule<'_>,
1671 ) -> Result<u32> {
1672 let module = self.module_for(for_module);
1673
1674 let mut args = Vec::new();
1675 for (core_wasm_name, instance) in self.info.imports_for(for_module).modules() {
1676 match instance {
1677 ImportInstance::Names(names) => {
1683 let mut exports = Vec::new();
1684 for (name, import) in names {
1685 log::trace!(
1686 "attempting to materialize import of `{core_wasm_name}::{name}` for {for_module:?}"
1687 );
1688 let (kind, index) = self
1689 .materialize_import(&shims, for_module, import)
1690 .with_context(|| {
1691 format!("failed to satisfy import `{core_wasm_name}::{name}`")
1692 })?;
1693 exports.push((name.as_str(), kind, index));
1694 }
1695 let index = self
1696 .component
1697 .core_instantiate_exports(Some(core_wasm_name), exports);
1698 args.push((core_wasm_name.as_str(), ModuleArg::Instance(index)));
1699 }
1700
1701 ImportInstance::Whole(which) => {
1704 let instance = self.instance_for(which.to_custom_module());
1705 args.push((core_wasm_name.as_str(), ModuleArg::Instance(instance)));
1706 }
1707 }
1708 }
1709
1710 Ok(self
1712 .component
1713 .core_instantiate(Some(for_module.debug_name()), module, args))
1714 }
1715
1716 fn materialize_import(
1723 &mut self,
1724 shims: &Shims<'_>,
1725 for_module: CustomModule<'_>,
1726 import: &'a Import,
1727 ) -> Result<(ExportKind, u32)> {
1728 let resolve = &self.info.encoder.metadata.resolve;
1729 match import {
1730 Import::AdapterExport {
1733 adapter,
1734 func,
1735 ty: _,
1736 } => {
1737 assert!(self.info.encoder.adapters.contains_key(adapter));
1738 Ok(self.materialize_shim_import(shims, &ShimKind::Adapter { adapter, func }))
1739 }
1740
1741 Import::MainModuleMemory => {
1744 let index = self
1745 .memory_index
1746 .ok_or_else(|| anyhow!("main module cannot import memory"))?;
1747 Ok((ExportKind::Memory, index))
1748 }
1749
1750 Import::MainModuleExport { name, kind } => {
1752 let instance = self.instance_index.unwrap();
1753 let index = self.core_alias_export(Some(name), instance, name, *kind);
1754 Ok((*kind, index))
1755 }
1756
1757 Import::Item(item) => {
1761 let instance = self.instance_for(item.which.to_custom_module());
1762 let index =
1763 self.core_alias_export(Some(&item.name), instance, &item.name, item.kind);
1764 Ok((item.kind, index))
1765 }
1766
1767 Import::ExportedResourceDrop(_key, id) => {
1773 let index = self
1774 .component
1775 .resource_drop(self.type_encoding_maps.id_to_index[id]);
1776 Ok((ExportKind::Func, index))
1777 }
1778 Import::ExportedResourceRep(_key, id) => {
1779 let index = self
1780 .component
1781 .resource_rep(self.type_encoding_maps.id_to_index[id]);
1782 Ok((ExportKind::Func, index))
1783 }
1784 Import::ExportedResourceNew(_key, id) => {
1785 let index = self
1786 .component
1787 .resource_new(self.type_encoding_maps.id_to_index[id]);
1788 Ok((ExportKind::Func, index))
1789 }
1790
1791 Import::ImportedResourceDrop(key, iface, id) => {
1796 let ty = &resolve.types[*id];
1797 let name = ty.name.as_ref().unwrap();
1798 self.materialize_wit_import(
1799 shims,
1800 for_module,
1801 iface.map(|_| resolve.name_world_key(key)),
1802 &format!("{name}_drop"),
1803 key,
1804 AbiVariant::GuestImport,
1805 )
1806 }
1807 Import::ExportedTaskReturn(key, interface, func) => {
1808 let (options, _sig) = task_return_options_and_type(resolve, func);
1809 let result_ty = func.result;
1810 if options.is_empty() {
1811 let mut encoder = if interface.is_none() {
1817 self.root_import_type_encoder(*interface)
1818 } else {
1819 self.root_export_type_encoder(*interface)
1820 };
1821
1822 let result = match result_ty.as_ref() {
1823 Some(ty) => Some(encoder.encode_valtype(resolve, ty)?),
1824 None => None,
1825 };
1826 let index = self.component.task_return(result, []);
1827 Ok((ExportKind::Func, index))
1828 } else {
1829 let metadata = &self.info.module_metadata_for(for_module);
1830 let encoding = metadata
1831 .export_encodings
1832 .get(resolve, key, &func.name)
1833 .unwrap();
1834 Ok(self.materialize_shim_import(
1835 shims,
1836 &ShimKind::TaskReturn {
1837 for_module,
1838 interface: *interface,
1839 func: &func.name,
1840 result: result_ty,
1841 encoding,
1842 },
1843 ))
1844 }
1845 }
1846 Import::BackpressureInc => {
1847 let index = self.component.backpressure_inc();
1848 Ok((ExportKind::Func, index))
1849 }
1850 Import::BackpressureDec => {
1851 let index = self.component.backpressure_dec();
1852 Ok((ExportKind::Func, index))
1853 }
1854 Import::WaitableSetWait { cancellable } => Ok(self.materialize_shim_import(
1855 shims,
1856 &ShimKind::WaitableSetWait {
1857 cancellable: *cancellable,
1858 },
1859 )),
1860 Import::WaitableSetPoll { cancellable } => Ok(self.materialize_shim_import(
1861 shims,
1862 &ShimKind::WaitableSetPoll {
1863 cancellable: *cancellable,
1864 },
1865 )),
1866 Import::SubtaskDrop => {
1867 let index = self.component.subtask_drop();
1868 Ok((ExportKind::Func, index))
1869 }
1870 Import::SubtaskCancel { async_ } => {
1871 let index = self.component.subtask_cancel(*async_);
1872 Ok((ExportKind::Func, index))
1873 }
1874 Import::StreamNew(info) => {
1875 let ty = self.payload_type_index(info)?;
1876 let index = self.component.stream_new(ty);
1877 Ok((ExportKind::Func, index))
1878 }
1879 Import::StreamRead { info, .. } => Ok(self.materialize_payload_import(
1880 shims,
1881 for_module,
1882 info,
1883 PayloadFuncKind::StreamRead,
1884 )),
1885 Import::StreamWrite { info, .. } => Ok(self.materialize_payload_import(
1886 shims,
1887 for_module,
1888 info,
1889 PayloadFuncKind::StreamWrite,
1890 )),
1891 Import::StreamCancelRead { info, async_ } => {
1892 let ty = self.payload_type_index(info)?;
1893 let index = self.component.stream_cancel_read(ty, *async_);
1894 Ok((ExportKind::Func, index))
1895 }
1896 Import::StreamCancelWrite { info, async_ } => {
1897 let ty = self.payload_type_index(info)?;
1898 let index = self.component.stream_cancel_write(ty, *async_);
1899 Ok((ExportKind::Func, index))
1900 }
1901 Import::StreamDropReadable(info) => {
1902 let type_index = self.payload_type_index(info)?;
1903 let index = self.component.stream_drop_readable(type_index);
1904 Ok((ExportKind::Func, index))
1905 }
1906 Import::StreamDropWritable(info) => {
1907 let type_index = self.payload_type_index(info)?;
1908 let index = self.component.stream_drop_writable(type_index);
1909 Ok((ExportKind::Func, index))
1910 }
1911 Import::FutureNew(info) => {
1912 let ty = self.payload_type_index(info)?;
1913 let index = self.component.future_new(ty);
1914 Ok((ExportKind::Func, index))
1915 }
1916 Import::FutureRead { info, .. } => Ok(self.materialize_payload_import(
1917 shims,
1918 for_module,
1919 info,
1920 PayloadFuncKind::FutureRead,
1921 )),
1922 Import::FutureWrite { info, .. } => Ok(self.materialize_payload_import(
1923 shims,
1924 for_module,
1925 info,
1926 PayloadFuncKind::FutureWrite,
1927 )),
1928 Import::FutureCancelRead { info, async_ } => {
1929 let ty = self.payload_type_index(info)?;
1930 let index = self.component.future_cancel_read(ty, *async_);
1931 Ok((ExportKind::Func, index))
1932 }
1933 Import::FutureCancelWrite { info, async_ } => {
1934 let ty = self.payload_type_index(info)?;
1935 let index = self.component.future_cancel_write(ty, *async_);
1936 Ok((ExportKind::Func, index))
1937 }
1938 Import::FutureDropReadable(info) => {
1939 let type_index = self.payload_type_index(info)?;
1940 let index = self.component.future_drop_readable(type_index);
1941 Ok((ExportKind::Func, index))
1942 }
1943 Import::FutureDropWritable(info) => {
1944 let type_index = self.payload_type_index(info)?;
1945 let index = self.component.future_drop_writable(type_index);
1946 Ok((ExportKind::Func, index))
1947 }
1948 Import::ErrorContextNew { encoding } => Ok(self.materialize_shim_import(
1949 shims,
1950 &ShimKind::ErrorContextNew {
1951 encoding: *encoding,
1952 },
1953 )),
1954 Import::ErrorContextDebugMessage { encoding } => Ok(self.materialize_shim_import(
1955 shims,
1956 &ShimKind::ErrorContextDebugMessage {
1957 for_module,
1958 encoding: *encoding,
1959 },
1960 )),
1961 Import::ErrorContextDrop => {
1962 let index = self.component.error_context_drop();
1963 Ok((ExportKind::Func, index))
1964 }
1965 Import::WorldFunc(key, name, abi) => {
1966 self.materialize_wit_import(shims, for_module, None, name, key, *abi)
1967 }
1968 Import::InterfaceFunc(key, _, name, abi) => self.materialize_wit_import(
1969 shims,
1970 for_module,
1971 Some(resolve.name_world_key(key)),
1972 name,
1973 key,
1974 *abi,
1975 ),
1976
1977 Import::WaitableSetNew => {
1978 let index = self.component.waitable_set_new();
1979 Ok((ExportKind::Func, index))
1980 }
1981 Import::WaitableSetDrop => {
1982 let index = self.component.waitable_set_drop();
1983 Ok((ExportKind::Func, index))
1984 }
1985 Import::WaitableJoin => {
1986 let index = self.component.waitable_join();
1987 Ok((ExportKind::Func, index))
1988 }
1989 Import::ContextGet { ty, slot } => {
1990 let index = self.component.context_get((*ty).try_into()?, *slot);
1991 Ok((ExportKind::Func, index))
1992 }
1993 Import::ContextSet { ty, slot } => {
1994 let index = self.component.context_set((*ty).try_into()?, *slot);
1995 Ok((ExportKind::Func, index))
1996 }
1997 Import::ExportedTaskCancel => {
1998 let index = self.component.task_cancel();
1999 Ok((ExportKind::Func, index))
2000 }
2001 Import::ThreadIndex => {
2002 let index = self.component.thread_index();
2003 Ok((ExportKind::Func, index))
2004 }
2005 Import::ThreadNewIndirect => Ok(self.materialize_shim_import(
2006 shims,
2007 &ShimKind::ThreadNewIndirect {
2008 for_module,
2009 func_ty: FuncType::new([ValType::I32], []),
2011 },
2012 )),
2013 Import::ThreadResumeLater => {
2014 let index = self.component.thread_resume_later();
2015 Ok((ExportKind::Func, index))
2016 }
2017 Import::ThreadSuspend { cancellable } => {
2018 let index = self.component.thread_suspend(*cancellable);
2019 Ok((ExportKind::Func, index))
2020 }
2021 Import::ThreadYield { cancellable } => {
2022 let index = self.component.thread_yield(*cancellable);
2023 Ok((ExportKind::Func, index))
2024 }
2025 Import::ThreadSuspendThenResume { cancellable } => {
2026 let index = self.component.thread_suspend_then_resume(*cancellable);
2027 Ok((ExportKind::Func, index))
2028 }
2029 Import::ThreadYieldThenResume { cancellable } => {
2030 let index = self.component.thread_yield_then_resume(*cancellable);
2031 Ok((ExportKind::Func, index))
2032 }
2033 Import::ThreadSuspendThenPromote { cancellable } => {
2034 let index = self.component.thread_suspend_then_promote(*cancellable);
2035 Ok((ExportKind::Func, index))
2036 }
2037 Import::ThreadYieldThenPromote { cancellable } => {
2038 let index = self.component.thread_yield_then_promote(*cancellable);
2039 Ok((ExportKind::Func, index))
2040 }
2041 }
2042 }
2043
2044 fn materialize_shim_import(&mut self, shims: &Shims<'_>, kind: &ShimKind) -> (ExportKind, u32) {
2047 let index = self.core_alias_export(
2048 Some(&shims.shims[kind].debug_name),
2049 self.shim_instance_index
2050 .expect("shim should be instantiated"),
2051 &shims.shims[kind].name,
2052 ExportKind::Func,
2053 );
2054 (ExportKind::Func, index)
2055 }
2056
2057 fn materialize_payload_import(
2060 &mut self,
2061 shims: &Shims<'_>,
2062 for_module: CustomModule<'_>,
2063 info: &PayloadInfo,
2064 kind: PayloadFuncKind,
2065 ) -> (ExportKind, u32) {
2066 self.materialize_shim_import(
2067 shims,
2068 &ShimKind::PayloadFunc {
2069 for_module,
2070 info,
2071 kind,
2072 },
2073 )
2074 }
2075
2076 fn materialize_wit_import(
2079 &mut self,
2080 shims: &Shims<'_>,
2081 for_module: CustomModule<'_>,
2082 interface_key: Option<String>,
2083 name: &String,
2084 key: &WorldKey,
2085 abi: AbiVariant,
2086 ) -> Result<(ExportKind, u32)> {
2087 let resolve = &self.info.encoder.metadata.resolve;
2088 let import = &self.info.import_map[&interface_key];
2089 let (index, _, lowering) = import.lowerings.get_full(&(name.clone(), abi)).unwrap();
2090 let metadata = self.info.module_metadata_for(for_module);
2091
2092 let index = match lowering {
2093 Lowering::Direct => {
2096 let func_index = match &import.interface {
2097 Some(interface) => {
2098 let instance_index = self.instances[interface];
2099 self.component
2100 .alias_export(instance_index, name, ComponentExportKind::Func)
2101 }
2102 None => self.imported_funcs[name],
2103 };
2104 self.component.lower_func(
2105 Some(name),
2106 func_index,
2107 if let AbiVariant::GuestImportAsync = abi {
2108 vec![CanonicalOption::Async]
2109 } else {
2110 Vec::new()
2111 },
2112 )
2113 }
2114
2115 Lowering::Indirect { .. } => {
2119 let encoding = metadata.import_encodings.get(resolve, key, name).unwrap();
2120 return Ok(self.materialize_shim_import(
2121 shims,
2122 &ShimKind::IndirectLowering {
2123 interface: interface_key,
2124 index,
2125 realloc: for_module,
2126 encoding,
2127 },
2128 ));
2129 }
2130
2131 Lowering::ResourceDrop(id) => {
2134 let resource_idx = self.lookup_resource_index(*id);
2135 self.component.resource_drop(resource_idx)
2136 }
2137 };
2138 Ok((ExportKind::Func, index))
2139 }
2140
2141 fn encode_initialize_with_start(&mut self) -> Result<()> {
2160 let initialize = match self.info.info.exports.initialize() {
2161 Some(name) => name,
2162 None => return Ok(()),
2165 };
2166 let init_task = self.info.info.exports.wasm_init_task();
2167 let initialize_index = self.core_alias_export(
2168 Some("start"),
2169 self.instance_index.unwrap(),
2170 initialize,
2171 ExportKind::Func,
2172 );
2173 let init_task_index = init_task.map(|name| {
2174 self.core_alias_export(
2175 Some("init-task-for-start"),
2176 self.instance_index.unwrap(),
2177 name,
2178 ExportKind::Func,
2179 )
2180 });
2181 let mut shim = Module::default();
2182 let mut section = TypeSection::new();
2183 section.ty().function([], []);
2184 shim.section(§ion);
2185
2186 let mut section = ImportSection::new();
2187 section.import("", "", EntityType::Function(0));
2188 if init_task.is_some() {
2189 section.import("", "init", EntityType::Function(0));
2190 }
2191 shim.section(§ion);
2192
2193 if init_task.is_some() {
2194 let mut functions = FunctionSection::new();
2195 functions.function(0);
2196 shim.section(&functions);
2197 }
2198
2199 shim.section(&StartSection {
2200 function_index: if init_task.is_some() { 2 } else { 0 },
2201 });
2202
2203 if init_task.is_some() {
2204 let mut code = CodeSection::new();
2205 let mut func = wasm_encoder::Function::new([]);
2206 func.instructions().call(1);
2207 func.instructions().call(0);
2208 func.instructions().end();
2209 code.function(&func);
2210 shim.section(&code);
2211 }
2212
2213 let shim_module_index = self.component.core_module(Some("start-shim-module"), &shim);
2218 let mut shim_args = vec![("", ExportKind::Func, initialize_index)];
2219 if let Some(i) = init_task_index {
2220 shim_args.push(("init", ExportKind::Func, i));
2221 }
2222 let shim_args_instance_index = self
2223 .component
2224 .core_instantiate_exports(Some("start-shim-args"), shim_args);
2225 self.component.core_instantiate(
2226 Some("start-shim-instance"),
2227 shim_module_index,
2228 [("", ModuleArg::Instance(shim_args_instance_index))],
2229 );
2230 Ok(())
2231 }
2232
2233 fn instance_for(&self, module: CustomModule) -> u32 {
2236 match module {
2237 CustomModule::Main => self.instance_index.expect("instantiated by now"),
2238 CustomModule::Adapter(name) => self.adapter_instances[name],
2239 }
2240 }
2241
2242 fn module_for(&self, module: CustomModule) -> u32 {
2245 match module {
2246 CustomModule::Main => self.module_index.unwrap(),
2247 CustomModule::Adapter(name) => self.adapter_modules[name],
2248 }
2249 }
2250
2251 fn core_alias_export(
2254 &mut self,
2255 debug_name: Option<&str>,
2256 instance: u32,
2257 name: &str,
2258 kind: ExportKind,
2259 ) -> u32 {
2260 *self
2261 .aliased_core_items
2262 .entry((instance, name.to_string()))
2263 .or_insert_with(|| {
2264 self.component
2265 .core_alias_export(debug_name, instance, name, kind)
2266 })
2267 }
2268
2269 fn create_export_task_initialization_wrappers(&mut self) -> Result<()> {
2279 let instance_index = self.instance_index.unwrap();
2280 let resolve = &self.info.encoder.metadata.resolve;
2281 let world = &resolve.worlds[self.info.encoder.metadata.world];
2282 let exports = self.info.exports_for(CustomModule::Main);
2283
2284 let wasm_init_task_export = exports.wasm_init_task();
2285 let wasm_init_async_task_export = exports.wasm_init_async_task();
2286 if wasm_init_task_export.is_none() || wasm_init_async_task_export.is_none() {
2287 return Ok(());
2290 }
2291 let wasm_init_task = wasm_init_task_export.unwrap();
2292 let wasm_init_async_task = wasm_init_async_task_export.unwrap();
2293
2294 let funcs_to_wrap: Vec<_> = exports
2297 .iter()
2298 .flat_map(|(core_name, export)| match export {
2299 Export::WorldFunc(key, _, abi) => match &world.exports[key] {
2300 WorldItem::Function(f) => Some((core_name, f, abi)),
2301 _ => None,
2302 },
2303 Export::InterfaceFunc(_, id, func_name, abi) => {
2304 let func = &resolve.interfaces[*id].functions[func_name.as_str()];
2305 Some((core_name, func, abi))
2306 }
2307 _ => None,
2308 })
2309 .collect();
2310
2311 if funcs_to_wrap.is_empty() {
2312 return Ok(());
2314 }
2315
2316 let mut types = TypeSection::new();
2318 let mut imports = ImportSection::new();
2319 let mut functions = FunctionSection::new();
2320 let mut exports_section = ExportSection::new();
2321 let mut code = CodeSection::new();
2322
2323 types.ty().function([], []);
2325 let wasm_init_task_type_idx = 0;
2326
2327 imports.import(
2329 "",
2330 wasm_init_task,
2331 EntityType::Function(wasm_init_task_type_idx),
2332 );
2333 imports.import(
2334 "",
2335 wasm_init_async_task,
2336 EntityType::Function(wasm_init_task_type_idx),
2337 );
2338 let wasm_init_task_func_idx = 0u32;
2339 let wasm_init_async_task_func_idx = 1u32;
2340
2341 let mut type_indices = HashMap::new();
2342 let mut next_type_idx = 1u32;
2343 let mut next_func_idx = 2u32;
2344
2345 struct FuncInfo<'a> {
2347 name: &'a str,
2348 type_idx: u32,
2349 orig_func_idx: u32,
2350 is_async: bool,
2351 n_params: usize,
2352 }
2353 let mut func_info = Vec::new();
2354 for &(name, func, abi) in funcs_to_wrap.iter() {
2355 let sig = resolve.wasm_signature(*abi, func);
2356 let type_idx = *type_indices.entry(sig.clone()).or_insert_with(|| {
2357 let idx = next_type_idx;
2358 types.ty().function(
2359 sig.params.iter().map(to_val_type),
2360 sig.results.iter().map(to_val_type),
2361 );
2362 next_type_idx += 1;
2363 idx
2364 });
2365
2366 imports.import("", &import_func_name(func), EntityType::Function(type_idx));
2367 let orig_func_idx = next_func_idx;
2368 next_func_idx += 1;
2369
2370 func_info.push(FuncInfo {
2371 name,
2372 type_idx,
2373 orig_func_idx,
2374 is_async: abi.is_async(),
2375 n_params: sig.params.len(),
2376 });
2377 }
2378
2379 for info in func_info.iter() {
2381 let wrapper_func_idx = next_func_idx;
2382 functions.function(info.type_idx);
2383
2384 let mut func = wasm_encoder::Function::new([]);
2385 if info.is_async {
2386 func.instruction(&Instruction::Call(wasm_init_async_task_func_idx));
2387 } else {
2388 func.instruction(&Instruction::Call(wasm_init_task_func_idx));
2389 }
2390 for i in 0..info.n_params as u32 {
2391 func.instruction(&Instruction::LocalGet(i));
2392 }
2393 func.instruction(&Instruction::Call(info.orig_func_idx));
2394 func.instruction(&Instruction::End);
2395 code.function(&func);
2396
2397 exports_section.export(info.name, ExportKind::Func, wrapper_func_idx);
2398 next_func_idx += 1;
2399 }
2400
2401 let mut wrapper_module = Module::new();
2402 wrapper_module.section(&types);
2403 wrapper_module.section(&imports);
2404 wrapper_module.section(&functions);
2405 wrapper_module.section(&exports_section);
2406 wrapper_module.section(&code);
2407
2408 let wrapper_module_idx = self
2409 .component
2410 .core_module(Some("init-task-wrappers"), &wrapper_module);
2411
2412 let mut wrapper_imports = Vec::new();
2414 let init_idx = self.core_alias_export(
2415 Some(wasm_init_task),
2416 instance_index,
2417 wasm_init_task,
2418 ExportKind::Func,
2419 );
2420 let init_async_idx = self.core_alias_export(
2421 Some(wasm_init_async_task),
2422 instance_index,
2423 wasm_init_async_task,
2424 ExportKind::Func,
2425 );
2426 wrapper_imports.push((wasm_init_task.into(), ExportKind::Func, init_idx));
2427 wrapper_imports.push((
2428 wasm_init_async_task.into(),
2429 ExportKind::Func,
2430 init_async_idx,
2431 ));
2432
2433 for (name, func, _) in &funcs_to_wrap {
2435 let orig_idx =
2436 self.core_alias_export(Some(name), instance_index, name, ExportKind::Func);
2437 wrapper_imports.push((import_func_name(func), ExportKind::Func, orig_idx));
2438 }
2439
2440 let wrapper_args_idx = self.component.core_instantiate_exports(
2441 Some("init-task-wrappers-args"),
2442 wrapper_imports.iter().map(|(n, k, i)| (n.as_str(), *k, *i)),
2443 );
2444
2445 let wrapper_instance = self.component.core_instantiate(
2446 Some("init-task-wrappers-instance"),
2447 wrapper_module_idx,
2448 [("", ModuleArg::Instance(wrapper_args_idx))],
2449 );
2450
2451 for (name, _, _) in funcs_to_wrap {
2453 let wrapper_idx =
2454 self.core_alias_export(Some(&name), wrapper_instance, &name, ExportKind::Func);
2455 self.export_task_initialization_wrappers
2456 .insert(name.into(), wrapper_idx);
2457 }
2458
2459 Ok(())
2460 }
2461}
2462
2463#[derive(Default)]
2481struct Shims<'a> {
2482 shims: IndexMap<ShimKind<'a>, Shim<'a>>,
2484}
2485
2486struct Shim<'a> {
2487 options: RequiredOptions,
2490
2491 name: String,
2495
2496 debug_name: String,
2499
2500 kind: ShimKind<'a>,
2502
2503 sig: WasmSignature,
2505}
2506
2507#[derive(Debug, Clone, Hash, Eq, PartialEq)]
2510enum PayloadFuncKind {
2511 FutureWrite,
2512 FutureRead,
2513 StreamWrite,
2514 StreamRead,
2515}
2516
2517#[derive(Debug, Clone, Hash, Eq, PartialEq)]
2518enum ShimKind<'a> {
2519 IndirectLowering {
2523 interface: Option<String>,
2525 index: usize,
2527 realloc: CustomModule<'a>,
2529 encoding: StringEncoding,
2531 },
2532 Adapter {
2535 adapter: &'a str,
2537 func: &'a str,
2539 },
2540 ResourceDtor {
2543 module: CustomModule<'a>,
2545 export: &'a str,
2547 },
2548 PayloadFunc {
2552 for_module: CustomModule<'a>,
2555 info: &'a PayloadInfo,
2560 kind: PayloadFuncKind,
2562 },
2563 WaitableSetWait { cancellable: bool },
2567 WaitableSetPoll { cancellable: bool },
2571 TaskReturn {
2573 interface: Option<InterfaceId>,
2576 func: &'a str,
2579 result: Option<Type>,
2581 for_module: CustomModule<'a>,
2583 encoding: StringEncoding,
2585 },
2586 ErrorContextNew {
2590 encoding: StringEncoding,
2592 },
2593 ErrorContextDebugMessage {
2597 for_module: CustomModule<'a>,
2599 encoding: StringEncoding,
2601 },
2602 ThreadNewIndirect {
2605 for_module: CustomModule<'a>,
2607 func_ty: FuncType,
2609 },
2610}
2611
2612#[derive(Debug, Copy, Clone, Hash, Eq, PartialEq)]
2622enum CustomModule<'a> {
2623 Main,
2626 Adapter(&'a str),
2629}
2630
2631impl<'a> CustomModule<'a> {
2632 fn debug_name(&self) -> &'a str {
2633 match self {
2634 CustomModule::Main => "main",
2635 CustomModule::Adapter(s) => s,
2636 }
2637 }
2638}
2639
2640impl<'a> Shims<'a> {
2641 fn append_indirect(
2646 &mut self,
2647 world: &'a ComponentWorld<'a>,
2648 for_module: CustomModule<'a>,
2649 ) -> Result<()> {
2650 let module_imports = world.imports_for(for_module);
2651 let module_exports = world.exports_for(for_module);
2652 let resolve = &world.encoder.metadata.resolve;
2653
2654 for (module, field, import) in module_imports.imports() {
2655 match import {
2656 Import::ImportedResourceDrop(..)
2659 | Import::MainModuleMemory
2660 | Import::MainModuleExport { .. }
2661 | Import::Item(_)
2662 | Import::ExportedResourceDrop(..)
2663 | Import::ExportedResourceRep(..)
2664 | Import::ExportedResourceNew(..)
2665 | Import::ExportedTaskCancel
2666 | Import::ErrorContextDrop
2667 | Import::BackpressureInc
2668 | Import::BackpressureDec
2669 | Import::SubtaskDrop
2670 | Import::SubtaskCancel { .. }
2671 | Import::FutureNew(..)
2672 | Import::StreamNew(..)
2673 | Import::FutureCancelRead { .. }
2674 | Import::FutureCancelWrite { .. }
2675 | Import::FutureDropWritable { .. }
2676 | Import::FutureDropReadable { .. }
2677 | Import::StreamCancelRead { .. }
2678 | Import::StreamCancelWrite { .. }
2679 | Import::StreamDropWritable { .. }
2680 | Import::StreamDropReadable { .. }
2681 | Import::WaitableSetNew
2682 | Import::WaitableSetDrop
2683 | Import::WaitableJoin
2684 | Import::ContextGet { .. }
2685 | Import::ContextSet { .. }
2686 | Import::ThreadIndex
2687 | Import::ThreadResumeLater
2688 | Import::ThreadSuspend { .. }
2689 | Import::ThreadYield { .. }
2690 | Import::ThreadSuspendThenResume { .. }
2691 | Import::ThreadYieldThenResume { .. }
2692 | Import::ThreadSuspendThenPromote { .. }
2693 | Import::ThreadYieldThenPromote { .. } => {}
2694
2695 Import::ExportedTaskReturn(key, interface, func) => {
2699 let (options, sig) = task_return_options_and_type(resolve, func);
2700 if options.is_empty() {
2701 continue;
2702 }
2703 let name = self.shims.len().to_string();
2704 let encoding = world
2705 .module_metadata_for(for_module)
2706 .export_encodings
2707 .get(resolve, key, &func.name)
2708 .ok_or_else(|| {
2709 anyhow::anyhow!(
2710 "missing component metadata for export of \
2711 `{module}::{field}`"
2712 )
2713 })?;
2714 self.push(Shim {
2715 name,
2716 debug_name: format!("task-return-{}", func.name),
2717 options,
2718 kind: ShimKind::TaskReturn {
2719 interface: *interface,
2720 func: &func.name,
2721 result: func.result,
2722 for_module,
2723 encoding,
2724 },
2725 sig,
2726 });
2727 }
2728
2729 Import::FutureWrite { async_, info } => {
2730 self.append_indirect_payload_push(
2731 resolve,
2732 for_module,
2733 module,
2734 *async_,
2735 info,
2736 PayloadFuncKind::FutureWrite,
2737 vec![WasmType::I32; 2],
2738 vec![WasmType::I32],
2739 );
2740 }
2741 Import::FutureRead { async_, info } => {
2742 self.append_indirect_payload_push(
2743 resolve,
2744 for_module,
2745 module,
2746 *async_,
2747 info,
2748 PayloadFuncKind::FutureRead,
2749 vec![WasmType::I32; 2],
2750 vec![WasmType::I32],
2751 );
2752 }
2753 Import::StreamWrite { async_, info } => {
2754 self.append_indirect_payload_push(
2755 resolve,
2756 for_module,
2757 module,
2758 *async_,
2759 info,
2760 PayloadFuncKind::StreamWrite,
2761 vec![WasmType::I32; 3],
2762 vec![WasmType::I32],
2763 );
2764 }
2765 Import::StreamRead { async_, info } => {
2766 self.append_indirect_payload_push(
2767 resolve,
2768 for_module,
2769 module,
2770 *async_,
2771 info,
2772 PayloadFuncKind::StreamRead,
2773 vec![WasmType::I32; 3],
2774 vec![WasmType::I32],
2775 );
2776 }
2777
2778 Import::WaitableSetWait { cancellable } => {
2779 let name = self.shims.len().to_string();
2780 self.push(Shim {
2781 name,
2782 debug_name: "waitable-set.wait".to_string(),
2783 options: RequiredOptions::empty(),
2784 kind: ShimKind::WaitableSetWait {
2785 cancellable: *cancellable,
2786 },
2787 sig: WasmSignature {
2788 params: vec![WasmType::I32; 2],
2789 results: vec![WasmType::I32],
2790 indirect_params: false,
2791 retptr: false,
2792 },
2793 });
2794 }
2795
2796 Import::WaitableSetPoll { cancellable } => {
2797 let name = self.shims.len().to_string();
2798 self.push(Shim {
2799 name,
2800 debug_name: "waitable-set.poll".to_string(),
2801 options: RequiredOptions::empty(),
2802 kind: ShimKind::WaitableSetPoll {
2803 cancellable: *cancellable,
2804 },
2805 sig: WasmSignature {
2806 params: vec![WasmType::I32; 2],
2807 results: vec![WasmType::I32],
2808 indirect_params: false,
2809 retptr: false,
2810 },
2811 });
2812 }
2813
2814 Import::ErrorContextNew { encoding } => {
2815 let name = self.shims.len().to_string();
2816 self.push(Shim {
2817 name,
2818 debug_name: "error-new".to_string(),
2819 options: RequiredOptions::MEMORY | RequiredOptions::STRING_ENCODING,
2820 kind: ShimKind::ErrorContextNew {
2821 encoding: *encoding,
2822 },
2823 sig: WasmSignature {
2824 params: vec![WasmType::I32; 2],
2825 results: vec![WasmType::I32],
2826 indirect_params: false,
2827 retptr: false,
2828 },
2829 });
2830 }
2831
2832 Import::ErrorContextDebugMessage { encoding } => {
2833 let name = self.shims.len().to_string();
2834 self.push(Shim {
2835 name,
2836 debug_name: "error-debug-message".to_string(),
2837 options: RequiredOptions::MEMORY
2838 | RequiredOptions::STRING_ENCODING
2839 | RequiredOptions::REALLOC,
2840 kind: ShimKind::ErrorContextDebugMessage {
2841 for_module,
2842 encoding: *encoding,
2843 },
2844 sig: WasmSignature {
2845 params: vec![WasmType::I32; 2],
2846 results: vec![],
2847 indirect_params: false,
2848 retptr: false,
2849 },
2850 });
2851 }
2852
2853 Import::ThreadNewIndirect => {
2854 let name = self.shims.len().to_string();
2855 self.push(Shim {
2856 name,
2857 debug_name: "thread.new-indirect".to_string(),
2858 options: RequiredOptions::empty(),
2859 kind: ShimKind::ThreadNewIndirect {
2860 for_module,
2861 func_ty: FuncType::new([ValType::I32], vec![]),
2863 },
2864 sig: WasmSignature {
2865 params: vec![WasmType::I32; 2],
2866 results: vec![WasmType::I32],
2867 indirect_params: false,
2868 retptr: false,
2869 },
2870 });
2871 }
2872
2873 Import::AdapterExport { adapter, func, ty } => {
2876 let name = self.shims.len().to_string();
2877 log::debug!("shim {name} is adapter `{module}::{field}`");
2878 self.push(Shim {
2879 name,
2880 debug_name: format!("adapt-{module}-{field}"),
2881 options: RequiredOptions::MEMORY,
2885 kind: ShimKind::Adapter { adapter, func },
2886 sig: WasmSignature {
2887 params: ty.params().iter().map(to_wasm_type).collect(),
2888 results: ty.results().iter().map(to_wasm_type).collect(),
2889 indirect_params: false,
2890 retptr: false,
2891 },
2892 });
2893
2894 fn to_wasm_type(ty: &wasmparser::ValType) -> WasmType {
2895 match ty {
2896 wasmparser::ValType::I32 => WasmType::I32,
2897 wasmparser::ValType::I64 => WasmType::I64,
2898 wasmparser::ValType::F32 => WasmType::F32,
2899 wasmparser::ValType::F64 => WasmType::F64,
2900 _ => unreachable!(),
2901 }
2902 }
2903 }
2904
2905 Import::InterfaceFunc(key, _, name, abi) => {
2909 self.append_indirect_wit_func(
2910 world,
2911 for_module,
2912 module,
2913 field,
2914 key,
2915 name,
2916 Some(resolve.name_world_key(key)),
2917 *abi,
2918 )?;
2919 }
2920 Import::WorldFunc(key, name, abi) => {
2921 self.append_indirect_wit_func(
2922 world, for_module, module, field, key, name, None, *abi,
2923 )?;
2924 }
2925 }
2926 }
2927
2928 for (export_name, export) in module_exports.iter() {
2934 let id = match export {
2935 Export::ResourceDtor(id) => id,
2936 _ => continue,
2937 };
2938 let resource = resolve.types[*id].name.as_ref().unwrap();
2939 let name = self.shims.len().to_string();
2940 self.push(Shim {
2941 name,
2942 debug_name: format!("dtor-{resource}"),
2943 options: RequiredOptions::empty(),
2944 kind: ShimKind::ResourceDtor {
2945 module: for_module,
2946 export: export_name,
2947 },
2948 sig: WasmSignature {
2949 params: vec![WasmType::I32],
2950 results: Vec::new(),
2951 indirect_params: false,
2952 retptr: false,
2953 },
2954 });
2955 }
2956
2957 Ok(())
2958 }
2959
2960 fn append_indirect_payload_push(
2963 &mut self,
2964 resolve: &Resolve,
2965 for_module: CustomModule<'a>,
2966 module: &str,
2967 async_: bool,
2968 info: &'a PayloadInfo,
2969 kind: PayloadFuncKind,
2970 params: Vec<WasmType>,
2971 results: Vec<WasmType>,
2972 ) {
2973 let debug_name = format!("{module}-{}", info.name);
2974 let name = self.shims.len().to_string();
2975
2976 let payload = info.payload(resolve);
2977 let (wit_param, wit_result) = match kind {
2978 PayloadFuncKind::StreamRead | PayloadFuncKind::FutureRead => (None, payload),
2979 PayloadFuncKind::StreamWrite | PayloadFuncKind::FutureWrite => (payload, None),
2980 };
2981 self.push(Shim {
2982 name,
2983 debug_name,
2984 options: RequiredOptions::MEMORY
2985 | RequiredOptions::for_import(
2986 resolve,
2987 &Function {
2988 name: String::new(),
2989 kind: FunctionKind::Freestanding,
2990 params: match wit_param {
2991 Some(ty) => vec![Param {
2992 name: "a".to_string(),
2993 ty,
2994 span: Default::default(),
2995 }],
2996 None => Vec::new(),
2997 },
2998 result: wit_result,
2999 docs: Default::default(),
3000 stability: Stability::Unknown,
3001 span: Default::default(),
3002 external_id: None,
3003 },
3004 if async_ {
3005 AbiVariant::GuestImportAsync
3006 } else {
3007 AbiVariant::GuestImport
3008 },
3009 ),
3010 kind: ShimKind::PayloadFunc {
3011 for_module,
3012 info,
3013 kind,
3014 },
3015 sig: WasmSignature {
3016 params,
3017 results,
3018 indirect_params: false,
3019 retptr: false,
3020 },
3021 });
3022 }
3023
3024 fn append_indirect_wit_func(
3027 &mut self,
3028 world: &'a ComponentWorld<'a>,
3029 for_module: CustomModule<'a>,
3030 module: &str,
3031 field: &str,
3032 key: &WorldKey,
3033 name: &String,
3034 interface_key: Option<String>,
3035 abi: AbiVariant,
3036 ) -> Result<()> {
3037 let resolve = &world.encoder.metadata.resolve;
3038 let metadata = world.module_metadata_for(for_module);
3039 let interface = &world.import_map[&interface_key];
3040 let (index, _, lowering) = interface.lowerings.get_full(&(name.clone(), abi)).unwrap();
3041 let shim_name = self.shims.len().to_string();
3042 match lowering {
3043 Lowering::Direct | Lowering::ResourceDrop(_) => {}
3044
3045 Lowering::Indirect { sig, options } => {
3046 log::debug!(
3047 "shim {shim_name} is import `{module}::{field}` lowering {index} `{name}`",
3048 );
3049 let encoding = metadata
3050 .import_encodings
3051 .get(resolve, key, name)
3052 .ok_or_else(|| {
3053 anyhow::anyhow!(
3054 "missing component metadata for import of \
3055 `{module}::{field}`"
3056 )
3057 })?;
3058 self.push(Shim {
3059 name: shim_name,
3060 debug_name: format!("indirect-{module}-{field}"),
3061 options: *options,
3062 kind: ShimKind::IndirectLowering {
3063 interface: interface_key,
3064 index,
3065 realloc: for_module,
3066 encoding,
3067 },
3068 sig: sig.clone(),
3069 });
3070 }
3071 }
3072
3073 Ok(())
3074 }
3075
3076 fn push(&mut self, shim: Shim<'a>) {
3077 if !self.shims.contains_key(&shim.kind) {
3081 self.shims.insert(shim.kind.clone(), shim);
3082 }
3083 }
3084}
3085
3086fn task_return_options_and_type(
3087 resolve: &Resolve,
3088 func: &Function,
3089) -> (RequiredOptions, WasmSignature) {
3090 let func_tmp = Function {
3091 name: String::new(),
3092 kind: FunctionKind::Freestanding,
3093 params: match &func.result {
3094 Some(ty) => vec![Param {
3095 name: "a".to_string(),
3096 ty: *ty,
3097 span: Default::default(),
3098 }],
3099 None => Vec::new(),
3100 },
3101 result: None,
3102 docs: Default::default(),
3103 stability: Stability::Unknown,
3104 span: Default::default(),
3105 external_id: None,
3106 };
3107 let abi = AbiVariant::GuestImport;
3108 let mut options = RequiredOptions::for_import(resolve, func, abi);
3109 options.remove(RequiredOptions::REALLOC);
3111 let sig = resolve.wasm_signature(abi, &func_tmp);
3112 (options, sig)
3113}
3114
3115#[derive(Clone, Debug)]
3117pub struct Item {
3118 pub alias: String,
3119 pub kind: ExportKind,
3120 pub which: MainOrAdapter,
3121 pub name: String,
3122}
3123
3124#[derive(Debug, PartialEq, Clone)]
3126pub enum MainOrAdapter {
3127 Main,
3128 Adapter(String),
3129}
3130
3131impl MainOrAdapter {
3132 fn to_custom_module(&self) -> CustomModule<'_> {
3133 match self {
3134 MainOrAdapter::Main => CustomModule::Main,
3135 MainOrAdapter::Adapter(s) => CustomModule::Adapter(s),
3136 }
3137 }
3138}
3139
3140#[derive(Clone)]
3142pub enum Instance {
3143 MainOrAdapter(MainOrAdapter),
3145
3146 Items(Vec<Item>),
3148}
3149
3150#[derive(Clone)]
3153pub struct LibraryInfo {
3154 pub instantiate_after_shims: bool,
3156
3157 pub arguments: Vec<(String, Instance)>,
3159}
3160
3161pub(super) struct Adapter {
3163 wasm: Vec<u8>,
3165
3166 metadata: ModuleMetadata,
3168
3169 required_exports: IndexSet<WorldKey>,
3172
3173 library_info: Option<LibraryInfo>,
3178}
3179
3180#[derive(Default)]
3182pub struct ComponentEncoder {
3183 module: Vec<u8>,
3184 module_import_map: Option<ModuleImportMap>,
3185 pub(super) metadata: Bindgen,
3186 validate: bool,
3187 pub(super) main_module_exports: IndexSet<WorldKey>,
3188 pub(super) adapters: IndexMap<String, Adapter>,
3189 import_name_map: HashMap<String, String>,
3190 realloc_via_memory_grow: bool,
3191 merge_imports_based_on_semver: Option<bool>,
3192 pub(super) reject_legacy_names: bool,
3193 debug_names: bool,
3194}
3195
3196impl ComponentEncoder {
3197 pub fn module(mut self, module: &[u8]) -> Result<Self> {
3203 let (wasm, metadata) = self.decode(module.as_ref())?;
3204 let (wasm, module_import_map) = ModuleImportMap::new(wasm)?;
3205 let exports = self
3206 .merge_metadata(metadata)
3207 .context("failed merge WIT metadata for module with previous metadata")?;
3208 self.main_module_exports.extend(exports);
3209 self.module = if let Some(producers) = &self.metadata.producers {
3210 producers.add_to_wasm(&wasm)?
3211 } else {
3212 wasm.to_vec()
3213 };
3214 self.module_import_map = module_import_map;
3215 Ok(self)
3216 }
3217
3218 fn decode<'a>(&self, wasm: &'a [u8]) -> Result<(Cow<'a, [u8]>, Bindgen)> {
3219 let (bytes, metadata) = metadata::decode(wasm)?;
3220 match bytes {
3221 Some(wasm) => Ok((Cow::Owned(wasm), metadata)),
3222 None => Ok((Cow::Borrowed(wasm), metadata)),
3223 }
3224 }
3225
3226 fn merge_metadata(&mut self, metadata: Bindgen) -> Result<IndexSet<WorldKey>> {
3227 self.metadata.merge(metadata)
3228 }
3229
3230 pub fn validate(mut self, validate: bool) -> Self {
3232 self.validate = validate;
3233 self
3234 }
3235
3236 pub fn debug_names(mut self, debug_names: bool) -> Self {
3238 self.debug_names = debug_names;
3239 self
3240 }
3241
3242 pub fn merge_imports_based_on_semver(mut self, merge: bool) -> Self {
3250 self.merge_imports_based_on_semver = Some(merge);
3251 self
3252 }
3253
3254 pub fn reject_legacy_names(mut self, reject: bool) -> Self {
3263 self.reject_legacy_names = reject;
3264 self
3265 }
3266
3267 pub fn adapter(self, name: &str, bytes: &[u8]) -> Result<Self> {
3285 self.library_or_adapter(name, bytes, None)
3286 }
3287
3288 pub fn library(self, name: &str, bytes: &[u8], library_info: LibraryInfo) -> Result<Self> {
3301 self.library_or_adapter(name, bytes, Some(library_info))
3302 }
3303
3304 fn library_or_adapter(
3305 mut self,
3306 name: &str,
3307 bytes: &[u8],
3308 library_info: Option<LibraryInfo>,
3309 ) -> Result<Self> {
3310 let (wasm, mut metadata) = self.decode(bytes)?;
3311 let adapter_metadata = mem::take(&mut metadata.metadata);
3319 let exports = self.merge_metadata(metadata).with_context(|| {
3320 format!("failed to merge WIT packages of adapter `{name}` into main packages")
3321 })?;
3322 if let Some(library_info) = &library_info {
3323 for (_, instance) in &library_info.arguments {
3325 let resolve = |which: &_| match which {
3326 MainOrAdapter::Main => Ok(()),
3327 MainOrAdapter::Adapter(name) => {
3328 if self.adapters.contains_key(name.as_str()) {
3329 Ok(())
3330 } else {
3331 Err(anyhow!("instance refers to unknown adapter `{name}`"))
3332 }
3333 }
3334 };
3335
3336 match instance {
3337 Instance::MainOrAdapter(which) => resolve(which)?,
3338 Instance::Items(items) => {
3339 for item in items {
3340 resolve(&item.which)?;
3341 }
3342 }
3343 }
3344 }
3345 }
3346 self.adapters.insert(
3347 name.to_string(),
3348 Adapter {
3349 wasm: wasm.to_vec(),
3350 metadata: adapter_metadata,
3351 required_exports: exports,
3352 library_info,
3353 },
3354 );
3355 Ok(self)
3356 }
3357
3358 pub fn realloc_via_memory_grow(mut self, value: bool) -> Self {
3363 self.realloc_via_memory_grow = value;
3364 self
3365 }
3366
3367 pub fn import_name_map(mut self, map: HashMap<String, String>) -> Self {
3378 self.import_name_map = map;
3379 self
3380 }
3381
3382 pub fn encode(&mut self) -> Result<Vec<u8>> {
3384 if self.module.is_empty() {
3385 bail!("a module is required when encoding a component");
3386 }
3387
3388 if self.merge_imports_based_on_semver.unwrap_or(true) {
3389 self.metadata
3390 .resolve
3391 .merge_world_imports_based_on_semver(self.metadata.world)?;
3392 }
3393
3394 self.finalize_resolve_with_nominal_ids();
3395
3396 let world = ComponentWorld::new(self).context("failed to decode world from module")?;
3397 let mut state = EncodingState {
3398 component: ComponentBuilder::default(),
3399 module_index: None,
3400 instance_index: None,
3401 memory_index: None,
3402 shim_instance_index: None,
3403 fixups_module_index: None,
3404 adapter_modules: IndexMap::new(),
3405 adapter_instances: IndexMap::new(),
3406 type_encoding_maps: Default::default(),
3407 instances: Default::default(),
3408 imported_funcs: Default::default(),
3409 aliased_core_items: Default::default(),
3410 info: &world,
3411 export_task_initialization_wrappers: HashMap::new(),
3412 };
3413 state.encode_imports(&self.import_name_map)?;
3414 state.encode_core_modules();
3415 state.encode_core_instantiation()?;
3416 state.encode_exports(CustomModule::Main)?;
3417 for name in self.adapters.keys() {
3418 state.encode_exports(CustomModule::Adapter(name))?;
3419 }
3420 state.component.append_names();
3421 state
3422 .component
3423 .raw_custom_section(&crate::base_producers().raw_custom_section());
3424 let bytes = state.component.finish();
3425
3426 if self.validate {
3427 Validator::new_with_features(WasmFeatures::all())
3428 .validate_all(&bytes)
3429 .context("failed to validate component output")?;
3430 }
3431
3432 Ok(bytes)
3433 }
3434
3435 fn finalize_resolve_with_nominal_ids(&mut self) {
3444 let world = &self.metadata.resolve.worlds[self.metadata.world];
3451 let main_module_exports = self
3452 .main_module_exports
3453 .iter()
3454 .map(|i| world.exports.get_index_of(i).unwrap())
3455 .collect::<Vec<_>>();
3456 let adapter_exports = self
3457 .adapters
3458 .values()
3459 .map(|adapter| {
3460 adapter
3461 .required_exports
3462 .iter()
3463 .map(|i| world.exports.get_index_of(i).unwrap())
3464 .collect::<Vec<_>>()
3465 })
3466 .collect::<Vec<_>>();
3467
3468 self.metadata
3472 .resolve
3473 .generate_nominal_type_ids(self.metadata.world);
3474
3475 self.main_module_exports.clear();
3478 let world = &self.metadata.resolve.worlds[self.metadata.world];
3479 for index in main_module_exports {
3480 let (key, _) = world.exports.get_index(index).unwrap();
3481 self.main_module_exports.insert(key.clone());
3482 }
3483 for (exports, adapter) in adapter_exports.into_iter().zip(self.adapters.values_mut()) {
3484 adapter.required_exports.clear();
3485 for index in exports {
3486 let (key, _) = world.exports.get_index(index).unwrap();
3487 adapter.required_exports.insert(key.clone());
3488 }
3489 }
3490 }
3491}
3492
3493impl ComponentWorld<'_> {
3494 fn imports_for(&self, module: CustomModule) -> &ImportMap {
3496 match module {
3497 CustomModule::Main => &self.info.imports,
3498 CustomModule::Adapter(name) => &self.adapters[name].info.imports,
3499 }
3500 }
3501
3502 fn exports_for(&self, module: CustomModule) -> &ExportMap {
3504 match module {
3505 CustomModule::Main => &self.info.exports,
3506 CustomModule::Adapter(name) => &self.adapters[name].info.exports,
3507 }
3508 }
3509
3510 fn module_metadata_for(&self, module: CustomModule) -> &ModuleMetadata {
3512 match module {
3513 CustomModule::Main => &self.encoder.metadata.metadata,
3514 CustomModule::Adapter(name) => &self.encoder.adapters[name].metadata,
3515 }
3516 }
3517}
3518
3519#[cfg(all(test, feature = "dummy-module"))]
3520mod test {
3521 use super::*;
3522 use crate::{dummy_module, embed_component_metadata};
3523 use wit_parser::ManglingAndAbi;
3524
3525 #[test]
3526 fn it_renames_imports() {
3527 let mut resolve = Resolve::new();
3528 let pkg = resolve
3529 .push_str(
3530 "test.wit",
3531 r#"
3532package test:wit;
3533
3534interface i {
3535 f: func();
3536}
3537
3538world test {
3539 import i;
3540 import foo: interface {
3541 f: func();
3542 }
3543}
3544"#,
3545 )
3546 .unwrap();
3547 let world = resolve.select_world(&[pkg], None).unwrap();
3548
3549 let mut module = dummy_module(&resolve, world, ManglingAndAbi::Standard32);
3550
3551 embed_component_metadata(&mut module, &resolve, world, StringEncoding::UTF8).unwrap();
3552
3553 let encoded = ComponentEncoder::default()
3554 .import_name_map(HashMap::from([
3555 (
3556 "foo".to_string(),
3557 "unlocked-dep=<foo:bar/foo@{>=1.0.0 <1.1.0}>".to_string(),
3558 ),
3559 (
3560 "test:wit/i".to_string(),
3561 "locked-dep=<foo:bar/i@1.2.3>".to_string(),
3562 ),
3563 ]))
3564 .module(&module)
3565 .unwrap()
3566 .validate(true)
3567 .encode()
3568 .unwrap();
3569
3570 let wat = wasmprinter::print_bytes(encoded).unwrap();
3571 assert!(wat.contains("unlocked-dep=<foo:bar/foo@{>=1.0.0 <1.1.0}>"));
3572 assert!(wat.contains("locked-dep=<foo:bar/i@1.2.3>"));
3573 }
3574}