1 use crate::component::matching::InstanceType;
2 use crate::component::types;
3 use crate::component::InstanceExportLookup;
4 use crate::prelude::*;
5 use crate::runtime::vm::component::ComponentRuntimeInfo;
6 use crate::runtime::vm::{
7     CompiledModuleId, VMArrayCallFunction, VMFuncRef, VMFunctionBody, VMWasmCallFunction,
8 };
9 use crate::{
10     code::CodeObject, code_memory::CodeMemory, type_registry::TypeCollection, Engine, Module,
11     ResourcesRequired,
12 };
13 use crate::{FuncType, ValType};
14 use alloc::sync::Arc;
15 use core::any::Any;
16 use core::mem;
17 use core::ops::Range;
18 use core::ptr::NonNull;
19 #[cfg(feature = "std")]
20 use std::path::Path;
21 use wasmtime_environ::component::{
22     AllCallFunc, CompiledComponentInfo, ComponentArtifacts, ComponentTypes, Export, ExportIndex,
23     GlobalInitializer, InstantiateModule, NameMapNoIntern, StaticModuleIndex, TrampolineIndex,
24     TypeComponentIndex, TypeDef, VMComponentOffsets,
25 };
26 use wasmtime_environ::{FunctionLoc, HostPtr, ObjectKind, PrimaryMap};
27 
28 /// A compiled WebAssembly Component.
29 ///
30 /// This structure represents a compiled component that is ready to be
31 /// instantiated. This owns a region of virtual memory which contains executable
32 /// code compiled from a WebAssembly binary originally. This is the analog of
33 /// [`Module`](crate::Module) in the component embedding API.
34 ///
35 /// A [`Component`] can be turned into an
36 /// [`Instance`](crate::component::Instance) through a
37 /// [`Linker`](crate::component::Linker). [`Component`]s are safe to share
38 /// across threads. The compilation model of a component is the same as that of
39 /// [a module](crate::Module) which is to say:
40 ///
41 /// * Compilation happens synchronously during [`Component::new`].
42 /// * The result of compilation can be saved into storage with
43 ///   [`Component::serialize`].
44 /// * A previously compiled artifact can be parsed with
45 ///   [`Component::deserialize`].
46 /// * No compilation happens at runtime for a component — everything is done
47 ///   by the time [`Component::new`] returns.
48 ///
49 /// ## Components and `Clone`
50 ///
51 /// Using `clone` on a `Component` is a cheap operation. It will not create an
52 /// entirely new component, but rather just a new reference to the existing
53 /// component. In other words it's a shallow copy, not a deep copy.
54 ///
55 /// ## Examples
56 ///
57 /// For example usage see the documentation of [`Module`](crate::Module) as
58 /// [`Component`] has the same high-level API.
59 #[derive(Clone)]
60 pub struct Component {
61     inner: Arc<ComponentInner>,
62 }
63 
64 struct ComponentInner {
65     /// Unique id for this component within this process.
66     ///
67     /// Note that this is repurposing ids for modules intentionally as there
68     /// shouldn't be an issue overlapping them.
69     id: CompiledModuleId,
70 
71     /// The engine that this component belongs to.
72     engine: Engine,
73 
74     /// Component type index
75     ty: TypeComponentIndex,
76 
77     /// Core wasm modules that the component defined internally, indexed by the
78     /// compile-time-assigned `ModuleUpvarIndex`.
79     static_modules: PrimaryMap<StaticModuleIndex, Module>,
80 
81     /// Code-related information such as the compiled artifact, type
82     /// information, etc.
83     ///
84     /// Note that the `Arc` here is used to share this allocation with internal
85     /// modules.
86     code: Arc<CodeObject>,
87 
88     /// Metadata produced during compilation.
89     info: CompiledComponentInfo,
90 
91     /// A cached handle to the `wasmtime::FuncType` for the canonical ABI's
92     /// `realloc`, to avoid the need to look up types in the registry and take
93     /// locks when calling `realloc` via `TypedFunc::call_raw`.
94     realloc_func_type: Arc<dyn Any + Send + Sync>,
95 }
96 
97 pub(crate) struct AllCallFuncPointers {
98     pub wasm_call: NonNull<VMWasmCallFunction>,
99     pub array_call: VMArrayCallFunction,
100 }
101 
102 impl Component {
103     /// Compiles a new WebAssembly component from the in-memory list of bytes
104     /// provided.
105     ///
106     /// The `bytes` provided can either be the binary or text format of a
107     /// [WebAssembly component]. Note that the text format requires the `wat`
108     /// feature of this crate to be enabled. This API does not support
109     /// streaming compilation.
110     ///
111     /// This function will synchronously validate the entire component,
112     /// including all core modules, and then compile all components, modules,
113     /// etc., found within the provided bytes.
114     ///
115     /// [WebAssembly component]: https://github.com/WebAssembly/component-model/blob/main/design/mvp/Binary.md
116     ///
117     /// # Errors
118     ///
119     /// This function may fail and return an error. Errors may include
120     /// situations such as:
121     ///
122     /// * The binary provided could not be decoded because it's not a valid
123     ///   WebAssembly binary
124     /// * The WebAssembly binary may not validate (e.g. contains type errors)
125     /// * Implementation-specific limits were exceeded with a valid binary (for
126     ///   example too many locals)
127     /// * The wasm binary may use features that are not enabled in the
128     ///   configuration of `engine`
129     /// * If the `wat` feature is enabled and the input is text, then it may be
130     ///   rejected if it fails to parse.
131     ///
132     /// The error returned should contain full information about why compilation
133     /// failed.
134     ///
135     /// # Examples
136     ///
137     /// The `new` function can be invoked with a in-memory array of bytes:
138     ///
139     /// ```no_run
140     /// # use wasmtime::*;
141     /// # use wasmtime::component::Component;
142     /// # fn main() -> anyhow::Result<()> {
143     /// # let engine = Engine::default();
144     /// # let wasm_bytes: Vec<u8> = Vec::new();
145     /// let component = Component::new(&engine, &wasm_bytes)?;
146     /// # Ok(())
147     /// # }
148     /// ```
149     ///
150     /// Or you can also pass in a string to be parsed as the wasm text
151     /// format:
152     ///
153     /// ```
154     /// # use wasmtime::*;
155     /// # use wasmtime::component::Component;
156     /// # fn main() -> anyhow::Result<()> {
157     /// # let engine = Engine::default();
158     /// let component = Component::new(&engine, "(component (core module))")?;
159     /// # Ok(())
160     /// # }
161     #[cfg(any(feature = "cranelift", feature = "winch"))]
162     pub fn new(engine: &Engine, bytes: impl AsRef<[u8]>) -> Result<Component> {
163         crate::CodeBuilder::new(engine)
164             .wasm(bytes.as_ref(), None)?
165             .compile_component()
166     }
167 
168     /// Compiles a new WebAssembly component from a wasm file on disk pointed
169     /// to by `file`.
170     ///
171     /// This is a convenience function for reading the contents of `file` on
172     /// disk and then calling [`Component::new`].
173     #[cfg(all(feature = "std", any(feature = "cranelift", feature = "winch")))]
174     pub fn from_file(engine: &Engine, file: impl AsRef<Path>) -> Result<Component> {
175         crate::CodeBuilder::new(engine)
176             .wasm_file(file.as_ref())?
177             .compile_component()
178     }
179 
180     /// Compiles a new WebAssembly component from the in-memory wasm image
181     /// provided.
182     ///
183     /// This function is the same as [`Component::new`] except that it does not
184     /// accept the text format of WebAssembly. Even if the `wat` feature
185     /// is enabled an error will be returned here if `binary` is the text
186     /// format.
187     ///
188     /// For more information on semantics and errors see [`Component::new`].
189     #[cfg(any(feature = "cranelift", feature = "winch"))]
190     pub fn from_binary(engine: &Engine, binary: &[u8]) -> Result<Component> {
191         crate::CodeBuilder::new(engine)
192             .wasm(binary, None)?
193             .wat(false)?
194             .compile_component()
195     }
196 
197     /// Same as [`Module::deserialize`], but for components.
198     ///
199     /// Note that the bytes referenced here must contain contents previously
200     /// produced by [`Engine::precompile_component`] or
201     /// [`Component::serialize`].
202     ///
203     /// For more information see the [`Module::deserialize`] method.
204     ///
205     /// # Unsafety
206     ///
207     /// The unsafety of this method is the same as that of the
208     /// [`Module::deserialize`] method.
209     ///
210     /// [`Module::deserialize`]: crate::Module::deserialize
211     pub unsafe fn deserialize(engine: &Engine, bytes: impl AsRef<[u8]>) -> Result<Component> {
212         let code = engine.load_code_bytes(bytes.as_ref(), ObjectKind::Component)?;
213         Component::from_parts(engine, code, None)
214     }
215 
216     /// Same as [`Module::deserialize_file`], but for components.
217     ///
218     /// Note that the file referenced here must contain contents previously
219     /// produced by [`Engine::precompile_component`] or
220     /// [`Component::serialize`].
221     ///
222     /// For more information see the [`Module::deserialize_file`] method.
223     ///
224     /// # Unsafety
225     ///
226     /// The unsafety of this method is the same as that of the
227     /// [`Module::deserialize_file`] method.
228     ///
229     /// [`Module::deserialize_file`]: crate::Module::deserialize_file
230     #[cfg(feature = "std")]
231     pub unsafe fn deserialize_file(engine: &Engine, path: impl AsRef<Path>) -> Result<Component> {
232         let code = engine.load_code_file(path.as_ref(), ObjectKind::Component)?;
233         Component::from_parts(engine, code, None)
234     }
235 
236     /// Returns the type of this component as a [`types::Component`].
237     ///
238     /// This method enables runtime introspection of the type of a component
239     /// before instantiation, if necessary.
240     ///
241     /// ## Component types and Resources
242     ///
243     /// An important point to note here is that the precise type of imports and
244     /// exports of a component change when it is instantiated with respect to
245     /// resources. For example a [`Component`] represents an un-instantiated
246     /// component meaning that its imported resources are represented as abstract
247     /// resource types. These abstract types are not equal to any other
248     /// component's types.
249     ///
250     /// For example:
251     ///
252     /// ```
253     /// # use wasmtime::Engine;
254     /// # use wasmtime::component::Component;
255     /// # use wasmtime::component::types::ComponentItem;
256     /// # fn main() -> wasmtime::Result<()> {
257     /// # let engine = Engine::default();
258     /// let a = Component::new(&engine, r#"
259     ///     (component (import "x" (type (sub resource))))
260     /// "#)?;
261     /// let b = Component::new(&engine, r#"
262     ///     (component (import "x" (type (sub resource))))
263     /// "#)?;
264     ///
265     /// let (_, a_ty) = a.component_type().imports(&engine).next().unwrap();
266     /// let (_, b_ty) = b.component_type().imports(&engine).next().unwrap();
267     ///
268     /// let a_ty = match a_ty {
269     ///     ComponentItem::Resource(ty) => ty,
270     ///     _ => unreachable!(),
271     /// };
272     /// let b_ty = match b_ty {
273     ///     ComponentItem::Resource(ty) => ty,
274     ///     _ => unreachable!(),
275     /// };
276     /// assert!(a_ty != b_ty);
277     /// # Ok(())
278     /// # }
279     /// ```
280     ///
281     /// Additionally, however, these abstract types are "substituted" during
282     /// instantiation meaning that a component type will appear to have changed
283     /// once it is instantiated.
284     ///
285     /// ```
286     /// # use wasmtime::{Engine, Store};
287     /// # use wasmtime::component::{Component, Linker, ResourceType};
288     /// # use wasmtime::component::types::ComponentItem;
289     /// # fn main() -> wasmtime::Result<()> {
290     /// # let engine = Engine::default();
291     /// // Here this component imports a resource and then exports it as-is
292     /// // which means that the export is equal to the import.
293     /// let a = Component::new(&engine, r#"
294     ///     (component
295     ///         (import "x" (type $x (sub resource)))
296     ///         (export "x" (type $x))
297     ///     )
298     /// "#)?;
299     ///
300     /// let (_, import) = a.component_type().imports(&engine).next().unwrap();
301     /// let (_, export) = a.component_type().exports(&engine).next().unwrap();
302     ///
303     /// let import = match import {
304     ///     ComponentItem::Resource(ty) => ty,
305     ///     _ => unreachable!(),
306     /// };
307     /// let export = match export {
308     ///     ComponentItem::Resource(ty) => ty,
309     ///     _ => unreachable!(),
310     /// };
311     /// assert_eq!(import, export);
312     ///
313     /// // However after instantiation the resource type "changes"
314     /// let mut store = Store::new(&engine, ());
315     /// let mut linker = Linker::new(&engine);
316     /// linker.root().resource("x", ResourceType::host::<()>(), |_, _| Ok(()))?;
317     /// let instance = linker.instantiate(&mut store, &a)?;
318     /// let instance_ty = instance.get_resource(&mut store, "x").unwrap();
319     ///
320     /// // Here `instance_ty` is not the same as either `import` or `export`,
321     /// // but it is equal to what we provided as an import.
322     /// assert!(instance_ty != import);
323     /// assert!(instance_ty != export);
324     /// assert!(instance_ty == ResourceType::host::<()>());
325     /// # Ok(())
326     /// # }
327     /// ```
328     ///
329     /// Finally, each instantiation of an exported resource from a component is
330     /// considered "fresh" for all instantiations meaning that different
331     /// instantiations will have different exported resource types:
332     ///
333     /// ```
334     /// # use wasmtime::{Engine, Store};
335     /// # use wasmtime::component::{Component, Linker};
336     /// # fn main() -> wasmtime::Result<()> {
337     /// # let engine = Engine::default();
338     /// let a = Component::new(&engine, r#"
339     ///     (component
340     ///         (type $x (resource (rep i32)))
341     ///         (export "x" (type $x))
342     ///     )
343     /// "#)?;
344     ///
345     /// let mut store = Store::new(&engine, ());
346     /// let linker = Linker::new(&engine);
347     /// let instance1 = linker.instantiate(&mut store, &a)?;
348     /// let instance2 = linker.instantiate(&mut store, &a)?;
349     ///
350     /// let x1 = instance1.get_resource(&mut store, "x").unwrap();
351     /// let x2 = instance2.get_resource(&mut store, "x").unwrap();
352     ///
353     /// // Despite these two resources being the same export of the same
354     /// // component they come from two different instances meaning that their
355     /// // types will be unique.
356     /// assert!(x1 != x2);
357     /// # Ok(())
358     /// # }
359     /// ```
360     pub fn component_type(&self) -> types::Component {
361         self.with_uninstantiated_instance_type(|ty| types::Component::from(self.inner.ty, ty))
362     }
363 
364     fn with_uninstantiated_instance_type<R>(&self, f: impl FnOnce(&InstanceType<'_>) -> R) -> R {
365         let resources = Arc::new(PrimaryMap::new());
366         f(&InstanceType {
367             types: self.types(),
368             resources: &resources,
369         })
370     }
371 
372     /// Final assembly step for a component from its in-memory representation.
373     ///
374     /// If the `artifacts` are specified as `None` here then they will be
375     /// deserialized from `code_memory`.
376     pub(crate) fn from_parts(
377         engine: &Engine,
378         code_memory: Arc<CodeMemory>,
379         artifacts: Option<ComponentArtifacts>,
380     ) -> Result<Component> {
381         let ComponentArtifacts {
382             ty,
383             info,
384             types,
385             static_modules,
386         } = match artifacts {
387             Some(artifacts) => artifacts,
388             None => postcard::from_bytes(code_memory.wasmtime_info()).err2anyhow()?,
389         };
390 
391         // Validate that the component can be used with the current instance
392         // allocator.
393         engine.allocator().validate_component(
394             &info.component,
395             &VMComponentOffsets::new(HostPtr, &info.component),
396             &|module_index| &static_modules[module_index].module,
397         )?;
398 
399         // Create a signature registration with the `Engine` for all trampolines
400         // and core wasm types found within this component, both for the
401         // component and for all included core wasm modules.
402         let signatures = TypeCollection::new_for_module(engine, types.module_types());
403 
404         // Assemble the `CodeObject` artifact which is shared by all core wasm
405         // modules as well as the final component.
406         let types = Arc::new(types);
407         let code = Arc::new(CodeObject::new(code_memory, signatures, types.into()));
408 
409         // Convert all information about static core wasm modules into actual
410         // `Module` instances by converting each `CompiledModuleInfo`, the
411         // `types` type information, and the code memory to a runtime object.
412         let static_modules = static_modules
413             .into_iter()
414             .map(|(_, info)| Module::from_parts_raw(engine, code.clone(), info, false))
415             .collect::<Result<_>>()?;
416 
417         let realloc_func_type = Arc::new(FuncType::new(
418             engine,
419             [ValType::I32, ValType::I32, ValType::I32, ValType::I32],
420             [ValType::I32],
421         )) as _;
422 
423         Ok(Component {
424             inner: Arc::new(ComponentInner {
425                 id: CompiledModuleId::new(),
426                 engine: engine.clone(),
427                 ty,
428                 static_modules,
429                 code,
430                 info,
431                 realloc_func_type,
432             }),
433         })
434     }
435 
436     pub(crate) fn ty(&self) -> TypeComponentIndex {
437         self.inner.ty
438     }
439 
440     pub(crate) fn env_component(&self) -> &wasmtime_environ::component::Component {
441         &self.inner.info.component
442     }
443 
444     pub(crate) fn static_module(&self, idx: StaticModuleIndex) -> &Module {
445         &self.inner.static_modules[idx]
446     }
447 
448     #[inline]
449     pub(crate) fn types(&self) -> &Arc<ComponentTypes> {
450         self.inner.component_types()
451     }
452 
453     pub(crate) fn signatures(&self) -> &TypeCollection {
454         self.inner.code.signatures()
455     }
456 
457     pub(crate) fn text(&self) -> &[u8] {
458         self.inner.code.code_memory().text()
459     }
460 
461     pub(crate) fn trampoline_ptrs(&self, index: TrampolineIndex) -> AllCallFuncPointers {
462         let AllCallFunc {
463             wasm_call,
464             array_call,
465         } = &self.inner.info.trampolines[index];
466         AllCallFuncPointers {
467             wasm_call: self.func(wasm_call).cast(),
468             array_call: unsafe {
469                 mem::transmute::<NonNull<VMFunctionBody>, VMArrayCallFunction>(
470                     self.func(array_call),
471                 )
472             },
473         }
474     }
475 
476     fn func(&self, loc: &FunctionLoc) -> NonNull<VMFunctionBody> {
477         let text = self.text();
478         let trampoline = &text[loc.start as usize..][..loc.length as usize];
479         NonNull::new(trampoline.as_ptr() as *mut VMFunctionBody).unwrap()
480     }
481 
482     pub(crate) fn code_object(&self) -> &Arc<CodeObject> {
483         &self.inner.code
484     }
485 
486     /// Same as [`Module::serialize`], except for a component.
487     ///
488     /// Note that the artifact produced here must be passed to
489     /// [`Component::deserialize`] and is not compatible for use with
490     /// [`Module`].
491     ///
492     /// [`Module::serialize`]: crate::Module::serialize
493     /// [`Module`]: crate::Module
494     pub fn serialize(&self) -> Result<Vec<u8>> {
495         Ok(self.code_object().code_memory().mmap().to_vec())
496     }
497 
498     pub(crate) fn runtime_info(&self) -> Arc<dyn ComponentRuntimeInfo> {
499         self.inner.clone()
500     }
501 
502     /// Creates a new `VMFuncRef` with all fields filled out for the destructor
503     /// specified.
504     ///
505     /// The `dtor`'s own `VMFuncRef` won't have `wasm_call` filled out but this
506     /// component may have `resource_drop_wasm_to_native_trampoline` filled out
507     /// if necessary in which case it's filled in here.
508     pub(crate) fn resource_drop_func_ref(&self, dtor: &crate::func::HostFunc) -> VMFuncRef {
509         // Host functions never have their `wasm_call` filled in at this time.
510         assert!(dtor.func_ref().wasm_call.is_none());
511 
512         // Note that if `resource_drop_wasm_to_native_trampoline` is not present
513         // then this can't be called by the component, so it's ok to leave it
514         // blank.
515         let wasm_call = self
516             .inner
517             .info
518             .resource_drop_wasm_to_array_trampoline
519             .as_ref()
520             .map(|i| self.func(i).cast());
521         VMFuncRef {
522             wasm_call,
523             ..*dtor.func_ref()
524         }
525     }
526 
527     /// Returns a summary of the resources required to instantiate this
528     /// [`Component`][crate::component::Component].
529     ///
530     /// Note that when a component imports and instantiates another component or
531     /// core module, we cannot determine ahead of time how many resources
532     /// instantiating this component will require, and therefore this method
533     /// will return `None` in these scenarios.
534     ///
535     /// Potential uses of the returned information:
536     ///
537     /// * Determining whether your pooling allocator configuration supports
538     ///   instantiating this component.
539     ///
540     /// * Deciding how many of which `Component` you want to instantiate within
541     ///   a fixed amount of resources, e.g. determining whether to create 5
542     ///   instances of component X or 10 instances of component Y.
543     ///
544     /// # Example
545     ///
546     /// ```
547     /// # fn main() -> wasmtime::Result<()> {
548     /// use wasmtime::{Config, Engine, component::Component};
549     ///
550     /// let mut config = Config::new();
551     /// config.wasm_multi_memory(true);
552     /// config.wasm_component_model(true);
553     /// let engine = Engine::new(&config)?;
554     ///
555     /// let component = Component::new(&engine, &r#"
556     ///     (component
557     ///         ;; Define a core module that uses two memories.
558     ///         (core module $m
559     ///             (memory 1)
560     ///             (memory 6)
561     ///         )
562     ///
563     ///         ;; Instantiate that core module three times.
564     ///         (core instance $i1 (instantiate (module $m)))
565     ///         (core instance $i2 (instantiate (module $m)))
566     ///         (core instance $i3 (instantiate (module $m)))
567     ///     )
568     /// "#)?;
569     ///
570     /// let resources = component.resources_required()
571     ///     .expect("this component does not import any core modules or instances");
572     ///
573     /// // Instantiating the component will require allocating two memories per
574     /// // core instance, and there are three instances, so six total memories.
575     /// assert_eq!(resources.num_memories, 6);
576     /// assert_eq!(resources.max_initial_memory_size, Some(6));
577     ///
578     /// // The component doesn't need any tables.
579     /// assert_eq!(resources.num_tables, 0);
580     /// assert_eq!(resources.max_initial_table_size, None);
581     /// # Ok(()) }
582     /// ```
583     pub fn resources_required(&self) -> Option<ResourcesRequired> {
584         let mut resources = ResourcesRequired {
585             num_memories: 0,
586             max_initial_memory_size: None,
587             num_tables: 0,
588             max_initial_table_size: None,
589         };
590         for init in &self.env_component().initializers {
591             match init {
592                 GlobalInitializer::InstantiateModule(inst) => match inst {
593                     InstantiateModule::Static(index, _) => {
594                         let module = self.static_module(*index);
595                         resources.add(&module.resources_required());
596                     }
597                     InstantiateModule::Import(_, _) => {
598                         // We can't statically determine the resources required
599                         // to instantiate this component.
600                         return None;
601                     }
602                 },
603                 GlobalInitializer::LowerImport { .. }
604                 | GlobalInitializer::ExtractMemory(_)
605                 | GlobalInitializer::ExtractRealloc(_)
606                 | GlobalInitializer::ExtractPostReturn(_)
607                 | GlobalInitializer::Resource(_) => {}
608             }
609         }
610         Some(resources)
611     }
612 
613     /// Returns the range, in the host's address space, that this module's
614     /// compiled code resides at.
615     ///
616     /// For more information see
617     /// [`Module::image_range`](crate::Module::image_range).
618     pub fn image_range(&self) -> Range<*const u8> {
619         self.inner.code.code_memory().mmap().image_range()
620     }
621 
622     /// Looks up a specific export of this component by `name` optionally nested
623     /// within the `instance` provided.
624     ///
625     /// This method is primarily used to acquire a [`ComponentExportIndex`]
626     /// which can be used with [`Instance`](crate::component::Instance) when
627     /// looking up exports. Export lookup with [`ComponentExportIndex`] can
628     /// skip string lookups at runtime and instead use a more efficient
629     /// index-based lookup.
630     ///
631     /// This method takes a few arguments:
632     ///
633     /// * `engine` - the engine that was used to compile this component.
634     /// * `instance` - an optional "parent instance" for the export being looked
635     ///   up. If this is `None` then the export is looked up on the root of the
636     ///   component itself, and otherwise the export is looked up on the
637     ///   `instance` specified. Note that `instance` must have come from a
638     ///   previous invocation of this method.
639     /// * `name` - the name of the export that's being looked up.
640     ///
641     /// If the export is located then two values are returned: a
642     /// [`types::ComponentItem`] which enables introspection about the type of
643     /// the export and a [`ComponentExportIndex`]. The index returned notably
644     /// implements the [`InstanceExportLookup`] trait which enables using it
645     /// with [`Instance::get_func`](crate::component::Instance::get_func) for
646     /// example.
647     ///
648     /// # Examples
649     ///
650     /// ```
651     /// use wasmtime::{Engine, Store};
652     /// use wasmtime::component::{Component, Linker};
653     /// use wasmtime::component::types::ComponentItem;
654     ///
655     /// # fn main() -> wasmtime::Result<()> {
656     /// let engine = Engine::default();
657     /// let component = Component::new(
658     ///     &engine,
659     ///     r#"
660     ///         (component
661     ///             (core module $m
662     ///                 (func (export "f"))
663     ///             )
664     ///             (core instance $i (instantiate $m))
665     ///             (func (export "f")
666     ///                 (canon lift (core func $i "f")))
667     ///         )
668     ///     "#,
669     /// )?;
670     ///
671     /// // Perform a lookup of the function "f" before instantiaton.
672     /// let (ty, export) = component.export_index(None, "f").unwrap();
673     /// assert!(matches!(ty, ComponentItem::ComponentFunc(_)));
674     ///
675     /// // After instantiation use `export` to lookup the function in question
676     /// // which notably does not do a string lookup at runtime.
677     /// let mut store = Store::new(&engine, ());
678     /// let instance = Linker::new(&engine).instantiate(&mut store, &component)?;
679     /// let func = instance.get_typed_func::<(), ()>(&mut store, &export)?;
680     /// // ...
681     /// # Ok(())
682     /// # }
683     /// ```
684     pub fn export_index(
685         &self,
686         instance: Option<&ComponentExportIndex>,
687         name: &str,
688     ) -> Option<(types::ComponentItem, ComponentExportIndex)> {
689         let info = self.env_component();
690         let index = self.lookup_export_index(instance, name)?;
691         let ty = match info.export_items[index] {
692             Export::Instance { ty, .. } => TypeDef::ComponentInstance(ty),
693             Export::LiftedFunction { ty, .. } => TypeDef::ComponentFunc(ty),
694             Export::ModuleStatic { ty, .. } | Export::ModuleImport { ty, .. } => {
695                 TypeDef::Module(ty)
696             }
697             Export::Type(ty) => ty,
698         };
699         let item = self.with_uninstantiated_instance_type(|instance| {
700             types::ComponentItem::from(&self.inner.engine, &ty, instance)
701         });
702         Some((
703             item,
704             ComponentExportIndex {
705                 id: self.inner.id,
706                 index,
707             },
708         ))
709     }
710 
711     pub(crate) fn lookup_export_index(
712         &self,
713         instance: Option<&ComponentExportIndex>,
714         name: &str,
715     ) -> Option<ExportIndex> {
716         let info = self.env_component();
717         let exports = match instance {
718             Some(idx) => {
719                 if idx.id != self.inner.id {
720                     return None;
721                 }
722                 match &info.export_items[idx.index] {
723                     Export::Instance { exports, .. } => exports,
724                     _ => return None,
725                 }
726             }
727             None => &info.exports,
728         };
729         exports.get(name, &NameMapNoIntern).copied()
730     }
731 
732     pub(crate) fn id(&self) -> CompiledModuleId {
733         self.inner.id
734     }
735 
736     /// Returns the [`Engine`] that this [`Component`] was compiled by.
737     pub fn engine(&self) -> &Engine {
738         &self.inner.engine
739     }
740 }
741 
742 /// A value which represents a known export of a component.
743 ///
744 /// This is the return value of [`Component::export_index`] and implements the
745 /// [`InstanceExportLookup`] trait to work with lookups like
746 /// [`Instance::get_func`](crate::component::Instance::get_func).
747 #[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
748 pub struct ComponentExportIndex {
749     pub(crate) id: CompiledModuleId,
750     pub(crate) index: ExportIndex,
751 }
752 
753 impl InstanceExportLookup for ComponentExportIndex {
754     fn lookup(&self, component: &Component) -> Option<ExportIndex> {
755         if component.inner.id == self.id {
756             Some(self.index)
757         } else {
758             None
759         }
760     }
761 }
762 
763 impl ComponentRuntimeInfo for ComponentInner {
764     fn component(&self) -> &wasmtime_environ::component::Component {
765         &self.info.component
766     }
767 
768     fn component_types(&self) -> &Arc<ComponentTypes> {
769         match self.code.types() {
770             crate::code::Types::Component(types) => types,
771             // The only creator of a `Component` is itself which uses the other
772             // variant, so this shouldn't be possible.
773             crate::code::Types::Module(_) => unreachable!(),
774         }
775     }
776 
777     fn realloc_func_type(&self) -> &Arc<dyn Any + Send + Sync> {
778         &self.realloc_func_type
779     }
780 }
781 
782 #[cfg(test)]
783 mod tests {
784     use crate::component::Component;
785     use crate::{Config, Engine};
786     use wasmtime_environ::MemoryInitialization;
787 
788     #[test]
789     fn cow_on_by_default() {
790         let mut config = Config::new();
791         config.wasm_component_model(true);
792         let engine = Engine::new(&config).unwrap();
793         let component = Component::new(
794             &engine,
795             r#"
796                 (component
797                     (core module
798                         (memory 1)
799                         (data (i32.const 100) "abcd")
800                     )
801                 )
802             "#,
803         )
804         .unwrap();
805 
806         for (_, module) in component.inner.static_modules.iter() {
807             let init = &module.env_module().memory_initialization;
808             assert!(matches!(init, MemoryInitialization::Static { .. }));
809         }
810     }
811 }
812