Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

The API breaking changes from future WASIX/Network/Threading addition #3141

Merged
merged 6 commits into from
Sep 2, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 2 additions & 3 deletions docs/migration_to_3.0.0.md
Original file line number Diff line number Diff line change
Expand Up @@ -195,14 +195,13 @@ import_object.define("env", "host_function", host_function);
let instance = Instance::new(&mut store, &module, &import_object).expect("Could not instantiate module.");
```

For WASI, don't forget to import memory to `WasiEnv`
For WASI, don't forget to initialize the `WasiEnv` (it will import the memory)

```rust
let mut wasi_env = WasiState::new("hello").finalize()?;
let import_object = wasi_env.import_object(&mut store, &module)?;
let instance = Instance::new(&mut store, &module, &import_object).expect("Could not instantiate module.");
let memory = instance.exports.get_memory("memory")?;
wasi_env.data_mut(&mut store).set_memory(memory.clone());
wasi_env.initialize(&mut store, &instance).unwrap();
```

#### `ChainableNamedResolver` is removed
Expand Down
1 change: 1 addition & 0 deletions lib/api/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ indexmap = { version = "1.6" }
cfg-if = "1.0"
thiserror = "1.0"
more-asserts = "0.2"
bytes = "1"
# - Optional shared dependencies.
wat = { version = "1.0", optional = true }
tracing = { version = "0.1", optional = true }
Expand Down
51 changes: 47 additions & 4 deletions lib/api/src/js/module.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ use crate::js::store::AsStoreMut;
use crate::js::types::{AsJs, ExportType, ImportType};
use crate::js::RuntimeError;
use crate::AsStoreRef;
use bytes::Bytes;
use js_sys::{Reflect, Uint8Array, WebAssembly};
use std::borrow::Cow;
use std::fmt;
use std::io;
use std::path::Path;
Expand Down Expand Up @@ -48,6 +50,46 @@ pub struct ModuleTypeHints {
pub exports: Vec<ExternType>,
}

pub trait IntoBytes {
fn into_bytes(self) -> Bytes;
}

impl IntoBytes for Bytes {
fn into_bytes(self) -> Bytes {
self
}
}

impl IntoBytes for Vec<u8> {
fn into_bytes(self) -> Bytes {
Bytes::from(self)
}
}

impl IntoBytes for &[u8] {
fn into_bytes(self) -> Bytes {
Bytes::from(self.to_vec())
}
}

impl<const N: usize> IntoBytes for &[u8; N] {
fn into_bytes(self) -> Bytes {
Bytes::from(self.to_vec())
}
}

impl IntoBytes for &str {
fn into_bytes(self) -> Bytes {
Bytes::from(self.as_bytes().to_vec())
}
}

impl IntoBytes for Cow<'_, [u8]> {
fn into_bytes(self) -> Bytes {
Bytes::from(self.to_vec())
}
}

/// A WebAssembly Module contains stateless WebAssembly
/// code that has already been compiled and can be instantiated
/// multiple times.
Expand All @@ -63,7 +105,7 @@ pub struct Module {
// WebAssembly type hints
type_hints: Option<ModuleTypeHints>,
#[cfg(feature = "js-serializable-module")]
raw_bytes: Option<Vec<u8>>,
raw_bytes: Option<Bytes>,
}

impl Module {
Expand Down Expand Up @@ -199,7 +241,7 @@ impl Module {
type_hints,
name,
#[cfg(feature = "js-serializable-module")]
raw_bytes: Some(binary.to_vec()),
raw_bytes: Some(binary.into_bytes()),
})
}

Expand Down Expand Up @@ -263,7 +305,7 @@ impl Module {
/// can later process via [`Module::deserialize`].
///
#[cfg(feature = "js-serializable-module")]
pub fn serialize(&self) -> Result<Vec<u8>, SerializeError> {
pub fn serialize(&self) -> Result<Bytes, SerializeError> {
self.raw_bytes.clone().ok_or(SerializeError::Generic(
"Not able to serialize module".to_string(),
))
Expand All @@ -276,8 +318,9 @@ impl Module {
#[cfg(feature = "js-serializable-module")]
pub unsafe fn deserialize(
_store: &impl AsStoreRef,
bytes: &[u8],
bytes: impl IntoBytes,
) -> Result<Self, DeserializeError> {
let bytes = bytes.into_bytes();
Self::new(_store, bytes).map_err(|e| DeserializeError::Compiler(e))
}

Expand Down
2 changes: 1 addition & 1 deletion lib/api/src/js/ptr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ impl<T, M: MemorySize> WasmPtr<T, M> {

/// Get the offset into Wasm linear memory for this `WasmPtr`.
#[inline]
pub fn offset(self) -> M::Offset {
pub fn offset(&self) -> M::Offset {
self.offset
}

Expand Down
7 changes: 6 additions & 1 deletion lib/api/src/sys/function_env.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ impl<T> FunctionEnv<T> {
}

/// Get the data as reference
pub fn as_ref<'a>(&self, store: &'a impl AsStoreMut) -> &'a T
pub fn as_ref<'a>(&self, store: &'a impl AsStoreRef) -> &'a T
where
T: Any + Send + 'static + Sized,
{
Expand Down Expand Up @@ -105,6 +105,11 @@ impl<T: Send + 'static> FunctionEnvMut<'_, T> {
self.func_env.as_mut(&mut self.store_mut)
}

/// Borrows a new immmutable reference
pub fn as_ref(&self) -> FunctionEnv<T> {
self.func_env.clone()
}

/// Borrows a new mutable reference
pub fn as_mut(&mut self) -> FunctionEnvMut<'_, T> {
FunctionEnvMut {
Expand Down
52 changes: 47 additions & 5 deletions lib/api/src/sys/module.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
use crate::sys::InstantiationError;
use crate::AsStoreMut;
use crate::AsStoreRef;
use bytes::Bytes;
use std::borrow::Cow;
use std::fmt;
use std::io;
use std::path::Path;
Expand Down Expand Up @@ -54,6 +56,46 @@ pub struct Module {
module_info: Arc<ModuleInfo>,
}

pub trait IntoBytes {
fn into_bytes(self) -> Bytes;
}

impl IntoBytes for Bytes {
fn into_bytes(self) -> Bytes {
self
}
}

impl IntoBytes for Vec<u8> {
fn into_bytes(self) -> Bytes {
Bytes::from(self)
}
}

impl IntoBytes for &[u8] {
fn into_bytes(self) -> Bytes {
Bytes::from(self.to_vec())
}
}

impl<const N: usize> IntoBytes for &[u8; N] {
fn into_bytes(self) -> Bytes {
Bytes::from(self.to_vec())
}
}

impl IntoBytes for &str {
fn into_bytes(self) -> Bytes {
Bytes::from(self.as_bytes().to_vec())
}
}

impl IntoBytes for Cow<'_, [u8]> {
fn into_bytes(self) -> Bytes {
Bytes::from(self.to_vec())
}
}

impl Module {
#[cfg(feature = "compiler")]
/// Creates a new WebAssembly Module given the configuration
Expand Down Expand Up @@ -124,7 +166,6 @@ impl Module {
e
)))
})?;

Self::from_binary(store, bytes.as_ref())
}

Expand Down Expand Up @@ -206,8 +247,8 @@ impl Module {
/// # Ok(())
/// # }
/// ```
pub fn serialize(&self) -> Result<Vec<u8>, SerializeError> {
self.artifact.serialize()
pub fn serialize(&self) -> Result<Bytes, SerializeError> {
self.artifact.serialize().map(|bytes| bytes.into())
}

/// Serializes a module into a file that the `Engine`
Expand Down Expand Up @@ -254,9 +295,10 @@ impl Module {
/// ```
pub unsafe fn deserialize(
store: &impl AsStoreRef,
bytes: &[u8],
bytes: impl IntoBytes,
) -> Result<Self, DeserializeError> {
let artifact = store.as_store_ref().engine().deserialize(bytes)?;
let bytes = bytes.into_bytes();
let artifact = store.as_store_ref().engine().deserialize(&bytes)?;
Ok(Self::from_artifact(artifact))
}

Expand Down
2 changes: 1 addition & 1 deletion lib/api/src/sys/ptr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ impl<T, M: MemorySize> WasmPtr<T, M> {

/// Get the offset into Wasm linear memory for this `WasmPtr`.
#[inline]
pub fn offset(self) -> M::Offset {
pub fn offset(&self) -> M::Offset {
self.offset
}

Expand Down
2 changes: 1 addition & 1 deletion lib/c-api/src/wasm_c_api/module.rs
Original file line number Diff line number Diff line change
Expand Up @@ -475,7 +475,7 @@ pub unsafe extern "C" fn wasm_module_deserialize(
#[no_mangle]
pub unsafe extern "C" fn wasm_module_serialize(module: &wasm_module_t, out: &mut wasm_byte_vec_t) {
let byte_vec = c_try!(module.inner.serialize(); otherwise ());
out.set_buffer(byte_vec);
out.set_buffer(byte_vec.to_vec());
}

#[cfg(test)]
Expand Down
15 changes: 5 additions & 10 deletions lib/cli/src/commands/inspect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,16 +25,11 @@ impl Inspect {
fn inner_execute(&self) -> Result<()> {
let (store, _compiler_type) = self.store.get_store()?;
let module_contents = std::fs::read(&self.path)?;
let module = Module::new(&store, &module_contents)?;
println!(
"Type: {}",
if !is_wasm(&module_contents) {
"wat"
} else {
"wasm"
}
);
println!("Size: {}", ByteSize(module_contents.len() as _));
let iswasm = is_wasm(&module_contents);
let module_len = module_contents.len();
let module = Module::new(&store, module_contents)?;
println!("Type: {}", if !iswasm { "wat" } else { "wasm" });
println!("Size: {}", ByteSize(module_len as _));
println!("Imports:");
println!(" Functions:");
for f in module.imports().functions() {
Expand Down
4 changes: 2 additions & 2 deletions lib/cli/src/commands/run.rs
Original file line number Diff line number Diff line change
Expand Up @@ -272,7 +272,7 @@ impl Run {
let module_result: Result<Module> = if !self.disable_cache && contents.len() > 0x1000 {
self.get_module_from_cache(&store, &contents, &compiler_type)
} else {
Module::new(&store, &contents).map_err(|e| e.into())
Module::new(&store, contents).map_err(|e| e.into())
};
#[cfg(not(feature = "cache"))]
let module_result = Module::new(&store, &contents);
Expand Down Expand Up @@ -319,7 +319,7 @@ impl Run {
warning!("cached module is corrupted: {}", err);
}
}
let module = Module::new(store, &contents)?;
let module = Module::new(store, contents)?;
// Store the compiled Module in cache
cache.store(hash, &module)?;
Ok(module)
Expand Down
33 changes: 31 additions & 2 deletions lib/wasi/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,11 @@ use wasmer_wasi_types::__WASI_CLOCK_MONOTONIC;
use derivative::*;
use std::ops::Deref;
use thiserror::Error;
use tracing::trace;
use wasmer::{
imports, namespace, AsStoreMut, AsStoreRef, Exports, Function, FunctionEnv, Imports, Memory,
Memory32, MemoryAccessError, MemorySize, MemoryView, Module, TypedFunction,
imports, namespace, AsStoreMut, AsStoreRef, ExportError, Exports, Function, FunctionEnv,
Imports, Instance, Memory, Memory32, MemoryAccessError, MemorySize, MemoryView, Module,
TypedFunction,
};

pub use runtime::{
Expand Down Expand Up @@ -166,6 +168,33 @@ impl WasiFunctionEnv {
self.env.as_mut(store)
}

/// Initializes the WasiEnv using the instance exports
/// (this must be executed before attempting to use it)
/// (as the stores can not by themselves be passed between threads we can store the module
/// in a thread-local variables and use it later - for multithreading)
pub fn initialize(
&mut self,
store: &mut impl AsStoreMut,
instance: &Instance,
) -> Result<(), ExportError> {
// List all the exports and imports
for ns in instance.module().exports() {
//trace!("module::export - {} ({:?})", ns.name(), ns.ty());
trace!("module::export - {}", ns.name());
}
for ns in instance.module().imports() {
trace!("module::import - {}::{}", ns.module(), ns.name());
}

// First we get the malloc function which if it exists will be used to
// create the pthread_self structure
let memory = instance.exports.get_memory("memory")?.clone();
let env = self.data_mut(store);
env.set_memory(memory);

Ok(())
}

/// Like `import_object` but containing all the WASI versions detected in
/// the module.
pub fn import_object_for_all_wasi_versions(
Expand Down
2 changes: 1 addition & 1 deletion tests/compilers/serialize.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ fn test_deserialize(config: crate::Config) -> Result<()> {
let serialized_bytes = module.serialize()?;

let headless_store = config.headless_store();
let deserialized_module = unsafe { Module::deserialize(&headless_store, &serialized_bytes)? };
let deserialized_module = unsafe { Module::deserialize(&headless_store, serialized_bytes)? };
assert_eq!(deserialized_module.name(), Some("name"));
assert_eq!(
deserialized_module.exports().collect::<Vec<_>>(),
Expand Down