mirror of
https://github.com/mii443/wasmer.git
synced 2025-09-02 07:29:21 +00:00
Add resolver chaining and recursive resolving
This commit is contained in:
@ -8,7 +8,7 @@ use std::{
|
||||
ffi::c_void,
|
||||
sync::{Arc, Mutex},
|
||||
};
|
||||
use wasmer_engine::NamedResolver;
|
||||
use wasmer_engine::{ChainableResolver, NamedResolver};
|
||||
use wasmer_runtime::Export;
|
||||
|
||||
/// The `LikeNamespace` trait represents objects that act as a namespace for imports.
|
||||
@ -157,6 +157,8 @@ impl NamedResolver for ImportObject {
|
||||
}
|
||||
}
|
||||
|
||||
impl ChainableResolver for ImportObject {}
|
||||
|
||||
/// Iterator for an `ImportObject`'s exports.
|
||||
pub struct ImportObjectIterator {
|
||||
elements: VecDeque<((String, String), Export)>,
|
||||
@ -180,12 +182,6 @@ impl IntoIterator for ImportObject {
|
||||
}
|
||||
}
|
||||
|
||||
impl Extend<((String, String), Export)> for ImportObject {
|
||||
fn extend<T: IntoIterator<Item = ((String, String), Export)>>(&mut self, _iter: T) {
|
||||
unimplemented!("Extend not yet implemented");
|
||||
}
|
||||
}
|
||||
|
||||
// The import! macro for ImportObject
|
||||
|
||||
/// Generate an [`ImportObject`] easily with the `imports!` macro.
|
||||
@ -210,6 +206,7 @@ impl Extend<((String, String), Export)> for ImportObject {
|
||||
/// }
|
||||
/// ```
|
||||
#[macro_export]
|
||||
// TOOD: port of lost fixes of imports macro from wasmer master/imports macro tests
|
||||
macro_rules! imports {
|
||||
( $( $ns_name:expr => $ns:tt ),* $(,)? ) => {{
|
||||
use $crate::ImportObject;
|
||||
@ -251,17 +248,17 @@ macro_rules! import_namespace {
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use crate::{Global, Store, Val};
|
||||
use wasm_common::Type;
|
||||
use wasmer_runtime::Export;
|
||||
|
||||
#[test]
|
||||
#[ignore]
|
||||
fn extending_works() {
|
||||
fn chaining_works() {
|
||||
let store = Store::default();
|
||||
let g = Global::new(&store, Val::I32(0));
|
||||
|
||||
let mut imports1 = imports! {
|
||||
let imports1 = imports! {
|
||||
"dog" => {
|
||||
"happy" => g.clone()
|
||||
}
|
||||
@ -276,19 +273,18 @@ mod test {
|
||||
}
|
||||
};
|
||||
|
||||
imports1.extend(imports2);
|
||||
let resolver = imports1.chain_front(imports2);
|
||||
|
||||
let small_cat_export = imports1.get_export("cat", "small");
|
||||
assert!(small_cat_export.is_some());
|
||||
let small_cat_export = resolver.resolve(0, "cat", "small");
|
||||
assert!(small_cat_export.is_ok());
|
||||
|
||||
let happy = imports1.get_export("dog", "happy");
|
||||
let small = imports1.get_export("dog", "small");
|
||||
assert!(happy.is_some());
|
||||
assert!(small.is_some());
|
||||
let happy = resolver.resolve(0, "dog", "happy");
|
||||
let small = resolver.resolve(0, "dog", "small");
|
||||
assert!(happy.is_ok());
|
||||
assert!(small.is_ok());
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore]
|
||||
fn extending_conflict_overwrites() {
|
||||
let store = Store::default();
|
||||
let g1 = Global::new(&store, Val::I32(0));
|
||||
@ -306,8 +302,8 @@ mod test {
|
||||
},
|
||||
};
|
||||
|
||||
imports1.extend(imports2);
|
||||
let happy_dog_entry = imports1.get_export("dog", "happy").unwrap();
|
||||
let resolver = imports1.chain_front(imports2);
|
||||
let happy_dog_entry = resolver.resolve(0, "dog", "happy").unwrap();
|
||||
|
||||
assert!(if let Export::Global(happy_dog_global) = happy_dog_entry {
|
||||
happy_dog_global.global.ty == Type::I64
|
||||
@ -327,7 +323,7 @@ mod test {
|
||||
"dog" => namespace
|
||||
};
|
||||
|
||||
let happy_dog_entry = imports1.get_export("dog", "happy").unwrap();
|
||||
let happy_dog_entry = imports1.resolve(0, "dog", "happy").unwrap();
|
||||
|
||||
assert!(if let Export::Global(happy_dog_global) = happy_dog_entry {
|
||||
happy_dog_global.global.ty == Type::I32
|
||||
|
@ -32,8 +32,8 @@ pub use wasm_common::{Bytes, Pages, ValueType, WasmExternType, WasmTypeList};
|
||||
pub use wasmer_compiler::CompilerConfig;
|
||||
pub use wasmer_compiler::{Features, Target};
|
||||
pub use wasmer_engine::{
|
||||
DeserializeError, Engine, InstantiationError, LinkError, NamedResolver, Resolver, RuntimeError,
|
||||
SerializeError,
|
||||
ChainableResolver, DeserializeError, Engine, InstantiationError, LinkError, NamedResolver,
|
||||
Resolver, ResolverChain, RuntimeError, SerializeError,
|
||||
};
|
||||
pub use wasmer_runtime::{raise_user_trap, MemoryError};
|
||||
|
||||
|
@ -86,7 +86,6 @@ add_test(test-imports test-imports)
|
||||
|
||||
target_link_libraries(test-import-object general ${WASMER_LIB})
|
||||
target_compile_options(test-import-object PRIVATE ${COMPILER_OPTIONS})
|
||||
# TODO: reenable this test
|
||||
#add_test(test-import-object test-import-object)
|
||||
|
||||
|
||||
|
@ -34,7 +34,9 @@ pub use crate::engine::Engine;
|
||||
pub use crate::error::{
|
||||
DeserializeError, ImportError, InstantiationError, LinkError, SerializeError,
|
||||
};
|
||||
pub use crate::resolver::{resolve_imports, NamedResolver, NullResolver, Resolver};
|
||||
pub use crate::resolver::{
|
||||
resolve_imports, ChainableResolver, NamedResolver, NullResolver, Resolver, ResolverChain,
|
||||
};
|
||||
pub use crate::serialize::SerializableFunctionFrameInfo;
|
||||
pub use crate::trap::*;
|
||||
pub use crate::tunables::Tunables;
|
||||
|
@ -63,8 +63,8 @@ impl<T: NamedResolver> Resolver for T {
|
||||
pub struct NullResolver {}
|
||||
|
||||
impl Resolver for NullResolver {
|
||||
fn resolve(&self, _idx: u32, _module: &str, _field: &str) -> Option<Export> {
|
||||
None
|
||||
fn resolve(&self, _idx: u32, _module: &str, _field: &str) -> Result<Export, u32> {
|
||||
Err(0)
|
||||
}
|
||||
}
|
||||
|
||||
@ -136,7 +136,7 @@ pub fn resolve_imports(
|
||||
for ((module_name, field, import_idx), import_index) in module.imports.iter() {
|
||||
let resolved = resolver.resolve(*import_idx, module_name, field);
|
||||
let import_extern = get_extern_from_import(module, import_index);
|
||||
let resolved = match resolved {
|
||||
let resolved = match resolved.ok() {
|
||||
None => {
|
||||
return Err(LinkError::Import(
|
||||
module_name.to_string(),
|
||||
@ -229,3 +229,77 @@ pub fn resolve_imports(
|
||||
global_imports,
|
||||
))
|
||||
}
|
||||
|
||||
/// A [`Resolver`] that links two resolvers together in a chain.
|
||||
pub struct ResolverChain<A: Resolver, B: Resolver> {
|
||||
a: A,
|
||||
b: B,
|
||||
}
|
||||
|
||||
/// A trait for chaining resolvers together.
|
||||
///
|
||||
/// TODO: add example
|
||||
pub trait ChainableResolver: Resolver + Sized {
|
||||
/// Chain a resolver in front of the current resolver.
|
||||
///
|
||||
/// This will cause the second resolver to override the first.
|
||||
///
|
||||
/// TODO: add example
|
||||
fn chain_front<U>(self, other: U) -> ResolverChain<U, Self>
|
||||
where
|
||||
U: Resolver,
|
||||
{
|
||||
ResolverChain { a: other, b: self }
|
||||
}
|
||||
|
||||
/// Chain a resolver behind the current resolver.
|
||||
///
|
||||
/// This will cause the first resolver to override the second.
|
||||
///
|
||||
/// TODO: add example
|
||||
fn chain_back<U>(self, other: U) -> ResolverChain<Self, U>
|
||||
where
|
||||
U: Resolver,
|
||||
{
|
||||
ResolverChain { a: self, b: other }
|
||||
}
|
||||
}
|
||||
|
||||
impl<A, B> ChainableResolver for ResolverChain<A, B>
|
||||
where
|
||||
A: Resolver,
|
||||
B: Resolver,
|
||||
{
|
||||
}
|
||||
|
||||
impl<A, B> Resolver for ResolverChain<A, B>
|
||||
where
|
||||
A: Resolver,
|
||||
B: Resolver,
|
||||
{
|
||||
fn resolve(&self, index: u32, module: &str, field: &str) -> Result<Export, u32> {
|
||||
if index == 0 {
|
||||
self.a
|
||||
.resolve(0, module, field)
|
||||
.or_else(|e1| self.b.resolve(0, module, field).map_err(|e2| e1 + e2))
|
||||
} else {
|
||||
match self.a.resolve(index, module, field) {
|
||||
Ok(_) => self.b.resolve(index - 1, module, field).map_err(|e| e + 1),
|
||||
Err(e1) => self.b.resolve(index, module, field).map_err(|e2| e1 + e2),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<A, B> Clone for ResolverChain<A, B>
|
||||
where
|
||||
A: Resolver + Clone,
|
||||
B: Resolver + Clone,
|
||||
{
|
||||
fn clone(&self) -> Self {
|
||||
Self {
|
||||
a: self.a.clone(),
|
||||
b: self.b.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user