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