diff --git a/lib/api/Cargo.toml b/lib/api/Cargo.toml index e4e44966622..ac174bdb0e3 100644 --- a/lib/api/Cargo.toml +++ b/lib/api/Cargo.toml @@ -154,5 +154,7 @@ js-default = ["js", "std", "wasm-types-polyfill"] wasm-types-polyfill = ["js", "wasmparser"] +js-serializable-module = [] + [package.metadata.docs.rs] features = ["compiler", "core", "cranelift", "default-compiler", "default-dylib", "default-engine", "dylib", "engine", "jit", "native", "singlepass", "sys", "sys-default", "universal"] diff --git a/lib/api/src/js/error.rs b/lib/api/src/js/error.rs index 205cf2de946..15fdcc3a458 100644 --- a/lib/api/src/js/error.rs +++ b/lib/api/src/js/error.rs @@ -87,3 +87,40 @@ pub enum WasmError { #[cfg_attr(feature = "std", error("{0}"))] Generic(String), } + +/// The Serialize error can occur when serializing a +/// compiled Module into a binary. +/// Copied from wasmer_engine::SerializeError +#[derive(Debug)] +#[cfg_attr(feature = "std", derive(Error))] +pub enum SerializeError { + /// An IO error + #[cfg_attr(feature = "std", error(transparent))] + Io(#[from] std::io::Error), + /// A generic serialization error + #[cfg_attr(feature = "std", error("{0}"))] + Generic(String), +} + +/// The Deserialize error can occur when loading a +/// compiled Module from a binary. +/// Copied from wasmer_engine::DeSerializeError +#[derive(Error, Debug)] +pub enum DeserializeError { + /// An IO error + #[cfg_attr(feature = "std", error(transparent))] + Io(#[from] std::io::Error), + /// A generic deserialization error + #[cfg_attr(feature = "std", error("{0}"))] + Generic(String), + /// Incompatible serialized binary + #[cfg_attr(feature = "std", error("incompatible binary: {0}"))] + Incompatible(String), + /// The provided binary is corrupted + #[cfg_attr(feature = "std", error("corrupted binary: {0}"))] + CorruptedBinary(String), + /// The binary was valid, but we got an error when + /// trying to allocate the required resources. + #[cfg_attr(feature = "std", error(transparent))] + Compiler(CompileError), +} diff --git a/lib/api/src/js/mod.rs b/lib/api/src/js/mod.rs index 6acaefc4f58..95e7d15ccec 100644 --- a/lib/api/src/js/mod.rs +++ b/lib/api/src/js/mod.rs @@ -51,6 +51,7 @@ pub use wasmer_derive::WasmerEnv; pub use crate::js::cell::WasmCell; pub use crate::js::env::{HostEnvInitError, LazyInit, WasmerEnv}; +pub use crate::js::error::{DeserializeError, SerializeError}; pub use crate::js::export::Export; pub use crate::js::exports::{ExportError, Exportable, Exports, ExportsIterator}; pub use crate::js::externals::{ diff --git a/lib/api/src/js/module.rs b/lib/api/src/js/module.rs index 076c2f49892..e05d5ace014 100644 --- a/lib/api/src/js/module.rs +++ b/lib/api/src/js/module.rs @@ -3,9 +3,9 @@ use crate::js::resolver::Resolver; use crate::js::store::Store; use crate::js::types::{ExportType, ImportType}; // use crate::js::InstantiationError; -use crate::js::error::CompileError; #[cfg(feature = "wat")] use crate::js::error::WasmError; +use crate::js::error::{CompileError, DeserializeError, SerializeError}; use crate::js::RuntimeError; use js_sys::{Reflect, Uint8Array, WebAssembly}; use std::fmt; @@ -62,6 +62,8 @@ pub struct Module { name: Option, // WebAssembly type hints type_hints: Option, + #[cfg(feature = "js-serializable-module")] + raw_bytes: Option>, } impl Module { @@ -194,6 +196,8 @@ impl Module { module, type_hints, name, + #[cfg(feature = "js-serializable-module")] + raw_bytes: Some(binary.to_vec()), }) } @@ -273,6 +277,25 @@ impl Module { // self.artifact.module_ref().name.as_deref() } + /// Serializes a module into a binary representation that the `Engine` + /// can later process via [`Module::deserialize`]. + /// + #[cfg(feature = "js-serializable-module")] + pub fn serialize(&self) -> Result, SerializeError> { + self.raw_bytes.clone().ok_or(SerializeError::Generic( + "Not able to serialize module".to_string(), + )) + } + + /// Deserializes a serialized Module binary into a `Module`. + /// + /// This is safe since deserialization under `js` is essentially same as reconstructing `Module`. + /// We maintain the `unsafe` to preserve the same API as Wasmer + #[cfg(feature = "js-serializable-module")] + pub unsafe fn deserialize(store: &Store, bytes: &[u8]) -> Result { + Self::new(store, bytes).map_err(|e| DeserializeError::Compiler(e)) + } + /// Sets the name of the current module. /// This is normally useful for stacktraces and debugging. /// @@ -512,6 +535,8 @@ impl From for Module { module, name: None, type_hints: None, + #[cfg(feature = "js-serializable-module")] + raw_bytes: None, } } } diff --git a/lib/cache/Cargo.toml b/lib/cache/Cargo.toml index 1368ee5a25a..f25564fbf96 100644 --- a/lib/cache/Cargo.toml +++ b/lib/cache/Cargo.toml @@ -11,7 +11,7 @@ readme = "README.md" edition = "2018" [dependencies] -wasmer = { path = "../api", version = "=2.2.1", default-features = false, features = ["sys"] } +wasmer = { path = "../api", version = "=2.2.1", default-features = false} hex = "0.4" thiserror = "1" blake3 = "1.0" @@ -25,6 +25,8 @@ wasmer-engine-universal = { path = "../engine-universal", version = "=2.2.1" } wasmer-engine-dylib = { path = "../engine-dylib", version = "=2.2.1" } [features] +default = ["wasmer/js-serializable-module", "filesystem"] +filesystem = [] blake3-pure = ["blake3/pure"] [[bench]] diff --git a/lib/cache/src/filesystem.rs b/lib/cache/src/filesystem.rs index cbd30c1cdbb..39753ef9dc9 100644 --- a/lib/cache/src/filesystem.rs +++ b/lib/cache/src/filesystem.rs @@ -1,3 +1,4 @@ +#![cfg_attr(not(feature = "filesystem"), allow(unused))] use crate::cache::Cache; use crate::hash::Hash; use std::fs::{create_dir_all, File}; @@ -35,6 +36,7 @@ pub struct FileSystemCache { ext: Option, } +#[cfg(feature = "filesystem")] impl FileSystemCache { /// Construct a new `FileSystemCache` around the specified directory. pub fn new>(path: P) -> io::Result { @@ -84,6 +86,7 @@ impl FileSystemCache { } } +#[cfg(feature = "filesystem")] impl Cache for FileSystemCache { type DeserializeError = DeserializeError; type SerializeError = SerializeError; diff --git a/lib/cache/src/lib.rs b/lib/cache/src/lib.rs index ffe1e9ce65f..51d81be777c 100644 --- a/lib/cache/src/lib.rs +++ b/lib/cache/src/lib.rs @@ -24,6 +24,7 @@ mod filesystem; mod hash; pub use crate::cache::Cache; +#[cfg(feature = "filesystem")] pub use crate::filesystem::FileSystemCache; pub use crate::hash::Hash;