1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81
use super::InstantiationError;
use crate::{module::FuncIdx, AsContextMut, Error, Instance, InstanceEntityBuilder};
/// A partially instantiated [`Instance`] where the `start` function has not yet been executed.
///
/// # Note
///
/// Some users require Wasm modules to not have a `start` function that is required for
/// conformant module instantiation. This API provides control over the precise instantiation
/// process with regard to this need.
#[derive(Debug)]
pub struct InstancePre {
handle: Instance,
builder: InstanceEntityBuilder,
}
impl InstancePre {
/// Creates a new [`InstancePre`].
pub(super) fn new(handle: Instance, builder: InstanceEntityBuilder) -> Self {
Self { handle, builder }
}
/// Returns the index of the `start` function if any.
///
/// Returns `None` if the Wasm module does not have a `start` function.
fn start_fn(&self) -> Option<u32> {
self.builder.get_start().map(FuncIdx::into_u32)
}
/// Runs the `start` function of the [`Instance`] and returns its handle.
///
/// # Note
///
/// This finishes the instantiation procedure.
///
/// # Errors
///
/// If executing the `start` function traps.
///
/// # Panics
///
/// If the `start` function is invalid albeit successful validation.
pub fn start(self, mut context: impl AsContextMut) -> Result<Instance, Error> {
let opt_start_index = self.start_fn();
context
.as_context_mut()
.store
.inner
.initialize_instance(self.handle, self.builder.finish());
if let Some(start_index) = opt_start_index {
let start_func = self
.handle
.get_func_by_index(&mut context, start_index)
.unwrap_or_else(|| {
panic!("encountered invalid start function after validation: {start_index}")
});
start_func.call(context.as_context_mut(), &[], &mut [])?
}
Ok(self.handle)
}
/// Finishes instantiation ensuring that no `start` function exists.
///
/// # Errors
///
/// If a `start` function exists that needs to be called for conformant module instantiation.
pub fn ensure_no_start(
self,
mut context: impl AsContextMut,
) -> Result<Instance, InstantiationError> {
if let Some(index) = self.start_fn() {
return Err(InstantiationError::FoundStartFn { index });
}
context
.as_context_mut()
.store
.inner
.initialize_instance(self.handle, self.builder.finish());
Ok(self.handle)
}
}