Skip to content

Commit

Permalink
Allow conversion from Rust errors to JS throws
Browse files Browse the repository at this point in the history
  • Loading branch information
RReverser committed Jan 14, 2019
1 parent 1289318 commit dd2deaf
Show file tree
Hide file tree
Showing 6 changed files with 53 additions and 8 deletions.
7 changes: 4 additions & 3 deletions crates/cli-support/src/js/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -460,16 +460,17 @@ impl<'a> Context<'a> {
self.export_table();
self.gc();

// Note that it's important `throw` comes last *after* we gc. The
// Note that it's important `error_new` comes last *after* we gc. The
// `__wbindgen_malloc` function may call this but we only want to
// generate code for this if it's actually live (and __wbindgen_malloc
// isn't gc'd).
self.bind("__wbindgen_throw", &|me| {
self.bind("__wbindgen_error_new", &|me| {
me.expose_add_heap_object();
me.expose_get_string_from_wasm();
Ok(String::from(
"
function(ptr, len) {
throw new Error(getStringFromWasm(ptr, len));
return addHeapObject(new Error(getStringFromWasm(ptr, len)));
}
",
))
Expand Down
13 changes: 13 additions & 0 deletions src/convert/impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -418,3 +418,16 @@ impl<T: IntoWasmAbi> ReturnWasmAbi for Result<T, JsValue> {
}
}
}

if_std! {
use std::string::ToString;

impl<T: IntoWasmAbi, E: std::error::Error> ReturnWasmAbi for Result<T, E> {
type Abi = T::Abi;

fn return_abi(self, extra: &mut Stack) -> Self::Abi {
self.map_err(|err| JsValue::error(&err.to_string()))
.return_abi(extra)
}
}
}
8 changes: 8 additions & 0 deletions src/describe.rs
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,14 @@ impl<T: WasmDescribe> WasmDescribe for Result<T, JsValue> {
}
}

if_std! {
impl<T: WasmDescribe, E: std::error::Error> WasmDescribe for Result<T, E> {
fn describe() {
T::describe()
}
}
}

impl<T: WasmDescribe> WasmDescribe for Clamped<T> {
fn describe() {
inform(CLAMPED);
Expand Down
15 changes: 10 additions & 5 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,13 @@ impl JsValue {
}
}

/// Creates an instance of JS `Error` with the provided message.
///
/// The stacktrace generated by the JS engine will end at this invocation.
pub fn error(msg: &str) -> JsValue {
JsValue::_new(unsafe { __wbindgen_error_new(msg.as_ptr(), msg.len()) })
}

/// Creates a new `JsValue` from the JSON serialization of the object `t`
/// provided.
///
Expand Down Expand Up @@ -477,8 +484,8 @@ externs! {
fn __wbindgen_is_function(idx: u32) -> u32;
fn __wbindgen_is_string(idx: u32) -> u32;
fn __wbindgen_string_get(idx: u32, len: *mut usize) -> *mut u8;
fn __wbindgen_throw(a: *const u8, b: usize) -> !;
fn __wbindgen_rethrow(a: u32) -> !;
fn __wbindgen_error_new(ptr: *const u8, len: usize) -> u32;
fn __wbindgen_rethrow(err_idx: u32) -> !;

fn __wbindgen_cb_drop(idx: u32) -> u32;
fn __wbindgen_cb_forget(idx: u32) -> ();
Expand Down Expand Up @@ -610,9 +617,7 @@ pub fn throw(s: &str) -> ! {
#[cold]
#[inline(never)]
pub fn throw_str(s: &str) -> ! {
unsafe {
__wbindgen_throw(s.as_ptr(), s.len());
}
throw_val(JsValue::error(s));
}

/// Rethrow a JS exception
Expand Down
5 changes: 5 additions & 0 deletions tests/wasm/rethrow.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,8 @@ exports.call_throw_one = function() {
exports.call_ok = function() {
wasm.nothrow();
};

exports.call_parse_or_throw_rust_error = function() {
assert.strictEqual(wasm.parse_or_throw_rust_error("12"), 12);
assert.throws(() => wasm.parse_or_throw_rust_error("12#"), new Error('invalid digit found in string'));
};
13 changes: 13 additions & 0 deletions tests/wasm/rethrow.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
use std::num::ParseIntError;

use wasm_bindgen::prelude::*;
use wasm_bindgen_test::*;

#[wasm_bindgen(module = "tests/wasm/rethrow.js")]
extern "C" {
fn call_throw_one();
fn call_ok();
fn call_parse_or_throw_rust_error();
}

#[wasm_bindgen_test]
Expand All @@ -26,3 +29,13 @@ fn ok_works() {
pub fn nothrow() -> Result<u32, JsValue> {
Ok(1)
}

#[wasm_bindgen_test]
fn parse_or_throw_rust_error_works() {
call_parse_or_throw_rust_error();
}

#[wasm_bindgen]
pub fn parse_or_throw_rust_error(s: &str) -> Result<u32, ParseIntError> {
s.parse()
}

0 comments on commit dd2deaf

Please sign in to comment.