wasmi/
linker.rs

1#[expect(deprecated)]
2use crate::InstancePre;
3use crate::{
4    collections::{
5        string_interner::{InternHint, Sym as Symbol},
6        StringInterner,
7    },
8    func::{FuncEntity, HostFuncEntity, HostFuncTrampolineEntity},
9    module::{ImportName, ImportType},
10    AsContext,
11    AsContextMut,
12    Caller,
13    Engine,
14    Error,
15    Extern,
16    ExternType,
17    Func,
18    FuncType,
19    Instance,
20    IntoFunc,
21    Module,
22    Val,
23};
24use alloc::{
25    collections::{btree_map::Entry, BTreeMap},
26    sync::Arc,
27    vec::Vec,
28};
29use core::{
30    fmt::{self, Debug, Display},
31    marker::PhantomData,
32};
33
34/// An error that may occur upon operating with [`Linker`] instances.
35#[derive(Debug)]
36pub enum LinkerError {
37    /// Encountered duplicate definitions for the same name.
38    DuplicateDefinition {
39        /// The duplicate import name of the definition.
40        import_name: ImportName,
41    },
42    /// Encountered when no definition for an import is found.
43    MissingDefinition {
44        /// The name of the import for which no definition was found.
45        name: ImportName,
46        /// The type of the import for which no definition has been found.
47        ty: ExternType,
48    },
49    /// Encountered when a definition with invalid type is found.
50    InvalidTypeDefinition {
51        /// The name of the import for which no definition was found.
52        name: ImportName,
53        /// The expected import type.
54        expected: ExternType,
55        /// The found definition type.
56        found: ExternType,
57    },
58}
59
60impl LinkerError {
61    /// Creates a new [`LinkerError`] for when an imported definition was not found.
62    fn missing_definition(import: &ImportType) -> Self {
63        Self::MissingDefinition {
64            name: import.import_name().clone(),
65            ty: import.ty().clone(),
66        }
67    }
68
69    /// Creates a new [`LinkerError`] for when an imported definition has an invalid type.
70    fn invalid_type_definition(import: &ImportType, found: &ExternType) -> Self {
71        Self::InvalidTypeDefinition {
72            name: import.import_name().clone(),
73            expected: import.ty().clone(),
74            found: found.clone(),
75        }
76    }
77}
78
79impl core::error::Error for LinkerError {}
80
81impl Display for LinkerError {
82    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
83        match self {
84            Self::DuplicateDefinition { import_name } => {
85                write!(
86                    f,
87                    "encountered duplicate definition with name `{import_name}`",
88                )
89            }
90            Self::MissingDefinition { name, ty } => {
91                write!(
92                    f,
93                    "cannot find definition for import {name} with type {ty:?}",
94                )
95            }
96            Self::InvalidTypeDefinition {
97                name,
98                expected,
99                found,
100            } => {
101                write!(f, "found definition for import {name} with type {expected:?} but found type {found:?}")
102            }
103        }
104    }
105}
106
107/// Wasm import keys.
108#[derive(Copy, Clone, PartialOrd, Ord, PartialEq, Eq)]
109#[repr(transparent)]
110struct ImportKey {
111    /// Merged module and name symbols.
112    ///
113    /// Merging allows for a faster `Ord` implementation.
114    module_and_name: u64,
115}
116
117impl Debug for ImportKey {
118    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
119        f.debug_struct("ImportKey")
120            .field("module", &self.module())
121            .field("name", &self.name())
122            .finish()
123    }
124}
125
126impl ImportKey {
127    /// Creates a new [`ImportKey`] from the given `module` and `name` symbols.
128    #[inline]
129    pub fn new(module: Symbol, name: Symbol) -> Self {
130        let module_and_name = (u64::from(module.into_u32()) << 32) | u64::from(name.into_u32());
131        Self { module_and_name }
132    }
133
134    /// Returns the `module` [`Symbol`] of the [`ImportKey`].
135    #[inline]
136    pub fn module(&self) -> Symbol {
137        Symbol::from_u32((self.module_and_name >> 32) as u32)
138    }
139
140    /// Returns the `name` [`Symbol`] of the [`ImportKey`].
141    #[inline]
142    pub fn name(&self) -> Symbol {
143        Symbol::from_u32(self.module_and_name as u32)
144    }
145}
146
147/// A [`Linker`] definition.
148#[derive(Debug)]
149enum Definition<T> {
150    /// An external item from an [`Instance`].
151    Extern(Extern),
152    /// A [`Linker`] internal host function.
153    HostFunc(HostFuncTrampolineEntity<T>),
154}
155
156impl<T> Clone for Definition<T> {
157    fn clone(&self) -> Self {
158        match self {
159            Self::Extern(definition) => Self::Extern(*definition),
160            Self::HostFunc(host_func) => Self::HostFunc(host_func.clone()),
161        }
162    }
163}
164
165impl<T> Definition<T> {
166    /// Returns the [`Extern`] item if this [`Definition`] is [`Definition::Extern`].
167    ///
168    /// Otherwise returns `None`.
169    fn as_extern(&self) -> Option<&Extern> {
170        match self {
171            Definition::Extern(item) => Some(item),
172            Definition::HostFunc(_) => None,
173        }
174    }
175
176    /// Returns the [`ExternType`] of the [`Definition`].
177    pub fn ty(&self, ctx: impl AsContext) -> ExternType {
178        match self {
179            Definition::Extern(item) => item.ty(ctx),
180            Definition::HostFunc(host_func) => ExternType::Func(host_func.func_type().clone()),
181        }
182    }
183
184    /// Returns the [`Func`] of the [`Definition`] if it is a function.
185    ///
186    /// Returns `None` otherwise.
187    ///
188    /// # Note
189    ///
190    /// - This allocates a new [`Func`] on the `ctx` if it is a [`Linker`]
191    ///   defined host function.
192    /// - This unifies handling of [`Definition::Extern(Extern::Func)`] and
193    ///   [`Definition::HostFunc`].
194    pub fn as_func(&self, mut ctx: impl AsContextMut<Data = T>) -> Option<Func> {
195        match self {
196            Definition::Extern(Extern::Func(func)) => Some(*func),
197            Definition::HostFunc(host_func) => {
198                let trampoline = ctx
199                    .as_context_mut()
200                    .store
201                    .alloc_trampoline(host_func.trampoline().clone());
202                let ty = host_func.func_type();
203                let entity = HostFuncEntity::new(ctx.as_context().engine(), ty, trampoline);
204                let func = ctx
205                    .as_context_mut()
206                    .store
207                    .inner
208                    .alloc_func(FuncEntity::Host(entity));
209                Some(func)
210            }
211            _ => None,
212        }
213    }
214}
215
216/// A linker used to define module imports and instantiate module instances.
217#[derive(Debug)]
218pub struct Linker<T> {
219    /// The underlying [`Engine`] for the [`Linker`].
220    ///
221    /// # Note
222    ///
223    /// Primarily required to define [`Linker`] owned host functions
224    //  using [`Linker::func_wrap`] and [`Linker::func_new`]. TODO: implement methods
225    engine: Engine,
226    /// Definitions shared with other [`Linker`] instances created by the same [`LinkerBuilder`].
227    ///
228    /// `None` if no [`LinkerBuilder`] was used for creation of the [`Linker`].
229    shared: Option<Arc<LinkerInner<T>>>,
230    /// Inner linker implementation details.
231    inner: LinkerInner<T>,
232}
233
234impl<T> Clone for Linker<T> {
235    fn clone(&self) -> Linker<T> {
236        Self {
237            engine: self.engine.clone(),
238            shared: self.shared.clone(),
239            inner: self.inner.clone(),
240        }
241    }
242}
243
244impl<T> Default for Linker<T> {
245    fn default() -> Self {
246        Self::new(&Engine::default())
247    }
248}
249
250impl<T> Linker<T> {
251    /// Creates a new [`Linker`].
252    pub fn new(engine: &Engine) -> Self {
253        Self {
254            engine: engine.clone(),
255            shared: None,
256            inner: LinkerInner::default(),
257        }
258    }
259
260    /// Creates a new [`LinkerBuilder`] to construct a [`Linker`].
261    #[expect(deprecated)]
262    pub fn build() -> LinkerBuilder<state::Constructing, T> {
263        LinkerBuilder {
264            inner: Arc::new(LinkerInner::default()),
265            marker: PhantomData,
266        }
267    }
268
269    /// Returns the underlying [`Engine`] of the [`Linker`].
270    pub fn engine(&self) -> &Engine {
271        &self.engine
272    }
273
274    /// Configures whether this [`Linker`] allows to shadow previous definitions with the same name.
275    ///
276    /// Disabled by default.
277    pub fn allow_shadowing(&mut self, allow: bool) -> &mut Self {
278        self.inner.allow_shadowing(allow);
279        self
280    }
281
282    /// Ensures that the `name` in `module` is undefined in the shared definitions.
283    ///
284    /// Returns `Ok` if no shared definition exists.
285    ///
286    /// # Errors
287    ///
288    /// If there exists a shared definition for `name` in `module`.
289    fn ensure_undefined(&self, module: &str, name: &str) -> Result<(), LinkerError> {
290        if let Some(shared) = &self.shared {
291            if shared.has_definition(module, name) {
292                return Err(LinkerError::DuplicateDefinition {
293                    import_name: ImportName::new(module, name),
294                });
295            }
296        }
297        Ok(())
298    }
299
300    /// Define a new item in this [`Linker`].
301    ///
302    /// # Errors
303    ///
304    /// If there already is a definition under the same name for this [`Linker`].
305    pub fn define(
306        &mut self,
307        module: &str,
308        name: &str,
309        item: impl Into<Extern>,
310    ) -> Result<&mut Self, LinkerError> {
311        self.ensure_undefined(module, name)?;
312        let key = self.inner.new_import_key(module, name);
313        self.inner.insert(key, Definition::Extern(item.into()))?;
314        Ok(self)
315    }
316
317    /// Creates a new named [`Func::new`]-style host [`Func`] for this [`Linker`].
318    ///
319    /// For more information see [`Linker::func_wrap`].
320    ///
321    /// # Errors
322    ///
323    /// If there already is a definition under the same name for this [`Linker`].
324    pub fn func_new(
325        &mut self,
326        module: &str,
327        name: &str,
328        ty: FuncType,
329        func: impl Fn(Caller<'_, T>, &[Val], &mut [Val]) -> Result<(), Error> + Send + Sync + 'static,
330    ) -> Result<&mut Self, LinkerError> {
331        self.ensure_undefined(module, name)?;
332        let func = HostFuncTrampolineEntity::new(ty, func);
333        let key = self.inner.new_import_key(module, name);
334        self.inner.insert(key, Definition::HostFunc(func))?;
335        Ok(self)
336    }
337
338    /// Creates a new named [`Func::new`]-style host [`Func`] for this [`Linker`].
339    ///
340    /// For information how to use this API see [`Func::wrap`].
341    ///
342    /// This method creates a host function for this [`Linker`] under the given name.
343    /// It is distinct in its ability to create a [`Store`] independent
344    /// host function. Host functions defined this way can be used to instantiate
345    /// instances in multiple different [`Store`] entities.
346    ///
347    /// The same applies to other [`Linker`] methods to define new [`Func`] instances
348    /// such as [`Linker::func_new`].
349    ///
350    /// In a concurrently running program, this means that these host functions
351    /// could be called concurrently if different [`Store`] entities are executing on
352    /// different threads.
353    ///
354    /// # Errors
355    ///
356    /// If there already is a definition under the same name for this [`Linker`].
357    ///
358    /// [`Store`]: crate::Store
359    pub fn func_wrap<Params, Args>(
360        &mut self,
361        module: &str,
362        name: &str,
363        func: impl IntoFunc<T, Params, Args>,
364    ) -> Result<&mut Self, LinkerError> {
365        self.ensure_undefined(module, name)?;
366        let func = HostFuncTrampolineEntity::wrap(func);
367        let key = self.inner.new_import_key(module, name);
368        self.inner.insert(key, Definition::HostFunc(func))?;
369        Ok(self)
370    }
371
372    /// Looks up a defined [`Extern`] by name in this [`Linker`].
373    ///
374    /// - Returns `None` if this name was not previously defined in this [`Linker`].
375    /// - Returns `None` if the definition is a [`Linker`] defined host function.
376    ///
377    /// # Panics
378    ///
379    /// If the [`Engine`] of this [`Linker`] and the [`Engine`] of `context` are not the same.
380    pub fn get(
381        &self,
382        context: impl AsContext<Data = T>,
383        module: &str,
384        name: &str,
385    ) -> Option<Extern> {
386        match self.get_definition(context, module, name) {
387            Some(Definition::Extern(item)) => Some(*item),
388            _ => None,
389        }
390    }
391
392    /// Looks up a [`Definition`] by name in this [`Linker`].
393    ///
394    /// Returns `None` if this name was not previously defined in this [`Linker`].
395    ///
396    /// # Panics
397    ///
398    /// If the [`Engine`] of this [`Linker`] and the [`Engine`] of `context` are not the same.
399    fn get_definition(
400        &self,
401        context: impl AsContext<Data = T>,
402        module: &str,
403        name: &str,
404    ) -> Option<&Definition<T>> {
405        assert!(Engine::same(
406            context.as_context().store.engine(),
407            self.engine()
408        ));
409        if let Some(shared) = &self.shared {
410            if let Some(item) = shared.get_definition(module, name) {
411                return Some(item);
412            }
413        }
414        self.inner.get_definition(module, name)
415    }
416
417    /// Convenience wrapper to define an entire [`Instance`]` in this [`Linker`].
418    ///
419    /// This is a convenience wrapper around [`Linker::define`] which defines all exports of
420    /// the `instance` for `self`. The module name for each export is `module_name` and the
421    /// field name for each export is the name in the `instance` itself.
422    ///
423    /// # Errors
424    ///
425    /// - If any item is re-defined in `self` (for example the same `module_name` was already defined).
426    /// - If `instance` comes from a different [`Store`](crate::Store) than this [`Linker`] originally
427    ///   was created with.
428    ///
429    /// # Panics
430    ///
431    /// If the [`Engine`] of this [`Linker`] and the [`Engine`] of `store` are not the same.
432    pub fn instance(
433        &mut self,
434        mut store: impl AsContextMut<Data = T>,
435        module_name: &str,
436        instance: Instance,
437    ) -> Result<&mut Self, Error> {
438        assert!(Engine::same(
439            store.as_context().store.engine(),
440            self.engine()
441        ));
442        let mut store = store.as_context_mut();
443        for export in instance.exports(&mut store) {
444            let key = self.inner.new_import_key(module_name, export.name());
445            let def = Definition::Extern(export.into_extern());
446            self.inner.insert(key, def)?;
447        }
448        Ok(self)
449    }
450
451    /// Aliases one module's name as another.
452    ///
453    /// This method will alias all currently defined under `module` to also be
454    /// defined under the name `as_module` too.
455    ///
456    /// # Errors
457    ///
458    /// Returns an error if any shadowing violations happen while defining new
459    /// items.
460    pub fn alias_module(&mut self, module: &str, as_module: &str) -> Result<(), Error> {
461        self.inner.alias_module(module, as_module)
462    }
463
464    /// Instantiates the given [`Module`] using the definitions in the [`Linker`].
465    ///
466    /// # Panics
467    ///
468    /// If the [`Engine`] of the [`Linker`] and `context` are not the same.
469    ///
470    /// # Errors
471    ///
472    /// - If the linker does not define imports of the instantiated [`Module`].
473    /// - If any imported item does not satisfy its type requirements.
474    #[deprecated(
475        since = "0.49.0",
476        note = "\
477            use `Linker::instantiate_and_start` instead. \
478            Prevent `start` function execution by enabling fuel metering and setting fuel to zero before instantiation. \
479        "
480    )]
481    #[expect(deprecated)]
482    pub fn instantiate(
483        &self,
484        mut context: impl AsContextMut<Data = T>,
485        module: &Module,
486    ) -> Result<InstancePre, Error> {
487        assert!(Engine::same(self.engine(), context.as_context().engine()));
488        // TODO: possibly add further resource limitation here on number of externals.
489        // Not clear that user can't import the same external lots of times to inflate this.
490        let externals = module
491            .imports()
492            .map(|import| self.process_import(&mut context, import))
493            .collect::<Result<Vec<Extern>, Error>>()?;
494        module.instantiate(context, externals)
495    }
496
497    /// Instantiates the given [`Module`] using the definitions in the [`Linker`].
498    ///
499    /// # Panics
500    ///
501    /// If the [`Engine`] of the [`Linker`] and `context` are not the same.
502    ///
503    /// # Errors
504    ///
505    /// - If the linker does not define imports of the instantiated [`Module`].
506    /// - If any imported item does not satisfy its type requirements.
507    /// - If the `start` function traps.
508    pub fn instantiate_and_start(
509        &self,
510        mut context: impl AsContextMut<Data = T>,
511        module: &Module,
512    ) -> Result<Instance, Error> {
513        #[expect(deprecated)]
514        self.instantiate(&mut context, module)
515            .and_then(|instance| instance.start(&mut context))
516    }
517
518    /// Processes a single [`Module`] import.
519    ///
520    /// # Panics
521    ///
522    /// If the [`Engine`] of the [`Linker`] and `context` are not the same.
523    ///
524    /// # Errors
525    ///
526    /// If the imported item does not satisfy constraints set by the [`Module`].
527    fn process_import(
528        &self,
529        mut context: impl AsContextMut<Data = T>,
530        import: ImportType,
531    ) -> Result<Extern, Error> {
532        assert!(Engine::same(self.engine(), context.as_context().engine()));
533        let module_name = import.module();
534        let field_name = import.name();
535        let resolved = self
536            .get_definition(context.as_context(), module_name, field_name)
537            .ok_or_else(|| LinkerError::missing_definition(&import))?;
538        let invalid_type =
539            |context| LinkerError::invalid_type_definition(&import, &resolved.ty(context));
540        match import.ty() {
541            ExternType::Func(_expected) => {
542                let func = resolved
543                    .as_func(&mut context)
544                    .ok_or_else(|| invalid_type(context))?;
545                Ok(Extern::Func(func))
546            }
547            ExternType::Table(_expected) => {
548                let table = resolved
549                    .as_extern()
550                    .copied()
551                    .and_then(Extern::into_table)
552                    .ok_or_else(|| invalid_type(context))?;
553                Ok(Extern::Table(table))
554            }
555            ExternType::Memory(_expected) => {
556                let memory = resolved
557                    .as_extern()
558                    .copied()
559                    .and_then(Extern::into_memory)
560                    .ok_or_else(|| invalid_type(context))?;
561                Ok(Extern::Memory(memory))
562            }
563            ExternType::Global(_expected) => {
564                let global = resolved
565                    .as_extern()
566                    .copied()
567                    .and_then(Extern::into_global)
568                    .ok_or_else(|| invalid_type(context))?;
569                Ok(Extern::Global(global))
570            }
571        }
572    }
573}
574
575/// Contains type states for the [`LinkerBuilder`] construction process.
576#[deprecated(since = "0.49.0", note = "use `Linker` or `Instance::new` instead")]
577pub mod state {
578    /// Signals that the [`LinkerBuilder`] is itself under construction.
579    ///
580    /// [`LinkerBuilder`]: super::LinkerBuilder
581    #[deprecated(since = "0.49.0", note = "use `Linker` or `Instance::new` instead")]
582    pub enum Constructing {}
583
584    /// Signals that the [`LinkerBuilder`] is ready to create new [`Linker`] instances.
585    ///
586    /// [`Linker`]: super::Linker
587    /// [`LinkerBuilder`]: super::LinkerBuilder
588    #[deprecated(since = "0.49.0", note = "use `Linker` or `Instance::new` instead")]
589    pub enum Ready {}
590}
591
592/// A linker used to define module imports and instantiate module instances.
593///
594/// Create this type via the [`Linker::build`] method.
595#[derive(Debug)]
596#[deprecated(since = "0.49.0", note = "use `Linker` or `Instance::new` instead")]
597pub struct LinkerBuilder<State, T> {
598    /// Internal linker implementation details.
599    inner: Arc<LinkerInner<T>>,
600    /// The [`LinkerBuilder`] type state.
601    marker: PhantomData<fn() -> State>,
602}
603
604#[expect(deprecated)]
605impl<T> Clone for LinkerBuilder<state::Ready, T> {
606    fn clone(&self) -> Self {
607        Self {
608            inner: self.inner.clone(),
609            marker: PhantomData,
610        }
611    }
612}
613
614#[expect(deprecated)]
615impl<T> LinkerBuilder<state::Ready, T> {
616    /// Finishes construction of the [`Linker`] by attaching an [`Engine`].
617    pub fn create(&self, engine: &Engine) -> Linker<T> {
618        Linker {
619            engine: engine.clone(),
620            shared: self.inner.clone().into(),
621            inner: <LinkerInner<T>>::default(),
622        }
623    }
624}
625
626#[expect(deprecated)]
627impl<T> LinkerBuilder<state::Constructing, T> {
628    /// Signals that the [`LinkerBuilder`] is now ready to create new [`Linker`] instances.
629    pub fn finish(self) -> LinkerBuilder<state::Ready, T> {
630        LinkerBuilder {
631            inner: self.inner,
632            marker: PhantomData,
633        }
634    }
635
636    /// Returns an exclusive reference to the underlying [`Linker`] internals if no [`Linker`] has been built, yet.
637    ///
638    /// # Panics
639    ///
640    /// If the [`LinkerBuilder`] has already created a [`Linker`] using [`LinkerBuilder::finish`].
641    fn inner_mut(&mut self) -> &mut LinkerInner<T> {
642        Arc::get_mut(&mut self.inner).unwrap_or_else(|| {
643            unreachable!("tried to define host function in LinkerBuilder after Linker creation")
644        })
645    }
646
647    /// Creates a new named [`Func::new`]-style host [`Func`] for this [`Linker`].
648    ///
649    /// For more information see [`Linker::func_wrap`].
650    ///
651    /// # Errors
652    ///
653    /// If there already is a definition under the same name for this [`Linker`].
654    ///
655    /// # Panics
656    ///
657    /// If the [`LinkerBuilder`] has already created a [`Linker`] using [`LinkerBuilder::finish`].
658    pub fn func_new(
659        &mut self,
660        module: &str,
661        name: &str,
662        ty: FuncType,
663        func: impl Fn(Caller<'_, T>, &[Val], &mut [Val]) -> Result<(), Error> + Send + Sync + 'static,
664    ) -> Result<&mut Self, LinkerError> {
665        self.inner_mut().func_new(module, name, ty, func)?;
666        Ok(self)
667    }
668
669    /// Creates a new named [`Func::new`]-style host [`Func`] for this [`Linker`].
670    ///
671    /// For information how to use this API see [`Func::wrap`].
672    ///
673    /// This method creates a host function for this [`Linker`] under the given name.
674    /// It is distinct in its ability to create a [`Store`] independent
675    /// host function. Host functions defined this way can be used to instantiate
676    /// instances in multiple different [`Store`] entities.
677    ///
678    /// The same applies to other [`Linker`] methods to define new [`Func`] instances
679    /// such as [`Linker::func_new`].
680    ///
681    /// In a concurrently running program, this means that these host functions
682    /// could be called concurrently if different [`Store`] entities are executing on
683    /// different threads.
684    ///
685    /// # Errors
686    ///
687    /// If there already is a definition under the same name for this [`Linker`].
688    ///
689    /// [`Store`]: crate::Store
690    ///
691    /// # Panics
692    ///
693    /// If the [`LinkerBuilder`] has already created a [`Linker`] using [`LinkerBuilder::finish`].
694    pub fn func_wrap<Params, Args>(
695        &mut self,
696        module: &str,
697        name: &str,
698        func: impl IntoFunc<T, Params, Args>,
699    ) -> Result<&mut Self, LinkerError> {
700        self.inner_mut().func_wrap(module, name, func)?;
701        Ok(self)
702    }
703}
704
705/// Internal [`Linker`] implementation.
706#[derive(Debug)]
707pub struct LinkerInner<T> {
708    /// Allows to efficiently store strings and deduplicate them..
709    strings: StringInterner,
710    /// Stores the definitions given their names.
711    ///
712    /// # Dev. Note
713    ///
714    /// Benchmarks show that [`BTreeMap`] performs better than [`HashMap`]
715    /// which is why we do not use [`wasmi_collections::Map`] here.
716    ///
717    /// [`HashMap`]: std::collections::HashMap
718    definitions: BTreeMap<ImportKey, Definition<T>>,
719    /// True if this linker allows to shadow previous definitions.
720    allow_shadowing: bool,
721}
722
723impl<T> Default for LinkerInner<T> {
724    fn default() -> Self {
725        Self {
726            strings: StringInterner::default(),
727            definitions: BTreeMap::default(),
728            allow_shadowing: false,
729        }
730    }
731}
732
733impl<T> Clone for LinkerInner<T> {
734    fn clone(&self) -> Self {
735        Self {
736            strings: self.strings.clone(),
737            definitions: self.definitions.clone(),
738            allow_shadowing: self.allow_shadowing,
739        }
740    }
741}
742
743impl<T> LinkerInner<T> {
744    /// Configures whether this [`LinkerInner`] allows to shadow previous definitions with the same name.
745    ///
746    /// Disabled by default.
747    pub fn allow_shadowing(&mut self, allow: bool) {
748        self.allow_shadowing = allow;
749    }
750
751    /// Returns the import key for the module name and item name.
752    fn new_import_key(&mut self, module: &str, name: &str) -> ImportKey {
753        ImportKey::new(
754            self.strings
755                .get_or_intern_with_hint(module, InternHint::LikelyExists),
756            self.strings
757                .get_or_intern_with_hint(name, InternHint::LikelyNew),
758        )
759    }
760
761    /// Returns the import key for the module name and item name.
762    fn get_import_key(&self, module: &str, name: &str) -> Option<ImportKey> {
763        Some(ImportKey::new(
764            self.strings.get(module)?,
765            self.strings.get(name)?,
766        ))
767    }
768
769    /// Resolves the module and item name of the import key if any.
770    fn resolve_import_key(&self, key: ImportKey) -> Option<(&str, &str)> {
771        let module_name = self.strings.resolve(key.module())?;
772        let item_name = self.strings.resolve(key.name())?;
773        Some((module_name, item_name))
774    }
775
776    /// Inserts the extern item under the import key.
777    ///
778    /// # Errors
779    ///
780    /// If there already is a definition for the import key for this [`Linker`].
781    fn insert(&mut self, key: ImportKey, item: Definition<T>) -> Result<(), LinkerError> {
782        match self.definitions.entry(key) {
783            Entry::Occupied(mut entry) if self.allow_shadowing => {
784                entry.insert(item);
785            }
786            Entry::Occupied(_) => {
787                let (module_name, field_name) = self
788                    .resolve_import_key(key)
789                    .unwrap_or_else(|| panic!("encountered missing import names for key {key:?}"));
790                let import_name = ImportName::new(module_name, field_name);
791                return Err(LinkerError::DuplicateDefinition { import_name });
792            }
793            Entry::Vacant(v) => {
794                v.insert(item);
795            }
796        }
797        Ok(())
798    }
799
800    /// Aliases one module's name as another.
801    ///
802    /// Read more about this method in [`Linker::alias_module`].
803    pub fn alias_module(&mut self, module: &str, as_module: &str) -> Result<(), Error> {
804        let module = self
805            .strings
806            .get_or_intern_with_hint(module, InternHint::LikelyExists);
807        let as_module = self
808            .strings
809            .get_or_intern_with_hint(as_module, InternHint::LikelyNew);
810        let items = self
811            .definitions
812            .iter()
813            .filter(|(key, _def)| key.module() == module)
814            .map(|(key, def)| (key.name(), def.clone()))
815            .collect::<Vec<_>>();
816        for (name, item) in items {
817            self.insert(ImportKey::new(as_module, name), item)?;
818        }
819        Ok(())
820    }
821
822    /// Creates a new named [`Func::new`]-style host [`Func`] for this [`Linker`].
823    ///
824    /// For more information see [`Linker::func_wrap`].
825    ///
826    /// # Errors
827    ///
828    /// If there already is a definition under the same name for this [`Linker`].
829    pub fn func_new(
830        &mut self,
831        module: &str,
832        name: &str,
833        ty: FuncType,
834        func: impl Fn(Caller<'_, T>, &[Val], &mut [Val]) -> Result<(), Error> + Send + Sync + 'static,
835    ) -> Result<&mut Self, LinkerError> {
836        let func = HostFuncTrampolineEntity::new(ty, func);
837        let key = self.new_import_key(module, name);
838        self.insert(key, Definition::HostFunc(func))?;
839        Ok(self)
840    }
841
842    /// Creates a new named [`Func::new`]-style host [`Func`] for this [`Linker`].
843    ///
844    /// For information how to use this API see [`Func::wrap`].
845    ///
846    /// This method creates a host function for this [`Linker`] under the given name.
847    /// It is distinct in its ability to create a [`Store`] independent
848    /// host function. Host functions defined this way can be used to instantiate
849    /// instances in multiple different [`Store`] entities.
850    ///
851    /// The same applies to other [`Linker`] methods to define new [`Func`] instances
852    /// such as [`Linker::func_new`].
853    ///
854    /// In a concurrently running program, this means that these host functions
855    /// could be called concurrently if different [`Store`] entities are executing on
856    /// different threads.
857    ///
858    /// # Errors
859    ///
860    /// If there already is a definition under the same name for this [`Linker`].
861    ///
862    /// [`Store`]: crate::Store
863    pub fn func_wrap<Params, Args>(
864        &mut self,
865        module: &str,
866        name: &str,
867        func: impl IntoFunc<T, Params, Args>,
868    ) -> Result<&mut Self, LinkerError> {
869        let func = HostFuncTrampolineEntity::wrap(func);
870        let key = self.new_import_key(module, name);
871        self.insert(key, Definition::HostFunc(func))?;
872        Ok(self)
873    }
874
875    /// Looks up a [`Definition`] by name in this [`Linker`].
876    ///
877    /// Returns `None` if this name was not previously defined in this [`Linker`].
878    ///
879    /// # Panics
880    ///
881    /// If the [`Engine`] of this [`Linker`] and the [`Engine`] of `context` are not the same.
882    fn get_definition(&self, module: &str, name: &str) -> Option<&Definition<T>> {
883        let key = self.get_import_key(module, name)?;
884        self.definitions.get(&key)
885    }
886
887    /// Returns `true` if [`LinkerInner`] contains a [`Definition`] for `name` in `module`.
888    fn has_definition(&self, module: &str, name: &str) -> bool {
889        let Some(key) = self.get_import_key(module, name) else {
890            return false;
891        };
892        self.definitions.contains_key(&key)
893    }
894}
895
896#[cfg(test)]
897mod tests {
898    use super::*;
899    use crate::{Store, ValType};
900
901    struct HostState {
902        a: i32,
903        b: i64,
904    }
905
906    #[test]
907    fn linker_funcs_work() {
908        let engine = Engine::default();
909        let mut linker = <Linker<HostState>>::new(&engine);
910        linker
911            .func_new(
912                "host",
913                "get_a",
914                FuncType::new([], [ValType::I32]),
915                |ctx: Caller<HostState>, _params: &[Val], results: &mut [Val]| {
916                    results[0] = Val::from(ctx.data().a);
917                    Ok(())
918                },
919            )
920            .unwrap();
921        linker
922            .func_new(
923                "host",
924                "set_a",
925                FuncType::new([ValType::I32], []),
926                |mut ctx: Caller<HostState>, params: &[Val], _results: &mut [Val]| {
927                    ctx.data_mut().a = params[0].i32().unwrap();
928                    Ok(())
929                },
930            )
931            .unwrap();
932        linker
933            .func_wrap("host", "get_b", |ctx: Caller<HostState>| ctx.data().b)
934            .unwrap();
935        linker
936            .func_wrap("host", "set_b", |mut ctx: Caller<HostState>, value: i64| {
937                ctx.data_mut().b = value
938            })
939            .unwrap();
940        let a_init = 42;
941        let b_init = 77;
942        let mut store = <Store<HostState>>::new(
943            &engine,
944            HostState {
945                a: a_init,
946                b: b_init,
947            },
948        );
949        let wasm = r#"
950                (module
951                    (import "host" "get_a" (func $host_get_a (result i32)))
952                    (import "host" "set_a" (func $host_set_a (param i32)))
953                    (import "host" "get_b" (func $host_get_b (result i64)))
954                    (import "host" "set_b" (func $host_set_b (param i64)))
955
956                    (func (export "wasm_get_a") (result i32)
957                        (call $host_get_a)
958                    )
959                    (func (export "wasm_set_a") (param $param i32)
960                        (call $host_set_a (local.get $param))
961                    )
962
963                    (func (export "wasm_get_b") (result i64)
964                        (call $host_get_b)
965                    )
966                    (func (export "wasm_set_b") (param $param i64)
967                        (call $host_set_b (local.get $param))
968                    )
969                )
970            "#;
971        let module = Module::new(&engine, wasm).unwrap();
972        let instance = linker.instantiate_and_start(&mut store, &module).unwrap();
973
974        let wasm_get_a = instance
975            .get_typed_func::<(), i32>(&store, "wasm_get_a")
976            .unwrap();
977        let wasm_set_a = instance
978            .get_typed_func::<i32, ()>(&store, "wasm_set_a")
979            .unwrap();
980        let wasm_get_b = instance
981            .get_typed_func::<(), i64>(&store, "wasm_get_b")
982            .unwrap();
983        let wasm_set_b = instance
984            .get_typed_func::<i64, ()>(&store, "wasm_set_b")
985            .unwrap();
986
987        assert_eq!(wasm_get_a.call(&mut store, ()).unwrap(), a_init);
988        wasm_set_a.call(&mut store, 100).unwrap();
989        assert_eq!(wasm_get_a.call(&mut store, ()).unwrap(), 100);
990
991        assert_eq!(wasm_get_b.call(&mut store, ()).unwrap(), b_init);
992        wasm_set_b.call(&mut store, 200).unwrap();
993        assert_eq!(wasm_get_b.call(&mut store, ()).unwrap(), 200);
994    }
995
996    #[test]
997    fn build_linker() {
998        let mut builder = <Linker<()>>::build();
999        builder
1000            .func_wrap("env", "foo", || std::println!("called foo"))
1001            .unwrap();
1002        builder
1003            .func_new(
1004                "env",
1005                "bar",
1006                FuncType::new([], []),
1007                |_caller, _params, _results| {
1008                    std::println!("called bar");
1009                    Ok(())
1010                },
1011            )
1012            .unwrap();
1013        let builder = builder.finish();
1014        for _ in 0..3 {
1015            let engine = Engine::default();
1016            let _ = builder.create(&engine);
1017        }
1018    }
1019
1020    #[test]
1021    fn linker_builder_uses() {
1022        use crate::{Engine, Linker, Module, Store};
1023        let wasm = r#"
1024            (module
1025                (import "host" "func.0" (func $host_func.0))
1026                (import "host" "func.1" (func $host_func.1))
1027                (func (export "hello")
1028                    (call $host_func.0)
1029                    (call $host_func.1)
1030                )
1031            )"#;
1032        let engine = Engine::default();
1033        let mut builder = <Linker<()>>::build();
1034        builder
1035            .func_wrap("host", "func.0", |_caller: Caller<()>| ())
1036            .unwrap();
1037        builder
1038            .func_wrap("host", "func.1", |_caller: Caller<()>| ())
1039            .unwrap();
1040        let linker = builder.finish().create(&engine);
1041        let mut store = Store::new(&engine, ());
1042        let module = Module::new(&engine, wasm).unwrap();
1043        linker.instantiate_and_start(&mut store, &module).unwrap();
1044    }
1045
1046    #[test]
1047    fn linker_builder_and_linker_uses() {
1048        use crate::{Engine, Linker, Module, Store};
1049        let wasm = r#"
1050            (module
1051                (import "host" "func.0" (func $host_func.0))
1052                (import "host" "func.1" (func $host_func.1))
1053                (func (export "hello")
1054                    (call $host_func.0)
1055                    (call $host_func.1)
1056                )
1057            )"#;
1058        let engine = Engine::default();
1059        let mut builder = <Linker<()>>::build();
1060        builder
1061            .func_wrap("host", "func.0", |_caller: Caller<()>| ())
1062            .unwrap();
1063        let mut linker = builder.finish().create(&engine);
1064        linker
1065            .func_wrap("host", "func.1", |_caller: Caller<()>| ())
1066            .unwrap();
1067        let mut store = Store::new(&engine, ());
1068        let module = Module::new(&engine, wasm).unwrap();
1069        linker.instantiate_and_start(&mut store, &module).unwrap();
1070    }
1071
1072    #[test]
1073    fn linker_builder_no_overwrite() {
1074        use crate::{Engine, Linker};
1075        let engine = Engine::default();
1076        let mut builder = <Linker<()>>::build();
1077        builder
1078            .func_wrap("host", "func.0", |_caller: Caller<()>| ())
1079            .unwrap();
1080        let mut linker = builder.finish().create(&engine);
1081        linker
1082            .func_wrap("host", "func.1", |_caller: Caller<()>| ())
1083            .unwrap();
1084        // The following definition won't shadow the previous 'host/func.0' func and errors instead:
1085        linker
1086            .func_wrap("host", "func.0", |_caller: Caller<()>| ())
1087            .unwrap_err();
1088    }
1089
1090    #[test]
1091    fn populate_via_imports() {
1092        use crate::{Engine, Func, Linker, Memory, MemoryType, Module, Store};
1093        let wasm = r#"
1094            (module
1095                (import "host" "hello" (func $host_hello (param i32) (result i32)))
1096                (import "env" "memory" (memory $mem 0 4096))
1097                (func (export "hello") (result i32)
1098                    (call $host_hello (i32.const 3))
1099                    (i32.const 2)
1100                    i32.add
1101                )
1102            )"#;
1103        let engine = Engine::default();
1104        let mut linker = <Linker<()>>::new(&engine);
1105        let mut store = Store::new(&engine, ());
1106        let memory = Memory::new(&mut store, MemoryType::new(1, Some(4096))).unwrap();
1107        let module = Module::new(&engine, wasm).unwrap();
1108        linker.define("env", "memory", memory).unwrap();
1109        let func = Func::new(
1110            &mut store,
1111            FuncType::new([ValType::I32], [ValType::I32]),
1112            |_caller, _params, _results| todo!(),
1113        );
1114        linker.define("host", "hello", func).unwrap();
1115        linker.instantiate_and_start(&mut store, &module).unwrap();
1116    }
1117}