Replace RuntimeError::raise with RuntimeError::custom

This commit is contained in:
Amanieu d'Antras
2021-12-17 18:26:41 +01:00
parent 75e4cabe9b
commit 17c0834abf
7 changed files with 52 additions and 25 deletions

View File

@@ -62,9 +62,9 @@ fn main() -> anyhow::Result<()> {
let module = Module::new(&store, wasm_bytes)?; let module = Module::new(&store, wasm_bytes)?;
// We declare the host function that we'll use to terminate execution. // We declare the host function that we'll use to terminate execution.
fn early_exit() { fn early_exit() -> Result<(), RuntimeError> {
// This is where it happens. // This is where it happens.
RuntimeError::raise(Box::new(ExitCode(1))); Err(RuntimeError::custom(Box::new(ExitCode(1))))
} }
// Create an import object. // Create an import object.

View File

@@ -644,6 +644,7 @@ impl wasmer_types::WasmValueType for Function {
/// This private inner module contains the low-level implementation /// This private inner module contains the low-level implementation
/// for `Function` and its siblings. /// for `Function` and its siblings.
mod inner { mod inner {
use super::RuntimeError;
use super::VMFunctionBody; use super::VMFunctionBody;
use std::array::TryFromSliceError; use std::array::TryFromSliceError;
use std::convert::{Infallible, TryInto}; use std::convert::{Infallible, TryInto};
@@ -1125,6 +1126,7 @@ mod inner {
})); }));
match result { match result {
Ok(Ok(result)) => return result.into_c_struct(), Ok(Ok(result)) => return result.into_c_struct(),
Ok(Err(trap)) => RuntimeError::raise(Box::new(trap)),
_ => unimplemented!(), _ => unimplemented!(),
// Ok(Err(trap)) => unsafe { raise_user_trap(Box::new(trap)) }, // Ok(Err(trap)) => unsafe { raise_user_trap(Box::new(trap)) },
// Err(panic) => unsafe { resume_panic(panic) }, // Err(panic) => unsafe { resume_panic(panic) },
@@ -1170,6 +1172,7 @@ mod inner {
})); }));
match result { match result {
Ok(Ok(result)) => return result.into_c_struct(), Ok(Ok(result)) => return result.into_c_struct(),
Ok(Err(trap)) => RuntimeError::raise(Box::new(trap)),
_ => unimplemented!(), _ => unimplemented!(),
// Ok(Err(trap)) => unsafe { raise_user_trap(Box::new(trap)) }, // Ok(Err(trap)) => unsafe { raise_user_trap(Box::new(trap)) },
// Err(panic) => unsafe { resume_panic(panic) }, // Err(panic) => unsafe { resume_panic(panic) },

View File

@@ -34,6 +34,10 @@ enum RuntimeErrorSource {
Js(JsValue), Js(JsValue),
} }
/// This is a hack to ensure the error type is Send+Sync
unsafe impl Send for RuntimeErrorSource {}
unsafe impl Sync for RuntimeErrorSource {}
impl fmt::Display for RuntimeErrorSource { impl fmt::Display for RuntimeErrorSource {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self { match self {
@@ -58,26 +62,28 @@ impl RuntimeError {
} }
} }
/// Creates a new user `RuntimeError` with the given `error`.
pub fn user(error: impl Error + Send + Sync + 'static) -> Self {
RuntimeError {
inner: Arc::new(RuntimeErrorSource::User(Box::new(error))),
}
}
/// Raises a custom user Error /// Raises a custom user Error
#[deprecated(since = "2.1.1", note = "prefer using RuntimeError::custom instead")]
pub fn raise(error: Box<dyn Error + Send + Sync>) -> ! { pub fn raise(error: Box<dyn Error + Send + Sync>) -> ! {
let error = if error.is::<RuntimeError>() { let error = Self::custom(error);
*error.downcast::<RuntimeError>().unwrap()
} else {
RuntimeError {
inner: Arc::new(RuntimeErrorSource::User(error)),
}
};
let js_error: JsValue = error.into(); let js_error: JsValue = error.into();
wasm_bindgen::throw_val(js_error) wasm_bindgen::throw_val(js_error)
} }
/// Creates a custom user Error.
///
/// This error object can be passed through Wasm frames and later retrieved
/// using the `downcast` method.
pub fn custom(error: Box<dyn Error + Send + Sync>) -> Self {
match error.downcast::<Self>() {
// The error is already a RuntimeError, we return it directly
Ok(runtime_error) => *runtime_error,
Err(error) => RuntimeError {
inner: Arc::new(RuntimeErrorSource::User(error)),
},
}
}
/// Returns a reference the `message` stored in `Trap`. /// Returns a reference the `message` stored in `Trap`.
pub fn message(&self) -> String { pub fn message(&self) -> String {
format!("{}", self.inner) format!("{}", self.inner)

View File

@@ -690,8 +690,8 @@ mod js {
impl std::error::Error for ExitCode {} impl std::error::Error for ExitCode {}
fn early_exit() { fn early_exit() -> Result<(), RuntimeError> {
RuntimeError::raise(Box::new(ExitCode(1))); Err(RuntimeError::custom(Box::new(ExitCode(1))))
} }
let import_object = imports! { let import_object = imports! {

View File

@@ -59,16 +59,14 @@ impl Error for LongJumpRet {}
/// _longjmp /// _longjmp
// This function differs from the js implementation, it should return Result<(), &'static str> // This function differs from the js implementation, it should return Result<(), &'static str>
#[allow(unreachable_code)] #[allow(unreachable_code)]
pub fn _longjmp(ctx: &EmEnv, env_addr: i32, val: c_int) { pub fn _longjmp(ctx: &EmEnv, env_addr: i32, val: c_int) -> Result<(), RuntimeError> {
let val = if val == 0 { 1 } else { val }; let val = if val == 0 { 1 } else { val };
get_emscripten_data(ctx) get_emscripten_data(ctx)
.set_threw_ref() .set_threw_ref()
.expect("set_threw is None") .expect("set_threw is None")
.call(env_addr, val) .call(env_addr, val)
.expect("set_threw failed to call"); .expect("set_threw failed to call");
// TODO: return Err("longjmp") Err(RuntimeError::custom(Box::new(LongJumpRet)))
RuntimeError::raise(Box::new(LongJumpRet));
unreachable!();
} }
// extern "C" { // extern "C" {

View File

@@ -107,10 +107,31 @@ impl RuntimeError {
} }
/// Raises a custom user Error /// Raises a custom user Error
#[deprecated(since = "2.1.1", note = "prefer using RuntimeError::custom instead")]
pub fn raise(error: Box<dyn Error + Send + Sync>) -> ! { pub fn raise(error: Box<dyn Error + Send + Sync>) -> ! {
unsafe { raise_user_trap(error) } unsafe { raise_user_trap(error) }
} }
/// Creates a custom user Error.
///
/// This error object can be passed through Wasm frames and later retrieved
/// using the `downcast` method.
pub fn custom(error: Box<dyn Error + Send + Sync>) -> Self {
match error.downcast::<Self>() {
// The error is already a RuntimeError, we return it directly
Ok(runtime_error) => *runtime_error,
Err(error) => {
let info = FRAME_INFO.read().unwrap();
Self::new_with_trace(
&info,
None,
RuntimeErrorSource::User(error),
Backtrace::new_unresolved(),
)
}
}
}
fn new_with_trace( fn new_with_trace(
info: &GlobalFrameInfo, info: &GlobalFrameInfo,
trap_pc: Option<usize>, trap_pc: Option<usize>,

View File

@@ -2521,10 +2521,9 @@ pub fn poll_oneoff(
unimplemented!(); unimplemented!();
} }
pub fn proc_exit(env: &WasiEnv, code: __wasi_exitcode_t) { pub fn proc_exit(env: &WasiEnv, code: __wasi_exitcode_t) -> Result<(), RuntimeError> {
debug!("wasi::proc_exit, {}", code); debug!("wasi::proc_exit, {}", code);
RuntimeError::raise(Box::new(WasiError::Exit(code))); Err(RuntimeError::custom(Box::new(WasiError::Exit(code))))
unreachable!();
} }
pub fn proc_raise(env: &WasiEnv, sig: __wasi_signal_t) -> __wasi_errno_t { pub fn proc_raise(env: &WasiEnv, sig: __wasi_signal_t) -> __wasi_errno_t {