Skip to content

Commit

Permalink
Caller get_export() implemented for Extern::Func. (#2108)
Browse files Browse the repository at this point in the history
* Caller get_export() implemented for func

* update tests for get_export() Extern::Func return

Signed-off-by: Christopher Agia <chrisagia@google.com>

* document get_export() for Extern::Func

Signed-off-by: Christopher Agia <chrisagia@google.com>
  • Loading branch information
agiachris authored Aug 7, 2020
1 parent e60a6f2 commit 2482bd8
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 18 deletions.
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!
/// 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

0 comments on commit 2482bd8

Please sign in to comment.