Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
Prev Previous commit
Convert Python errors to JS errors with row
  • Loading branch information
coolreader18 committed Mar 8, 2019
commit c563a6d4980710708d8913b663be34a0ee52d1cb
8 changes: 3 additions & 5 deletions wasm/lib/src/browser_module.rs
Original file line number Diff line number Diff line change
Expand Up @@ -221,8 +221,7 @@ fn promise_then(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
}
}
};
ret.map(|val| convert::py_to_js(vm, val))
.map_err(|err| convert::py_to_js(vm, err))
convert::pyresult_to_jsresult(vm, ret)
});

let ret_promise = future_to_promise(ret_future);
Expand Down Expand Up @@ -254,9 +253,8 @@ fn promise_catch(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
.upgrade()
.expect("that the vm is valid when the promise resolves");
let err = convert::js_to_py(vm, err);
vm.invoke(on_reject, PyFuncArgs::new(vec![err], vec![]))
.map(|val| convert::py_to_js(vm, val))
.map_err(|err| convert::py_to_js(vm, err))
let res = vm.invoke(on_reject, PyFuncArgs::new(vec![err], vec![]));
convert::pyresult_to_jsresult(vm, res)
}
});

Expand Down
57 changes: 51 additions & 6 deletions wasm/lib/src/convert.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,59 @@
use crate::browser_module;
use crate::vm_class::{AccessibleVM, WASMVirtualMachine};
use js_sys::{Array, ArrayBuffer, Object, Promise, Reflect, Uint8Array};
use rustpython_vm::obj::{objbytes, objtype};
use rustpython_vm::pyobject::{self, DictProtocol, PyFuncArgs, PyObjectRef, PyResult};
use num_traits::cast::ToPrimitive;
use rustpython_vm::obj::{objbytes, objint, objsequence, objtype};
use rustpython_vm::pyobject::{
self, AttributeProtocol, DictProtocol, PyFuncArgs, PyObjectRef, PyResult,
};
use rustpython_vm::VirtualMachine;
use wasm_bindgen::{closure::Closure, prelude::*, JsCast};

pub fn py_str_err(vm: &mut VirtualMachine, py_err: &PyObjectRef) -> String {
vm.to_pystr(&py_err)
.unwrap_or_else(|_| "Error, and error getting error message".into())
pub fn py_err_to_js_err(vm: &mut VirtualMachine, py_err: &PyObjectRef) -> JsValue {
macro_rules! map_exceptions {
($py_exc:ident, $msg:expr, { $($py_exc_ty:expr => $js_err_new:expr),*$(,)? }) => {
$(if objtype::isinstance($py_exc, $py_exc_ty) {
JsValue::from($js_err_new($msg))
} else)* {
JsValue::from(js_sys::Error::new($msg))
}
};
}
let msg = match py_err
.get_attr("msg")
.and_then(|msg| vm.to_pystr(&msg).ok())
{
Some(msg) => msg,
None => return js_sys::Error::new("error getting error").into(),
};
let js_err = map_exceptions!(py_err,& msg, {
// TypeError is sort of a catch-all for "this value isn't what I thought it was like"
&vm.ctx.exceptions.type_error => js_sys::TypeError::new,
&vm.ctx.exceptions.value_error => js_sys::TypeError::new,
&vm.ctx.exceptions.index_error => js_sys::TypeError::new,
&vm.ctx.exceptions.key_error => js_sys::TypeError::new,
&vm.ctx.exceptions.attribute_error => js_sys::TypeError::new,
&vm.ctx.exceptions.name_error => js_sys::ReferenceError::new,
&vm.ctx.exceptions.syntax_error => js_sys::SyntaxError::new,
});
if let Some(tb) = py_err.get_attr("__traceback__") {
if objtype::isinstance(&tb, &vm.ctx.list_type()) {
let elements = objsequence::get_elements(&tb).to_vec();
if let Some(top) = elements.get(0) {
if objtype::isinstance(&top, &vm.ctx.tuple_type()) {
let element = objsequence::get_elements(&top);

if let Some(lineno) = objint::to_int(vm, &element[1], 10)
.ok()
.and_then(|lineno| lineno.to_u32())
{
Reflect::set(&js_err, &"row".into(), &lineno.into());
}
}
}
}
}
js_err
}

pub fn js_py_typeerror(vm: &mut VirtualMachine, js_err: JsValue) -> PyObjectRef {
Expand Down Expand Up @@ -110,7 +155,7 @@ pub fn object_entries(obj: &Object) -> impl Iterator<Item = Result<(JsValue, JsV
pub fn pyresult_to_jsresult(vm: &mut VirtualMachine, result: PyResult) -> Result<JsValue, JsValue> {
result
.map(|value| py_to_js(vm, value))
.map_err(|err| py_str_err(vm, &err).into())
.map_err(|err| py_err_to_js_err(vm, &err).into())
}

pub fn js_to_py(vm: &mut VirtualMachine, js_val: JsValue) -> PyObjectRef {
Expand Down