mirror of
https://github.com/fluencelabs/wasmer
synced 2025-06-22 21:21:33 +00:00
Redesign import namespaces
This commit is contained in:
@ -1,3 +1,4 @@
|
|||||||
|
use hashbrown::HashMap;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use wabt::wat2wasm;
|
use wabt::wat2wasm;
|
||||||
use wasmer_clif_backend::CraneliftCompiler;
|
use wasmer_clif_backend::CraneliftCompiler;
|
||||||
@ -15,9 +16,8 @@ fn main() -> Result<(), String> {
|
|||||||
let wasm_binary = wat2wasm(IMPORT_MODULE.as_bytes()).expect("WAST not valid or malformed");
|
let wasm_binary = wat2wasm(IMPORT_MODULE.as_bytes()).expect("WAST not valid or malformed");
|
||||||
let inner_module = runtime::compile(&wasm_binary, &CraneliftCompiler::new())?;
|
let inner_module = runtime::compile(&wasm_binary, &CraneliftCompiler::new())?;
|
||||||
|
|
||||||
let mut imports = Imports::new();
|
let mut env_namespace = HashMap::new();
|
||||||
imports.register_export(
|
env_namespace.insert(
|
||||||
"env",
|
|
||||||
"print_i32",
|
"print_i32",
|
||||||
Export::Function {
|
Export::Function {
|
||||||
func: unsafe { FuncRef::new(print_num as _) },
|
func: unsafe { FuncRef::new(print_num as _) },
|
||||||
@ -28,13 +28,15 @@ fn main() -> Result<(), String> {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
let mut imports = Imports::new();
|
||||||
|
imports.register("env", env_namespace);
|
||||||
|
|
||||||
let imports = Rc::new(imports);
|
let imports = Rc::new(imports);
|
||||||
|
|
||||||
let inner_instance = inner_module.instantiate(imports)?;
|
let inner_instance = inner_module.instantiate(imports)?;
|
||||||
|
|
||||||
let mut outer_imports = Imports::new();
|
let mut outer_imports = Imports::new();
|
||||||
outer_imports.register_instance("env", inner_instance);
|
outer_imports.register("env", inner_instance);
|
||||||
let outer_imports = Rc::new(outer_imports);
|
let outer_imports = Rc::new(outer_imports);
|
||||||
let outer_module = runtime::compile(EXAMPLE_WASM, &CraneliftCompiler::new())?;
|
let outer_module = runtime::compile(EXAMPLE_WASM, &CraneliftCompiler::new())?;
|
||||||
let mut outer_instance = outer_module.instantiate(outer_imports)?;
|
let mut outer_instance = outer_module.instantiate(outer_imports)?;
|
||||||
@ -57,15 +59,3 @@ static IMPORT_MODULE: &str = r#"
|
|||||||
get_local $p0
|
get_local $p0
|
||||||
call $print_i32))
|
call $print_i32))
|
||||||
"#;
|
"#;
|
||||||
|
|
||||||
fn generate_imports() -> Rc<Imports> {
|
|
||||||
let wasm_binary = wat2wasm(IMPORT_MODULE.as_bytes()).expect("WAST not valid or malformed");
|
|
||||||
let module = wasmer_runtime::compile(&wasm_binary[..], &CraneliftCompiler::new())
|
|
||||||
.expect("WASM can't be compiled");
|
|
||||||
let instance = module
|
|
||||||
.instantiate(Rc::new(Imports::new()))
|
|
||||||
.expect("WASM can't be instantiated");
|
|
||||||
let mut imports = Imports::new();
|
|
||||||
imports.register_instance("env", instance);
|
|
||||||
Rc::new(imports)
|
|
||||||
}
|
|
||||||
|
@ -21,7 +21,7 @@ fn generate_imports() -> Rc<Imports> {
|
|||||||
// let module = wasmer_runtime::compile(&wasm_binary[..], &CraneliftCompiler::new()).expect("WASM can't be compiled");
|
// let module = wasmer_runtime::compile(&wasm_binary[..], &CraneliftCompiler::new()).expect("WASM can't be compiled");
|
||||||
// let instance = module.instantiate(Rc::new(Imports::new())).expect("WASM can't be instantiated");
|
// let instance = module.instantiate(Rc::new(Imports::new())).expect("WASM can't be instantiated");
|
||||||
let imports = Imports::new();
|
let imports = Imports::new();
|
||||||
// imports.register_instance("spectest", instance);
|
// imports.register("spectest", instance);
|
||||||
Rc::new(imports)
|
Rc::new(imports)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,7 +4,7 @@ use crate::{
|
|||||||
vm,
|
vm,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
pub enum Context {
|
pub enum Context {
|
||||||
External(*mut vm::Ctx),
|
External(*mut vm::Ctx),
|
||||||
Internal,
|
Internal,
|
||||||
|
@ -1,17 +1,27 @@
|
|||||||
use crate::{export::Export, Instance};
|
use crate::export::Export;
|
||||||
use hashbrown::{hash_map::Entry, HashMap};
|
use hashbrown::{hash_map::Entry, HashMap};
|
||||||
|
|
||||||
pub trait ImportResolver {
|
pub trait ImportResolver {
|
||||||
fn get(&self, namespace: &str, name: &str) -> Option<Export>;
|
fn get(&self, namespace: &str, name: &str) -> Option<Export>;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum Namespace {
|
pub trait Namespace {
|
||||||
Instance(Box<Instance>),
|
fn get_export(&self, name: &str) -> Option<Export>;
|
||||||
UserSupplied(HashMap<String, Export>),
|
}
|
||||||
|
|
||||||
|
impl Namespace for HashMap<String, Export> {
|
||||||
|
fn get_export(&self, name: &str) -> Option<Export> {
|
||||||
|
self.get(name).cloned()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl<'a> Namespace for HashMap<&'a str, Export> {
|
||||||
|
fn get_export(&self, name: &str) -> Option<Export> {
|
||||||
|
self.get(name).cloned()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Imports {
|
pub struct Imports {
|
||||||
map: HashMap<String, Namespace>,
|
map: HashMap<String, Box<dyn Namespace>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Imports {
|
impl Imports {
|
||||||
@ -21,38 +31,50 @@ impl Imports {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn register_instance(&mut self, namespace: impl Into<String>, instance: Box<Instance>) {
|
pub fn register(
|
||||||
match self.map.entry(namespace.into()) {
|
|
||||||
Entry::Vacant(empty) => empty.insert(Namespace::Instance(instance)),
|
|
||||||
Entry::Occupied(_) => {
|
|
||||||
panic!("cannot register an instance in a namespace that already exists")
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn register_export(
|
|
||||||
&mut self,
|
&mut self,
|
||||||
namespace: impl Into<String>,
|
|
||||||
name: impl Into<String>,
|
name: impl Into<String>,
|
||||||
export: Export,
|
namespace: impl Namespace + 'static,
|
||||||
) {
|
) -> Option<Box<dyn Namespace>> {
|
||||||
let namespace_item = self
|
match self.map.entry(name.into()) {
|
||||||
.map
|
Entry::Vacant(empty) => {
|
||||||
.entry(namespace.into())
|
empty.insert(Box::new(namespace));
|
||||||
.or_insert_with(|| Namespace::UserSupplied(HashMap::new()));
|
None
|
||||||
|
}
|
||||||
match namespace_item {
|
Entry::Occupied(mut occupied) => Some(occupied.insert(Box::new(namespace))),
|
||||||
Namespace::UserSupplied(ref mut map) => map.insert(name.into(), export),
|
}
|
||||||
Namespace::Instance(_) => panic!("cannot register an export in a namespace that has already been used to register an instance"),
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// pub fn register_instance(&mut self, namespace: impl Into<String>, instance: Box<Instance>) {
|
||||||
|
// match self.map.entry(namespace.into()) {
|
||||||
|
// Entry::Vacant(empty) => empty.insert(Namespace::Instance(instance)),
|
||||||
|
// Entry::Occupied(_) => {
|
||||||
|
// panic!("cannot register an instance in a namespace that already exists")
|
||||||
|
// }
|
||||||
|
// };
|
||||||
|
// }
|
||||||
|
|
||||||
|
// pub fn register_export(
|
||||||
|
// &mut self,
|
||||||
|
// namespace: impl Into<String>,
|
||||||
|
// name: impl Into<String>,
|
||||||
|
// export: Export,
|
||||||
|
// ) {
|
||||||
|
// let namespace_item = self
|
||||||
|
// .map
|
||||||
|
// .entry(namespace.into())
|
||||||
|
// .or_insert_with(|| Namespace::UserSupplied(HashMap::new()));
|
||||||
|
|
||||||
|
// match namespace_item {
|
||||||
|
// Namespace::UserSupplied(ref mut map) => map.insert(name.into(), export),
|
||||||
|
// Namespace::Instance(_) => panic!("cannot register an export in a namespace that has already been used to register an instance"),
|
||||||
|
// };
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ImportResolver for Imports {
|
impl ImportResolver for Imports {
|
||||||
fn get(&self, namespace: &str, name: &str) -> Option<Export> {
|
fn get(&self, namespace_name: &str, name: &str) -> Option<Export> {
|
||||||
match self.map.get(namespace)? {
|
let namespace = self.map.get(namespace_name)?;
|
||||||
Namespace::UserSupplied(map) => map.get(name).cloned(),
|
namespace.get_export(name)
|
||||||
Namespace::Instance(instance) => instance.get_export(name).ok(),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@ use crate::recovery::call_protected;
|
|||||||
use crate::{
|
use crate::{
|
||||||
backing::{ImportBacking, LocalBacking},
|
backing::{ImportBacking, LocalBacking},
|
||||||
export::{Context, Export},
|
export::{Context, Export},
|
||||||
import::ImportResolver,
|
import::{ImportResolver, Namespace},
|
||||||
module::{ExportIndex, Module},
|
module::{ExportIndex, Module},
|
||||||
types::{FuncIndex, FuncSig, MapIndex, Memory, MemoryIndex, Type, Value},
|
types::{FuncIndex, FuncSig, MapIndex, Memory, MemoryIndex, Type, Value},
|
||||||
vm,
|
vm,
|
||||||
@ -130,16 +130,6 @@ impl Instance {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_export(&self, name: &str) -> Result<Export, String> {
|
|
||||||
let export_index = self
|
|
||||||
.module
|
|
||||||
.exports
|
|
||||||
.get(name)
|
|
||||||
.ok_or_else(|| format!("there is no export with that name: {}", name))?;
|
|
||||||
|
|
||||||
Ok(self.get_export_from_index(export_index))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn exports(&self) -> ExportIter {
|
pub fn exports(&self) -> ExportIter {
|
||||||
ExportIter::new(self)
|
ExportIter::new(self)
|
||||||
}
|
}
|
||||||
@ -238,6 +228,14 @@ impl Instance {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Namespace for Box<Instance> {
|
||||||
|
fn get_export(&self, name: &str) -> Option<Export> {
|
||||||
|
let export_index = self.module.exports.get(name)?;
|
||||||
|
|
||||||
|
Some(self.get_export_from_index(export_index))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct FuncRef(*const vm::Func);
|
pub struct FuncRef(*const vm::Func);
|
||||||
|
|
||||||
|
@ -22,7 +22,7 @@ pub fn generate_imports() -> Rc<Imports> {
|
|||||||
.instantiate(Rc::new(Imports::new()))
|
.instantiate(Rc::new(Imports::new()))
|
||||||
.expect("WASM can't be instantiated");
|
.expect("WASM can't be instantiated");
|
||||||
let mut imports = Imports::new();
|
let mut imports = Imports::new();
|
||||||
imports.register_instance("spectest", instance);
|
imports.register("spectest", instance);
|
||||||
Rc::new(imports)
|
Rc::new(imports)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user