Caller get_export() implemented for Extern::Func. (#2108)

* 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>
This commit is contained in:
Christopher Agia
2020-08-07 12:24:42 -04:00
committed by GitHub
parent e60a6f2ad2
commit 2482bd80c2
2 changed files with 26 additions and 18 deletions

View File

@@ -1421,17 +1421,21 @@ pub trait IntoFunc<Params, Results> {
/// via [`Func::wrap`]. /// via [`Func::wrap`].
/// ///
/// This structure can be taken as the first parameter of a closure passed to /// 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 function, such as the calling module's memory, exports, etc.
/// ///
/// The primary purpose of this structure is to provide access to the /// The primary purpose of this structure is to provide access to the
/// caller's information, such as it's exported memory. This allows /// caller's information, namely it's exported memory and exported functions. This
/// functions which take pointers as arguments to easily read the memory the /// allows functions which take pointers as arguments to easily read the memory the
/// pointers point into. /// 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 /// Note that this Caller type a pretty temporary mechanism for accessing the
/// the caller's memory until interface types has been fully standardized and /// caller's information until interface types has been fully standardized and
/// implemented. /// 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> { pub struct Caller<'a> {
// Note that this is a `Weak` pointer instead of a `&'a Store`, // Note that this is a `Weak` pointer instead of a `&'a Store`,
// intentionally so. This allows us to break an `Rc` cycle which would // intentionally so. This allows us to break an `Rc` cycle which would
@@ -1457,14 +1461,18 @@ impl Caller<'_> {
/// Looks up an export from the caller's module by the `name` given. /// Looks up an export from the caller's module by the `name` given.
/// ///
/// Note that this function is only implemented for the `Extern::Memory` /// Note that this function is only implemented for the `Extern::Memory`
/// type currently. No other exported structure can be acquired through this /// and the `Extern::Func` types currently. No other exported structures
/// just yet, but this may be implemented in the future! /// 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 /// # 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 /// 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 caller instance may not have an export named `name`
/// * The export named `name` may not be an exported memory /// * The export named `name` may not be an exported memory
@@ -1479,10 +1487,7 @@ impl Caller<'_> {
return None; return None;
} }
let instance = InstanceHandle::from_vmctx(self.caller_vmctx); let instance = InstanceHandle::from_vmctx(self.caller_vmctx);
let export = match instance.lookup(name) { let export = instance.lookup(name)?;
Some(Export::Memory(m)) => m,
_ => return None,
};
// Our `Weak` pointer is used only to break a cycle where `Store` // Our `Weak` pointer is used only to break a cycle where `Store`
// stores instance handles which have this weak pointer as their // stores instance handles which have this weak pointer as their
// custom host data. This function should only be invoke-able while // custom host data. This function should only be invoke-able while
@@ -1490,8 +1495,11 @@ impl Caller<'_> {
debug_assert!(self.store.upgrade().is_some()); debug_assert!(self.store.upgrade().is_some());
let handle = let handle =
Store::from_inner(self.store.upgrade()?).existing_instance_handle(instance); Store::from_inner(self.store.upgrade()?).existing_instance_handle(instance);
let mem = Memory::from_wasmtime_memory(export, handle); match export {
Some(Extern::Memory(mem)) 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,
}
} }
} }

View File

@@ -409,7 +409,7 @@ fn caller_memory() -> anyhow::Result<()> {
let f = Func::wrap(&store, |c: Caller<'_>| { let f = Func::wrap(&store, |c: Caller<'_>| {
assert!(c.get_export("m").is_some()); 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("g").is_none());
assert!(c.get_export("t").is_none()); assert!(c.get_export("t").is_none());
}); });