1 #[cfg(feature = "component-model-async")]
2 use crate::component::concurrent::Accessor;
3 use crate::component::func::HostFunc;
4 use crate::component::instance::RuntimeImport;
5 use crate::component::matching::{InstanceType, TypeChecker};
6 use crate::component::types;
7 use crate::component::{
8     Component, ComponentNamedList, Instance, InstancePre, Lift, Lower, ResourceType, Val,
9 };
10 use crate::hash_map::HashMap;
11 use crate::prelude::*;
12 use crate::{AsContextMut, Engine, Module, StoreContextMut};
13 use alloc::sync::Arc;
14 use core::marker;
15 #[cfg(feature = "component-model-async")]
16 use core::pin::Pin;
17 use wasmtime_environ::PrimaryMap;
18 use wasmtime_environ::component::{NameMap, NameMapIntern};
19 
20 /// A type used to instantiate [`Component`]s.
21 ///
22 /// This type is used to both link components together as well as supply host
23 /// functionality to components. Values are defined in a [`Linker`] by their
24 /// import name and then components are instantiated with a [`Linker`] using the
25 /// names provided for name resolution of the component's imports.
26 ///
27 /// # Names and Semver
28 ///
29 /// Names defined in a [`Linker`] correspond to import names in the Component
30 /// Model. Names in the Component Model are allowed to be semver-qualified, for
31 /// example:
32 ///
33 /// * `wasi:cli/stdout@0.2.0`
34 /// * `wasi:http/types@0.2.0-rc-2023-10-25`
35 /// * `my:custom/plugin@1.0.0-pre.2`
36 ///
37 /// These version strings are taken into account when looking up names within a
38 /// [`Linker`]. You're allowed to define any number of versions within a
39 /// [`Linker`] still, for example you can define `a:b/[email protected]`, `a:b/[email protected]`,
40 /// and `a:b/[email protected]` all at the same time.
41 ///
42 /// Specifically though when names are looked up within a linker, for example
43 /// during instantiation, semver-compatible names are automatically consulted.
44 /// This means that if you define `a:b/[email protected]` in a [`Linker`] but a component
45 /// imports `a:b/[email protected]` then that import will resolve to the `0.2.1` version.
46 ///
47 /// This lookup behavior relies on hosts being well-behaved when using Semver,
48 /// specifically that interfaces once defined are never changed. This reflects
49 /// how Semver works at the Component Model layer, and it's assumed that if
50 /// versions are present then hosts are respecting this.
51 ///
52 /// Note that this behavior goes the other direction, too. If a component
53 /// imports `a:b/[email protected]` and the host has provided `a:b/[email protected]` then that
54 /// will also resolve correctly. This is because if an API was defined at 0.2.0
55 /// and 0.2.1 then it must be the same API.
56 ///
57 /// This behavior is intended to make it easier for hosts to upgrade WASI and
58 /// for guests to upgrade WASI. So long as the actual "meat" of the
59 /// functionality is defined then it should align correctly and components can
60 /// be instantiated.
61 pub struct Linker<T: 'static> {
62     engine: Engine,
63     strings: Strings,
64     map: NameMap<usize, Definition>,
65     path: Vec<usize>,
66     allow_shadowing: bool,
67     _marker: marker::PhantomData<fn() -> T>,
68 }
69 
70 impl<T: 'static> Clone for Linker<T> {
clone(&self) -> Linker<T>71     fn clone(&self) -> Linker<T> {
72         Linker {
73             engine: self.engine.clone(),
74             strings: self.strings.clone(),
75             map: self.map.clone(),
76             path: self.path.clone(),
77             allow_shadowing: self.allow_shadowing,
78             _marker: self._marker,
79         }
80     }
81 }
82 
83 #[derive(Clone, Default)]
84 pub struct Strings {
85     string2idx: HashMap<Arc<str>, usize>,
86     strings: Vec<Arc<str>>,
87 }
88 
89 /// Structure representing an "instance" being defined within a linker.
90 ///
91 /// Instances do not need to be actual [`Instance`]s and instead are defined by
92 /// a "bag of named items", so each [`LinkerInstance`] can further define items
93 /// internally.
94 pub struct LinkerInstance<'a, T: 'static> {
95     engine: &'a Engine,
96     path: &'a mut Vec<usize>,
97     path_len: usize,
98     strings: &'a mut Strings,
99     map: &'a mut NameMap<usize, Definition>,
100     allow_shadowing: bool,
101     _marker: marker::PhantomData<fn() -> T>,
102 }
103 
104 #[derive(Clone, Debug)]
105 pub(crate) enum Definition {
106     Instance(NameMap<usize, Definition>),
107     Func(Arc<HostFunc>),
108     Module(Module),
109     Resource(ResourceType, Arc<crate::func::HostFunc>),
110 }
111 
112 impl<T: 'static> Linker<T> {
113     /// Creates a new linker for the [`Engine`] specified with no items defined
114     /// within it.
new(engine: &Engine) -> Linker<T>115     pub fn new(engine: &Engine) -> Linker<T> {
116         Linker {
117             engine: engine.clone(),
118             strings: Strings::default(),
119             map: NameMap::default(),
120             allow_shadowing: false,
121             path: Vec::new(),
122             _marker: marker::PhantomData,
123         }
124     }
125 
126     /// Returns the [`Engine`] this is connected to.
engine(&self) -> &Engine127     pub fn engine(&self) -> &Engine {
128         &self.engine
129     }
130 
131     /// Configures whether or not name-shadowing is allowed.
132     ///
133     /// By default name shadowing is not allowed and it's an error to redefine
134     /// the same name within a linker.
allow_shadowing(&mut self, allow: bool) -> &mut Self135     pub fn allow_shadowing(&mut self, allow: bool) -> &mut Self {
136         self.allow_shadowing = allow;
137         self
138     }
139 
140     /// Returns the "root instance" of this linker, used to define names into
141     /// the root namespace.
root(&mut self) -> LinkerInstance<'_, T>142     pub fn root(&mut self) -> LinkerInstance<'_, T> {
143         LinkerInstance {
144             engine: &self.engine,
145             path: &mut self.path,
146             path_len: 0,
147             strings: &mut self.strings,
148             map: &mut self.map,
149             allow_shadowing: self.allow_shadowing,
150             _marker: self._marker,
151         }
152     }
153 
154     /// Returns a builder for the named instance specified.
155     ///
156     /// # Errors
157     ///
158     /// Returns an error if `name` is already defined within the linker.
instance(&mut self, name: &str) -> Result<LinkerInstance<'_, T>>159     pub fn instance(&mut self, name: &str) -> Result<LinkerInstance<'_, T>> {
160         self.root().into_instance(name)
161     }
162 
typecheck<'a>(&'a self, component: &'a Component) -> Result<TypeChecker<'a>>163     fn typecheck<'a>(&'a self, component: &'a Component) -> Result<TypeChecker<'a>> {
164         let mut cx = TypeChecker {
165             engine: &self.engine,
166             types: component.types(),
167             strings: &self.strings,
168             imported_resources: Default::default(),
169         };
170 
171         // Walk over the component's list of import names and use that to lookup
172         // the definition within this linker that it corresponds to. When found
173         // perform a typecheck against the component's expected type.
174         let env_component = component.env_component();
175         for (_idx, (name, ty)) in env_component.import_types.iter() {
176             let import = self.map.get(name, &self.strings);
177             cx.definition(ty, import)
178                 .with_context(|| format!("component imports {desc} `{name}`, but a matching implementation was not found in the linker", desc = ty.desc()))?;
179         }
180         Ok(cx)
181     }
182 
183     /// Returns the [`types::Component`] corresponding to `component` with resource
184     /// types imported by it replaced using imports present in [`Self`].
substituted_component_type(&self, component: &Component) -> Result<types::Component>185     pub fn substituted_component_type(&self, component: &Component) -> Result<types::Component> {
186         let cx = self.typecheck(&component)?;
187         Ok(types::Component::from(
188             component.ty(),
189             &InstanceType {
190                 types: cx.types,
191                 resources: &cx.imported_resources,
192             },
193         ))
194     }
195 
196     /// Performs a "pre-instantiation" to resolve the imports of the
197     /// [`Component`] specified with the items defined within this linker.
198     ///
199     /// This method will perform as much work as possible short of actually
200     /// instantiating an instance. Internally this will use the names defined
201     /// within this linker to satisfy the imports of the [`Component`] provided.
202     /// Additionally this will perform type-checks against the component's
203     /// imports against all items defined within this linker.
204     ///
205     /// Note that unlike internally in components where subtyping at the
206     /// interface-types layer is supported this is not supported here. Items
207     /// defined in this linker must match the component's imports precisely.
208     ///
209     /// # Errors
210     ///
211     /// Returns an error if this linker doesn't define a name that the
212     /// `component` imports or if a name defined doesn't match the type of the
213     /// item imported by the `component` provided.
instantiate_pre(&self, component: &Component) -> Result<InstancePre<T>>214     pub fn instantiate_pre(&self, component: &Component) -> Result<InstancePre<T>> {
215         let cx = self.typecheck(&component)?;
216 
217         // A successful typecheck resolves all of the imported resources used by
218         // this InstancePre. We keep a clone of this table in the InstancePre
219         // so that we can construct an InstanceType for typechecking.
220         let imported_resources = cx.imported_resources.clone();
221 
222         // Now that all imports are known to be defined and satisfied by this
223         // linker a list of "flat" import items (aka no instances) is created
224         // using the import map within the component created at
225         // component-compile-time.
226         let env_component = component.env_component();
227         let mut imports = PrimaryMap::with_capacity(env_component.imports.len());
228         for (idx, (import, names)) in env_component.imports.iter() {
229             let (root, _) = &env_component.import_types[*import];
230 
231             // This is the flattening process where we go from a definition
232             // optionally through a list of exported names to get to the final
233             // item.
234             let mut cur = self.map.get(root, &self.strings).unwrap();
235             for name in names {
236                 cur = match cur {
237                     Definition::Instance(map) => map.get(&name, &self.strings).unwrap(),
238                     _ => unreachable!(),
239                 };
240             }
241             let import = match cur {
242                 Definition::Module(m) => RuntimeImport::Module(m.clone()),
243                 Definition::Func(f) => RuntimeImport::Func(f.clone()),
244                 Definition::Resource(t, dtor) => RuntimeImport::Resource {
245                     ty: *t,
246                     dtor: dtor.clone(),
247                     dtor_funcref: component.resource_drop_func_ref(dtor),
248                 },
249 
250                 // This is guaranteed by the compilation process that "leaf"
251                 // runtime imports are never instances.
252                 Definition::Instance(_) => unreachable!(),
253             };
254             let i = imports.push(import);
255             assert_eq!(i, idx);
256         }
257         Ok(unsafe {
258             InstancePre::new_unchecked(component.clone(), Arc::new(imports), imported_resources)
259         })
260     }
261 
262     /// Instantiates the [`Component`] provided into the `store` specified.
263     ///
264     /// This function will use the items defined within this [`Linker`] to
265     /// satisfy the imports of the [`Component`] provided as necessary. For more
266     /// information about this see [`Linker::instantiate_pre`] as well.
267     ///
268     /// # Errors
269     ///
270     /// Returns an error if this [`Linker`] doesn't define an import that
271     /// `component` requires or if it is of the wrong type. Additionally this
272     /// can return an error if something goes wrong during instantiation such as
273     /// a runtime trap or a runtime limit being exceeded.
instantiate( &self, mut store: impl AsContextMut<Data = T>, component: &Component, ) -> Result<Instance>274     pub fn instantiate(
275         &self,
276         mut store: impl AsContextMut<Data = T>,
277         component: &Component,
278     ) -> Result<Instance> {
279         let store = store.as_context_mut();
280         store.0.validate_sync_call()?;
281         self.instantiate_pre(component)?.instantiate(store)
282     }
283 
284     /// Instantiates the [`Component`] provided into the `store` specified.
285     ///
286     /// This is exactly like [`Linker::instantiate`] except for [asynchronous
287     /// execution](crate#async).
288     ///
289     /// # Errors
290     ///
291     /// Returns an error if this [`Linker`] doesn't define an import that
292     /// `component` requires or if it is of the wrong type. Additionally this
293     /// can return an error if something goes wrong during instantiation such as
294     /// a runtime trap or a runtime limit being exceeded.
295     #[cfg(feature = "async")]
instantiate_async( &self, store: impl AsContextMut<Data = T>, component: &Component, ) -> Result<Instance> where T: Send,296     pub async fn instantiate_async(
297         &self,
298         store: impl AsContextMut<Data = T>,
299         component: &Component,
300     ) -> Result<Instance>
301     where
302         T: Send,
303     {
304         self.instantiate_pre(component)?
305             .instantiate_async(store)
306             .await
307     }
308 
309     /// Implement any imports of the given [`Component`] with a function which traps.
310     ///
311     /// By default a [`Linker`] will error when unknown imports are encountered when instantiating a [`Component`].
312     /// This changes this behavior from an instant error to a trap that will happen if the import is called.
define_unknown_imports_as_traps(&mut self, component: &Component) -> Result<()>313     pub fn define_unknown_imports_as_traps(&mut self, component: &Component) -> Result<()> {
314         use wasmtime_environ::component::ComponentTypes;
315         use wasmtime_environ::component::TypeDef;
316         // Recursively stub out all imports of the component with a function that traps.
317         fn stub_item<T>(
318             linker: &mut LinkerInstance<T>,
319             item_name: &str,
320             item_def: &TypeDef,
321             parent_instance: Option<&str>,
322             types: &ComponentTypes,
323         ) -> Result<()> {
324             // Skip if the item isn't an instance and has already been defined in the linker.
325             if !matches!(item_def, TypeDef::ComponentInstance(_)) && linker.get(item_name).is_some()
326             {
327                 return Ok(());
328             }
329 
330             match item_def {
331                 TypeDef::ComponentFunc(_) => {
332                     let fully_qualified_name = parent_instance
333                         .map(|parent| format!("{parent}#{item_name}"))
334                         .unwrap_or_else(|| item_name.to_owned());
335                     linker.func_new(&item_name, move |_, _, _, _| {
336                         bail!("unknown import: `{fully_qualified_name}` has not been defined")
337                     })?;
338                 }
339                 TypeDef::ComponentInstance(i) => {
340                     let instance = &types[*i];
341                     let mut linker_instance = linker.instance(item_name)?;
342                     for (export_name, export) in instance.exports.iter() {
343                         stub_item(
344                             &mut linker_instance,
345                             export_name,
346                             export,
347                             Some(item_name),
348                             types,
349                         )?;
350                     }
351                 }
352                 TypeDef::Resource(_) => {
353                     let ty = crate::component::ResourceType::host::<()>();
354                     linker.resource(item_name, ty, |_, _| Ok(()))?;
355                 }
356                 TypeDef::Component(_) | TypeDef::Module(_) => {
357                     bail!("unable to define {} imports as traps", item_def.desc())
358                 }
359                 _ => {}
360             }
361             Ok(())
362         }
363 
364         for (_, (import_name, import_type)) in &component.env_component().import_types {
365             stub_item(
366                 &mut self.root(),
367                 import_name,
368                 import_type,
369                 None,
370                 component.types(),
371             )?;
372         }
373         Ok(())
374     }
375 }
376 
377 impl<T: 'static> LinkerInstance<'_, T> {
as_mut(&mut self) -> LinkerInstance<'_, T>378     fn as_mut(&mut self) -> LinkerInstance<'_, T> {
379         LinkerInstance {
380             engine: self.engine,
381             path: self.path,
382             path_len: self.path_len,
383             strings: self.strings,
384             map: self.map,
385             allow_shadowing: self.allow_shadowing,
386             _marker: self._marker,
387         }
388     }
389 
390     /// Defines a new host-provided function into this [`LinkerInstance`].
391     ///
392     /// This method is used to give host functions to wasm components. The
393     /// `func` provided will be callable from linked components with the type
394     /// signature dictated by `Params` and `Return`. The `Params` is a tuple of
395     /// types that will come from wasm and `Return` is a value coming from the
396     /// host going back to wasm.
397     ///
398     /// Additionally the `func` takes a
399     /// [`StoreContextMut`](crate::StoreContextMut) as its first parameter.
400     ///
401     /// Note that `func` must be an `Fn` and must also be `Send + Sync +
402     /// 'static`. Shared state within a func is typically accessed with the `T`
403     /// type parameter from [`Store<T>`](crate::Store) which is accessible
404     /// through the leading [`StoreContextMut<'_, T>`](crate::StoreContextMut)
405     /// argument which can be provided to the `func` given here.
406     ///
407     /// # Blocking / Async Behavior
408     ///
409     /// The host function `func` provided here is a blocking function from the
410     /// perspective of WebAssembly. WebAssembly, and Rust, will be blocked until
411     /// `func` completes.
412     ///
413     /// To define a function which is async on the host, but blocking to the
414     /// guest, see the [`func_wrap_async`] method.
415     ///
416     /// [`func_wrap_async`]: LinkerInstance::func_wrap_async
417     //
418     // TODO: needs more words and examples
func_wrap<F, Params, Return>(&mut self, name: &str, func: F) -> Result<()> where F: Fn(StoreContextMut<T>, Params) -> Result<Return> + Send + Sync + 'static, Params: ComponentNamedList + Lift + 'static, Return: ComponentNamedList + Lower + 'static,419     pub fn func_wrap<F, Params, Return>(&mut self, name: &str, func: F) -> Result<()>
420     where
421         F: Fn(StoreContextMut<T>, Params) -> Result<Return> + Send + Sync + 'static,
422         Params: ComponentNamedList + Lift + 'static,
423         Return: ComponentNamedList + Lower + 'static,
424     {
425         self.insert(name, Definition::Func(HostFunc::func_wrap(func)))?;
426         Ok(())
427     }
428 
429     /// Defines a new host-provided async function into this [`LinkerInstance`].
430     ///
431     /// This function is similar to [`Self::func_wrap`] except it takes an async
432     /// host function instead of a blocking host function. The `F` function here
433     /// is intended to be:
434     ///
435     /// ```ignore
436     /// F: AsyncFn(StoreContextMut<'_, T>, Params) -> Result<Return>
437     /// ```
438     ///
439     /// however the returned future must be `Send` which is not possible to
440     /// bound at this time. This will be switched to an async closure once Rust
441     /// supports it.
442     ///
443     /// # Blocking / Async Behavior
444     ///
445     /// The function defined which WebAssembly calls will still appear as
446     /// blocking from the perspective of WebAssembly itself. The host, however,
447     /// can perform asynchronous operations without blocking the thread
448     /// performing a call.
449     ///
450     /// When defining host functions with this function, WebAssembly is invoked
451     /// on a separate stack within a Wasmtime-managed fiber (through the
452     /// `call_async`-style of invocation). This means that if the future
453     /// returned by `F` is not immediately ready then the fiber will be
454     /// suspended to block WebAssembly but not the host. When the future
455     /// becomes ready again the fiber will be resumed to continue execution
456     /// within WebAssembly.
457     ///
458     /// [`func_wrap_async`]: LinkerInstance::func_wrap_async
459     #[cfg(feature = "async")]
func_wrap_async<Params, Return, F>(&mut self, name: &str, f: F) -> Result<()> where F: Fn( StoreContextMut<'_, T>, Params, ) -> Box<dyn Future<Output = Result<Return>> + Send + '_> + Send + Sync + 'static, Params: ComponentNamedList + Lift + 'static, Return: ComponentNamedList + Lower + 'static,460     pub fn func_wrap_async<Params, Return, F>(&mut self, name: &str, f: F) -> Result<()>
461     where
462         F: Fn(
463                 StoreContextMut<'_, T>,
464                 Params,
465             ) -> Box<dyn Future<Output = Result<Return>> + Send + '_>
466             + Send
467             + Sync
468             + 'static,
469         Params: ComponentNamedList + Lift + 'static,
470         Return: ComponentNamedList + Lower + 'static,
471     {
472         self.insert(name, Definition::Func(HostFunc::func_wrap_async(f)))?;
473         Ok(())
474     }
475 
476     /// Defines a new host-provided async function into this [`LinkerInstance`].
477     ///
478     /// This function defines a host function available to call from
479     /// WebAssembly. WebAssembly may additionally make multiple invocations of
480     /// this function concurrently all at the same time. This function requires
481     /// the [`Config::wasm_component_model_async`] feature to be enabled.
482     ///
483     /// The function `f` provided will be invoked when called by WebAssembly.
484     /// WebAssembly components may then call `f` multiple times while previous
485     /// invocations of `f` are already running. Additionally while `f` is
486     /// running other host functions may be invoked.
487     ///
488     /// The `F` function here is intended to be:
489     ///
490     /// ```ignore
491     /// F: AsyncFn(&Accessor<T>, Params) -> Result<Return>
492     /// ```
493     ///
494     /// however the returned future must be `Send` which is not possible to
495     /// bound at this time. This will be switched to an async closure once Rust
496     /// supports it.
497     ///
498     /// The closure `f` is provided an [`Accessor`] which can be used to acquire
499     /// temporary, blocking, access to a [`StoreContextMut`] (through
500     /// [`Access`](crate::component::Access]). This models how a store is not
501     /// available to `f` across `await` points but it is temporarily available
502     /// while actively being polled.
503     ///
504     /// # Blocking / Async Behavior
505     ///
506     /// Unlike [`Self::func_wrap`] and [`Self::func_wrap_async`] this function
507     /// is asynchronous even from the perspective of guest WebAssembly. This
508     /// means that if `f` is not immediately resolved then the call from
509     /// WebAssembly will still return immediately (assuming it was lowered with
510     /// `async`). The closure `f` should not block the current thread and
511     /// should only perform blocking via `async` meaning that `f` won't block
512     /// either WebAssembly nor the host.
513     ///
514     /// Note that WebAssembly components can lower host functions both with and
515     /// without `async`. That means that even if a host function is defined in
516     /// the "concurrent" mode here a guest may still lower it synchronously. In
517     /// this situation Wasmtime will manage blocking the guest while the closure
518     /// `f` provided here completes. If a guest lowers this function with
519     /// `async`, though, then no blocking will happen.
520     ///
521     /// [`Config::wasm_component_model_async`]: crate::Config::wasm_component_model_async
522     /// [`func_wrap_async`]: LinkerInstance::func_wrap_async
523     #[cfg(feature = "component-model-async")]
func_wrap_concurrent<Params, Return, F>(&mut self, name: &str, f: F) -> Result<()> where T: 'static, F: Fn(&Accessor<T>, Params) -> Pin<Box<dyn Future<Output = Result<Return>> + Send + '_>> + Send + Sync + 'static, Params: ComponentNamedList + Lift + 'static, Return: ComponentNamedList + Lower + 'static,524     pub fn func_wrap_concurrent<Params, Return, F>(&mut self, name: &str, f: F) -> Result<()>
525     where
526         T: 'static,
527         F: Fn(&Accessor<T>, Params) -> Pin<Box<dyn Future<Output = Result<Return>> + Send + '_>>
528             + Send
529             + Sync
530             + 'static,
531         Params: ComponentNamedList + Lift + 'static,
532         Return: ComponentNamedList + Lower + 'static,
533     {
534         if !self.engine.tunables().concurrency_support {
535             bail!("concurrent host functions require `Config::concurrency_support`");
536         }
537         self.insert(name, Definition::Func(HostFunc::func_wrap_concurrent(f)))?;
538         Ok(())
539     }
540 
541     /// Define a new host-provided function using dynamically typed values.
542     ///
543     /// The `name` provided is the name of the function to define and the
544     /// `func` provided is the host-defined closure to invoke when this
545     /// function is called.
546     ///
547     /// This function is the "dynamic" version of defining a host function as
548     /// compared to [`LinkerInstance::func_wrap`]. With
549     /// [`LinkerInstance::func_wrap`] a function's type is statically known but
550     /// with this method the `func` argument's type isn't known ahead of time.
551     /// That means that `func` can be by imported component so long as it's
552     /// imported as a matching name.
553     ///
554     /// Type information will be available at execution time, however. For
555     /// example when `func` is invoked the second argument, a `&[Val]` list,
556     /// contains [`Val`] entries that say what type they are. Additionally the
557     /// third argument, `&mut [Val]`, is the expected number of results. Note
558     /// that the expected types of the results cannot be learned during the
559     /// execution of `func`. Learning that would require runtime introspection
560     /// of a component.
561     ///
562     /// Return values, stored in the third argument of `&mut [Val]`, are
563     /// type-checked at runtime to ensure that they have the appropriate type.
564     /// A trap will be raised if they do not have the right type.
565     ///
566     /// # Examples
567     ///
568     /// ```
569     /// use wasmtime::{Store, Engine};
570     /// use wasmtime::component::{Component, Linker, Val};
571     ///
572     /// # fn main() -> wasmtime::Result<()> {
573     /// let engine = Engine::default();
574     /// let component = Component::new(
575     ///     &engine,
576     ///     r#"
577     ///         (component
578     ///             (import "thunk" (func $thunk))
579     ///             (import "is-even" (func $is-even (param "x" u32) (result bool)))
580     ///
581     ///             (core module $m
582     ///                 (import "" "thunk" (func $thunk))
583     ///                 (import "" "is-even" (func $is-even (param i32) (result i32)))
584     ///
585     ///                 (func (export "run")
586     ///                     call $thunk
587     ///
588     ///                     (call $is-even (i32.const 1))
589     ///                     if unreachable end
590     ///
591     ///                     (call $is-even (i32.const 2))
592     ///                     i32.eqz
593     ///                     if unreachable end
594     ///                 )
595     ///             )
596     ///             (core func $thunk (canon lower (func $thunk)))
597     ///             (core func $is-even (canon lower (func $is-even)))
598     ///             (core instance $i (instantiate $m
599     ///                 (with "" (instance
600     ///                     (export "thunk" (func $thunk))
601     ///                     (export "is-even" (func $is-even))
602     ///                 ))
603     ///             ))
604     ///
605     ///             (func (export "run") (canon lift (core func $i "run")))
606     ///         )
607     ///     "#,
608     /// )?;
609     ///
610     /// let mut linker = Linker::<()>::new(&engine);
611     ///
612     /// // Sample function that takes no arguments.
613     /// linker.root().func_new("thunk", |_store, _ty, params, results| {
614     ///     assert!(params.is_empty());
615     ///     assert!(results.is_empty());
616     ///     println!("Look ma, host hands!");
617     ///     Ok(())
618     /// })?;
619     ///
620     /// // This function takes one argument and returns one result.
621     /// linker.root().func_new("is-even", |_store, _ty, params, results| {
622     ///     assert_eq!(params.len(), 1);
623     ///     let param = match params[0] {
624     ///         Val::U32(n) => n,
625     ///         _ => panic!("unexpected type"),
626     ///     };
627     ///
628     ///     assert_eq!(results.len(), 1);
629     ///     results[0] = Val::Bool(param % 2 == 0);
630     ///     Ok(())
631     /// })?;
632     ///
633     /// let mut store = Store::new(&engine, ());
634     /// let instance = linker.instantiate(&mut store, &component)?;
635     /// let run = instance.get_typed_func::<(), ()>(&mut store, "run")?;
636     /// run.call(&mut store, ())?;
637     /// # Ok(())
638     /// # }
639     /// ```
func_new( &mut self, name: &str, func: impl Fn(StoreContextMut<'_, T>, types::ComponentFunc, &[Val], &mut [Val]) -> Result<()> + Send + Sync + 'static, ) -> Result<()>640     pub fn func_new(
641         &mut self,
642         name: &str,
643         func: impl Fn(StoreContextMut<'_, T>, types::ComponentFunc, &[Val], &mut [Val]) -> Result<()>
644         + Send
645         + Sync
646         + 'static,
647     ) -> Result<()> {
648         self.insert(name, Definition::Func(HostFunc::func_new(func)))?;
649         Ok(())
650     }
651 
652     /// Define a new host-provided async function using dynamic types.
653     ///
654     /// As [`Self::func_wrap_async`] is a dual of [`Self::func_wrap`], this
655     /// function is the dual of [`Self::func_new`].
656     ///
657     /// For documentation on blocking behavior see [`Self::func_wrap_async`].
658     #[cfg(feature = "async")]
func_new_async<F>(&mut self, name: &str, func: F) -> Result<()> where F: for<'a> Fn( StoreContextMut<'a, T>, types::ComponentFunc, &'a [Val], &'a mut [Val], ) -> Box<dyn Future<Output = Result<()>> + Send + 'a> + Send + Sync + 'static,659     pub fn func_new_async<F>(&mut self, name: &str, func: F) -> Result<()>
660     where
661         F: for<'a> Fn(
662                 StoreContextMut<'a, T>,
663                 types::ComponentFunc,
664                 &'a [Val],
665                 &'a mut [Val],
666             ) -> Box<dyn Future<Output = Result<()>> + Send + 'a>
667             + Send
668             + Sync
669             + 'static,
670     {
671         self.insert(name, Definition::Func(HostFunc::func_new_async(func)))?;
672         Ok(())
673     }
674 
675     /// Define a new host-provided async function using dynamic types.
676     ///
677     /// As [`Self::func_wrap_concurrent`] is a dual of [`Self::func_wrap`], this
678     /// function is the dual of [`Self::func_new`].
679     ///
680     /// For documentation on async/blocking behavior see
681     /// [`Self::func_wrap_concurrent`].
682     #[cfg(feature = "component-model-async")]
func_new_concurrent<F>(&mut self, name: &str, f: F) -> Result<()> where T: 'static, F: for<'a> Fn( &'a Accessor<T>, types::ComponentFunc, &'a [Val], &'a mut [Val], ) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'a>> + Send + Sync + 'static,683     pub fn func_new_concurrent<F>(&mut self, name: &str, f: F) -> Result<()>
684     where
685         T: 'static,
686         F: for<'a> Fn(
687                 &'a Accessor<T>,
688                 types::ComponentFunc,
689                 &'a [Val],
690                 &'a mut [Val],
691             ) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'a>>
692             + Send
693             + Sync
694             + 'static,
695     {
696         if !self.engine.tunables().concurrency_support {
697             bail!("concurrent host functions require `Config::concurrency_support`");
698         }
699         self.insert(name, Definition::Func(HostFunc::func_new_concurrent(f)))?;
700         Ok(())
701     }
702 
703     /// Defines a [`Module`] within this instance.
704     ///
705     /// This can be used to provide a core wasm [`Module`] as an import to a
706     /// component. The [`Module`] provided is saved within the linker for the
707     /// specified `name` in this instance.
module(&mut self, name: &str, module: &Module) -> Result<()>708     pub fn module(&mut self, name: &str, module: &Module) -> Result<()> {
709         self.insert(name, Definition::Module(module.clone()))?;
710         Ok(())
711     }
712 
713     /// Defines a new resource of a given [`ResourceType`] in this linker.
714     ///
715     /// This function is used to specify resources defined in the host.
716     ///
717     /// The `name` argument is the name to define the resource within this
718     /// linker.
719     ///
720     /// The `dtor` provided is a destructor that will get invoked when an owned
721     /// version of this resource is destroyed from the guest. Note that this
722     /// destructor is not called when a host-owned resource is destroyed as it's
723     /// assumed the host knows how to handle destroying its own resources.
724     ///
725     /// The `dtor` closure is provided the store state as the first argument
726     /// along with the representation of the resource that was just destroyed.
727     ///
728     /// [`Resource<U>`]: crate::component::Resource
729     ///
730     /// # Errors
731     ///
732     /// The provided `dtor` closure returns an error if something goes wrong
733     /// when a guest calls the `dtor` to drop a `Resource<T>` such as
734     /// a runtime trap or a runtime limit being exceeded.
resource( &mut self, name: &str, ty: ResourceType, dtor: impl Fn(StoreContextMut<'_, T>, u32) -> Result<()> + Send + Sync + 'static, ) -> Result<()>735     pub fn resource(
736         &mut self,
737         name: &str,
738         ty: ResourceType,
739         dtor: impl Fn(StoreContextMut<'_, T>, u32) -> Result<()> + Send + Sync + 'static,
740     ) -> Result<()> {
741         let dtor = Arc::new(crate::func::HostFunc::wrap(
742             &self.engine,
743             move |mut cx: crate::Caller<'_, T>, (param,): (u32,)| dtor(cx.as_context_mut(), param),
744         )?);
745         self.insert(name, Definition::Resource(ty, dtor))?;
746         Ok(())
747     }
748 
749     /// Identical to [`Self::resource`], except that it takes an async destructor.
750     #[cfg(feature = "async")]
resource_async<F>(&mut self, name: &str, ty: ResourceType, dtor: F) -> Result<()> where T: Send, F: Fn(StoreContextMut<'_, T>, u32) -> Box<dyn Future<Output = Result<()>> + Send + '_> + Send + Sync + 'static,751     pub fn resource_async<F>(&mut self, name: &str, ty: ResourceType, dtor: F) -> Result<()>
752     where
753         T: Send,
754         F: Fn(StoreContextMut<'_, T>, u32) -> Box<dyn Future<Output = Result<()>> + Send + '_>
755             + Send
756             + Sync
757             + 'static,
758     {
759         let dtor = Arc::new(crate::func::HostFunc::wrap_async(
760             &self.engine,
761             move |cx: crate::Caller<'_, T>, (param,): (u32,)| dtor(cx.into(), param),
762         )?);
763         self.insert(name, Definition::Resource(ty, dtor))?;
764         Ok(())
765     }
766 
767     /// Identical to [`Self::resource`], except that it takes a concurrent destructor.
768     #[cfg(feature = "component-model-async")]
resource_concurrent<F>(&mut self, name: &str, ty: ResourceType, dtor: F) -> Result<()> where T: Send + 'static, F: Fn(&Accessor<T>, u32) -> Pin<Box<dyn Future<Output = Result<()>> + Send + '_>> + Send + Sync + 'static,769     pub fn resource_concurrent<F>(&mut self, name: &str, ty: ResourceType, dtor: F) -> Result<()>
770     where
771         T: Send + 'static,
772         F: Fn(&Accessor<T>, u32) -> Pin<Box<dyn Future<Output = Result<()>> + Send + '_>>
773             + Send
774             + Sync
775             + 'static,
776     {
777         if !self.engine.tunables().concurrency_support {
778             bail!("concurrent host functions require `Config::concurrency_support`");
779         }
780         // TODO: This isn't really concurrent -- it requires exclusive access to
781         // the store for the duration of the call, preventing guest code from
782         // running until it completes.  We should make it concurrent and clean
783         // up the implementation to avoid using e.g. `Accessor::new` and
784         // `tls::set` directly.
785         let dtor = Arc::new(dtor);
786         let dtor = Arc::new(crate::func::HostFunc::wrap_async(
787             &self.engine,
788             move |mut cx: crate::Caller<'_, T>, (param,): (u32,)| {
789                 let dtor = dtor.clone();
790                 Box::new(async move {
791                     let mut store = cx.as_context_mut();
792                     let accessor =
793                         &Accessor::new(crate::store::StoreToken::new(store.as_context_mut()));
794                     let mut future = std::pin::pin!(dtor(accessor, param));
795                     std::future::poll_fn(|cx| {
796                         crate::component::concurrent::tls::set(store.0, || future.as_mut().poll(cx))
797                     })
798                     .await
799                 })
800             },
801         )?);
802         self.insert(name, Definition::Resource(ty, dtor))?;
803         Ok(())
804     }
805 
806     /// Defines a nested instance within this instance.
807     ///
808     /// This can be used to describe arbitrarily nested levels of instances
809     /// within a linker to satisfy nested instance exports of components.
instance(&mut self, name: &str) -> Result<LinkerInstance<'_, T>>810     pub fn instance(&mut self, name: &str) -> Result<LinkerInstance<'_, T>> {
811         self.as_mut().into_instance(name)
812     }
813 
814     /// Same as [`LinkerInstance::instance`] except with different lifetime
815     /// parameters.
into_instance(mut self, name: &str) -> Result<Self>816     pub fn into_instance(mut self, name: &str) -> Result<Self> {
817         let name = self.insert(name, Definition::Instance(NameMap::default()))?;
818         self.map = match self.map.raw_get_mut(&name) {
819             Some(Definition::Instance(map)) => map,
820             _ => unreachable!(),
821         };
822         self.path.truncate(self.path_len);
823         self.path.push(name);
824         self.path_len += 1;
825         Ok(self)
826     }
827 
insert(&mut self, name: &str, item: Definition) -> Result<usize>828     fn insert(&mut self, name: &str, item: Definition) -> Result<usize> {
829         self.map
830             .insert(name, self.strings, self.allow_shadowing, item)
831     }
832 
get(&self, name: &str) -> Option<&Definition>833     fn get(&self, name: &str) -> Option<&Definition> {
834         self.map.get(name, self.strings)
835     }
836 }
837 
838 impl NameMapIntern for Strings {
839     type Key = usize;
840 
intern(&mut self, string: &str) -> usize841     fn intern(&mut self, string: &str) -> usize {
842         if let Some(idx) = self.string2idx.get(string) {
843             return *idx;
844         }
845         let string: Arc<str> = string.into();
846         let idx = self.strings.len();
847         self.strings.push(string.clone());
848         self.string2idx.insert(string, idx);
849         idx
850     }
851 
lookup(&self, string: &str) -> Option<usize>852     fn lookup(&self, string: &str) -> Option<usize> {
853         self.string2idx.get(string).cloned()
854     }
855 }
856