Fail with Trap in Instance::new() instead of Error (#683)
This commit is contained in:
@@ -7,7 +7,7 @@ use wasmtime::*;
|
|||||||
struct HelloCallback;
|
struct HelloCallback;
|
||||||
|
|
||||||
impl Callable for HelloCallback {
|
impl Callable for HelloCallback {
|
||||||
fn call(&self, _params: &[Val], _results: &mut [Val]) -> Result<(), HostRef<Trap>> {
|
fn call(&self, _params: &[Val], _results: &mut [Val]) -> Result<(), Trap> {
|
||||||
println!("Calling back...");
|
println!("Calling back...");
|
||||||
println!("> Hello World!");
|
println!("> Hello World!");
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ use wasmtime::*;
|
|||||||
struct Callback;
|
struct Callback;
|
||||||
|
|
||||||
impl Callable for Callback {
|
impl Callable for Callback {
|
||||||
fn call(&self, args: &[Val], results: &mut [Val]) -> Result<(), HostRef<Trap>> {
|
fn call(&self, args: &[Val], results: &mut [Val]) -> Result<(), Trap> {
|
||||||
println!("Calling back...");
|
println!("Calling back...");
|
||||||
println!("> {} {}", args[0].unwrap_i32(), args[1].unwrap_i64());
|
println!("> {} {}", args[0].unwrap_i32(), args[1].unwrap_i64());
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
use crate::r#ref::HostRef;
|
use crate::r#ref::HostRef;
|
||||||
use crate::runtime::Store;
|
use crate::runtime::Store;
|
||||||
use crate::trampoline::{generate_func_export, take_api_trap};
|
use crate::trampoline::{generate_func_export, take_api_trap};
|
||||||
use crate::trap::Trap;
|
use crate::trap::{Trap, TrapInfo};
|
||||||
use crate::types::FuncType;
|
use crate::types::FuncType;
|
||||||
use crate::values::Val;
|
use crate::values::Val;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
@@ -18,7 +18,7 @@ use wasmtime_runtime::Export;
|
|||||||
/// struct TimesTwo;
|
/// struct TimesTwo;
|
||||||
///
|
///
|
||||||
/// impl wasmtime::Callable for TimesTwo {
|
/// impl wasmtime::Callable for TimesTwo {
|
||||||
/// fn call(&self, params: &[Val], results: &mut [Val]) -> Result<(), HostRef<wasmtime::Trap>> {
|
/// fn call(&self, params: &[Val], results: &mut [Val]) -> Result<(), wasmtime::Trap> {
|
||||||
/// let mut value = params[0].unwrap_i32();
|
/// let mut value = params[0].unwrap_i32();
|
||||||
/// value *= 2;
|
/// value *= 2;
|
||||||
/// results[0] = value.into();
|
/// results[0] = value.into();
|
||||||
@@ -75,7 +75,7 @@ use wasmtime_runtime::Export;
|
|||||||
/// let results = run_function
|
/// let results = run_function
|
||||||
/// .borrow()
|
/// .borrow()
|
||||||
/// .call(&[original.into()])
|
/// .call(&[original.into()])
|
||||||
/// .map_err(|trap| trap.borrow().to_string())?;
|
/// .map_err(|trap| trap.to_string())?;
|
||||||
///
|
///
|
||||||
/// // Compare that the results returned matches what we expect.
|
/// // Compare that the results returned matches what we expect.
|
||||||
/// assert_eq!(original * 2, results[0].unwrap_i32());
|
/// assert_eq!(original * 2, results[0].unwrap_i32());
|
||||||
@@ -87,11 +87,11 @@ pub trait Callable {
|
|||||||
/// `params` is an immutable list of parameters provided to the function.
|
/// `params` is an immutable list of parameters provided to the function.
|
||||||
/// `results` is mutable list of results to be potentially set by your
|
/// `results` is mutable list of results to be potentially set by your
|
||||||
/// function. Produces a `Trap` if the function encounters any errors.
|
/// function. Produces a `Trap` if the function encounters any errors.
|
||||||
fn call(&self, params: &[Val], results: &mut [Val]) -> Result<(), HostRef<Trap>>;
|
fn call(&self, params: &[Val], results: &mut [Val]) -> Result<(), Trap>;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) trait WrappedCallable {
|
pub(crate) trait WrappedCallable {
|
||||||
fn call(&self, params: &[Val], results: &mut [Val]) -> Result<(), HostRef<Trap>>;
|
fn call(&self, params: &[Val], results: &mut [Val]) -> Result<(), Trap>;
|
||||||
fn signature(&self) -> &ir::Signature {
|
fn signature(&self) -> &ir::Signature {
|
||||||
match self.wasmtime_export() {
|
match self.wasmtime_export() {
|
||||||
Export::Function { signature, .. } => signature,
|
Export::Function { signature, .. } => signature,
|
||||||
@@ -119,7 +119,7 @@ impl WasmtimeFn {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl WrappedCallable for WasmtimeFn {
|
impl WrappedCallable for WasmtimeFn {
|
||||||
fn call(&self, params: &[Val], results: &mut [Val]) -> Result<(), HostRef<Trap>> {
|
fn call(&self, params: &[Val], results: &mut [Val]) -> Result<(), Trap> {
|
||||||
use std::cmp::max;
|
use std::cmp::max;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
|
|
||||||
@@ -150,7 +150,7 @@ impl WrappedCallable for WasmtimeFn {
|
|||||||
.context()
|
.context()
|
||||||
.compiler()
|
.compiler()
|
||||||
.get_published_trampoline(body, &signature, value_size)
|
.get_published_trampoline(body, &signature, value_size)
|
||||||
.map_err(|_| HostRef::new(Trap::fake()))?; //was ActionError::Setup)?;
|
.map_err(|e| Trap::new(format!("trampoline error: {:?}", e)))?;
|
||||||
|
|
||||||
// Call the trampoline.
|
// Call the trampoline.
|
||||||
if let Err(message) = unsafe {
|
if let Err(message) = unsafe {
|
||||||
@@ -160,8 +160,9 @@ impl WrappedCallable for WasmtimeFn {
|
|||||||
values_vec.as_mut_ptr() as *mut u8,
|
values_vec.as_mut_ptr() as *mut u8,
|
||||||
)
|
)
|
||||||
} {
|
} {
|
||||||
let trap = take_api_trap().unwrap_or_else(|| HostRef::new(Trap::new(message)));
|
let trap = take_api_trap()
|
||||||
return Err(trap);
|
.unwrap_or_else(|| HostRef::new(TrapInfo::new(format!("call error: {}", message))));
|
||||||
|
return Err(trap.into());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load the return values out of `values_vec`.
|
// Load the return values out of `values_vec`.
|
||||||
@@ -206,7 +207,7 @@ impl NativeCallable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl WrappedCallable for NativeCallable {
|
impl WrappedCallable for NativeCallable {
|
||||||
fn call(&self, params: &[Val], results: &mut [Val]) -> Result<(), HostRef<Trap>> {
|
fn call(&self, params: &[Val], results: &mut [Val]) -> Result<(), Trap> {
|
||||||
self.callable.call(params, results)
|
self.callable.call(params, results)
|
||||||
}
|
}
|
||||||
fn wasmtime_handle(&self) -> &InstanceHandle {
|
fn wasmtime_handle(&self) -> &InstanceHandle {
|
||||||
|
|||||||
@@ -147,7 +147,7 @@ impl Func {
|
|||||||
self.r#type.results().len()
|
self.r#type.results().len()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn call(&self, params: &[Val]) -> Result<Box<[Val]>, HostRef<Trap>> {
|
pub fn call(&self, params: &[Val]) -> Result<Box<[Val]>, Trap> {
|
||||||
let mut results = vec![Val::null(); self.result_arity()];
|
let mut results = vec![Val::null(); self.result_arity()];
|
||||||
self.callable.call(params, &mut results)?;
|
self.callable.call(params, &mut results)?;
|
||||||
Ok(results.into_boxed_slice())
|
Ok(results.into_boxed_slice())
|
||||||
|
|||||||
@@ -4,8 +4,9 @@ use crate::module::Module;
|
|||||||
use crate::r#ref::HostRef;
|
use crate::r#ref::HostRef;
|
||||||
use crate::runtime::Store;
|
use crate::runtime::Store;
|
||||||
use crate::trampoline::take_api_trap;
|
use crate::trampoline::take_api_trap;
|
||||||
|
use crate::trap::Trap;
|
||||||
use crate::types::{ExportType, ExternType};
|
use crate::types::{ExportType, ExternType};
|
||||||
use anyhow::Result;
|
use anyhow::{Error, Result};
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::collections::{HashMap, HashSet};
|
use std::collections::{HashMap, HashSet};
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
@@ -31,7 +32,7 @@ pub fn instantiate_in_context(
|
|||||||
imports: Vec<(String, String, Extern)>,
|
imports: Vec<(String, String, Extern)>,
|
||||||
mut context: Context,
|
mut context: Context,
|
||||||
exports: Rc<RefCell<HashMap<String, Option<wasmtime_runtime::Export>>>>,
|
exports: Rc<RefCell<HashMap<String, Option<wasmtime_runtime::Export>>>>,
|
||||||
) -> Result<(InstanceHandle, HashSet<Context>)> {
|
) -> Result<(InstanceHandle, HashSet<Context>), Error> {
|
||||||
let mut contexts = HashSet::new();
|
let mut contexts = HashSet::new();
|
||||||
let debug_info = context.debug_info();
|
let debug_info = context.debug_info();
|
||||||
let mut resolver = SimpleResolver { imports };
|
let mut resolver = SimpleResolver { imports };
|
||||||
@@ -42,10 +43,12 @@ pub fn instantiate_in_context(
|
|||||||
exports,
|
exports,
|
||||||
debug_info,
|
debug_info,
|
||||||
)
|
)
|
||||||
.map_err(|e| {
|
.map_err(|e| -> Error {
|
||||||
// TODO wrap HostRef<Trap> into Error
|
if let Some(trap) = take_api_trap() {
|
||||||
drop(take_api_trap());
|
Trap::from(trap).into()
|
||||||
e
|
} else {
|
||||||
|
e.into()
|
||||||
|
}
|
||||||
})?;
|
})?;
|
||||||
contexts.insert(context);
|
contexts.insert(context);
|
||||||
Ok((instance, contexts))
|
Ok((instance, contexts))
|
||||||
@@ -68,7 +71,7 @@ impl Instance {
|
|||||||
store: &HostRef<Store>,
|
store: &HostRef<Store>,
|
||||||
module: &HostRef<Module>,
|
module: &HostRef<Module>,
|
||||||
externs: &[Extern],
|
externs: &[Extern],
|
||||||
) -> Result<Instance> {
|
) -> Result<Instance, Error> {
|
||||||
let context = store.borrow_mut().context().clone();
|
let context = store.borrow_mut().context().clone();
|
||||||
let exports = store.borrow_mut().global_exports().clone();
|
let exports = store.borrow_mut().global_exports().clone();
|
||||||
let imports = module
|
let imports = module
|
||||||
|
|||||||
@@ -28,6 +28,6 @@ pub use crate::instance::Instance;
|
|||||||
pub use crate::module::Module;
|
pub use crate::module::Module;
|
||||||
pub use crate::r#ref::{AnyRef, HostInfo, HostRef};
|
pub use crate::r#ref::{AnyRef, HostInfo, HostRef};
|
||||||
pub use crate::runtime::{Config, Engine, Store};
|
pub use crate::runtime::{Config, Engine, Store};
|
||||||
pub use crate::trap::Trap;
|
pub use crate::trap::{FrameInfo, Trap, TrapInfo};
|
||||||
pub use crate::types::*;
|
pub use crate::types::*;
|
||||||
pub use crate::values::*;
|
pub use crate::values::*;
|
||||||
|
|||||||
@@ -96,6 +96,7 @@ unsafe extern "C" fn stub_fn(vmctx: *mut VMContext, call_id: u32, values_vec: *m
|
|||||||
0
|
0
|
||||||
}
|
}
|
||||||
Err(trap) => {
|
Err(trap) => {
|
||||||
|
let trap = trap.trap_info_unchecked();
|
||||||
record_api_trap(trap);
|
record_api_trap(trap);
|
||||||
1
|
1
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
use std::cell::Cell;
|
use std::cell::Cell;
|
||||||
|
|
||||||
use crate::r#ref::HostRef;
|
use crate::r#ref::HostRef;
|
||||||
use crate::Trap;
|
use crate::TrapInfo;
|
||||||
use wasmtime_environ::ir::{SourceLoc, TrapCode};
|
use wasmtime_environ::ir::{SourceLoc, TrapCode};
|
||||||
use wasmtime_environ::TrapInformation;
|
use wasmtime_environ::TrapInformation;
|
||||||
use wasmtime_jit::trampoline::binemit;
|
use wasmtime_jit::trampoline::binemit;
|
||||||
@@ -10,10 +10,10 @@ use wasmtime_jit::trampoline::binemit;
|
|||||||
pub const API_TRAP_CODE: TrapCode = TrapCode::User(13);
|
pub const API_TRAP_CODE: TrapCode = TrapCode::User(13);
|
||||||
|
|
||||||
thread_local! {
|
thread_local! {
|
||||||
static RECORDED_API_TRAP: Cell<Option<HostRef<Trap>>> = Cell::new(None);
|
static RECORDED_API_TRAP: Cell<Option<HostRef<TrapInfo>>> = Cell::new(None);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn record_api_trap(trap: HostRef<Trap>) {
|
pub fn record_api_trap(trap: HostRef<TrapInfo>) {
|
||||||
RECORDED_API_TRAP.with(|data| {
|
RECORDED_API_TRAP.with(|data| {
|
||||||
let trap = Cell::new(Some(trap));
|
let trap = Cell::new(Some(trap));
|
||||||
data.swap(&trap);
|
data.swap(&trap);
|
||||||
@@ -24,7 +24,7 @@ pub fn record_api_trap(trap: HostRef<Trap>) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn take_api_trap() -> Option<HostRef<Trap>> {
|
pub fn take_api_trap() -> Option<HostRef<TrapInfo>> {
|
||||||
RECORDED_API_TRAP.with(|data| data.take())
|
RECORDED_API_TRAP.with(|data| data.take())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,88 @@
|
|||||||
|
use crate::instance::Instance;
|
||||||
|
use crate::r#ref::HostRef;
|
||||||
|
use std::fmt;
|
||||||
|
use std::sync::{Arc, Mutex};
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct FrameInfo;
|
||||||
|
|
||||||
|
impl FrameInfo {
|
||||||
|
pub fn instance(&self) -> *const Instance {
|
||||||
|
unimplemented!("FrameInfo::instance");
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn func_index() -> usize {
|
||||||
|
unimplemented!("FrameInfo::func_index");
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn func_offset() -> usize {
|
||||||
|
unimplemented!("FrameInfo::func_offset");
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn module_offset() -> usize {
|
||||||
|
unimplemented!("FrameInfo::module_offset");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct TrapInfo {
|
||||||
|
message: String,
|
||||||
|
trace: Vec<FrameInfo>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TrapInfo {
|
||||||
|
pub fn new<I: Into<String>>(message: I) -> Self {
|
||||||
|
Self {
|
||||||
|
message: message.into(),
|
||||||
|
trace: vec![],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns a reference the `message` stored in `Trap`.
|
||||||
|
pub fn message(&self) -> &str {
|
||||||
|
&self.message
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn origin(&self) -> Option<&FrameInfo> {
|
||||||
|
self.trace.first()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn trace(&self) -> &[FrameInfo] {
|
||||||
|
&self.trace
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A struct to hold unsafe TrapInfo host reference, designed
|
||||||
|
/// to be Send-able. The only access for it provided via the
|
||||||
|
/// Trap::trap_info_unchecked() method.
|
||||||
|
struct UnsafeTrapInfo(HostRef<TrapInfo>);
|
||||||
|
|
||||||
|
impl UnsafeTrapInfo {
|
||||||
|
fn trap_info(&self) -> HostRef<TrapInfo> {
|
||||||
|
self.0.clone()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe impl Send for UnsafeTrapInfo {}
|
||||||
|
|
||||||
|
impl fmt::Debug for UnsafeTrapInfo {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
write!(f, "UnsafeTrapInfo")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// A struct representing an aborted instruction execution, with a message
|
/// A struct representing an aborted instruction execution, with a message
|
||||||
/// indicating the cause.
|
/// indicating the cause.
|
||||||
#[derive(Error, Debug)]
|
#[derive(Error, Debug)]
|
||||||
#[error("Wasm trap: {message}")]
|
#[error("Wasm trap: {message}")]
|
||||||
pub struct Trap {
|
pub struct Trap {
|
||||||
message: String,
|
message: String,
|
||||||
|
info: Arc<Mutex<UnsafeTrapInfo>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn _assert_trap_is_sync_and_send(t: &Trap) -> (&dyn Sync, &dyn Send) {
|
||||||
|
(t, t)
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Trap {
|
impl Trap {
|
||||||
@@ -15,20 +92,26 @@ impl Trap {
|
|||||||
/// let trap = wasmtime::Trap::new("unexpected error");
|
/// let trap = wasmtime::Trap::new("unexpected error");
|
||||||
/// assert_eq!("unexpected error", trap.message());
|
/// assert_eq!("unexpected error", trap.message());
|
||||||
/// ```
|
/// ```
|
||||||
pub fn new<I: Into<String>>(message: I) -> Trap {
|
pub fn new<I: Into<String>>(message: I) -> Self {
|
||||||
Self {
|
Trap::from(HostRef::new(TrapInfo::new(message)))
|
||||||
message: message.into(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Create a `Trap` without defining a message for the trap. Mostly useful
|
|
||||||
/// for prototypes and tests.
|
|
||||||
pub fn fake() -> Trap {
|
|
||||||
Self::new("TODO trap")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a reference the `message` stored in `Trap`.
|
/// Returns a reference the `message` stored in `Trap`.
|
||||||
pub fn message(&self) -> &str {
|
pub fn message(&self) -> &str {
|
||||||
&self.message
|
&self.message
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns inner TrapInfo assotiated with the Trap.
|
||||||
|
/// The method is unsafe: obtained TrapInfo is not thread safe.
|
||||||
|
pub(crate) unsafe fn trap_info_unchecked(&self) -> HostRef<TrapInfo> {
|
||||||
|
self.info.lock().unwrap().trap_info()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<HostRef<TrapInfo>> for Trap {
|
||||||
|
fn from(trap_info: HostRef<TrapInfo>) -> Self {
|
||||||
|
let message = trap_info.borrow().message().to_string();
|
||||||
|
let info = Arc::new(Mutex::new(UnsafeTrapInfo(trap_info)));
|
||||||
|
Trap { message, info }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
use super::{
|
use super::{
|
||||||
AnyRef, Callable, Engine, ExportType, Extern, ExternType, Func, FuncType, Global, GlobalType,
|
AnyRef, Callable, Engine, ExportType, Extern, ExternType, Func, FuncType, Global, GlobalType,
|
||||||
HostInfo, HostRef, ImportType, Instance, Limits, Memory, MemoryType, Module, Store, Table,
|
HostInfo, HostRef, ImportType, Instance, Limits, Memory, MemoryType, Module, Store, Table,
|
||||||
TableType, Trap, Val, ValType,
|
TableType, Trap, TrapInfo, Val, ValType,
|
||||||
};
|
};
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use std::{mem, ptr, slice};
|
use std::{mem, ptr, slice};
|
||||||
@@ -317,7 +317,7 @@ pub type wasm_message_t = wasm_name_t;
|
|||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct wasm_trap_t {
|
pub struct wasm_trap_t {
|
||||||
trap: HostRef<Trap>,
|
trap_info: HostRef<TrapInfo>,
|
||||||
}
|
}
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
@@ -469,7 +469,8 @@ pub unsafe extern "C" fn wasm_func_call(
|
|||||||
ptr::null_mut()
|
ptr::null_mut()
|
||||||
}
|
}
|
||||||
Err(trap) => {
|
Err(trap) => {
|
||||||
let trap = Box::new(wasm_trap_t { trap });
|
let trap_info = trap.trap_info_unchecked();
|
||||||
|
let trap = Box::new(wasm_trap_t { trap_info });
|
||||||
Box::into_raw(trap)
|
Box::into_raw(trap)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -539,7 +540,7 @@ impl wasm_val_t {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Callable for wasm_func_callback_t {
|
impl Callable for wasm_func_callback_t {
|
||||||
fn call(&self, params: &[Val], results: &mut [Val]) -> Result<(), HostRef<Trap>> {
|
fn call(&self, params: &[Val], results: &mut [Val]) -> Result<(), Trap> {
|
||||||
let params = params
|
let params = params
|
||||||
.iter()
|
.iter()
|
||||||
.map(|p| wasm_val_t::from_val(p))
|
.map(|p| wasm_val_t::from_val(p))
|
||||||
@@ -549,7 +550,8 @@ impl Callable for wasm_func_callback_t {
|
|||||||
let out = unsafe { func(params.as_ptr(), out_results.as_mut_ptr()) };
|
let out = unsafe { func(params.as_ptr(), out_results.as_mut_ptr()) };
|
||||||
if !out.is_null() {
|
if !out.is_null() {
|
||||||
let trap: Box<wasm_trap_t> = unsafe { Box::from_raw(out) };
|
let trap: Box<wasm_trap_t> = unsafe { Box::from_raw(out) };
|
||||||
return Err((*trap).into());
|
let trap_info: HostRef<TrapInfo> = (*trap).into();
|
||||||
|
return Err(Trap::from(trap_info));
|
||||||
}
|
}
|
||||||
for i in 0..results.len() {
|
for i in 0..results.len() {
|
||||||
results[i] = out_results[i].val();
|
results[i] = out_results[i].val();
|
||||||
@@ -558,9 +560,9 @@ impl Callable for wasm_func_callback_t {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Into<HostRef<Trap>> for wasm_trap_t {
|
impl Into<HostRef<TrapInfo>> for wasm_trap_t {
|
||||||
fn into(self) -> HostRef<Trap> {
|
fn into(self) -> HostRef<TrapInfo> {
|
||||||
self.trap
|
self.trap_info
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -571,7 +573,7 @@ struct CallbackWithEnv {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Callable for CallbackWithEnv {
|
impl Callable for CallbackWithEnv {
|
||||||
fn call(&self, params: &[Val], results: &mut [Val]) -> Result<(), HostRef<Trap>> {
|
fn call(&self, params: &[Val], results: &mut [Val]) -> Result<(), Trap> {
|
||||||
let params = params
|
let params = params
|
||||||
.iter()
|
.iter()
|
||||||
.map(|p| wasm_val_t::from_val(p))
|
.map(|p| wasm_val_t::from_val(p))
|
||||||
@@ -581,7 +583,8 @@ impl Callable for CallbackWithEnv {
|
|||||||
let out = unsafe { func(self.env, params.as_ptr(), out_results.as_mut_ptr()) };
|
let out = unsafe { func(self.env, params.as_ptr(), out_results.as_mut_ptr()) };
|
||||||
if !out.is_null() {
|
if !out.is_null() {
|
||||||
let trap: Box<wasm_trap_t> = unsafe { Box::from_raw(out) };
|
let trap: Box<wasm_trap_t> = unsafe { Box::from_raw(out) };
|
||||||
return Err((*trap).into());
|
let trap_info: HostRef<TrapInfo> = (*trap).into();
|
||||||
|
return Err(Trap::from(trap_info));
|
||||||
}
|
}
|
||||||
for i in 0..results.len() {
|
for i in 0..results.len() {
|
||||||
results[i] = out_results[i].val();
|
results[i] = out_results[i].val();
|
||||||
@@ -677,12 +680,13 @@ pub unsafe extern "C" fn wasm_instance_new(
|
|||||||
}
|
}
|
||||||
Box::into_raw(instance)
|
Box::into_raw(instance)
|
||||||
}
|
}
|
||||||
Err(_) => {
|
Err(trap) => {
|
||||||
if !result.is_null() {
|
if !result.is_null() {
|
||||||
// TODO Unwrap trap from error
|
let trap_info = match trap.downcast::<Trap>() {
|
||||||
let trap = Box::new(wasm_trap_t {
|
Ok(trap) => trap.trap_info_unchecked(),
|
||||||
trap: HostRef::new(Trap::new("trap during instantiation".to_string())),
|
Err(_) => HostRef::new(TrapInfo::new("instance error".to_string())),
|
||||||
});
|
};
|
||||||
|
let trap = Box::new(wasm_trap_t { trap_info });
|
||||||
(*result) = Box::into_raw(trap);
|
(*result) = Box::into_raw(trap);
|
||||||
}
|
}
|
||||||
ptr::null_mut()
|
ptr::null_mut()
|
||||||
@@ -925,7 +929,7 @@ pub unsafe extern "C" fn wasm_trap_new(
|
|||||||
}
|
}
|
||||||
let message = String::from_utf8_lossy(message).to_string();
|
let message = String::from_utf8_lossy(message).to_string();
|
||||||
let trap = Box::new(wasm_trap_t {
|
let trap = Box::new(wasm_trap_t {
|
||||||
trap: HostRef::new(Trap::new(message)),
|
trap_info: HostRef::new(TrapInfo::new(message)),
|
||||||
});
|
});
|
||||||
Box::into_raw(trap)
|
Box::into_raw(trap)
|
||||||
}
|
}
|
||||||
@@ -933,7 +937,7 @@ pub unsafe extern "C" fn wasm_trap_new(
|
|||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn wasm_trap_message(trap: *const wasm_trap_t, out: *mut wasm_message_t) {
|
pub unsafe extern "C" fn wasm_trap_message(trap: *const wasm_trap_t, out: *mut wasm_message_t) {
|
||||||
let mut buffer = Vec::new();
|
let mut buffer = Vec::new();
|
||||||
buffer.extend_from_slice((*trap).trap.borrow().message().as_bytes());
|
buffer.extend_from_slice((*trap).trap_info.borrow().message().as_bytes());
|
||||||
buffer.reserve_exact(1);
|
buffer.reserve_exact(1);
|
||||||
buffer.push(0);
|
buffer.push(0);
|
||||||
(*out).set_buffer(buffer);
|
(*out).set_buffer(buffer);
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ fn test_import_calling_export() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Callable for Callback {
|
impl Callable for Callback {
|
||||||
fn call(&self, _params: &[Val], _results: &mut [Val]) -> Result<(), HostRef<Trap>> {
|
fn call(&self, _params: &[Val], _results: &mut [Val]) -> Result<(), Trap> {
|
||||||
self.other
|
self.other
|
||||||
.borrow()
|
.borrow()
|
||||||
.as_ref()
|
.as_ref()
|
||||||
|
|||||||
@@ -7,8 +7,8 @@ fn test_trap_return() -> Result<(), String> {
|
|||||||
struct HelloCallback;
|
struct HelloCallback;
|
||||||
|
|
||||||
impl Callable for HelloCallback {
|
impl Callable for HelloCallback {
|
||||||
fn call(&self, _params: &[Val], _results: &mut [Val]) -> Result<(), HostRef<Trap>> {
|
fn call(&self, _params: &[Val], _results: &mut [Val]) -> Result<(), Trap> {
|
||||||
Err(HostRef::new(Trap::new("test 123")))
|
Err(Trap::new("test 123"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -32,7 +32,7 @@ fn test_trap_return() -> Result<(), String> {
|
|||||||
|
|
||||||
let imports = vec![hello_func.into()];
|
let imports = vec![hello_func.into()];
|
||||||
let instance = Instance::new(&store, &module, imports.as_slice())
|
let instance = Instance::new(&store, &module, imports.as_slice())
|
||||||
.map_err(|e| format!("failed to instantiate module: {}", e))?;
|
.map_err(|e| format!("failed to instantiate module: {:?}", e))?;
|
||||||
let run_func = instance.exports()[0]
|
let run_func = instance.exports()[0]
|
||||||
.func()
|
.func()
|
||||||
.expect("expected function export");
|
.expect("expected function export");
|
||||||
@@ -43,7 +43,7 @@ fn test_trap_return() -> Result<(), String> {
|
|||||||
.err()
|
.err()
|
||||||
.expect("error calling function");
|
.expect("error calling function");
|
||||||
|
|
||||||
assert_eq!(e.borrow().message(), "test 123");
|
assert_eq!(e.message(), "test 123");
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ use wasmtime::{
|
|||||||
pub fn dummy_imports(
|
pub fn dummy_imports(
|
||||||
store: &HostRef<Store>,
|
store: &HostRef<Store>,
|
||||||
import_tys: &[ImportType],
|
import_tys: &[ImportType],
|
||||||
) -> Result<Vec<Extern>, HostRef<Trap>> {
|
) -> Result<Vec<Extern>, Trap> {
|
||||||
let mut imports = Vec::with_capacity(import_tys.len());
|
let mut imports = Vec::with_capacity(import_tys.len());
|
||||||
for imp in import_tys {
|
for imp in import_tys {
|
||||||
imports.push(match imp.ty() {
|
imports.push(match imp.ty() {
|
||||||
@@ -45,7 +45,7 @@ impl DummyFunc {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Callable for DummyFunc {
|
impl Callable for DummyFunc {
|
||||||
fn call(&self, _params: &[Val], results: &mut [Val]) -> Result<(), HostRef<Trap>> {
|
fn call(&self, _params: &[Val], results: &mut [Val]) -> Result<(), Trap> {
|
||||||
for (ret_ty, result) in self.0.results().iter().zip(results) {
|
for (ret_ty, result) in self.0.results().iter().zip(results) {
|
||||||
*result = dummy_value(ret_ty)?;
|
*result = dummy_value(ret_ty)?;
|
||||||
}
|
}
|
||||||
@@ -55,38 +55,38 @@ impl Callable for DummyFunc {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Construct a dummy value for the given value type.
|
/// Construct a dummy value for the given value type.
|
||||||
pub fn dummy_value(val_ty: &ValType) -> Result<Val, HostRef<Trap>> {
|
pub fn dummy_value(val_ty: &ValType) -> Result<Val, Trap> {
|
||||||
Ok(match val_ty {
|
Ok(match val_ty {
|
||||||
ValType::I32 => Val::I32(0),
|
ValType::I32 => Val::I32(0),
|
||||||
ValType::I64 => Val::I64(0),
|
ValType::I64 => Val::I64(0),
|
||||||
ValType::F32 => Val::F32(0),
|
ValType::F32 => Val::F32(0),
|
||||||
ValType::F64 => Val::F64(0),
|
ValType::F64 => Val::F64(0),
|
||||||
ValType::V128 => {
|
ValType::V128 => {
|
||||||
return Err(HostRef::new(Trap::new(
|
return Err(Trap::new(
|
||||||
"dummy_value: unsupported function return type: v128".to_string(),
|
"dummy_value: unsupported function return type: v128".to_string(),
|
||||||
)))
|
))
|
||||||
}
|
}
|
||||||
ValType::AnyRef => {
|
ValType::AnyRef => {
|
||||||
return Err(HostRef::new(Trap::new(
|
return Err(Trap::new(
|
||||||
"dummy_value: unsupported function return type: anyref".to_string(),
|
"dummy_value: unsupported function return type: anyref".to_string(),
|
||||||
)))
|
))
|
||||||
}
|
}
|
||||||
ValType::FuncRef => {
|
ValType::FuncRef => {
|
||||||
return Err(HostRef::new(Trap::new(
|
return Err(Trap::new(
|
||||||
"dummy_value: unsupported function return type: funcref".to_string(),
|
"dummy_value: unsupported function return type: funcref".to_string(),
|
||||||
)))
|
))
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Construct a dummy global for the given global type.
|
/// Construct a dummy global for the given global type.
|
||||||
pub fn dummy_global(store: &HostRef<Store>, ty: GlobalType) -> Result<Global, HostRef<Trap>> {
|
pub fn dummy_global(store: &HostRef<Store>, ty: GlobalType) -> Result<Global, Trap> {
|
||||||
let val = dummy_value(ty.content())?;
|
let val = dummy_value(ty.content())?;
|
||||||
Ok(Global::new(store, ty, val))
|
Ok(Global::new(store, ty, val))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Construct a dummy table for the given table type.
|
/// Construct a dummy table for the given table type.
|
||||||
pub fn dummy_table(store: &HostRef<Store>, ty: TableType) -> Result<Table, HostRef<Trap>> {
|
pub fn dummy_table(store: &HostRef<Store>, ty: TableType) -> Result<Table, Trap> {
|
||||||
let init_val = dummy_value(&ty.element())?;
|
let init_val = dummy_value(&ty.element())?;
|
||||||
Ok(Table::new(store, ty, init_val))
|
Ok(Table::new(store, ty, init_val))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -82,7 +82,7 @@ impl wasmtime::Callable for WrappedFn {
|
|||||||
&self,
|
&self,
|
||||||
params: &[wasmtime::Val],
|
params: &[wasmtime::Val],
|
||||||
returns: &mut [wasmtime::Val],
|
returns: &mut [wasmtime::Val],
|
||||||
) -> Result<(), wasmtime::HostRef<wasmtime::Trap>> {
|
) -> Result<(), wasmtime::Trap> {
|
||||||
let gil = Python::acquire_gil();
|
let gil = Python::acquire_gil();
|
||||||
let py = gil.python();
|
let py = gil.python();
|
||||||
|
|
||||||
|
|||||||
@@ -91,7 +91,7 @@ pub fn instantiate(data: &[u8], bin_name: &str, workspace: Option<&Path>) -> any
|
|||||||
.borrow()
|
.borrow()
|
||||||
.call(&[])
|
.call(&[])
|
||||||
{
|
{
|
||||||
bail!("trapped: {:?}", trap.borrow());
|
bail!("trapped: {:?}", trap);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|||||||
@@ -9,9 +9,9 @@ struct MyCall<F>(F);
|
|||||||
|
|
||||||
impl<F> Callable for MyCall<F>
|
impl<F> Callable for MyCall<F>
|
||||||
where
|
where
|
||||||
F: Fn(&[Val], &mut [Val]) -> Result<(), HostRef<Trap>>,
|
F: Fn(&[Val], &mut [Val]) -> Result<(), Trap>,
|
||||||
{
|
{
|
||||||
fn call(&self, params: &[Val], results: &mut [Val]) -> Result<(), HostRef<Trap>> {
|
fn call(&self, params: &[Val], results: &mut [Val]) -> Result<(), Trap> {
|
||||||
(self.0)(params, results)
|
(self.0)(params, results)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -19,7 +19,7 @@ where
|
|||||||
fn wrap(
|
fn wrap(
|
||||||
store: &HostRef<Store>,
|
store: &HostRef<Store>,
|
||||||
ty: FuncType,
|
ty: FuncType,
|
||||||
callable: impl Fn(&[Val], &mut [Val]) -> Result<(), HostRef<Trap>> + 'static,
|
callable: impl Fn(&[Val], &mut [Val]) -> Result<(), Trap> + 'static,
|
||||||
) -> Func {
|
) -> Func {
|
||||||
Func::new(store, ty, Rc::new(MyCall(callable)))
|
Func::new(store, ty, Rc::new(MyCall(callable)))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ pub struct WastContext {
|
|||||||
|
|
||||||
enum Outcome<T = Vec<Val>> {
|
enum Outcome<T = Vec<Val>> {
|
||||||
Ok(T),
|
Ok(T),
|
||||||
Trap(HostRef<Trap>),
|
Trap(Trap),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WastContext {
|
impl WastContext {
|
||||||
@@ -101,7 +101,7 @@ impl WastContext {
|
|||||||
.filter_map(|e| e.downcast_ref::<InstantiationError>())
|
.filter_map(|e| e.downcast_ref::<InstantiationError>())
|
||||||
.next();
|
.next();
|
||||||
if let Some(InstantiationError::StartTrap(msg)) = err {
|
if let Some(InstantiationError::StartTrap(msg)) = err {
|
||||||
return Ok(Outcome::Trap(HostRef::new(Trap::new(msg.clone()))));
|
return Ok(Outcome::Trap(Trap::new(msg.clone())));
|
||||||
}
|
}
|
||||||
return Err(e);
|
return Err(e);
|
||||||
}
|
}
|
||||||
@@ -139,7 +139,7 @@ impl WastContext {
|
|||||||
fn module(&mut self, instance_name: Option<&str>, module: &[u8]) -> Result<()> {
|
fn module(&mut self, instance_name: Option<&str>, module: &[u8]) -> Result<()> {
|
||||||
let instance = match self.instantiate(module)? {
|
let instance = match self.instantiate(module)? {
|
||||||
Outcome::Ok(i) => i,
|
Outcome::Ok(i) => i,
|
||||||
Outcome::Trap(e) => bail!("instantiation failed with: {}", e.borrow().message()),
|
Outcome::Trap(e) => bail!("instantiation failed with: {}", e.message()),
|
||||||
};
|
};
|
||||||
if let Some(name) = instance_name {
|
if let Some(name) = instance_name {
|
||||||
self.instances.insert(name.to_string(), instance.clone());
|
self.instances.insert(name.to_string(), instance.clone());
|
||||||
@@ -241,7 +241,6 @@ impl WastContext {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
Outcome::Trap(t) => {
|
Outcome::Trap(t) => {
|
||||||
let t = t.borrow();
|
|
||||||
bail!("{}\nunexpected trap: {}", context(span), t.message())
|
bail!("{}\nunexpected trap: {}", context(span), t.message())
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -254,7 +253,6 @@ impl WastContext {
|
|||||||
bail!("{}\nexpected trap, got {:?}", context(span), values)
|
bail!("{}\nexpected trap, got {:?}", context(span), values)
|
||||||
}
|
}
|
||||||
Outcome::Trap(t) => {
|
Outcome::Trap(t) => {
|
||||||
let t = t.borrow();
|
|
||||||
if t.message().contains(message) {
|
if t.message().contains(message) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -283,7 +281,6 @@ impl WastContext {
|
|||||||
bail!("{}\nexpected trap, got {:?}", context(span), values)
|
bail!("{}\nexpected trap, got {:?}", context(span), values)
|
||||||
}
|
}
|
||||||
Outcome::Trap(t) => {
|
Outcome::Trap(t) => {
|
||||||
let t = t.borrow();
|
|
||||||
if t.message().contains(message) {
|
if t.message().contains(message) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -315,7 +312,6 @@ impl WastContext {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
Outcome::Trap(t) => {
|
Outcome::Trap(t) => {
|
||||||
let t = t.borrow();
|
|
||||||
bail!("{}\nunexpected trap: {}", context(span), t.message())
|
bail!("{}\nunexpected trap: {}", context(span), t.message())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -340,7 +336,6 @@ impl WastContext {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
Outcome::Trap(t) => {
|
Outcome::Trap(t) => {
|
||||||
let t = t.borrow();
|
|
||||||
bail!("{}\nunexpected trap: {}", context(span), t.message())
|
bail!("{}\nunexpected trap: {}", context(span), t.message())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -365,7 +360,6 @@ impl WastContext {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
Outcome::Trap(t) => {
|
Outcome::Trap(t) => {
|
||||||
let t = t.borrow();
|
|
||||||
bail!("{}\nunexpected trap: {}", context(span), t.message())
|
bail!("{}\nunexpected trap: {}", context(span), t.message())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -390,7 +384,6 @@ impl WastContext {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
Outcome::Trap(t) => {
|
Outcome::Trap(t) => {
|
||||||
let t = t.borrow();
|
|
||||||
bail!("{}\nunexpected trap: {}", context(span), t.message())
|
bail!("{}\nunexpected trap: {}", context(span), t.message())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -415,7 +408,6 @@ impl WastContext {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
Outcome::Trap(t) => {
|
Outcome::Trap(t) => {
|
||||||
let t = t.borrow();
|
|
||||||
bail!("{}\nunexpected trap: {}", context(span), t.message())
|
bail!("{}\nunexpected trap: {}", context(span), t.message())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -440,7 +432,6 @@ impl WastContext {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
Outcome::Trap(t) => {
|
Outcome::Trap(t) => {
|
||||||
let t = t.borrow();
|
|
||||||
bail!("{}\nunexpected trap: {}", context(span), t.message())
|
bail!("{}\nunexpected trap: {}", context(span), t.message())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -349,7 +349,10 @@ fn instantiate_module(
|
|||||||
})
|
})
|
||||||
.collect::<Result<Vec<_>, _>>()?;
|
.collect::<Result<Vec<_>, _>>()?;
|
||||||
|
|
||||||
let instance = HostRef::new(Instance::new(store, &module, &imports)?);
|
let instance = HostRef::new(match Instance::new(store, &module, &imports) {
|
||||||
|
Ok(instance) => instance,
|
||||||
|
Err(trap) => bail!("Failed to instantiate {:?}: {:?}", path, trap),
|
||||||
|
});
|
||||||
|
|
||||||
Ok((instance, module, data))
|
Ok((instance, module, data))
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user