diff --git a/Cargo.lock b/Cargo.lock index 294264ce..f59e3b4d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1887,6 +1887,7 @@ dependencies = [ "wasmer-interface-types-fl 0.21.1", "wasmer-runtime-core-fl", "wasmer-runtime-fl", + "wasmer-wasi-fl", ] [[package]] @@ -1897,6 +1898,7 @@ dependencies = [ "wasmer-interface-types-fl 0.21.1", "wasmer-runtime-core-fl", "wasmer-runtime-fl", + "wasmer-wasi-fl", ] [[package]] diff --git a/crates/it-parser/src/extractor/it.rs b/crates/it-parser/src/extractor/it.rs index db6e8138..44c0533c 100644 --- a/crates/it-parser/src/extractor/it.rs +++ b/crates/it-parser/src/extractor/it.rs @@ -21,7 +21,8 @@ use crate::ParserResult; use walrus::IdsToIndices; use wasmer_it::ast::Interfaces; //use wasmer_core::Module as WasmerModule; -use marine_wasm_backend_traits::Module as ModuleTrait; +use marine_wasm_backend_traits::WasmBackend; +use marine_wasm_backend_traits::Module as WasmModule; use std::borrow::Cow; use std::path::Path; @@ -43,7 +44,9 @@ where } /// Extracts IT section of provided Wasm binary and converts it to a MITInterfaces. -pub fn extract_it_from_module(wasmer_module: &M) -> ParserResult> { +pub fn extract_it_from_module( + wasmer_module: &::M, +) -> ParserResult> { let wit_sections = wasmer_module .custom_sections(IT_SECTION_NAME) .ok_or(ITParserError::NoITSection)?; diff --git a/crates/module-info-parser/src/sdk_version/version_extractor.rs b/crates/module-info-parser/src/sdk_version/version_extractor.rs index 1f50ae48..e80962b4 100644 --- a/crates/module-info-parser/src/sdk_version/version_extractor.rs +++ b/crates/module-info-parser/src/sdk_version/version_extractor.rs @@ -21,7 +21,9 @@ use crate::extract_custom_sections_by_name; use crate::try_as_one_section; //use wasmer_core::Module as WasmerModule; -use marine_wasm_backend_traits::Module as ModuleTrait; +use marine_wasm_backend_traits::WasmBackend; +use marine_wasm_backend_traits::Module as WasmModule; + use marine_rs_sdk_main::VERSION_SECTION_NAME; use walrus::ModuleConfig; use walrus::Module; @@ -57,8 +59,8 @@ pub fn extract_from_module(wasm_module: &Module) -> ModuleInfoResult( - wasmer_module: &M, +pub fn extract_from_wasmer_module( + wasmer_module: &::M, ) -> ModuleInfoResult> { let sections = wasmer_module.custom_sections(VERSION_SECTION_NAME); diff --git a/crates/wasm-backend-traits/Cargo.toml b/crates/wasm-backend-traits/Cargo.toml index aa583a45..10d64cb7 100644 --- a/crates/wasm-backend-traits/Cargo.toml +++ b/crates/wasm-backend-traits/Cargo.toml @@ -11,4 +11,5 @@ thiserror = "1.0.24" wasmer-it = { package = "wasmer-interface-types-fl", version = "0.21.1" } wasmer-runtime = { package = "wasmer-runtime-fl", version = "=0.17.1" } # dynamicfunc-fat-closures allows using state inside DynamicFunc -wasmer-core = { package = "wasmer-runtime-core-fl", version = "=0.17.1", features = ["dynamicfunc-fat-closures"] } \ No newline at end of file +wasmer-core = { package = "wasmer-runtime-core-fl", version = "=0.17.1", features = ["dynamicfunc-fat-closures"] } +wasmer-wasi = { package = "wasmer-wasi-fl", version = "0.17.1" } \ No newline at end of file diff --git a/crates/wasm-backend-traits/src/lib.rs b/crates/wasm-backend-traits/src/lib.rs index c61b178d..c601ac92 100644 --- a/crates/wasm-backend-traits/src/lib.rs +++ b/crates/wasm-backend-traits/src/lib.rs @@ -1,3 +1,5 @@ +use std::fmt::Display; +use std::path::PathBuf; use thiserror::Error; pub struct Value {} @@ -11,25 +13,63 @@ pub enum WasmBackendError { pub type WasmBackendResult = Result; pub trait WasmBackend: Clone + 'static { - type M: Module; + type IO: ImportObject; + type E: Export; + type M: Module; + type I: Instance; + type Wasi: WasiImplementation; fn compile(wasm: &[u8]) -> WasmBackendResult; } -pub trait Module { - type I: Instance; - +pub trait Module { fn custom_sections(&self, key: &str) -> Option<&[Vec]>; - fn instantiate(&self, imports: &wasmer_runtime::ImportObject) -> WasmBackendResult; + fn instantiate( + &self, + imports: &::IO, + ) -> WasmBackendResult<::I>; } -pub trait Instance { - - fn export_iter<'a>(&'a self) -> Box + 'a>; +pub trait Instance { + fn export_iter<'a>(&'a self) + -> Box + 'a>; fn exports(&self) -> &wasmer_core::instance::Exports; - fn import_object(&self) -> &wasmer_runtime::ImportObject; + fn import_object(&self) -> &::IO; // maybe hide them inside impl fn context(&self) -> &wasmer_core::vm::Ctx; fn context_mut(&mut self) -> &mut wasmer_core::vm::Ctx; } + +pub trait Export {} + +pub trait ImportObject: + Clone + Extend<(String, String, ::E)> +{ + fn new() -> Self; + fn extend_with_self(&mut self, other: Self); + + fn register( + &mut self, + name: S, + namespace: N, + ) -> Option> + where + S: Into, + N: wasmer_runtime::LikeNamespace + Send + 'static; + + fn maybe_with_namespace(&self, namespace: &str, f: Func) -> Option + where + Func: FnOnce(&(dyn wasmer_runtime::LikeNamespace + Send)) -> Option, + InnerRet: Sized; +} + +pub trait WasiImplementation { + fn generate_import_object_for_version( + version: wasmer_wasi::WasiVersion, + args: Vec>, + envs: Vec>, + preopened_files: Vec, + mapped_dirs: Vec<(String, PathBuf)>, + ) -> Result<::IO, String>; +} diff --git a/crates/wasmer-backend/Cargo.toml b/crates/wasmer-backend/Cargo.toml index b0ea17d3..c60ee7be 100644 --- a/crates/wasmer-backend/Cargo.toml +++ b/crates/wasmer-backend/Cargo.toml @@ -10,4 +10,5 @@ marine-wasm-backend-traits = {path = "../wasm-backend-traits", version = "0.1.0" wasmer-runtime = { package = "wasmer-runtime-fl", version = "=0.17.1" } # dynamicfunc-fat-closures allows using state inside DynamicFunc wasmer-core = { package = "wasmer-runtime-core-fl", version = "=0.17.1", features = ["dynamicfunc-fat-closures"] } -wasmer-it = { package = "wasmer-interface-types-fl", version = "0.21.1" } \ No newline at end of file +wasmer-it = { package = "wasmer-interface-types-fl", version = "0.21.1" } +wasmer-wasi = { package = "wasmer-wasi-fl", version = "0.17.1" } \ No newline at end of file diff --git a/crates/wasmer-backend/src/lib.rs b/crates/wasmer-backend/src/lib.rs index b719c6d6..efa6d7b5 100644 --- a/crates/wasmer-backend/src/lib.rs +++ b/crates/wasmer-backend/src/lib.rs @@ -3,19 +3,26 @@ use marine_wasm_backend_traits::WasmBackendResult; use marine_wasm_backend_traits::WasmBackendError; use marine_wasm_backend_traits::Module; use marine_wasm_backend_traits::Instance; +use marine_wasm_backend_traits::ImportObject; +use marine_wasm_backend_traits::Export; +use marine_wasm_backend_traits::WasiImplementation; + +use std::path::PathBuf; #[derive(Clone)] pub struct WasmerBackend {} impl WasmBackend for WasmerBackend { + type E = WasmerExport; type M = WasmerModule; + type I = WasmerInstance; + type IO = WasmerImportObject; + type Wasi = WasmerWasiImplementation; fn compile(wasm: &[u8]) -> WasmBackendResult { - wasmer_runtime::compile(wasm).map_err(|_| { - WasmBackendError::SomeError - }).map(|module| { - WasmerModule { module } - }) + wasmer_runtime::compile(wasm) + .map_err(|_| WasmBackendError::SomeError) + .map(|module| WasmerModule { module }) } } @@ -23,29 +30,31 @@ pub struct WasmerModule { module: wasmer_core::Module, } -impl Module for WasmerModule { - type I = WasmerInstance; - +impl Module for WasmerModule { fn custom_sections(&self, name: &str) -> Option<&[Vec]> { self.module.custom_sections(name) } - fn instantiate(&self, imports: &wasmer_runtime::ImportObject) -> WasmBackendResult { + fn instantiate(&self, imports: &WasmerImportObject) -> WasmBackendResult { self.module - .instantiate(&imports) - .map_err(|_| { - WasmBackendError::SomeError + .instantiate(&imports.import_object) + .map_err(|_| WasmBackendError::SomeError) + .map(|instance| WasmerInstance { + instance, + import_object: imports.clone(), }) - .map(|instance| {WasmerInstance{instance}}) } } pub struct WasmerInstance { - instance: wasmer_core::Instance, + pub instance: wasmer_core::Instance, + pub import_object: WasmerImportObject, } -impl Instance for WasmerInstance { - fn export_iter<'a>(&'a self) -> Box + 'a> { +impl Instance for WasmerInstance { + fn export_iter<'a>( + &'a self, + ) -> Box + 'a> { let exports = self.instance.exports(); Box::new(exports) } @@ -54,13 +63,94 @@ impl Instance for WasmerInstance { &self.instance.exports } - fn import_object(&self) -> &wasmer_runtime::ImportObject { - &self.instance.import_object + fn import_object(&self) -> &WasmerImportObject { + &self.import_object } - fn context(&self) -> &wasmer_core::vm::Ctx { self.instance.context() } - fn context_mut(&mut self) -> &mut wasmer_core::vm::Ctx { self.instance.context_mut()} + fn context(&self) -> &wasmer_core::vm::Ctx { + self.instance.context() + } + fn context_mut(&mut self) -> &mut wasmer_core::vm::Ctx { + self.instance.context_mut() + } } + +#[derive(Clone)] +pub struct WasmerImportObject { + pub import_object: wasmer_runtime::ImportObject, +} + +impl Extend<(String, String, WasmerExport)> for WasmerImportObject { + fn extend(&mut self, iter: T) + where + T: IntoIterator, + { + self.import_object.extend( + iter.into_iter() + .map(|(s1, s2, export)| (s1, s2, export.export)), + ) + } +} + +impl ImportObject for WasmerImportObject { + fn new() -> Self { + WasmerImportObject { + import_object: wasmer_runtime::ImportObject::new(), + } + } + + fn extend_with_self(&mut self, other: Self) { + self.import_object.extend(other.import_object); + } + + fn register( + &mut self, + name: S, + namespace: N, + ) -> Option> + where + S: Into, + N: wasmer_runtime::LikeNamespace + Send + 'static, + { + self.import_object.register(name, namespace) + } + + fn maybe_with_namespace(&self, namespace: &str, f: Func) -> Option + where + Func: FnOnce(&(dyn wasmer_runtime::LikeNamespace + Send)) -> Option, + InnerRet: Sized, + { + self.import_object.maybe_with_namespace(namespace, f) + } +} + +pub struct WasmerExport { + export: wasmer_runtime::Export, +} + +impl Export for WasmerExport {} + +pub struct WasmerWasiImplementation {} + +impl WasiImplementation for WasmerWasiImplementation { + fn generate_import_object_for_version( + version: wasmer_wasi::WasiVersion, + args: Vec>, + envs: Vec>, + preopened_files: Vec, + mapped_dirs: Vec<(String, PathBuf)>, + ) -> Result { + wasmer_wasi::generate_import_object_for_version( + version, + args, + envs, + preopened_files, + mapped_dirs, + ) + .map(|import_object| WasmerImportObject { import_object }) + } +} + /* pub struct WasmerExportIter { export_iter: Box + 'a> @@ -72,4 +162,4 @@ impl<'a> Iterator for WasmerExportIter<'a> { fn next(&mut self) -> Option { self.export_iter.as_mut().next() } -}*/ \ No newline at end of file +}*/ diff --git a/runtime/src/config.rs b/runtime/src/config.rs index 752f62a3..5c82bc92 100644 --- a/runtime/src/config.rs +++ b/runtime/src/config.rs @@ -18,8 +18,11 @@ use super::IValue; use super::IType; use crate::HostImportError; +use marine_wasm_backend_traits::WasmBackend; +use marine_wasm_backend_traits::ImportObject; + use wasmer_wasi::WasiVersion; -use wasmer_runtime::ImportObject; +//use wasmer_runtime::ImportObject; use wasmer_core::vm::Ctx; use std::path::PathBuf; @@ -46,13 +49,13 @@ pub struct HostImportDescriptor { pub error_handler: Option Option + 'static>>, } -pub struct MModuleConfig { +pub struct MModuleConfig { /// Maximum number of Wasm memory pages that loaded module can use. /// Each Wasm page is 65536 bytes long. pub max_heap_pages_count: u32, /// Import object that will be used in module instantiation process. - pub raw_imports: ImportObject, + pub raw_imports: ::IO, /// Imports from the host side that will be used in module instantiation process. pub host_imports: HashMap, @@ -70,12 +73,12 @@ pub struct MModuleConfig { pub wasi_mapped_dirs: HashMap, } -impl Default for MModuleConfig { +impl Default for MModuleConfig { fn default() -> Self { // some reasonable defaults Self { max_heap_pages_count: DEFAULT_HEAP_PAGES_COUNT, - raw_imports: ImportObject::new(), + raw_imports: ::IO::new(), host_imports: HashMap::new(), wasi_version: WasiVersion::Latest, wasi_envs: HashMap::new(), @@ -88,7 +91,7 @@ impl Default for MModuleConfig { // TODO: implement debug for MModuleConfig #[allow(dead_code)] -impl MModuleConfig { +impl MModuleConfig { pub fn with_mem_pages_count(mut self, mem_pages_count: u32) -> Self { self.max_heap_pages_count = mem_pages_count; self diff --git a/runtime/src/engine.rs b/runtime/src/engine.rs index 32ee2a8a..d9b692e0 100644 --- a/runtime/src/engine.rs +++ b/runtime/src/engine.rs @@ -66,7 +66,7 @@ impl Marine { &mut self, name: S, wasm_bytes: &[u8], - config: MModuleConfig, + config: MModuleConfig, ) -> MResult<()> { self.load_module_(name.into(), wasm_bytes, config) } @@ -75,7 +75,7 @@ impl Marine { &mut self, name: String, wasm_bytes: &[u8], - config: MModuleConfig, + config: MModuleConfig, ) -> MResult<()> { let _prepared_wasm_bytes = crate::misc::prepare_module(wasm_bytes, config.max_heap_pages_count)?; diff --git a/runtime/src/errors.rs b/runtime/src/errors.rs index 09fdb572..9b325c86 100644 --- a/runtime/src/errors.rs +++ b/runtime/src/errors.rs @@ -103,7 +103,7 @@ pub enum MError { IncorrectWIT(String), #[error("WASM BACKEND ERROR: {0}")] - WasmBackendError(WasmBackendError) + WasmBackendError(WasmBackendError), } impl From for MError { diff --git a/runtime/src/misc/version_checker.rs b/runtime/src/misc/version_checker.rs index 87ff3e12..d1a446f6 100644 --- a/runtime/src/misc/version_checker.rs +++ b/runtime/src/misc/version_checker.rs @@ -21,15 +21,15 @@ use marine_module_info_parser::sdk_version; use marine_min_it_version::min_sdk_version; use marine_min_it_version::min_it_version; -use marine_wasm_backend_traits::Module; +use marine_wasm_backend_traits::WasmBackend; //use wasmer_core::Module; -pub(crate) fn check_sdk_version( - name: impl Into, - wasmer_module: &M, +pub(crate) fn check_sdk_version( + name: String, + wasmer_module: &::M, ) -> PrepareResult<()> { - let module_version = sdk_version::extract_from_wasmer_module(wasmer_module)?; + let module_version = sdk_version::extract_from_wasmer_module::(wasmer_module)?; let module_version = match module_version { Some(module_version) => module_version, None => return Err(PrepareError::ModuleWithoutVersion(name.into())), diff --git a/runtime/src/module/marine_module.rs b/runtime/src/module/marine_module.rs index 29ede59e..4504aa05 100644 --- a/runtime/src/module/marine_module.rs +++ b/runtime/src/module/marine_module.rs @@ -24,6 +24,8 @@ use crate::MModuleConfig; use marine_wasm_backend_traits::WasmBackend; use marine_wasm_backend_traits::Module; use marine_wasm_backend_traits::Instance; +use marine_wasm_backend_traits::ImportObject; +use marine_wasm_backend_traits::WasiImplementation; use marine_it_interfaces::MITInterfaces; use marine_it_parser::extract_it_from_module; @@ -31,7 +33,7 @@ use marine_utils::SharedString; //use wasmer_core::Instance as WasmerInstance; use wasmer_core::import::Namespace; //use wasmer_runtime::compile; -use wasmer_runtime::ImportObject; +//use wasmer_runtime::ImportObject; use wasmer_it::interpreter::Interpreter; use std::collections::HashMap; @@ -77,22 +79,22 @@ pub(crate) struct MModule { // wasmer_instance is needed because WITInstance contains dynamic functions // that internally keep pointer to it. #[allow(unused)] - wasmer_instance: Box<<::M as Module>::I>, + wasmer_instance: Box<::I>, // import_object is needed because ImportObject::extend doesn't really deep copy // imports, so we need to store imports of this module to prevent their removing. #[allow(unused)] - it_import_object: ImportObject, + it_import_object: ::IO, // host_import_object is needed because ImportObject::extend doesn't really deep copy // imports, so we need to store imports of this module to prevent their removing. #[allow(unused)] - host_import_object: ImportObject, + host_import_object: ::IO, // host_closures_import_object is needed because ImportObject::extend doesn't really deep copy // imports, so we need to store imports of this module to prevent their removing. #[allow(unused)] - host_closures_import_object: ImportObject, + host_closures_import_object: ::IO, // TODO: replace with dyn Trait export_funcs: ExportFunctions, @@ -106,13 +108,13 @@ impl MModule { pub(crate) fn new( name: &str, wasm_bytes: &[u8], - config: MModuleConfig, + config: MModuleConfig, modules: &HashMap>, ) -> MResult { let wasmer_module = WB::compile(wasm_bytes)?; - crate::misc::check_sdk_version(name, &wasmer_module)?; + crate::misc::check_sdk_version::(name.to_string(), &wasmer_module)?; - let it = extract_it_from_module(&wasmer_module)?; + let it = extract_it_from_module::(&wasmer_module)?; crate::misc::check_it_version(name, &it.version)?; let mit = MITInterfaces::new(it); @@ -214,10 +216,10 @@ impl MModule { } fn create_import_objects( - config: MModuleConfig, + config: MModuleConfig, mit: &MITInterfaces<'_>, - wit_import_object: ImportObject, - ) -> MResult<(ImportObject, ImportObject)> { + wit_import_object: ::IO, + ) -> MResult<(::IO, ::IO)> { use crate::host_imports::create_host_import_func; let wasi_envs = config @@ -232,7 +234,7 @@ impl MModule { let wasi_preopened_files = config.wasi_preopened_files.into_iter().collect::>(); let wasi_mapped_dirs = config.wasi_mapped_dirs.into_iter().collect::>(); - let mut wasi_import_object = wasmer_wasi::generate_import_object_for_version( + let mut wasi_import_object = ::Wasi::generate_import_object_for_version( config.wasi_version, vec![], wasi_envs, @@ -252,12 +254,12 @@ impl MModule { let host_import = create_host_import_func(descriptor, record_types.clone()); host_closures_namespace.insert(import_name, host_import); } - let mut host_closures_import_object = ImportObject::new(); + let mut host_closures_import_object = ::IO::new(); host_closures_import_object.register("host", host_closures_namespace); - wasi_import_object.extend(wit_import_object); - wasi_import_object.extend(config.raw_imports); - wasi_import_object.extend(host_closures_import_object.clone()); + wasi_import_object.extend_with_self(wit_import_object); + wasi_import_object.extend_with_self(config.raw_imports); + wasi_import_object.extend_with_self(host_closures_import_object.clone()); Ok((wasi_import_object, host_closures_import_object)) } @@ -298,7 +300,7 @@ impl MModule { fn adjust_wit_imports( wit: &MITInterfaces<'_>, wit_instance: Arc>>, - ) -> MResult { + ) -> MResult<::IO> { use marine_it_interfaces::ITAstType; use wasmer_core::typed_func::DynamicFunc; use wasmer_core::vm::Ctx; @@ -387,7 +389,8 @@ impl MModule { arguments, output_types, } => { - let interpreter: ITInterpreter = adapter_instructions.clone().try_into()?; + let interpreter: ITInterpreter = + adapter_instructions.clone().try_into()?; let raw_import = create_raw_import( wit_instance.clone(), @@ -412,7 +415,7 @@ impl MModule { }) .collect::>>()?; - let mut import_object = ImportObject::new(); + let mut import_object = ::IO::new(); // TODO: refactor this for (namespace_name, funcs) in wit_import_funcs.into_iter() { diff --git a/runtime/src/module/wit_instance.rs b/runtime/src/module/wit_instance.rs index f50651e5..19e5c619 100644 --- a/runtime/src/module/wit_instance.rs +++ b/runtime/src/module/wit_instance.rs @@ -20,8 +20,9 @@ use super::IRecordType; use crate::MResult; use marine_wasm_backend_traits::WasmBackend; -use marine_wasm_backend_traits::Module; +//use marine_wasm_backend_traits::Module; use marine_wasm_backend_traits::Instance; +use marine_wasm_backend_traits::ImportObject; use marine_it_interfaces::MITInterfaces; use marine_it_interfaces::ITAstType; @@ -50,7 +51,7 @@ pub(super) struct ITInstance { impl ITInstance { pub(super) fn new( - wasmer_instance: &<::M as Module>::I, + wasmer_instance: &::I, module_name: &str, wit: &MITInterfaces<'_>, modules: &HashMap>, @@ -71,8 +72,8 @@ impl ITInstance { }) } - fn extract_raw_exports( - wasmer_instance: &I, + fn extract_raw_exports( + wasmer_instance: &::I, it: &MITInterfaces<'_>, ) -> MResult>> { use wasmer_core::DynFunc; @@ -141,7 +142,7 @@ impl ITInstance { .collect::>>() } - fn extract_memories(wasmer_instance: &I) -> Vec { + fn extract_memories(wasmer_instance: &::I) -> Vec { use wasmer_core::export::Export::Memory; let mut memories = wasmer_instance @@ -180,7 +181,8 @@ impl ITInstance { } } -impl<'v, WB: WasmBackend> wasm::structures::Instance, WITMemory, WITMemoryView<'v>> +impl<'v, WB: WasmBackend> + wasm::structures::Instance, WITMemory, WITMemoryView<'v>> for ITInstance { fn export(&self, _export_name: &str) -> Option<&ITExport> { @@ -188,7 +190,10 @@ impl<'v, WB: WasmBackend> wasm::structures::Instance, None } - fn local_or_import(&self, index: I) -> Option<&WITFunction> { + fn local_or_import( + &self, + index: I, + ) -> Option<&WITFunction> { self.funcs.get(&index.index()) } diff --git a/web-runtime/src/engine.rs b/web-runtime/src/engine.rs index ecda49a3..1535e347 100644 --- a/web-runtime/src/engine.rs +++ b/web-runtime/src/engine.rs @@ -65,11 +65,7 @@ impl Marine { } /// Load a new module inside Marine. - pub fn load_module>( - &mut self, - name: S, - wasm_bytes: &[u8], - ) -> MResult<()> { + pub fn load_module>(&mut self, name: S, wasm_bytes: &[u8]) -> MResult<()> { self.load_module_(name.into(), wasm_bytes) }