mirror of
https://github.com/fluencelabs/wasmer
synced 2024-12-13 14:25:32 +00:00
Merge pull request #957 from wasmerio/feature/add-support-for-new-wasi
Add support for new WASI snapshot, backwards compat too
This commit is contained in:
commit
b9138aaddd
@ -6,6 +6,7 @@
|
|||||||
- [#992](https://github.com/wasmerio/wasmer/pull/992) Updates WAPM version to 0.4.1, fix arguments issue introduced in #990
|
- [#992](https://github.com/wasmerio/wasmer/pull/992) Updates WAPM version to 0.4.1, fix arguments issue introduced in #990
|
||||||
- [#990](https://github.com/wasmerio/wasmer/pull/990) Default wasmer CLI to `run`. Wasmer will now attempt to parse unrecognized command line options as if they were applied to the run command: `wasmer mywasm.wasm --dir=.` now works!
|
- [#990](https://github.com/wasmerio/wasmer/pull/990) Default wasmer CLI to `run`. Wasmer will now attempt to parse unrecognized command line options as if they were applied to the run command: `wasmer mywasm.wasm --dir=.` now works!
|
||||||
- [#987](https://github.com/wasmerio/wasmer/pull/987) Fix `runtime-c-api` header files when compiled by gnuc.
|
- [#987](https://github.com/wasmerio/wasmer/pull/987) Fix `runtime-c-api` header files when compiled by gnuc.
|
||||||
|
- [#957](https://github.com/wasmerio/wasmer/pull/957) Change the meaning of `wasmer_wasi::is_wasi_module` to detect any type of WASI module, add support for new wasi snapshot_preview1
|
||||||
|
|
||||||
## 0.10.2 - 2019-11-18
|
## 0.10.2 - 2019-11-18
|
||||||
|
|
||||||
|
@ -58,8 +58,8 @@ members = [
|
|||||||
"lib/wasi-tests",
|
"lib/wasi-tests",
|
||||||
"lib/emscripten-tests",
|
"lib/emscripten-tests",
|
||||||
"lib/middleware-common-tests",
|
"lib/middleware-common-tests",
|
||||||
"examples/plugin-for-example",
|
|
||||||
"examples/parallel",
|
"examples/parallel",
|
||||||
|
"examples/plugin-for-example",
|
||||||
"examples/parallel-guest",
|
"examples/parallel-guest",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -16,7 +16,13 @@ fn serializing_works() {
|
|||||||
b"GOROOT=$HOME/.cargo/bin".into_iter().cloned().collect(),
|
b"GOROOT=$HOME/.cargo/bin".into_iter().cloned().collect(),
|
||||||
];
|
];
|
||||||
let wasm_binary = include_bytes!("../wasitests/fd_read.wasm");
|
let wasm_binary = include_bytes!("../wasitests/fd_read.wasm");
|
||||||
let import_object = generate_import_object(
|
let module = compile(&wasm_binary[..])
|
||||||
|
.map_err(|e| format!("Can't compile module: {:?}", e))
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let wasi_version = get_wasi_version(&module).expect("WASI module");
|
||||||
|
let import_object = generate_import_object_for_version(
|
||||||
|
wasi_version,
|
||||||
args.clone(),
|
args.clone(),
|
||||||
envs.clone(),
|
envs.clone(),
|
||||||
vec![],
|
vec![],
|
||||||
@ -25,9 +31,6 @@ fn serializing_works() {
|
|||||||
std::path::PathBuf::from("wasitests/test_fs/hamlet"),
|
std::path::PathBuf::from("wasitests/test_fs/hamlet"),
|
||||||
)],
|
)],
|
||||||
);
|
);
|
||||||
let module = compile(&wasm_binary[..])
|
|
||||||
.map_err(|e| format!("Can't compile module: {:?}", e))
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
let state_bytes = {
|
let state_bytes = {
|
||||||
let instance = module.instantiate(&import_object).unwrap();
|
let instance = module.instantiate(&import_object).unwrap();
|
||||||
|
@ -2,7 +2,7 @@ macro_rules! assert_wasi_output {
|
|||||||
($file:expr, $name:expr, $po_dir_args: expr, $mapdir_args:expr, $envvar_args:expr, $expected:expr) => {{
|
($file:expr, $name:expr, $po_dir_args: expr, $mapdir_args:expr, $envvar_args:expr, $expected:expr) => {{
|
||||||
use wasmer_dev_utils::stdio::StdioCapturer;
|
use wasmer_dev_utils::stdio::StdioCapturer;
|
||||||
use wasmer_runtime_core::{backend::Compiler, Func};
|
use wasmer_runtime_core::{backend::Compiler, Func};
|
||||||
use wasmer_wasi::generate_import_object;
|
use wasmer_wasi::{generate_import_object_for_version, get_wasi_version};
|
||||||
|
|
||||||
#[cfg(feature = "clif")]
|
#[cfg(feature = "clif")]
|
||||||
fn get_compiler() -> impl Compiler {
|
fn get_compiler() -> impl Compiler {
|
||||||
@ -33,7 +33,15 @@ macro_rules! assert_wasi_output {
|
|||||||
let module = wasmer_runtime_core::compile_with(&wasm_bytes[..], &get_compiler())
|
let module = wasmer_runtime_core::compile_with(&wasm_bytes[..], &get_compiler())
|
||||||
.expect("WASM can't be compiled");
|
.expect("WASM can't be compiled");
|
||||||
|
|
||||||
let import_object = generate_import_object(vec![], vec![], $po_dir_args, $mapdir_args);
|
let wasi_version = get_wasi_version(&module).expect("WASI module");
|
||||||
|
|
||||||
|
let import_object = generate_import_object_for_version(
|
||||||
|
wasi_version,
|
||||||
|
vec![],
|
||||||
|
vec![],
|
||||||
|
$po_dir_args,
|
||||||
|
$mapdir_args,
|
||||||
|
);
|
||||||
|
|
||||||
let instance = module
|
let instance = module
|
||||||
.instantiate(&import_object)
|
.instantiate(&import_object)
|
||||||
|
@ -22,4 +22,4 @@ serde = { version = "1", features = ["derive"] }
|
|||||||
wasmer-runtime-core = { path = "../runtime-core", version = "0.10.2" }
|
wasmer-runtime-core = { path = "../runtime-core", version = "0.10.2" }
|
||||||
|
|
||||||
[target.'cfg(windows)'.dependencies]
|
[target.'cfg(windows)'.dependencies]
|
||||||
winapi = "0.3"
|
winapi = "0.3"
|
@ -12,7 +12,7 @@
|
|||||||
|
|
||||||
//! Wasmer's WASI implementation
|
//! Wasmer's WASI implementation
|
||||||
//!
|
//!
|
||||||
//! Use `generate_import_object` to create an `ImportObject`. This `ImportObject`
|
//! Use `generate_import_object` to create an [`ImportObject`]. This [`ImportObject`]
|
||||||
//! can be combined with a module to create an `Instance` which can execute WASI
|
//! can be combined with a module to create an `Instance` which can execute WASI
|
||||||
//! Wasm functions.
|
//! Wasm functions.
|
||||||
//!
|
//!
|
||||||
@ -37,7 +37,7 @@ use self::syscalls::*;
|
|||||||
use std::ffi::c_void;
|
use std::ffi::c_void;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
pub use self::utils::is_wasi_module;
|
pub use self::utils::{get_wasi_version, is_wasi_module, WasiVersion};
|
||||||
|
|
||||||
use wasmer_runtime_core::{func, import::ImportObject, imports};
|
use wasmer_runtime_core::{func, import::ImportObject, imports};
|
||||||
|
|
||||||
@ -47,7 +47,8 @@ pub struct ExitCode {
|
|||||||
pub code: syscalls::types::__wasi_exitcode_t,
|
pub code: syscalls::types::__wasi_exitcode_t,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a Wasi [`ImportObject`] with [`WasiState`].
|
/// Creates a Wasi [`ImportObject`] with [`WasiState`] with the latest snapshot
|
||||||
|
/// of WASI.
|
||||||
pub fn generate_import_object(
|
pub fn generate_import_object(
|
||||||
args: Vec<Vec<u8>>,
|
args: Vec<Vec<u8>>,
|
||||||
envs: Vec<Vec<u8>>,
|
envs: Vec<Vec<u8>>,
|
||||||
@ -79,7 +80,7 @@ pub fn generate_import_object(
|
|||||||
imports! {
|
imports! {
|
||||||
// This generates the wasi state.
|
// This generates the wasi state.
|
||||||
state_gen,
|
state_gen,
|
||||||
"wasi_unstable" => {
|
"wasi_snapshot_preview1" => {
|
||||||
"args_get" => func!(args_get),
|
"args_get" => func!(args_get),
|
||||||
"args_sizes_get" => func!(args_sizes_get),
|
"args_sizes_get" => func!(args_sizes_get),
|
||||||
"clock_res_get" => func!(clock_res_get),
|
"clock_res_get" => func!(clock_res_get),
|
||||||
@ -128,3 +129,101 @@ pub fn generate_import_object(
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Creates a Wasi [`ImportObject`] with [`WasiState`] for the given [`WasiVersion`].
|
||||||
|
pub fn generate_import_object_for_version(
|
||||||
|
version: WasiVersion,
|
||||||
|
args: Vec<Vec<u8>>,
|
||||||
|
envs: Vec<Vec<u8>>,
|
||||||
|
preopened_files: Vec<PathBuf>,
|
||||||
|
mapped_dirs: Vec<(String, PathBuf)>,
|
||||||
|
) -> ImportObject {
|
||||||
|
match version {
|
||||||
|
WasiVersion::Snapshot0 => {
|
||||||
|
generate_import_object_snapshot0(args, envs, preopened_files, mapped_dirs)
|
||||||
|
}
|
||||||
|
WasiVersion::Snapshot1 => generate_import_object(args, envs, preopened_files, mapped_dirs),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Creates a legacy Wasi [`ImportObject`] with [`WasiState`].
|
||||||
|
fn generate_import_object_snapshot0(
|
||||||
|
args: Vec<Vec<u8>>,
|
||||||
|
envs: Vec<Vec<u8>>,
|
||||||
|
preopened_files: Vec<PathBuf>,
|
||||||
|
mapped_dirs: Vec<(String, PathBuf)>,
|
||||||
|
) -> ImportObject {
|
||||||
|
let state_gen = move || {
|
||||||
|
// TODO: look into removing all these unnecessary clones
|
||||||
|
fn state_destructor(data: *mut c_void) {
|
||||||
|
unsafe {
|
||||||
|
drop(Box::from_raw(data as *mut WasiState));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let preopened_files = preopened_files.clone();
|
||||||
|
let mapped_dirs = mapped_dirs.clone();
|
||||||
|
//let wasi_builder = create_wasi_instance();
|
||||||
|
|
||||||
|
let state = Box::new(WasiState {
|
||||||
|
fs: WasiFs::new(&preopened_files, &mapped_dirs).expect("Could not create WASI FS"),
|
||||||
|
args: args.clone(),
|
||||||
|
envs: envs.clone(),
|
||||||
|
});
|
||||||
|
|
||||||
|
(
|
||||||
|
Box::into_raw(state) as *mut c_void,
|
||||||
|
state_destructor as fn(*mut c_void),
|
||||||
|
)
|
||||||
|
};
|
||||||
|
imports! {
|
||||||
|
// This generates the wasi state.
|
||||||
|
state_gen,
|
||||||
|
"wasi_unstable" => {
|
||||||
|
"args_get" => func!(args_get),
|
||||||
|
"args_sizes_get" => func!(args_sizes_get),
|
||||||
|
"clock_res_get" => func!(clock_res_get),
|
||||||
|
"clock_time_get" => func!(clock_time_get),
|
||||||
|
"environ_get" => func!(environ_get),
|
||||||
|
"environ_sizes_get" => func!(environ_sizes_get),
|
||||||
|
"fd_advise" => func!(fd_advise),
|
||||||
|
"fd_allocate" => func!(fd_allocate),
|
||||||
|
"fd_close" => func!(fd_close),
|
||||||
|
"fd_datasync" => func!(fd_datasync),
|
||||||
|
"fd_fdstat_get" => func!(fd_fdstat_get),
|
||||||
|
"fd_fdstat_set_flags" => func!(fd_fdstat_set_flags),
|
||||||
|
"fd_fdstat_set_rights" => func!(fd_fdstat_set_rights),
|
||||||
|
"fd_filestat_get" => func!(legacy::snapshot0::fd_filestat_get),
|
||||||
|
"fd_filestat_set_size" => func!(fd_filestat_set_size),
|
||||||
|
"fd_filestat_set_times" => func!(fd_filestat_set_times),
|
||||||
|
"fd_pread" => func!(fd_pread),
|
||||||
|
"fd_prestat_get" => func!(fd_prestat_get),
|
||||||
|
"fd_prestat_dir_name" => func!(fd_prestat_dir_name),
|
||||||
|
"fd_pwrite" => func!(fd_pwrite),
|
||||||
|
"fd_read" => func!(fd_read),
|
||||||
|
"fd_readdir" => func!(fd_readdir),
|
||||||
|
"fd_renumber" => func!(fd_renumber),
|
||||||
|
"fd_seek" => func!(legacy::snapshot0::fd_seek),
|
||||||
|
"fd_sync" => func!(fd_sync),
|
||||||
|
"fd_tell" => func!(fd_tell),
|
||||||
|
"fd_write" => func!(fd_write),
|
||||||
|
"path_create_directory" => func!(path_create_directory),
|
||||||
|
"path_filestat_get" => func!(legacy::snapshot0::path_filestat_get),
|
||||||
|
"path_filestat_set_times" => func!(path_filestat_set_times),
|
||||||
|
"path_link" => func!(path_link),
|
||||||
|
"path_open" => func!(path_open),
|
||||||
|
"path_readlink" => func!(path_readlink),
|
||||||
|
"path_remove_directory" => func!(path_remove_directory),
|
||||||
|
"path_rename" => func!(path_rename),
|
||||||
|
"path_symlink" => func!(path_symlink),
|
||||||
|
"path_unlink_file" => func!(path_unlink_file),
|
||||||
|
"poll_oneoff" => func!(legacy::snapshot0::poll_oneoff),
|
||||||
|
"proc_exit" => func!(proc_exit),
|
||||||
|
"proc_raise" => func!(proc_raise),
|
||||||
|
"random_get" => func!(random_get),
|
||||||
|
"sched_yield" => func!(sched_yield),
|
||||||
|
"sock_recv" => func!(sock_recv),
|
||||||
|
"sock_send" => func!(sock_send),
|
||||||
|
"sock_shutdown" => func!(sock_shutdown),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
5
lib/wasi/src/syscalls/legacy/mod.rs
Normal file
5
lib/wasi/src/syscalls/legacy/mod.rs
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
//! These modules provide wrappers and implementations for older version of WASI.
|
||||||
|
//!
|
||||||
|
//! If you are relying on legacy WASI, please upgrade for the best experience.
|
||||||
|
|
||||||
|
pub mod snapshot0;
|
178
lib/wasi/src/syscalls/legacy/snapshot0.rs
Normal file
178
lib/wasi/src/syscalls/legacy/snapshot0.rs
Normal file
@ -0,0 +1,178 @@
|
|||||||
|
use crate::ptr::{Array, WasmPtr};
|
||||||
|
use crate::syscalls;
|
||||||
|
use crate::syscalls::types::{self, snapshot0};
|
||||||
|
use wasmer_runtime_core::{debug, vm::Ctx};
|
||||||
|
|
||||||
|
/// Wrapper around `syscalls::fd_filestat_get` with extra logic to handle the size
|
||||||
|
/// difference of `wasi_filestat_t`
|
||||||
|
///
|
||||||
|
/// WARNING: this function involves saving, clobbering, and restoring unrelated
|
||||||
|
/// Wasm memory. If the memory clobbered by the current syscall is also used by
|
||||||
|
/// that syscall, then it may break.
|
||||||
|
pub fn fd_filestat_get(
|
||||||
|
ctx: &mut Ctx,
|
||||||
|
fd: types::__wasi_fd_t,
|
||||||
|
buf: WasmPtr<snapshot0::__wasi_filestat_t>,
|
||||||
|
) -> types::__wasi_errno_t {
|
||||||
|
let memory = ctx.memory(0);
|
||||||
|
|
||||||
|
// transmute the WasmPtr<T1> into a WasmPtr<T2> where T2 > T1, this will read extra memory.
|
||||||
|
// The edge case of this causing an OOB is not handled, if the new field is OOB, then the entire
|
||||||
|
// memory access will fail.
|
||||||
|
let new_buf: WasmPtr<types::__wasi_filestat_t> = unsafe { std::mem::transmute(buf) };
|
||||||
|
|
||||||
|
// Copy the data including the extra data
|
||||||
|
let new_filestat_setup: types::__wasi_filestat_t =
|
||||||
|
wasi_try!(new_buf.deref(memory)).get().clone();
|
||||||
|
|
||||||
|
// Set up complete, make the call with the pointer that will write to the
|
||||||
|
// struct and some unrelated memory after the struct.
|
||||||
|
let result = syscalls::fd_filestat_get(ctx, fd, new_buf);
|
||||||
|
|
||||||
|
// reborrow memory
|
||||||
|
let memory = ctx.memory(0);
|
||||||
|
|
||||||
|
// get the values written to memory
|
||||||
|
let new_filestat = wasi_try!(new_buf.deref(memory)).get();
|
||||||
|
// translate the new struct into the old struct in host memory
|
||||||
|
let old_stat = snapshot0::__wasi_filestat_t {
|
||||||
|
st_dev: new_filestat.st_dev,
|
||||||
|
st_ino: new_filestat.st_ino,
|
||||||
|
st_filetype: new_filestat.st_filetype,
|
||||||
|
st_nlink: new_filestat.st_nlink as u32,
|
||||||
|
st_size: new_filestat.st_size,
|
||||||
|
st_atim: new_filestat.st_atim,
|
||||||
|
st_mtim: new_filestat.st_mtim,
|
||||||
|
st_ctim: new_filestat.st_ctim,
|
||||||
|
};
|
||||||
|
|
||||||
|
// write back the original values at the pointer's memory locations
|
||||||
|
// (including the memory unrelated to the pointer)
|
||||||
|
wasi_try!(new_buf.deref(memory)).set(new_filestat_setup);
|
||||||
|
|
||||||
|
// Now that this memory is back as it was, write the translated filestat
|
||||||
|
// into memory leaving it as it should be
|
||||||
|
wasi_try!(buf.deref(memory)).set(old_stat);
|
||||||
|
|
||||||
|
result
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Wrapper around `syscalls::path_filestat_get` with extra logic to handle the size
|
||||||
|
/// difference of `wasi_filestat_t`
|
||||||
|
pub fn path_filestat_get(
|
||||||
|
ctx: &mut Ctx,
|
||||||
|
fd: types::__wasi_fd_t,
|
||||||
|
flags: types::__wasi_lookupflags_t,
|
||||||
|
path: WasmPtr<u8, Array>,
|
||||||
|
path_len: u32,
|
||||||
|
buf: WasmPtr<snapshot0::__wasi_filestat_t>,
|
||||||
|
) -> types::__wasi_errno_t {
|
||||||
|
// see `fd_filestat_get` in this file for an explanation of this strange behavior
|
||||||
|
let memory = ctx.memory(0);
|
||||||
|
|
||||||
|
let new_buf: WasmPtr<types::__wasi_filestat_t> = unsafe { std::mem::transmute(buf) };
|
||||||
|
let new_filestat_setup: types::__wasi_filestat_t =
|
||||||
|
wasi_try!(new_buf.deref(memory)).get().clone();
|
||||||
|
|
||||||
|
let result = syscalls::path_filestat_get(ctx, fd, flags, path, path_len, new_buf);
|
||||||
|
|
||||||
|
let memory = ctx.memory(0);
|
||||||
|
let new_filestat = wasi_try!(new_buf.deref(memory)).get();
|
||||||
|
let old_stat = snapshot0::__wasi_filestat_t {
|
||||||
|
st_dev: new_filestat.st_dev,
|
||||||
|
st_ino: new_filestat.st_ino,
|
||||||
|
st_filetype: new_filestat.st_filetype,
|
||||||
|
st_nlink: new_filestat.st_nlink as u32,
|
||||||
|
st_size: new_filestat.st_size,
|
||||||
|
st_atim: new_filestat.st_atim,
|
||||||
|
st_mtim: new_filestat.st_mtim,
|
||||||
|
st_ctim: new_filestat.st_ctim,
|
||||||
|
};
|
||||||
|
|
||||||
|
wasi_try!(new_buf.deref(memory)).set(new_filestat_setup);
|
||||||
|
wasi_try!(buf.deref(memory)).set(old_stat);
|
||||||
|
|
||||||
|
result
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Wrapper around `syscalls::fd_seek` with extra logic to remap the values
|
||||||
|
/// of `__wasi_whence_t`
|
||||||
|
pub fn fd_seek(
|
||||||
|
ctx: &mut Ctx,
|
||||||
|
fd: types::__wasi_fd_t,
|
||||||
|
offset: types::__wasi_filedelta_t,
|
||||||
|
whence: snapshot0::__wasi_whence_t,
|
||||||
|
newoffset: WasmPtr<types::__wasi_filesize_t>,
|
||||||
|
) -> types::__wasi_errno_t {
|
||||||
|
let new_whence = match whence {
|
||||||
|
snapshot0::__WASI_WHENCE_CUR => types::__WASI_WHENCE_CUR,
|
||||||
|
snapshot0::__WASI_WHENCE_END => types::__WASI_WHENCE_END,
|
||||||
|
snapshot0::__WASI_WHENCE_SET => types::__WASI_WHENCE_SET,
|
||||||
|
// if it's invalid, let the new fd_seek handle it
|
||||||
|
_ => whence,
|
||||||
|
};
|
||||||
|
syscalls::fd_seek(ctx, fd, offset, new_whence, newoffset)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Wrapper around `syscalls::poll_oneoff` with extra logic to add the removed
|
||||||
|
/// userdata field back
|
||||||
|
pub fn poll_oneoff(
|
||||||
|
ctx: &mut Ctx,
|
||||||
|
in_: WasmPtr<snapshot0::__wasi_subscription_t, Array>,
|
||||||
|
out_: WasmPtr<types::__wasi_event_t, Array>,
|
||||||
|
nsubscriptions: u32,
|
||||||
|
nevents: WasmPtr<u32>,
|
||||||
|
) -> types::__wasi_errno_t {
|
||||||
|
// in this case the new type is smaller than the old type, so it all fits into memory,
|
||||||
|
// we just need to readjust and copy it
|
||||||
|
|
||||||
|
// we start by adjusting `in_` into a format that the new code can understand
|
||||||
|
let memory = ctx.memory(0);
|
||||||
|
let mut in_origs: Vec<snapshot0::__wasi_subscription_t> = vec![];
|
||||||
|
for in_sub in wasi_try!(in_.deref(memory, 0, nsubscriptions)) {
|
||||||
|
in_origs.push(in_sub.get().clone());
|
||||||
|
}
|
||||||
|
|
||||||
|
// get a pointer to the smaller new type
|
||||||
|
let in_new_type_ptr: WasmPtr<types::__wasi_subscription_t, Array> =
|
||||||
|
unsafe { std::mem::transmute(in_) };
|
||||||
|
|
||||||
|
for (in_sub_new, orig) in wasi_try!(in_new_type_ptr.deref(memory, 0, nsubscriptions))
|
||||||
|
.iter()
|
||||||
|
.zip(in_origs.iter())
|
||||||
|
{
|
||||||
|
in_sub_new.set(types::__wasi_subscription_t {
|
||||||
|
userdata: orig.userdata,
|
||||||
|
type_: orig.type_,
|
||||||
|
u: if orig.type_ == types::__WASI_EVENTTYPE_CLOCK {
|
||||||
|
types::__wasi_subscription_u {
|
||||||
|
clock: types::__wasi_subscription_clock_t {
|
||||||
|
clock_id: unsafe { orig.u.clock.clock_id },
|
||||||
|
timeout: unsafe { orig.u.clock.timeout },
|
||||||
|
precision: unsafe { orig.u.clock.precision },
|
||||||
|
flags: unsafe { orig.u.clock.flags },
|
||||||
|
},
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
types::__wasi_subscription_u {
|
||||||
|
fd_readwrite: unsafe { orig.u.fd_readwrite },
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// make the call
|
||||||
|
let result = syscalls::poll_oneoff(ctx, in_new_type_ptr, out_, nsubscriptions, nevents);
|
||||||
|
|
||||||
|
// replace the old values of in, in case the calling code reuses the memory
|
||||||
|
let memory = ctx.memory(0);
|
||||||
|
|
||||||
|
for (in_sub, orig) in wasi_try!(in_.deref(memory, 0, nsubscriptions))
|
||||||
|
.iter()
|
||||||
|
.zip(in_origs.into_iter())
|
||||||
|
{
|
||||||
|
in_sub.set(orig);
|
||||||
|
}
|
||||||
|
|
||||||
|
result
|
||||||
|
}
|
@ -5,6 +5,8 @@ pub mod unix;
|
|||||||
#[cfg(any(target_os = "windows"))]
|
#[cfg(any(target_os = "windows"))]
|
||||||
pub mod windows;
|
pub mod windows;
|
||||||
|
|
||||||
|
pub mod legacy;
|
||||||
|
|
||||||
use self::types::*;
|
use self::types::*;
|
||||||
use crate::{
|
use crate::{
|
||||||
ptr::{Array, WasmPtr},
|
ptr::{Array, WasmPtr},
|
||||||
|
@ -416,7 +416,7 @@ pub struct __wasi_iovec_t {
|
|||||||
|
|
||||||
unsafe impl ValueType for __wasi_iovec_t {}
|
unsafe impl ValueType for __wasi_iovec_t {}
|
||||||
|
|
||||||
pub type __wasi_linkcount_t = u32;
|
pub type __wasi_linkcount_t = u64;
|
||||||
|
|
||||||
pub type __wasi_lookupflags_t = u32;
|
pub type __wasi_lookupflags_t = u32;
|
||||||
pub const __WASI_LOOKUP_SYMLINK_FOLLOW: u32 = 1 << 0;
|
pub const __WASI_LOOKUP_SYMLINK_FOLLOW: u32 = 1 << 0;
|
||||||
@ -559,7 +559,6 @@ pub const __WASI_SUBSCRIPTION_CLOCK_ABSTIME: u16 = 1 << 0;
|
|||||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
pub struct __wasi_subscription_clock_t {
|
pub struct __wasi_subscription_clock_t {
|
||||||
pub userdata: __wasi_userdata_t,
|
|
||||||
pub clock_id: __wasi_clockid_t,
|
pub clock_id: __wasi_clockid_t,
|
||||||
pub timeout: __wasi_timestamp_t,
|
pub timeout: __wasi_timestamp_t,
|
||||||
pub precision: __wasi_timestamp_t,
|
pub precision: __wasi_timestamp_t,
|
||||||
@ -575,8 +574,8 @@ pub struct __wasi_subscription_fs_readwrite_t {
|
|||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
pub union __wasi_subscription_u {
|
pub union __wasi_subscription_u {
|
||||||
clock: __wasi_subscription_clock_t,
|
pub clock: __wasi_subscription_clock_t,
|
||||||
fd_readwrite: __wasi_subscription_fs_readwrite_t,
|
pub fd_readwrite: __wasi_subscription_fs_readwrite_t,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
@ -698,6 +697,107 @@ pub type __wasi_timestamp_t = u64;
|
|||||||
pub type __wasi_userdata_t = u64;
|
pub type __wasi_userdata_t = u64;
|
||||||
|
|
||||||
pub type __wasi_whence_t = u8;
|
pub type __wasi_whence_t = u8;
|
||||||
pub const __WASI_WHENCE_CUR: u8 = 0;
|
pub const __WASI_WHENCE_SET: u8 = 0;
|
||||||
pub const __WASI_WHENCE_END: u8 = 1;
|
pub const __WASI_WHENCE_CUR: u8 = 1;
|
||||||
pub const __WASI_WHENCE_SET: u8 = 2;
|
pub const __WASI_WHENCE_END: u8 = 2;
|
||||||
|
|
||||||
|
pub mod snapshot0 {
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
pub type __wasi_linkcount_t = u32;
|
||||||
|
use wasmer_runtime_core::types::ValueType;
|
||||||
|
|
||||||
|
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct __wasi_subscription_clock_t {
|
||||||
|
pub userdata: super::__wasi_userdata_t,
|
||||||
|
pub clock_id: super::__wasi_clockid_t,
|
||||||
|
pub timeout: super::__wasi_timestamp_t,
|
||||||
|
pub precision: super::__wasi_timestamp_t,
|
||||||
|
pub flags: super::__wasi_subclockflags_t,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone)]
|
||||||
|
#[repr(C)]
|
||||||
|
pub union __wasi_subscription_u {
|
||||||
|
pub clock: __wasi_subscription_clock_t,
|
||||||
|
pub fd_readwrite: super::__wasi_subscription_fs_readwrite_t,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone)]
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct __wasi_subscription_t {
|
||||||
|
pub userdata: super::__wasi_userdata_t,
|
||||||
|
pub type_: super::__wasi_eventtype_t,
|
||||||
|
pub u: __wasi_subscription_u,
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe impl ValueType for __wasi_subscription_t {}
|
||||||
|
|
||||||
|
pub type __wasi_whence_t = u8;
|
||||||
|
pub const __WASI_WHENCE_CUR: u8 = 0;
|
||||||
|
pub const __WASI_WHENCE_END: u8 = 1;
|
||||||
|
pub const __WASI_WHENCE_SET: u8 = 2;
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct __wasi_filestat_t {
|
||||||
|
pub st_dev: super::__wasi_device_t,
|
||||||
|
pub st_ino: super::__wasi_inode_t,
|
||||||
|
pub st_filetype: super::__wasi_filetype_t,
|
||||||
|
pub st_nlink: __wasi_linkcount_t,
|
||||||
|
pub st_size: super::__wasi_filesize_t,
|
||||||
|
pub st_atim: super::__wasi_timestamp_t,
|
||||||
|
pub st_mtim: super::__wasi_timestamp_t,
|
||||||
|
pub st_ctim: super::__wasi_timestamp_t,
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe impl ValueType for __wasi_filestat_t {}
|
||||||
|
|
||||||
|
impl std::fmt::Debug for __wasi_filestat_t {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
let convert_ts_into_time_string = |ts| {
|
||||||
|
let tspec =
|
||||||
|
time::Timespec::new(ts as i64 / 1_000_000_000, (ts % 1_000_000_000) as i32);
|
||||||
|
let tm = time::at(tspec);
|
||||||
|
let out_time = tm.rfc822();
|
||||||
|
format!("{} ({})", out_time, ts)
|
||||||
|
};
|
||||||
|
f.debug_struct("__wasi_filestat_t")
|
||||||
|
.field("st_dev", &self.st_dev)
|
||||||
|
.field("st_ino", &self.st_ino)
|
||||||
|
.field(
|
||||||
|
"st_filetype",
|
||||||
|
&format!(
|
||||||
|
"{} ({})",
|
||||||
|
super::wasi_filetype_to_name(self.st_filetype),
|
||||||
|
self.st_filetype,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.field("st_nlink", &self.st_nlink)
|
||||||
|
.field("st_size", &self.st_size)
|
||||||
|
.field("st_atim", &convert_ts_into_time_string(self.st_atim))
|
||||||
|
.field("st_mtim", &convert_ts_into_time_string(self.st_mtim))
|
||||||
|
.field("st_ctim", &convert_ts_into_time_string(self.st_ctim))
|
||||||
|
.finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::fmt::Debug for __wasi_subscription_t {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
f.debug_struct("__wasi_subscription_t")
|
||||||
|
.field("userdata", &self.userdata)
|
||||||
|
.field("type", &super::eventtype_to_str(self.type_))
|
||||||
|
.field(
|
||||||
|
"u",
|
||||||
|
match self.type_ {
|
||||||
|
super::__WASI_EVENTTYPE_CLOCK => unsafe { &self.u.clock },
|
||||||
|
super::__WASI_EVENTTYPE_FD_READ | super::__WASI_EVENTTYPE_FD_WRITE => unsafe {
|
||||||
|
&self.u.fd_readwrite
|
||||||
|
},
|
||||||
|
_ => &"INVALID EVENTTYPE",
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1,18 +1,41 @@
|
|||||||
use wasmer_runtime_core::module::Module;
|
use wasmer_runtime_core::module::Module;
|
||||||
|
|
||||||
/// Check if a provided module is compiled with WASI support
|
#[allow(dead_code)]
|
||||||
|
/// Check if a provided module is compiled for some version of WASI.
|
||||||
|
/// Use [`get_wasi_version`] to find out which version of WASI the module is.
|
||||||
pub fn is_wasi_module(module: &Module) -> bool {
|
pub fn is_wasi_module(module: &Module) -> bool {
|
||||||
if module.info().imported_functions.is_empty() {
|
get_wasi_version(module).is_some()
|
||||||
return false;
|
}
|
||||||
}
|
|
||||||
for (_, import_name) in &module.info().imported_functions {
|
/// The version of WASI. This is determined by the namespace string
|
||||||
let namespace = module
|
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||||
.info()
|
pub enum WasiVersion {
|
||||||
.namespace_table
|
/// "wasi_unstable"
|
||||||
.get(import_name.namespace_index);
|
Snapshot0,
|
||||||
if namespace != "wasi_unstable" {
|
/// "wasi_snapshot_preview1"
|
||||||
return false;
|
Snapshot1,
|
||||||
}
|
}
|
||||||
}
|
|
||||||
true
|
/// Detect the version of WASI being used from the namespace
|
||||||
|
pub fn get_wasi_version(module: &Module) -> Option<WasiVersion> {
|
||||||
|
let mut import_iter = module
|
||||||
|
.info()
|
||||||
|
.imported_functions
|
||||||
|
.iter()
|
||||||
|
.map(|(_, import_name)| import_name.namespace_index);
|
||||||
|
|
||||||
|
// returns None if empty
|
||||||
|
let first = import_iter.next()?;
|
||||||
|
if import_iter.all(|idx| idx == first) {
|
||||||
|
// once we know that all the namespaces are the same, we can use it to
|
||||||
|
// detect which version of WASI this is
|
||||||
|
match module.info().namespace_table.get(first) {
|
||||||
|
"wasi_unstable" => Some(WasiVersion::Snapshot0),
|
||||||
|
"wasi_snapshot_preview1" => Some(WasiVersion::Snapshot1),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// not all funcs have the same namespace, therefore it's not WASI
|
||||||
|
None
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -26,7 +26,7 @@ use wasmer_clif_backend::CraneliftCompiler;
|
|||||||
use wasmer_llvm_backend::{LLVMCompiler, LLVMOptions};
|
use wasmer_llvm_backend::{LLVMCompiler, LLVMOptions};
|
||||||
use wasmer_runtime::{
|
use wasmer_runtime::{
|
||||||
cache::{Cache as BaseCache, FileSystemCache, WasmHash},
|
cache::{Cache as BaseCache, FileSystemCache, WasmHash},
|
||||||
Func, Value, VERSION,
|
Value, VERSION,
|
||||||
};
|
};
|
||||||
#[cfg(feature = "managed")]
|
#[cfg(feature = "managed")]
|
||||||
use wasmer_runtime_core::tiering::{run_tiering, InteractiveShellContext, ShellExitOperation};
|
use wasmer_runtime_core::tiering::{run_tiering, InteractiveShellContext, ShellExitOperation};
|
||||||
@ -41,25 +41,6 @@ use wasmer_singlepass_backend::SinglePassCompiler;
|
|||||||
#[cfg(feature = "wasi")]
|
#[cfg(feature = "wasi")]
|
||||||
use wasmer_wasi;
|
use wasmer_wasi;
|
||||||
|
|
||||||
// stub module to make conditional compilation happy
|
|
||||||
#[cfg(not(feature = "wasi"))]
|
|
||||||
mod wasmer_wasi {
|
|
||||||
use wasmer_runtime_core::{import::ImportObject, module::Module};
|
|
||||||
|
|
||||||
pub fn is_wasi_module(_module: &Module) -> bool {
|
|
||||||
false
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn generate_import_object(
|
|
||||||
_args: Vec<Vec<u8>>,
|
|
||||||
_envs: Vec<Vec<u8>>,
|
|
||||||
_preopened_files: Vec<std::path::PathBuf>,
|
|
||||||
_mapped_dirs: Vec<(String, std::path::PathBuf)>,
|
|
||||||
) -> ImportObject {
|
|
||||||
unimplemented!()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, StructOpt)]
|
#[derive(Debug, StructOpt)]
|
||||||
#[structopt(name = "wasmer", about = "Wasm execution runtime.", author)]
|
#[structopt(name = "wasmer", about = "Wasm execution runtime.", author)]
|
||||||
/// The options for the wasmer Command Line Interface
|
/// The options for the wasmer Command Line Interface
|
||||||
@ -335,6 +316,7 @@ fn get_mapped_dirs(input: &[String]) -> Result<Vec<(String, PathBuf)>, String> {
|
|||||||
Ok(md)
|
Ok(md)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "wasi")]
|
||||||
fn get_env_var_args(input: &[String]) -> Result<Vec<(&str, &str)>, String> {
|
fn get_env_var_args(input: &[String]) -> Result<Vec<(&str, &str)>, String> {
|
||||||
let mut ev = vec![];
|
let mut ev = vec![];
|
||||||
for entry in input.iter() {
|
for entry in input.iter() {
|
||||||
@ -350,11 +332,111 @@ fn get_env_var_args(input: &[String]) -> Result<Vec<(&str, &str)>, String> {
|
|||||||
Ok(ev)
|
Ok(ev)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Helper function for `execute_wasm` (the `Run` command)
|
||||||
|
#[cfg(feature = "wasi")]
|
||||||
|
fn execute_wasi(
|
||||||
|
wasi_version: wasmer_wasi::WasiVersion,
|
||||||
|
options: &Run,
|
||||||
|
env_vars: Vec<(&str, &str)>,
|
||||||
|
module: wasmer_runtime_core::Module,
|
||||||
|
mapped_dirs: Vec<(String, PathBuf)>,
|
||||||
|
) -> Result<(), String> {
|
||||||
|
let args = if let Some(cn) = &options.command_name {
|
||||||
|
[cn.clone()]
|
||||||
|
} else {
|
||||||
|
[options.path.to_str().unwrap().to_owned()]
|
||||||
|
}
|
||||||
|
.iter()
|
||||||
|
.chain(options.args.iter())
|
||||||
|
.cloned()
|
||||||
|
.map(|arg| arg.into_bytes())
|
||||||
|
.collect();
|
||||||
|
let envs = env_vars
|
||||||
|
.into_iter()
|
||||||
|
.map(|(k, v)| format!("{}={}", k, v).into_bytes())
|
||||||
|
.collect();
|
||||||
|
let preopened_files = options.pre_opened_directories.clone();
|
||||||
|
|
||||||
|
let import_object = wasmer_wasi::generate_import_object_for_version(
|
||||||
|
wasi_version,
|
||||||
|
args,
|
||||||
|
envs,
|
||||||
|
preopened_files,
|
||||||
|
mapped_dirs,
|
||||||
|
);
|
||||||
|
|
||||||
|
#[allow(unused_mut)] // mut used in feature
|
||||||
|
let mut instance = module
|
||||||
|
.instantiate(&import_object)
|
||||||
|
.map_err(|e| format!("Can't instantiate WASI module: {:?}", e))?;
|
||||||
|
|
||||||
|
let start: wasmer_runtime::Func<(), ()> =
|
||||||
|
instance.func("_start").map_err(|e| format!("{:?}", e))?;
|
||||||
|
|
||||||
|
#[cfg(feature = "managed")]
|
||||||
|
{
|
||||||
|
let start_raw: extern "C" fn(&mut wasmer_runtime_core::vm::Ctx) =
|
||||||
|
unsafe { ::std::mem::transmute(start.get_vm_func()) };
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
run_tiering(
|
||||||
|
module.info(),
|
||||||
|
&wasm_binary,
|
||||||
|
if let Some(ref path) = options.resume {
|
||||||
|
let mut f = File::open(path).unwrap();
|
||||||
|
let mut out: Vec<u8> = vec![];
|
||||||
|
f.read_to_end(&mut out).unwrap();
|
||||||
|
Some(
|
||||||
|
wasmer_runtime_core::state::InstanceImage::from_bytes(&out)
|
||||||
|
.expect("failed to decode image"),
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
},
|
||||||
|
&import_object,
|
||||||
|
start_raw,
|
||||||
|
&mut instance,
|
||||||
|
options
|
||||||
|
.optimized_backends
|
||||||
|
.iter()
|
||||||
|
.map(|&backend| -> Box<dyn Fn() -> Box<dyn Compiler> + Send> {
|
||||||
|
Box::new(move || get_compiler_by_backend(backend).unwrap())
|
||||||
|
})
|
||||||
|
.collect(),
|
||||||
|
interactive_shell,
|
||||||
|
)?
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(feature = "managed"))]
|
||||||
|
{
|
||||||
|
use wasmer_runtime::error::RuntimeError;
|
||||||
|
let result = start.call();
|
||||||
|
|
||||||
|
if let Err(ref err) = result {
|
||||||
|
match err {
|
||||||
|
RuntimeError::Trap { msg } => return Err(format!("wasm trap occured: {}", msg)),
|
||||||
|
#[cfg(feature = "wasi")]
|
||||||
|
RuntimeError::Error { data } => {
|
||||||
|
if let Some(error_code) = data.downcast_ref::<wasmer_wasi::ExitCode>() {
|
||||||
|
std::process::exit(error_code.code as i32)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#[cfg(not(feature = "wasi"))]
|
||||||
|
RuntimeError::Error { .. } => (),
|
||||||
|
}
|
||||||
|
return Err(format!("error: {:?}", err));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
/// Execute a wasm/wat file
|
/// Execute a wasm/wat file
|
||||||
fn execute_wasm(options: &Run) -> Result<(), String> {
|
fn execute_wasm(options: &Run) -> Result<(), String> {
|
||||||
let disable_cache = options.disable_cache;
|
let disable_cache = options.disable_cache;
|
||||||
|
|
||||||
let mapped_dirs = get_mapped_dirs(&options.mapped_dirs[..])?;
|
let mapped_dirs = get_mapped_dirs(&options.mapped_dirs[..])?;
|
||||||
|
#[cfg(feature = "wasi")]
|
||||||
let env_vars = get_env_var_args(&options.env_vars[..])?;
|
let env_vars = get_env_var_args(&options.env_vars[..])?;
|
||||||
let wasm_path = &options.path;
|
let wasm_path = &options.path;
|
||||||
|
|
||||||
@ -595,90 +677,22 @@ fn execute_wasm(options: &Run) -> Result<(), String> {
|
|||||||
)
|
)
|
||||||
.map_err(|e| format!("{:?}", e))?;
|
.map_err(|e| format!("{:?}", e))?;
|
||||||
} else {
|
} else {
|
||||||
if cfg!(feature = "wasi") && wasmer_wasi::is_wasi_module(&module) {
|
#[cfg(feature = "wasi")]
|
||||||
let import_object = wasmer_wasi::generate_import_object(
|
let wasi_version = wasmer_wasi::get_wasi_version(&module);
|
||||||
if let Some(cn) = &options.command_name {
|
#[cfg(feature = "wasi")]
|
||||||
[cn.clone()]
|
let is_wasi = wasi_version.is_some();
|
||||||
} else {
|
#[cfg(not(feature = "wasi"))]
|
||||||
[options.path.to_str().unwrap().to_owned()]
|
let is_wasi = false;
|
||||||
}
|
|
||||||
.iter()
|
if is_wasi {
|
||||||
.chain(options.args.iter())
|
#[cfg(feature = "wasi")]
|
||||||
.cloned()
|
execute_wasi(
|
||||||
.map(|arg| arg.into_bytes())
|
wasi_version.unwrap(),
|
||||||
.collect(),
|
options,
|
||||||
env_vars
|
env_vars,
|
||||||
.into_iter()
|
module,
|
||||||
.map(|(k, v)| format!("{}={}", k, v).into_bytes())
|
|
||||||
.collect(),
|
|
||||||
options.pre_opened_directories.clone(),
|
|
||||||
mapped_dirs,
|
mapped_dirs,
|
||||||
);
|
)?;
|
||||||
|
|
||||||
#[allow(unused_mut)] // mut used in feature
|
|
||||||
let mut instance = module
|
|
||||||
.instantiate(&import_object)
|
|
||||||
.map_err(|e| format!("Can't instantiate WASI module: {:?}", e))?;
|
|
||||||
|
|
||||||
let start: Func<(), ()> = instance.func("_start").map_err(|e| format!("{:?}", e))?;
|
|
||||||
|
|
||||||
#[cfg(feature = "managed")]
|
|
||||||
{
|
|
||||||
let start_raw: extern "C" fn(&mut wasmer_runtime_core::vm::Ctx) =
|
|
||||||
unsafe { ::std::mem::transmute(start.get_vm_func()) };
|
|
||||||
|
|
||||||
unsafe {
|
|
||||||
run_tiering(
|
|
||||||
module.info(),
|
|
||||||
&wasm_binary,
|
|
||||||
if let Some(ref path) = options.resume {
|
|
||||||
let mut f = File::open(path).unwrap();
|
|
||||||
let mut out: Vec<u8> = vec![];
|
|
||||||
f.read_to_end(&mut out).unwrap();
|
|
||||||
Some(
|
|
||||||
wasmer_runtime_core::state::InstanceImage::from_bytes(&out)
|
|
||||||
.expect("failed to decode image"),
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
},
|
|
||||||
&import_object,
|
|
||||||
start_raw,
|
|
||||||
&mut instance,
|
|
||||||
options
|
|
||||||
.optimized_backends
|
|
||||||
.iter()
|
|
||||||
.map(|&backend| -> Box<dyn Fn() -> Box<dyn Compiler> + Send> {
|
|
||||||
Box::new(move || get_compiler_by_backend(backend).unwrap())
|
|
||||||
})
|
|
||||||
.collect(),
|
|
||||||
interactive_shell,
|
|
||||||
)?
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(not(feature = "managed"))]
|
|
||||||
{
|
|
||||||
use wasmer_runtime::error::RuntimeError;
|
|
||||||
let result = start.call();
|
|
||||||
|
|
||||||
if let Err(ref err) = result {
|
|
||||||
match err {
|
|
||||||
RuntimeError::Trap { msg } => {
|
|
||||||
return Err(format!("wasm trap occured: {}", msg))
|
|
||||||
}
|
|
||||||
#[cfg(feature = "wasi")]
|
|
||||||
RuntimeError::Error { data } => {
|
|
||||||
if let Some(error_code) = data.downcast_ref::<wasmer_wasi::ExitCode>() {
|
|
||||||
std::process::exit(error_code.code as i32)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#[cfg(not(feature = "wasi"))]
|
|
||||||
RuntimeError::Error { .. } => (),
|
|
||||||
}
|
|
||||||
return Err(format!("error: {:?}", err));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
let import_object = wasmer_runtime_core::import::ImportObject::new();
|
let import_object = wasmer_runtime_core::import::ImportObject::new();
|
||||||
let instance = module
|
let instance = module
|
||||||
|
Loading…
Reference in New Issue
Block a user