wasmtime/runtime/component/
component.rs

1use crate::component::matching::InstanceType;
2use crate::component::types;
3use crate::component::InstanceExportLookup;
4use crate::prelude::*;
5use crate::runtime::vm::component::ComponentRuntimeInfo;
6#[cfg(feature = "std")]
7use crate::runtime::vm::open_file_for_mmap;
8use crate::runtime::vm::{
9    CompiledModuleId, VMArrayCallFunction, VMFuncRef, VMFunctionBody, VMWasmCallFunction,
10};
11use crate::{
12    code::CodeObject, code_memory::CodeMemory, type_registry::TypeCollection, Engine, Module,
13    ResourcesRequired,
14};
15use crate::{FuncType, ValType};
16use alloc::sync::Arc;
17use core::any::Any;
18use core::ops::Range;
19use core::ptr::NonNull;
20#[cfg(feature = "std")]
21use std::path::Path;
22use wasmtime_environ::component::{
23    AllCallFunc, CompiledComponentInfo, ComponentArtifacts, ComponentTypes, Export, ExportIndex,
24    GlobalInitializer, InstantiateModule, NameMapNoIntern, StaticModuleIndex, TrampolineIndex,
25    TypeComponentIndex, TypeDef, VMComponentOffsets,
26};
27use wasmtime_environ::TypeTrace;
28use 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)]
62pub struct Component {
63    inner: Arc<ComponentInner>,
64}
65
66struct 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
99pub(crate) struct AllCallFuncPointers {
100    pub wasm_call: NonNull<VMWasmCallFunction>,
101    pub array_call: NonNull<VMArrayCallFunction>,
102}
103
104impl 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            mut types,
389            mut static_modules,
390        } = match artifacts {
391            Some(artifacts) => artifacts,
392            None => postcard::from_bytes(code_memory.wasmtime_info())?,
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 = engine.register_and_canonicalize_types(
407            types.module_types_mut(),
408            static_modules.iter_mut().map(|(_, m)| &mut m.module),
409        );
410        types.canonicalize_for_runtime_usage(&mut |idx| signatures.shared_type(idx).unwrap());
411
412        // Assemble the `CodeObject` artifact which is shared by all core wasm
413        // modules as well as the final component.
414        let types = Arc::new(types);
415        let code = Arc::new(CodeObject::new(code_memory, signatures, types.into()));
416
417        // Convert all information about static core wasm modules into actual
418        // `Module` instances by converting each `CompiledModuleInfo`, the
419        // `types` type information, and the code memory to a runtime object.
420        let static_modules = static_modules
421            .into_iter()
422            .map(|(_, info)| Module::from_parts_raw(engine, code.clone(), info, false))
423            .collect::<Result<_>>()?;
424
425        let realloc_func_type = Arc::new(FuncType::new(
426            engine,
427            [ValType::I32, ValType::I32, ValType::I32, ValType::I32],
428            [ValType::I32],
429        )) as _;
430
431        Ok(Component {
432            inner: Arc::new(ComponentInner {
433                id: CompiledModuleId::new(),
434                engine: engine.clone(),
435                ty,
436                static_modules,
437                code,
438                info,
439                realloc_func_type,
440            }),
441        })
442    }
443
444    pub(crate) fn ty(&self) -> TypeComponentIndex {
445        self.inner.ty
446    }
447
448    pub(crate) fn env_component(&self) -> &wasmtime_environ::component::Component {
449        &self.inner.info.component
450    }
451
452    pub(crate) fn static_module(&self, idx: StaticModuleIndex) -> &Module {
453        &self.inner.static_modules[idx]
454    }
455
456    #[inline]
457    pub(crate) fn types(&self) -> &Arc<ComponentTypes> {
458        self.inner.component_types()
459    }
460
461    pub(crate) fn signatures(&self) -> &TypeCollection {
462        self.inner.code.signatures()
463    }
464
465    pub(crate) fn text(&self) -> &[u8] {
466        self.inner.code.code_memory().text()
467    }
468
469    pub(crate) fn trampoline_ptrs(&self, index: TrampolineIndex) -> AllCallFuncPointers {
470        let AllCallFunc {
471            wasm_call,
472            array_call,
473        } = &self.inner.info.trampolines[index];
474        AllCallFuncPointers {
475            wasm_call: self.func(wasm_call).cast(),
476            array_call: self.func(array_call).cast(),
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().into());
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::ExtractCallback(_)
611                | GlobalInitializer::ExtractPostReturn(_)
612                | GlobalInitializer::Resource(_) => {}
613            }
614        }
615        Some(resources)
616    }
617
618    /// Returns the range, in the host's address space, that this module's
619    /// compiled code resides at.
620    ///
621    /// For more information see
622    /// [`Module::image_range`](crate::Module::image_range).
623    pub fn image_range(&self) -> Range<*const u8> {
624        self.inner.code.code_memory().mmap().image_range()
625    }
626
627    /// Force initialization of copy-on-write images to happen here-and-now
628    /// instead of when they're requested during first instantiation.
629    ///
630    /// When [copy-on-write memory
631    /// initialization](crate::Config::memory_init_cow) is enabled then Wasmtime
632    /// will lazily create the initialization image for a component. This method
633    /// can be used to explicitly dictate when this initialization happens.
634    ///
635    /// Note that this largely only matters on Linux when memfd is used.
636    /// Otherwise the copy-on-write image typically comes from disk and in that
637    /// situation the creation of the image is trivial as the image is always
638    /// sourced from disk. On Linux, though, when memfd is used a memfd is
639    /// created and the initialization image is written to it.
640    ///
641    /// Also note that this method is not required to be called, it's available
642    /// as a performance optimization if required but is otherwise handled
643    /// automatically.
644    pub fn initialize_copy_on_write_image(&self) -> Result<()> {
645        for (_, module) in self.inner.static_modules.iter() {
646            module.initialize_copy_on_write_image()?;
647        }
648        Ok(())
649    }
650
651    /// Looks up a specific export of this component by `name` optionally nested
652    /// within the `instance` provided.
653    ///
654    /// This method is primarily used to acquire a [`ComponentExportIndex`]
655    /// which can be used with [`Instance`](crate::component::Instance) when
656    /// looking up exports. Export lookup with [`ComponentExportIndex`] can
657    /// skip string lookups at runtime and instead use a more efficient
658    /// index-based lookup.
659    ///
660    /// This method takes a few arguments:
661    ///
662    /// * `engine` - the engine that was used to compile this component.
663    /// * `instance` - an optional "parent instance" for the export being looked
664    ///   up. If this is `None` then the export is looked up on the root of the
665    ///   component itself, and otherwise the export is looked up on the
666    ///   `instance` specified. Note that `instance` must have come from a
667    ///   previous invocation of this method.
668    /// * `name` - the name of the export that's being looked up.
669    ///
670    /// If the export is located then two values are returned: a
671    /// [`types::ComponentItem`] which enables introspection about the type of
672    /// the export and a [`ComponentExportIndex`]. The index returned notably
673    /// implements the [`InstanceExportLookup`] trait which enables using it
674    /// with [`Instance::get_func`](crate::component::Instance::get_func) for
675    /// example.
676    ///
677    /// # Examples
678    ///
679    /// ```
680    /// use wasmtime::{Engine, Store};
681    /// use wasmtime::component::{Component, Linker};
682    /// use wasmtime::component::types::ComponentItem;
683    ///
684    /// # fn main() -> wasmtime::Result<()> {
685    /// let engine = Engine::default();
686    /// let component = Component::new(
687    ///     &engine,
688    ///     r#"
689    ///         (component
690    ///             (core module $m
691    ///                 (func (export "f"))
692    ///             )
693    ///             (core instance $i (instantiate $m))
694    ///             (func (export "f")
695    ///                 (canon lift (core func $i "f")))
696    ///         )
697    ///     "#,
698    /// )?;
699    ///
700    /// // Perform a lookup of the function "f" before instantiaton.
701    /// let (ty, export) = component.export_index(None, "f").unwrap();
702    /// assert!(matches!(ty, ComponentItem::ComponentFunc(_)));
703    ///
704    /// // After instantiation use `export` to lookup the function in question
705    /// // which notably does not do a string lookup at runtime.
706    /// let mut store = Store::new(&engine, ());
707    /// let instance = Linker::new(&engine).instantiate(&mut store, &component)?;
708    /// let func = instance.get_typed_func::<(), ()>(&mut store, &export)?;
709    /// // ...
710    /// # Ok(())
711    /// # }
712    /// ```
713    pub fn export_index(
714        &self,
715        instance: Option<&ComponentExportIndex>,
716        name: &str,
717    ) -> Option<(types::ComponentItem, ComponentExportIndex)> {
718        let info = self.env_component();
719        let index = self.lookup_export_index(instance, name)?;
720        let ty = match info.export_items[index] {
721            Export::Instance { ty, .. } => TypeDef::ComponentInstance(ty),
722            Export::LiftedFunction { ty, .. } => TypeDef::ComponentFunc(ty),
723            Export::ModuleStatic { ty, .. } | Export::ModuleImport { ty, .. } => {
724                TypeDef::Module(ty)
725            }
726            Export::Type(ty) => ty,
727        };
728        let item = self.with_uninstantiated_instance_type(|instance| {
729            types::ComponentItem::from(&self.inner.engine, &ty, instance)
730        });
731        Some((
732            item,
733            ComponentExportIndex {
734                id: self.inner.id,
735                index,
736            },
737        ))
738    }
739
740    pub(crate) fn lookup_export_index(
741        &self,
742        instance: Option<&ComponentExportIndex>,
743        name: &str,
744    ) -> Option<ExportIndex> {
745        let info = self.env_component();
746        let exports = match instance {
747            Some(idx) => {
748                if idx.id != self.inner.id {
749                    return None;
750                }
751                match &info.export_items[idx.index] {
752                    Export::Instance { exports, .. } => exports,
753                    _ => return None,
754                }
755            }
756            None => &info.exports,
757        };
758        exports.get(name, &NameMapNoIntern).copied()
759    }
760
761    pub(crate) fn id(&self) -> CompiledModuleId {
762        self.inner.id
763    }
764
765    /// Returns the [`Engine`] that this [`Component`] was compiled by.
766    pub fn engine(&self) -> &Engine {
767        &self.inner.engine
768    }
769}
770
771/// A value which represents a known export of a component.
772///
773/// This is the return value of [`Component::export_index`] and implements the
774/// [`InstanceExportLookup`] trait to work with lookups like
775/// [`Instance::get_func`](crate::component::Instance::get_func).
776#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
777pub struct ComponentExportIndex {
778    pub(crate) id: CompiledModuleId,
779    pub(crate) index: ExportIndex,
780}
781
782impl InstanceExportLookup for ComponentExportIndex {
783    fn lookup(&self, component: &Component) -> Option<ExportIndex> {
784        if component.inner.id == self.id {
785            Some(self.index)
786        } else {
787            None
788        }
789    }
790}
791
792impl ComponentRuntimeInfo for ComponentInner {
793    fn component(&self) -> &wasmtime_environ::component::Component {
794        &self.info.component
795    }
796
797    fn component_types(&self) -> &Arc<ComponentTypes> {
798        match self.code.types() {
799            crate::code::Types::Component(types) => types,
800            // The only creator of a `Component` is itself which uses the other
801            // variant, so this shouldn't be possible.
802            crate::code::Types::Module(_) => unreachable!(),
803        }
804    }
805
806    fn realloc_func_type(&self) -> &Arc<dyn Any + Send + Sync> {
807        &self.realloc_func_type
808    }
809}
810
811#[cfg(test)]
812mod tests {
813    use crate::component::Component;
814    use crate::{Config, Engine};
815    use wasmtime_environ::MemoryInitialization;
816
817    #[test]
818    fn cow_on_by_default() {
819        let mut config = Config::new();
820        config.wasm_component_model(true);
821        let engine = Engine::new(&config).unwrap();
822        let component = Component::new(
823            &engine,
824            r#"
825                (component
826                    (core module
827                        (memory 1)
828                        (data (i32.const 100) "abcd")
829                    )
830                )
831            "#,
832        )
833        .unwrap();
834
835        for (_, module) in component.inner.static_modules.iter() {
836            let init = &module.env_module().memory_initialization;
837            assert!(matches!(init, MemoryInitialization::Static { .. }));
838        }
839    }
840}