Skip to main content

wasmtime/runtime/component/
linker.rs

1#[cfg(feature = "component-model-async")]
2use crate::component::concurrent::Accessor;
3use crate::component::func::HostFunc;
4use crate::component::instance::RuntimeImport;
5use crate::component::matching::{InstanceType, TypeChecker};
6use crate::component::types;
7use crate::component::{
8    Component, ComponentNamedList, Instance, InstancePre, Lift, Lower, ResourceType, Val,
9};
10use crate::prelude::*;
11use crate::{AsContextMut, Engine, Module, StoreContextMut};
12use alloc::sync::Arc;
13use core::marker;
14#[cfg(feature = "component-model-async")]
15use core::pin::Pin;
16use wasmtime_environ::component::{NameMap, NameMapIntern};
17use wasmtime_environ::{Atom, PrimaryMap, StringPool};
18
19/// A type used to instantiate [`Component`]s.
20///
21/// This type is used to supply host functionality to components. Values are
22/// defined in a [`Linker`] by their import name and then components are
23/// instantiated with a [`Linker`] using the names provided for name resolution
24/// of the component's imports.
25///
26/// # Names and Semver
27///
28/// Names defined in a [`Linker`] correspond to import names in the Component
29/// Model. Names in the Component Model are allowed to be semver-qualified, for
30/// example:
31///
32/// * `wasi:cli/stdout@0.2.0`
33/// * `wasi:http/types@0.2.0-rc-2023-10-25`
34/// * `my:custom/plugin@1.0.0-pre.2`
35///
36/// These version strings are taken into account when looking up names within a
37/// [`Linker`]. You're allowed to define any number of versions within a
38/// [`Linker`] still, for example you can define `a:b/c@0.2.0`, `a:b/c@0.2.1`,
39/// and `a:b/c@0.3.0` all at the same time.
40///
41/// Specifically though when names are looked up within a linker, for example
42/// during instantiation, semver-compatible names are automatically consulted.
43/// This means that if you define `a:b/c@0.2.1` in a [`Linker`] but a component
44/// imports `a:b/c@0.2.0` then that import will resolve to the `0.2.1` version.
45///
46/// This lookup behavior relies on hosts being well-behaved when using Semver,
47/// specifically that interfaces once defined are never changed. This reflects
48/// how Semver works at the Component Model layer, and it's assumed that if
49/// versions are present then hosts are respecting this.
50///
51/// Note that this behavior goes the other direction, too. If a component
52/// imports `a:b/c@0.2.1` and the host has provided `a:b/c@0.2.0` then that
53/// will also resolve correctly. This is because if an API was defined at 0.2.0
54/// and 0.2.1 then it must be the same API.
55///
56/// This behavior is intended to make it easier for hosts to upgrade WASI and
57/// for guests to upgrade WASI. So long as the actual "meat" of the
58/// functionality is defined then it should align correctly and components can
59/// be instantiated.
60pub struct Linker<T: 'static> {
61    engine: Engine,
62    strings: StringPool,
63    map: NameMap<Atom, Definition>,
64    path: Vec<Atom>,
65    allow_shadowing: bool,
66    _marker: marker::PhantomData<fn() -> T>,
67}
68
69impl<T: 'static> Clone for Linker<T> {
70    fn clone(&self) -> Linker<T> {
71        Linker {
72            engine: self.engine.clone(),
73            strings: self.strings.clone_panic_on_oom(),
74            map: self.map.clone_panic_on_oom(),
75            path: self.path.clone(),
76            allow_shadowing: self.allow_shadowing,
77            _marker: self._marker,
78        }
79    }
80}
81
82/// Structure representing an "instance" being defined within a linker.
83///
84/// Instances do not need to be actual [`Instance`]s and instead are defined by
85/// a "bag of named items", so each [`LinkerInstance`] can further define items
86/// internally.
87pub struct LinkerInstance<'a, T: 'static> {
88    engine: &'a Engine,
89    path: &'a mut Vec<Atom>,
90    path_len: usize,
91    strings: &'a mut StringPool,
92    map: &'a mut NameMap<Atom, Definition>,
93    allow_shadowing: bool,
94    _marker: marker::PhantomData<fn() -> T>,
95}
96
97#[derive(Debug)]
98pub(crate) enum Definition {
99    Instance(NameMap<Atom, Definition>),
100    Func(Arc<HostFunc>),
101    Module(Module),
102    Resource(ResourceType, Arc<crate::func::HostFunc>),
103}
104
105impl TryClone for Definition {
106    fn try_clone(&self) -> Result<Self, OutOfMemory> {
107        Ok(match self {
108            Self::Instance(i) => Self::Instance(i.try_clone()?),
109            Self::Func(f) => Self::Func(f.try_clone()?),
110            Self::Module(m) => Self::Module(m.clone()),
111            Self::Resource(r, f) => Self::Resource(*r, f.try_clone()?),
112        })
113    }
114}
115
116impl<T: 'static> Linker<T> {
117    /// Creates a new linker for the [`Engine`] specified with no items defined
118    /// within it.
119    pub fn new(engine: &Engine) -> Linker<T> {
120        Linker {
121            engine: engine.clone(),
122            strings: StringPool::default(),
123            map: NameMap::default(),
124            allow_shadowing: false,
125            path: Vec::new(),
126            _marker: marker::PhantomData,
127        }
128    }
129
130    /// Returns the [`Engine`] this is connected to.
131    pub fn engine(&self) -> &Engine {
132        &self.engine
133    }
134
135    /// Configures whether or not name-shadowing is allowed.
136    ///
137    /// By default name shadowing is not allowed and it's an error to redefine
138    /// the same name within a linker.
139    pub fn allow_shadowing(&mut self, allow: bool) -> &mut Self {
140        self.allow_shadowing = allow;
141        self
142    }
143
144    /// Returns the "root instance" of this linker, used to define names into
145    /// the root namespace.
146    pub fn root(&mut self) -> LinkerInstance<'_, T> {
147        LinkerInstance {
148            engine: &self.engine,
149            path: &mut self.path,
150            path_len: 0,
151            strings: &mut self.strings,
152            map: &mut self.map,
153            allow_shadowing: self.allow_shadowing,
154            _marker: self._marker,
155        }
156    }
157
158    /// Returns a builder for the named instance specified.
159    ///
160    /// # Errors
161    ///
162    /// Returns an error if `name` is already defined within the linker.
163    pub fn instance(&mut self, name: &str) -> Result<LinkerInstance<'_, T>> {
164        self.root().into_instance(name)
165    }
166
167    fn typecheck<'a>(&'a self, component: &'a Component) -> Result<TypeChecker<'a>> {
168        let mut cx = TypeChecker {
169            engine: &self.engine,
170            types: component.types(),
171            strings: &self.strings,
172            imported_resources: try_new::<Arc<_>>(TryPrimaryMap::new())?,
173        };
174
175        // Walk over the component's list of import names and use that to look up
176        // the definition within this linker that it corresponds to. When found
177        // perform a typecheck against the component's expected type.
178        let env_component = component.env_component();
179        for (_idx, (name, ty)) in env_component.import_types.iter() {
180            let import = self.map.get(name, &self.strings);
181            cx.definition(&ty.ty, import).with_context(|| {
182                format!(
183                    "component imports {desc} `{name}`, but \
184                     a matching implementation was not found in the linker",
185                    desc = ty.ty.desc()
186                )
187            })?;
188        }
189        Ok(cx)
190    }
191
192    /// Returns the [`types::Component`] corresponding to `component` with resource
193    /// types imported by it replaced using imports present in [`Self`].
194    ///
195    /// # Errors
196    ///
197    /// This function will return an [`OutOfMemory`][crate::OutOfMemory] error when
198    /// memory allocation fails. See the `OutOfMemory` type's documentation for
199    /// details on Wasmtime's out-of-memory handling.
200    ///
201    /// Returns an error if `component` was not compiled by the same
202    /// [`Engine`](crate::Engine) as this linker.
203    pub fn substituted_component_type(&self, component: &Component) -> Result<types::Component> {
204        ensure!(
205            Engine::same(&self.engine, component.engine()),
206            "cross-`Engine` usage is not supported"
207        );
208        let cx = self.typecheck(&component)?;
209        Ok(types::Component::from(
210            component.ty(),
211            &InstanceType {
212                types: cx.types,
213                resources: Some(&cx.imported_resources),
214            },
215        ))
216    }
217
218    /// Performs a "pre-instantiation" to resolve the imports of the
219    /// [`Component`] specified with the items defined within this linker.
220    ///
221    /// This method will perform as much work as possible short of actually
222    /// instantiating an instance. Internally this will use the names defined
223    /// within this linker to satisfy the imports of the [`Component`] provided.
224    /// Additionally this will perform type-checks against the component's
225    /// imports against all items defined within this linker.
226    ///
227    /// Note that unlike internally in components where subtyping at the
228    /// interface-types layer is supported this is not supported here. Items
229    /// defined in this linker must match the component's imports precisely.
230    ///
231    /// # Errors
232    ///
233    /// Returns an error if this linker doesn't define a name that the
234    /// `component` imports or if a name defined doesn't match the type of the
235    /// item imported by the `component` provided.
236    ///
237    /// Returns an error if `component` was not compiled by the same
238    /// [`Engine`](crate::Engine) as this linker.
239    ///
240    /// This function will return an [`OutOfMemory`][crate::OutOfMemory] error when
241    /// memory allocation fails. See the `OutOfMemory` type's documentation for
242    /// details on Wasmtime's out-of-memory handling.
243    pub fn instantiate_pre(&self, component: &Component) -> Result<InstancePre<T>> {
244        ensure!(
245            Engine::same(&self.engine, component.engine()),
246            "cross-`Engine` instantiation is not currently supported"
247        );
248        let cx = self.typecheck(&component)?;
249
250        // A successful typecheck resolves all of the imported resources used by
251        // this InstancePre. We keep a clone of this table in the InstancePre
252        // so that we can construct an InstanceType for typechecking.
253        let imported_resources = cx.imported_resources.clone();
254
255        // Now that all imports are known to be defined and satisfied by this
256        // linker a list of "flat" import items (aka no instances) is created
257        // using the import map within the component created at
258        // component-compile-time.
259        let env_component = component.env_component();
260        let mut imports = TryPrimaryMap::with_capacity(env_component.imports.len())?;
261        for (idx, (import, names)) in env_component.imports.iter() {
262            let (root, _) = &env_component.import_types[*import];
263
264            // This is the flattening process where we go from a definition
265            // optionally through a list of exported names to get to the final
266            // item.
267            let mut cur = self.map.get(root, &self.strings).unwrap();
268            for name in names {
269                cur = match cur {
270                    Definition::Instance(map) => map.get(&name, &self.strings).unwrap(),
271                    _ => unreachable!(),
272                };
273            }
274            let import = match cur {
275                Definition::Module(m) => RuntimeImport::Module(m.clone()),
276                Definition::Func(f) => RuntimeImport::Func(f.clone()),
277                Definition::Resource(t, dtor) => RuntimeImport::Resource {
278                    ty: *t,
279                    dtor: dtor.clone(),
280                    dtor_funcref: component.resource_drop_func_ref(dtor),
281                },
282
283                // This is guaranteed by the compilation process that "leaf"
284                // runtime imports are never instances.
285                Definition::Instance(_) => unreachable!(),
286            };
287            let i = imports.push(import)?;
288            assert_eq!(i, idx);
289        }
290        Ok(unsafe {
291            InstancePre::new_unchecked(
292                component.clone(),
293                try_new::<Arc<_>>(PrimaryMap::from(imports))?,
294                imported_resources,
295            )
296        })
297    }
298
299    /// Instantiates the [`Component`] provided into the `store` specified.
300    ///
301    /// This function will use the items defined within this [`Linker`] to
302    /// satisfy the imports of the [`Component`] provided as necessary. For more
303    /// information about this see [`Linker::instantiate_pre`] as well.
304    ///
305    /// # Errors
306    ///
307    /// Returns an error if this [`Linker`] doesn't define an import that
308    /// `component` requires or if it is of the wrong type. Additionally this
309    /// can return an error if something goes wrong during instantiation such as
310    /// a runtime trap or a runtime limit being exceeded.
311    ///
312    /// This function will return an [`OutOfMemory`][crate::OutOfMemory] error when
313    /// memory allocation fails. See the `OutOfMemory` type's documentation for
314    /// details on Wasmtime's out-of-memory handling.
315    pub fn instantiate(
316        &self,
317        mut store: impl AsContextMut<Data = T>,
318        component: &Component,
319    ) -> Result<Instance> {
320        let store = store.as_context_mut();
321        store.0.validate_sync_call()?;
322        self.instantiate_pre(component)?.instantiate(store)
323    }
324
325    /// Instantiates the [`Component`] provided into the `store` specified.
326    ///
327    /// This is exactly like [`Linker::instantiate`] except for [asynchronous
328    /// execution](crate#async).
329    ///
330    /// # Errors
331    ///
332    /// Returns an error if this [`Linker`] doesn't define an import that
333    /// `component` requires or if it is of the wrong type. Additionally this
334    /// can return an error if something goes wrong during instantiation such as
335    /// a runtime trap or a runtime limit being exceeded.
336    ///
337    /// This function will return an [`OutOfMemory`][crate::OutOfMemory] error when
338    /// memory allocation fails. See the `OutOfMemory` type's documentation for
339    /// details on Wasmtime's out-of-memory handling.
340    #[cfg(feature = "async")]
341    pub async fn instantiate_async(
342        &self,
343        store: impl AsContextMut<Data = T>,
344        component: &Component,
345    ) -> Result<Instance>
346    where
347        T: Send,
348    {
349        self.instantiate_pre(component)?
350            .instantiate_async(store)
351            .await
352    }
353
354    /// Implement any imports of the given [`Component`] with a function which traps.
355    ///
356    /// By default a [`Linker`] will error when unknown imports are encountered when instantiating a [`Component`].
357    /// This changes this behavior from an instant error to a trap that will happen if the import is called.
358    ///
359    /// # Errors
360    ///
361    /// This function will return an [`OutOfMemory`][crate::OutOfMemory] error when
362    /// memory allocation fails. See the `OutOfMemory` type's documentation for
363    /// details on Wasmtime's out-of-memory handling.
364    pub fn define_unknown_imports_as_traps(&mut self, component: &Component) -> Result<()> {
365        self.define_unknown_imports(component, StubKind::Trap)
366    }
367
368    /// Implement any imports of the given [`Component`] with functions which
369    /// ignore their arguments and return default values.
370    ///
371    /// By default a [`Linker`] will error when unknown imports are encountered
372    /// when instantiating a [`Component`]. This changes that behavior from an
373    /// instant error to returning defaults when the import is called. See
374    /// [`Type::default_value`](crate::component::types::Type::default_value)
375    /// for what each type defaults to.
376    ///
377    /// Values are built when the import is called, not here, as a handle's
378    /// type depends on the instance it is flowing into.
379    ///
380    /// Not every result has a default: a `future`, `stream`, or
381    /// `error-context`, or a guest-defined resource, has none. Such an import
382    /// is still defined, but traps when called rather than preventing
383    /// instantiation, so a component which never calls it can still be run.
384    ///
385    /// # Errors
386    ///
387    /// This function will return an [`OutOfMemory`][crate::OutOfMemory] error when
388    /// memory allocation fails. See the `OutOfMemory` type's documentation for
389    /// details on Wasmtime's out-of-memory handling.
390    pub fn define_unknown_imports_as_default_values(
391        &mut self,
392        _store: impl AsContextMut<Data = T>,
393        component: &Component,
394    ) -> Result<()> {
395        self.define_unknown_imports(component, StubKind::DefaultValue)
396    }
397
398    /// Stub out all of `component`'s undefined imports.
399    fn define_unknown_imports(&mut self, component: &Component, kind: StubKind) -> Result<()> {
400        // Recursively stub out all imports of the component.
401        use wasmtime_environ::component::{ComponentTypes, ResourceIndex, TypeDef};
402
403        fn stub_item<T>(
404            linker: &mut LinkerInstance<T>,
405            resources: &mut TryEntitySet<ResourceIndex>,
406            item_name: &str,
407            item_def: &TypeDef,
408            parent_instance: Option<&str>,
409            types: &Arc<ComponentTypes>,
410            kind: StubKind,
411        ) -> Result<()> {
412            // The first definition of a resource needs to be present, but all other future
413            // references to the same resource are aliases of the original resource definition.
414            // Once a resource is visited here all future hits on the same resource shouldn't
415            // do anything else effectively. If item_name is already defined then we'll bail
416            // out in the below matches!, and otherwise a stub will be inserted, so no matter
417            // what the first resource is defined and all others will refer to that.
418            if let TypeDef::Resource(ty) = item_def
419                && !resources.insert(types[*ty].unwrap_concrete_ty())?
420            {
421                return Ok(());
422            }
423
424            // Skip if the item isn't an instance and has already been defined in the linker.
425            if !matches!(item_def, TypeDef::ComponentInstance(_)) && linker.get(item_name).is_some()
426            {
427                return Ok(());
428            }
429
430            match item_def {
431                TypeDef::ComponentFunc(_func_idx) => {
432                    let fully_qualified_name = match parent_instance {
433                        Some(parent) => {
434                            let mut s = TryString::new();
435                            s.push_str(parent)?;
436                            s.push('#')?;
437                            s.push_str(item_name)?;
438                            s
439                        }
440                        None => {
441                            let mut s = TryString::new();
442                            s.push_str(item_name)?;
443                            s
444                        }
445                    };
446
447                    // An `async func`-typed import can never be satisfied by
448                    // `func_new` (only a sync-typed import can) — see
449                    // `typecheck_async`'s doc comment. Stub it with
450                    // `func_new_concurrent` instead so unsatisfied async
451                    // imports can be stubbed too, not just sync
452                    // ones; if concurrency support isn't enabled there's no
453                    // way to stub it here, so fall through to `func_new` and
454                    // let instantiation fail with that same explanatory
455                    // error.
456                    #[cfg(feature = "component-model-async")]
457                    if types[*_func_idx].async_ && linker.engine.tunables().concurrency_support {
458                        linker.func_new_concurrent(&item_name, move |accessor, ty, params, results| {
459                            let fully_qualified_name = fully_qualified_name.try_clone();
460                            Box::pin(async move {
461                                let fully_qualified_name = fully_qualified_name?;
462                                match kind {
463                                    StubKind::Trap => bail!(
464                                        "unknown import: `{fully_qualified_name}` has not been defined"
465                                    ),
466                                    StubKind::DefaultValue => accessor
467                                        .with(|store| fill_defaults(store, &ty, params, results))
468                                        .with_context(|| {
469                                            format_err!(
470                                                "unknown import: `{fully_qualified_name}` has no \
471                                                 default value"
472                                            )
473                                        }),
474                                }
475                            })
476                        })?;
477                        return Ok(());
478                    }
479
480                    linker.func_new(&item_name, move |store, ty, params, results| match kind {
481                        StubKind::Trap => {
482                            bail!("unknown import: `{fully_qualified_name}` has not been defined")
483                        }
484                        StubKind::DefaultValue => fill_defaults(store, &ty, params, results)
485                            .with_context(|| {
486                                format_err!(
487                                    "unknown import: `{fully_qualified_name}` has no default value"
488                                )
489                            }),
490                    })?;
491                }
492                TypeDef::ComponentInstance(i) => {
493                    let instance = &types[*i];
494                    let mut linker_instance = linker.instance(item_name)?;
495                    for (export_name, export) in instance.exports.iter() {
496                        stub_item(
497                            &mut linker_instance,
498                            resources,
499                            export_name,
500                            &export.ty,
501                            Some(item_name),
502                            types,
503                            kind,
504                        )?;
505                    }
506                }
507                TypeDef::Resource(_) => {
508                    let ty = crate::component::ResourceType::host::<()>();
509                    linker.resource(item_name, ty, |_, _| Ok(()))?;
510                }
511                TypeDef::Component(_) | TypeDef::Module(_) => {
512                    bail!(
513                        "unable to define {} imports as {}",
514                        item_def.desc(),
515                        kind.desc()
516                    )
517                }
518                _ => {}
519            }
520            Ok(())
521        }
522
523        let mut resources = TryEntitySet::new();
524
525        for (_, (import_name, import_type)) in &component.env_component().import_types {
526            stub_item(
527                &mut self.root(),
528                &mut resources,
529                import_name,
530                &import_type.ty,
531                None,
532                component.types(),
533                kind,
534            )?;
535        }
536        Ok(())
537    }
538}
539
540/// Which flavor of stub `Linker::define_unknown_imports` installs.
541#[derive(Copy, Clone)]
542enum StubKind {
543    /// Stubs trap when called.
544    Trap,
545    /// Stubs return default values; see
546    /// `Linker::define_unknown_imports_as_default_values`.
547    DefaultValue,
548}
549
550impl StubKind {
551    /// A human readable description, for error messages.
552    fn desc(&self) -> &'static str {
553        match self {
554            StubKind::Trap => "traps",
555            StubKind::DefaultValue => "default values",
556        }
557    }
558}
559
560/// Drop every handle within `params`.
561fn drop_params(mut store: impl AsContextMut, params: &[Val]) -> Result<()> {
562    let mut store = store.as_context_mut();
563    for param in params {
564        drop_val(store.as_context_mut(), param)?;
565    }
566    Ok(())
567}
568
569/// Drop every handle within `val`.
570fn drop_val<T>(mut store: StoreContextMut<'_, T>, val: &Val) -> Result<()> {
571    match val {
572        // Drop through the internal entry point rather than the public
573        // `resource_drop`: this runs while servicing a guest call on a fiber,
574        // where `resource_drop`'s `validate_sync_call` check would reject the
575        // drop with "cannot do blocking `call` from an async context".
576        Val::Resource(resource) => resource.resource_drop_in_guest_call(&mut store)?,
577
578        // Without `component-model-async` these are uninhabited, so there is
579        // nothing to close.
580        #[cfg(feature = "component-model-async")]
581        Val::Future(future) => future.clone().close(&mut store)?,
582        #[cfg(feature = "component-model-async")]
583        Val::Stream(stream) => stream.clone().close(&mut store)?,
584        #[cfg(not(feature = "component-model-async"))]
585        Val::Future(_) | Val::Stream(_) => {}
586
587        Val::List(vals) | Val::Tuple(vals) | Val::FixedLengthList(vals) => {
588            for val in vals {
589                drop_val(store.as_context_mut(), val)?;
590            }
591        }
592        Val::Record(fields) => {
593            for (_, val) in fields {
594                drop_val(store.as_context_mut(), val)?;
595            }
596        }
597        Val::Map(entries) => {
598            for (key, val) in entries {
599                drop_val(store.as_context_mut(), key)?;
600                drop_val(store.as_context_mut(), val)?;
601            }
602        }
603        Val::Variant(_, Some(val)) | Val::Option(Some(val)) => {
604            drop_val(store.as_context_mut(), val)?
605        }
606        Val::Result(Ok(Some(val)) | Err(Some(val))) => drop_val(store.as_context_mut(), val)?,
607
608        // Lifting an `error-context` reads its representation without taking
609        // ownership of a handle, so there is nothing to drop.
610        Val::ErrorContext(_) => {}
611
612        Val::Bool(_)
613        | Val::S8(_)
614        | Val::U8(_)
615        | Val::S16(_)
616        | Val::U16(_)
617        | Val::S32(_)
618        | Val::U32(_)
619        | Val::S64(_)
620        | Val::U64(_)
621        | Val::Float32(_)
622        | Val::Float64(_)
623        | Val::Char(_)
624        | Val::String(_)
625        | Val::Enum(_)
626        | Val::Flags(_)
627        | Val::Variant(_, None)
628        | Val::Option(None)
629        | Val::Result(Ok(None) | Err(None)) => {}
630    }
631    Ok(())
632}
633
634/// Write a default value for each of `ty`'s results into `results`, after
635/// disposing of `params`.
636///
637/// `ty` comes from the call itself rather than from the linker, so its `own`
638/// and `borrow` types are those of the instance being called, which is what
639/// makes the handles this produces pass the guest's type check.
640fn fill_defaults(
641    mut store: impl AsContextMut,
642    ty: &types::ComponentFunc,
643    params: &[Val],
644    results: &mut [Val],
645) -> Result<()> {
646    drop_params(&mut store, params)?;
647    for (slot, ty) in results.iter_mut().zip(ty.results()) {
648        *slot = ty.default_value(&mut store)?;
649    }
650    Ok(())
651}
652
653impl<T: 'static> LinkerInstance<'_, T> {
654    fn as_mut(&mut self) -> LinkerInstance<'_, T> {
655        LinkerInstance {
656            engine: self.engine,
657            path: self.path,
658            path_len: self.path_len,
659            strings: self.strings,
660            map: self.map,
661            allow_shadowing: self.allow_shadowing,
662            _marker: self._marker,
663        }
664    }
665
666    /// Defines a new host-provided function into this [`LinkerInstance`].
667    ///
668    /// This method is used to give host functions to wasm components. The
669    /// `func` provided will be callable from linked components with the type
670    /// signature dictated by `Params` and `Return`. The `Params` is a tuple of
671    /// types that will come from wasm and `Return` is a value coming from the
672    /// host going back to wasm.
673    ///
674    /// Additionally the `func` takes a
675    /// [`StoreContextMut`](crate::StoreContextMut) as its first parameter.
676    ///
677    /// Note that `func` must be an `Fn` and must also be `Send + Sync +
678    /// 'static`. Shared state within a func is typically accessed with the `T`
679    /// type parameter from [`Store<T>`](crate::Store) which is accessible
680    /// through the leading [`StoreContextMut<'_, T>`](crate::StoreContextMut)
681    /// argument which can be provided to the `func` given here.
682    ///
683    /// # Blocking / Async Behavior
684    ///
685    /// The host function `func` provided here is a blocking function from the
686    /// perspective of WebAssembly. WebAssembly, and Rust, will be blocked until
687    /// `func` completes.
688    ///
689    /// To define a function which is async on the host, but blocking to the
690    /// guest, see the [`func_wrap_async`] method.
691    ///
692    /// [`func_wrap_async`]: LinkerInstance::func_wrap_async
693    ///
694    /// # Errors
695    ///
696    /// This function will return an [`OutOfMemory`][crate::OutOfMemory] error when
697    /// memory allocation fails. See the `OutOfMemory` type's documentation for
698    /// details on Wasmtime's out-of-memory handling.
699    //
700    // TODO: needs more words and examples
701    pub fn func_wrap<F, Params, Return>(&mut self, name: &str, func: F) -> Result<()>
702    where
703        F: Fn(StoreContextMut<T>, Params) -> Result<Return> + Send + Sync + 'static,
704        Params: ComponentNamedList + Lift + 'static,
705        Return: ComponentNamedList + Lower + 'static,
706    {
707        self.insert(name, Definition::Func(HostFunc::func_wrap(func)?))?;
708        Ok(())
709    }
710
711    /// Defines a new host-provided async function into this [`LinkerInstance`].
712    ///
713    /// This function is similar to [`Self::func_wrap`] except it takes an async
714    /// host function instead of a blocking host function. The `F` function here
715    /// is intended to be:
716    ///
717    /// ```ignore
718    /// F: AsyncFn(StoreContextMut<'_, T>, Params) -> Result<Return>
719    /// ```
720    ///
721    /// however the returned future must be `Send` which is not possible to
722    /// bound at this time. This will be switched to an async closure once Rust
723    /// supports it.
724    ///
725    /// # Blocking / Async Behavior
726    ///
727    /// The function defined which WebAssembly calls will still appear as
728    /// blocking from the perspective of WebAssembly itself. The host, however,
729    /// can perform asynchronous operations without blocking the thread
730    /// performing a call.
731    ///
732    /// When defining host functions with this function, WebAssembly is invoked
733    /// on a separate stack within a Wasmtime-managed fiber (through the
734    /// `call_async`-style of invocation). This means that if the future
735    /// returned by `F` is not immediately ready then the fiber will be
736    /// suspended to block WebAssembly but not the host. When the future
737    /// becomes ready again the fiber will be resumed to continue execution
738    /// within WebAssembly.
739    ///
740    /// [`func_wrap_async`]: LinkerInstance::func_wrap_async
741    #[cfg(feature = "async")]
742    pub fn func_wrap_async<Params, Return, F>(&mut self, name: &str, f: F) -> Result<()>
743    where
744        F: Fn(
745                StoreContextMut<'_, T>,
746                Params,
747            ) -> Box<dyn Future<Output = Result<Return>> + Send + '_>
748            + Send
749            + Sync
750            + 'static,
751        Params: ComponentNamedList + Lift + 'static,
752        Return: ComponentNamedList + Lower + 'static,
753    {
754        self.insert(name, Definition::Func(HostFunc::func_wrap_async(f)?))?;
755        Ok(())
756    }
757
758    /// Defines a new host-provided async function into this [`LinkerInstance`].
759    ///
760    /// This function defines a host function available to call from
761    /// WebAssembly. WebAssembly may additionally make multiple invocations of
762    /// this function concurrently all at the same time. This function requires
763    /// the [`Config::wasm_component_model_async`] feature to be enabled.
764    ///
765    /// The function `f` provided will be invoked when called by WebAssembly.
766    /// WebAssembly components may then call `f` multiple times while previous
767    /// invocations of `f` are already running. Additionally while `f` is
768    /// running other host functions may be invoked.
769    ///
770    /// The `F` function here is intended to be:
771    ///
772    /// ```ignore
773    /// F: AsyncFn(&Accessor<T>, Params) -> Result<Return>
774    /// ```
775    ///
776    /// however the returned future must be `Send` which is not possible to
777    /// bound at this time. This will be switched to an async closure once Rust
778    /// supports it.
779    ///
780    /// The closure `f` is provided an [`Accessor`] which can be used to acquire
781    /// temporary, blocking, access to a [`StoreContextMut`] (through
782    /// [`Access`](crate::component::Access]). This models how a store is not
783    /// available to `f` across `await` points but it is temporarily available
784    /// while actively being polled.
785    ///
786    /// # Blocking / Async Behavior
787    ///
788    /// Unlike [`Self::func_wrap`] and [`Self::func_wrap_async`] this function
789    /// is asynchronous even from the perspective of guest WebAssembly. This
790    /// means that if `f` is not immediately resolved then the call from
791    /// WebAssembly will still return immediately (assuming it was lowered with
792    /// `async`). The closure `f` should not block the current thread and
793    /// should only perform blocking via `async` meaning that `f` won't block
794    /// either WebAssembly nor the host.
795    ///
796    /// Note that WebAssembly components can lower host functions both with and
797    /// without `async`. That means that even if a host function is defined in
798    /// the "concurrent" mode here a guest may still lower it synchronously. In
799    /// this situation Wasmtime will manage blocking the guest while the closure
800    /// `f` provided here completes. If a guest lowers this function with
801    /// `async`, though, then no blocking will happen.
802    ///
803    /// [`Config::wasm_component_model_async`]: crate::Config::wasm_component_model_async
804    /// [`func_wrap_async`]: LinkerInstance::func_wrap_async
805    #[cfg(feature = "component-model-async")]
806    pub fn func_wrap_concurrent<Params, Return, F>(&mut self, name: &str, f: F) -> Result<()>
807    where
808        T: 'static,
809        F: Fn(&Accessor<T>, Params) -> Pin<Box<dyn Future<Output = Result<Return>> + Send + '_>>
810            + Send
811            + Sync
812            + 'static,
813        Params: ComponentNamedList + Lift + 'static,
814        Return: ComponentNamedList + Lower + 'static,
815    {
816        if !self.engine.tunables().concurrency_support {
817            bail!("concurrent host functions require `Config::concurrency_support`");
818        }
819        self.insert(name, Definition::Func(HostFunc::func_wrap_concurrent(f)?))?;
820        Ok(())
821    }
822
823    /// Define a new host-provided function using dynamically typed values.
824    ///
825    /// The `name` provided is the name of the function to define and the
826    /// `func` provided is the host-defined closure to invoke when this
827    /// function is called.
828    ///
829    /// This function is the "dynamic" version of defining a host function as
830    /// compared to [`LinkerInstance::func_wrap`]. With
831    /// [`LinkerInstance::func_wrap`] a function's type is statically known but
832    /// with this method the `func` argument's type isn't known ahead of time.
833    /// That means that `func` can be by imported component so long as it's
834    /// imported as a matching name.
835    ///
836    /// Type information will be available at execution time, however. For
837    /// example when `func` is invoked the second argument, a `&[Val]` list,
838    /// contains [`Val`] entries that say what type they are. Additionally the
839    /// third argument, `&mut [Val]`, is the expected number of results. Note
840    /// that the expected types of the results cannot be learned during the
841    /// execution of `func`. Learning that would require runtime introspection
842    /// of a component.
843    ///
844    /// Return values, stored in the third argument of `&mut [Val]`, are
845    /// type-checked at runtime to ensure that they have the appropriate type.
846    /// A trap will be raised if they do not have the right type.
847    ///
848    /// # Examples
849    ///
850    /// ```
851    /// use wasmtime::{Store, Engine};
852    /// use wasmtime::component::{Component, Linker, Val};
853    ///
854    /// # fn main() -> wasmtime::Result<()> {
855    /// let engine = Engine::default();
856    /// let component = Component::new(
857    ///     &engine,
858    ///     r#"
859    ///         (component
860    ///             (import "thunk" (func $thunk))
861    ///             (import "is-even" (func $is-even (param "x" u32) (result bool)))
862    ///
863    ///             (core module $m
864    ///                 (import "" "thunk" (func $thunk))
865    ///                 (import "" "is-even" (func $is-even (param i32) (result i32)))
866    ///
867    ///                 (func (export "run")
868    ///                     call $thunk
869    ///
870    ///                     (call $is-even (i32.const 1))
871    ///                     if unreachable end
872    ///
873    ///                     (call $is-even (i32.const 2))
874    ///                     i32.eqz
875    ///                     if unreachable end
876    ///                 )
877    ///             )
878    ///             (core func $thunk (canon lower (func $thunk)))
879    ///             (core func $is-even (canon lower (func $is-even)))
880    ///             (core instance $i (instantiate $m
881    ///                 (with "" (instance
882    ///                     (export "thunk" (func $thunk))
883    ///                     (export "is-even" (func $is-even))
884    ///                 ))
885    ///             ))
886    ///
887    ///             (func (export "run") (canon lift (core func $i "run")))
888    ///         )
889    ///     "#,
890    /// )?;
891    ///
892    /// let mut linker = Linker::<()>::new(&engine);
893    ///
894    /// // Sample function that takes no arguments.
895    /// linker.root().func_new("thunk", |_store, _ty, params, results| {
896    ///     assert!(params.is_empty());
897    ///     assert!(results.is_empty());
898    ///     println!("Look ma, host hands!");
899    ///     Ok(())
900    /// })?;
901    ///
902    /// // This function takes one argument and returns one result.
903    /// linker.root().func_new("is-even", |_store, _ty, params, results| {
904    ///     assert_eq!(params.len(), 1);
905    ///     let param = match params[0] {
906    ///         Val::U32(n) => n,
907    ///         _ => panic!("unexpected type"),
908    ///     };
909    ///
910    ///     assert_eq!(results.len(), 1);
911    ///     results[0] = Val::Bool(param % 2 == 0);
912    ///     Ok(())
913    /// })?;
914    ///
915    /// let mut store = Store::new(&engine, ());
916    /// let instance = linker.instantiate(&mut store, &component)?;
917    /// let run = instance.get_typed_func::<(), ()>(&mut store, "run")?;
918    /// run.call(&mut store, ())?;
919    /// # Ok(())
920    /// # }
921    /// ```
922    ///
923    /// # Errors
924    ///
925    /// This function will return an [`OutOfMemory`][crate::OutOfMemory] error when
926    /// memory allocation fails. See the `OutOfMemory` type's documentation for
927    /// details on Wasmtime's out-of-memory handling.
928    pub fn func_new(
929        &mut self,
930        name: &str,
931        func: impl Fn(StoreContextMut<'_, T>, types::ComponentFunc, &[Val], &mut [Val]) -> Result<()>
932        + Send
933        + Sync
934        + 'static,
935    ) -> Result<()> {
936        self.insert(name, Definition::Func(HostFunc::func_new(func)?))?;
937        Ok(())
938    }
939
940    /// Define a new host-provided async function using dynamic types.
941    ///
942    /// As [`Self::func_wrap_async`] is a dual of [`Self::func_wrap`], this
943    /// function is the dual of [`Self::func_new`].
944    ///
945    /// For documentation on blocking behavior see [`Self::func_wrap_async`].
946    #[cfg(feature = "async")]
947    pub fn func_new_async<F>(&mut self, name: &str, func: F) -> Result<()>
948    where
949        F: for<'a> Fn(
950                StoreContextMut<'a, T>,
951                types::ComponentFunc,
952                &'a [Val],
953                &'a mut [Val],
954            ) -> Box<dyn Future<Output = Result<()>> + Send + 'a>
955            + Send
956            + Sync
957            + 'static,
958    {
959        self.insert(name, Definition::Func(HostFunc::func_new_async(func)?))?;
960        Ok(())
961    }
962
963    /// Define a new host-provided async function using dynamic types.
964    ///
965    /// As [`Self::func_wrap_concurrent`] is a dual of [`Self::func_wrap`], this
966    /// function is the dual of [`Self::func_new`].
967    ///
968    /// For documentation on async/blocking behavior see
969    /// [`Self::func_wrap_concurrent`].
970    #[cfg(feature = "component-model-async")]
971    pub fn func_new_concurrent<F>(&mut self, name: &str, f: F) -> Result<()>
972    where
973        T: 'static,
974        F: for<'a> Fn(
975                &'a Accessor<T>,
976                types::ComponentFunc,
977                &'a [Val],
978                &'a mut [Val],
979            ) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'a>>
980            + Send
981            + Sync
982            + 'static,
983    {
984        if !self.engine.tunables().concurrency_support {
985            bail!("concurrent host functions require `Config::concurrency_support`");
986        }
987        self.insert(name, Definition::Func(HostFunc::func_new_concurrent(f)?))?;
988        Ok(())
989    }
990
991    /// Defines a [`Module`] within this instance.
992    ///
993    /// This can be used to provide a core wasm [`Module`] as an import to a
994    /// component. The [`Module`] provided is saved within the linker for the
995    /// specified `name` in this instance.
996    ///
997    /// # Errors
998    ///
999    /// This function will return an [`OutOfMemory`][crate::OutOfMemory] error when
1000    /// memory allocation fails. See the `OutOfMemory` type's documentation for
1001    /// details on Wasmtime's out-of-memory handling.
1002    ///
1003    /// Returns an error if `module` was not compiled by the same
1004    /// [`Engine`](crate::Engine) as this linker.
1005    pub fn module(&mut self, name: &str, module: &Module) -> Result<()> {
1006        ensure!(
1007            Engine::same(self.engine, module.engine()),
1008            "cross-`Engine` usage is not supported"
1009        );
1010        self.insert(name, Definition::Module(module.clone()))?;
1011        Ok(())
1012    }
1013
1014    /// Defines a new resource of a given [`ResourceType`] in this linker.
1015    ///
1016    /// This function is used to specify resources defined in the host.
1017    ///
1018    /// The `name` argument is the name to define the resource within this
1019    /// linker.
1020    ///
1021    /// The `dtor` provided is a destructor that will get invoked when an owned
1022    /// version of this resource is destroyed from the guest. Note that this
1023    /// destructor is not called when a host-owned resource is destroyed as it's
1024    /// assumed the host knows how to handle destroying its own resources.
1025    ///
1026    /// The `dtor` closure is provided the store state as the first argument
1027    /// along with the representation of the resource that was just destroyed.
1028    ///
1029    /// [`Resource<U>`]: crate::component::Resource
1030    ///
1031    /// # Errors
1032    ///
1033    /// The provided `dtor` closure returns an error if something goes wrong
1034    /// when a guest calls the `dtor` to drop a `Resource<T>` such as
1035    /// a runtime trap or a runtime limit being exceeded.
1036    ///
1037    /// This function will return an [`OutOfMemory`][crate::OutOfMemory] error when
1038    /// memory allocation fails. See the `OutOfMemory` type's documentation for
1039    /// details on Wasmtime's out-of-memory handling.
1040    pub fn resource(
1041        &mut self,
1042        name: &str,
1043        ty: ResourceType,
1044        dtor: impl Fn(StoreContextMut<'_, T>, u32) -> Result<()> + Send + Sync + 'static,
1045    ) -> Result<()> {
1046        let dtor = try_new::<Arc<_>>(crate::func::HostFunc::wrap(
1047            &self.engine,
1048            move |mut cx: crate::Caller<'_, T>, (param,): (u32,)| dtor(cx.as_context_mut(), param),
1049        )?)?;
1050        self.insert(name, Definition::Resource(ty, dtor))?;
1051        Ok(())
1052    }
1053
1054    /// Identical to [`Self::resource`], except that it takes an async destructor.
1055    #[cfg(feature = "async")]
1056    pub fn resource_async<F>(&mut self, name: &str, ty: ResourceType, dtor: F) -> Result<()>
1057    where
1058        T: Send,
1059        F: Fn(StoreContextMut<'_, T>, u32) -> Box<dyn Future<Output = Result<()>> + Send + '_>
1060            + Send
1061            + Sync
1062            + 'static,
1063    {
1064        let dtor = try_new::<Arc<_>>(crate::func::HostFunc::wrap_async(
1065            &self.engine,
1066            move |cx: crate::Caller<'_, T>, (param,): (u32,)| dtor(cx.into(), param),
1067        )?)?;
1068        self.insert(name, Definition::Resource(ty, dtor))?;
1069        Ok(())
1070    }
1071
1072    /// Identical to [`Self::resource`], except that it takes a concurrent destructor.
1073    #[cfg(feature = "component-model-async")]
1074    pub fn resource_concurrent<F>(&mut self, name: &str, ty: ResourceType, dtor: F) -> Result<()>
1075    where
1076        T: Send + 'static,
1077        F: Fn(&Accessor<T>, u32) -> Pin<Box<dyn Future<Output = Result<()>> + Send + '_>>
1078            + Send
1079            + Sync
1080            + 'static,
1081    {
1082        if !self.engine.tunables().concurrency_support {
1083            bail!("concurrent host functions require `Config::concurrency_support`");
1084        }
1085        // TODO: This isn't really concurrent -- it requires exclusive access to
1086        // the store for the duration of the call, preventing guest code from
1087        // running until it completes.  We should make it concurrent and clean
1088        // up the implementation to avoid using e.g. `Accessor::new` and
1089        // `tls::set` directly.
1090        let dtor = Arc::new(dtor);
1091        let dtor = Arc::new(crate::func::HostFunc::wrap_async(
1092            &self.engine,
1093            move |mut cx: crate::Caller<'_, T>, (param,): (u32,)| {
1094                let dtor = dtor.clone();
1095                Box::new(async move {
1096                    let mut store = cx.as_context_mut();
1097                    let accessor =
1098                        &Accessor::new(crate::store::StoreToken::new(store.as_context_mut()));
1099                    let mut future = core::pin::pin!(dtor(accessor, param));
1100                    core::future::poll_fn(|cx| {
1101                        crate::component::concurrent::tls::set(store.0, || future.as_mut().poll(cx))
1102                    })
1103                    .await
1104                })
1105            },
1106        )?);
1107        self.insert(name, Definition::Resource(ty, dtor))?;
1108        Ok(())
1109    }
1110
1111    /// Defines a nested instance within this instance.
1112    ///
1113    /// This can be used to describe arbitrarily nested levels of instances
1114    /// within a linker to satisfy nested instance exports of components.
1115    pub fn instance(&mut self, name: &str) -> Result<LinkerInstance<'_, T>> {
1116        self.as_mut().into_instance(name)
1117    }
1118
1119    /// Same as [`LinkerInstance::instance`] except with different lifetime
1120    /// parameters.
1121    pub fn into_instance(mut self, name: &str) -> Result<Self> {
1122        let atom = self.strings.intern(name)?;
1123
1124        // If this item is already an instance then don't stomp over it with a
1125        // new empty instance (or fail due to shadowing being disallowed).
1126        // Instead continue through to below to explicitly allow re-opening an
1127        // instance multiple times over separate API calls.
1128        //
1129        // If this item isn't defined, or is defined as anything other than an
1130        // instance, however, the insert a fresh new instance and see what
1131        // happens as a result.
1132        match self.map.raw_get_mut(&atom) {
1133            Some(Definition::Instance(_)) => {}
1134            _ => {
1135                self.insert(name, Definition::Instance(NameMap::default()))?;
1136            }
1137        }
1138        self.map = match self.map.raw_get_mut(&atom) {
1139            Some(Definition::Instance(map)) => map,
1140            _ => unreachable!(),
1141        };
1142        self.path.truncate(self.path_len);
1143        self.path.push(atom);
1144        self.path_len += 1;
1145        Ok(self)
1146    }
1147
1148    fn insert(&mut self, name: &str, item: Definition) -> Result<Atom> {
1149        self.map
1150            .insert(name, self.strings, self.allow_shadowing, item)
1151    }
1152
1153    fn get(&self, name: &str) -> Option<&Definition> {
1154        self.map.get(name, self.strings)
1155    }
1156}