Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 25 additions & 17 deletions crates/wasmtime/src/func.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1421,17 +1421,21 @@ pub trait IntoFunc<Params, Results> {
/// via [`Func::wrap`].
///
/// This structure can be taken as the first parameter of a closure passed to
/// [`Func::wrap`], and it can be used to learn information about the caller of
/// [Func::wrap], and it can be used to learn information about the caller of
/// the function, such as the calling module's memory, exports, etc.
///
/// The primary purpose of this structure is to provide access to the
/// caller's information, such as it's exported memory. This allows
/// functions which take pointers as arguments to easily read the memory the
/// pointers point into.
/// caller's information, namely it's exported memory and exported functions. This
/// allows functions which take pointers as arguments to easily read the memory the
/// pointers point into, or if a function is expected to call malloc in the wasm
/// module to reserve space for the output you can do that.
///
/// Note that this is intended to be a pretty temporary mechanism for accessing
/// the caller's memory until interface types has been fully standardized and
/// implemented.
/// Note that this Caller type a pretty temporary mechanism for accessing the
/// caller's information until interface types has been fully standardized and
/// implemented. The interface types proposal will obsolete this type and this will
/// be removed in the future at some point after interface types is implemented. If
/// you're relying on this Caller type it's recommended to become familiar with
/// interface types to ensure that your use case is covered by the proposal.
pub struct Caller<'a> {
// Note that this is a `Weak` pointer instead of a `&'a Store`,
// intentionally so. This allows us to break an `Rc` cycle which would
Expand All @@ -1457,14 +1461,18 @@ impl Caller<'_> {
/// Looks up an export from the caller's module by the `name` given.
///
/// Note that this function is only implemented for the `Extern::Memory`
/// type currently. No other exported structure can be acquired through this
/// just yet, but this may be implemented in the future!
Comment thread
agiachris marked this conversation as resolved.
/// and the `Extern::Func` types currently. No other exported structures
/// can be acquired through this just yet, but this may be implemented
/// in the future!
///
/// Note that when accessing and calling exported functions, one should adhere
/// to the guidlines of the interface types proposal.
///
/// # Return
///
/// If a memory export with the `name` provided was found, then it is
/// If a memory or function export with the `name` provided was found, then it is
/// returned as a `Memory`. There are a number of situations, however, where
/// the memory may not be available:
/// the memory or function may not be available:
///
/// * The caller instance may not have an export named `name`
/// * The export named `name` may not be an exported memory
Expand All @@ -1479,19 +1487,19 @@ impl Caller<'_> {
return None;
}
let instance = InstanceHandle::from_vmctx(self.caller_vmctx);
let export = match instance.lookup(name) {
Some(Export::Memory(m)) => m,
_ => return None,
};
let export = instance.lookup(name)?;
// Our `Weak` pointer is used only to break a cycle where `Store`
// stores instance handles which have this weak pointer as their
// custom host data. This function should only be invoke-able while
// the `Store` is active, so this upgrade should always succeed.
debug_assert!(self.store.upgrade().is_some());
let handle =
Store::from_inner(self.store.upgrade()?).existing_instance_handle(instance);
let mem = Memory::from_wasmtime_memory(export, handle);
Some(Extern::Memory(mem))
match export {
Export::Memory(m) => Some(Extern::Memory(Memory::from_wasmtime_memory(m, handle))),
Export::Function(f) => Some(Extern::Func(Func::from_wasmtime_function(f, handle))),
_ => None,
}
}
}

Expand Down
2 changes: 1 addition & 1 deletion tests/all/func.rs
Original file line number Diff line number Diff line change
Expand Up @@ -409,7 +409,7 @@ fn caller_memory() -> anyhow::Result<()> {

let f = Func::wrap(&store, |c: Caller<'_>| {
assert!(c.get_export("m").is_some());
assert!(c.get_export("f").is_none());
assert!(c.get_export("f").is_some());
assert!(c.get_export("g").is_none());
assert!(c.get_export("t").is_none());
});
Expand Down