|
1 | 1 | use crate::browser_module;
|
2 | 2 | use crate::vm_class::{AccessibleVM, WASMVirtualMachine};
|
3 | 3 | use js_sys::{Array, ArrayBuffer, Object, Promise, Reflect, Uint8Array};
|
4 |
| -use rustpython_vm::obj::{objbytes, objtype}; |
5 |
| -use rustpython_vm::pyobject::{self, DictProtocol, PyFuncArgs, PyObjectRef, PyResult}; |
| 4 | +use num_traits::cast::ToPrimitive; |
| 5 | +use rustpython_vm::obj::{objbytes, objint, objsequence, objtype}; |
| 6 | +use rustpython_vm::pyobject::{ |
| 7 | + self, AttributeProtocol, DictProtocol, PyFuncArgs, PyObjectRef, PyResult, |
| 8 | +}; |
6 | 9 | use rustpython_vm::VirtualMachine;
|
7 | 10 | use wasm_bindgen::{closure::Closure, prelude::*, JsCast};
|
8 | 11 |
|
9 |
| -pub fn py_str_err(vm: &mut VirtualMachine, py_err: &PyObjectRef) -> String { |
10 |
| - vm.to_pystr(&py_err) |
11 |
| - .unwrap_or_else(|_| "Error, and error getting error message".into()) |
| 12 | +pub fn py_err_to_js_err(vm: &mut VirtualMachine, py_err: &PyObjectRef) -> JsValue { |
| 13 | + macro_rules! map_exceptions { |
| 14 | + ($py_exc:ident, $msg:expr, { $($py_exc_ty:expr => $js_err_new:expr),*$(,)? }) => { |
| 15 | + $(if objtype::isinstance($py_exc, $py_exc_ty) { |
| 16 | + JsValue::from($js_err_new($msg)) |
| 17 | + } else)* { |
| 18 | + JsValue::from(js_sys::Error::new($msg)) |
| 19 | + } |
| 20 | + }; |
| 21 | + } |
| 22 | + let msg = match py_err |
| 23 | + .get_attr("msg") |
| 24 | + .and_then(|msg| vm.to_pystr(&msg).ok()) |
| 25 | + { |
| 26 | + Some(msg) => msg, |
| 27 | + None => return js_sys::Error::new("error getting error").into(), |
| 28 | + }; |
| 29 | + let js_err = map_exceptions!(py_err,& msg, { |
| 30 | + // TypeError is sort of a catch-all for "this value isn't what I thought it was like" |
| 31 | + &vm.ctx.exceptions.type_error => js_sys::TypeError::new, |
| 32 | + &vm.ctx.exceptions.value_error => js_sys::TypeError::new, |
| 33 | + &vm.ctx.exceptions.index_error => js_sys::TypeError::new, |
| 34 | + &vm.ctx.exceptions.key_error => js_sys::TypeError::new, |
| 35 | + &vm.ctx.exceptions.attribute_error => js_sys::TypeError::new, |
| 36 | + &vm.ctx.exceptions.name_error => js_sys::ReferenceError::new, |
| 37 | + &vm.ctx.exceptions.syntax_error => js_sys::SyntaxError::new, |
| 38 | + }); |
| 39 | + if let Some(tb) = py_err.get_attr("__traceback__") { |
| 40 | + if objtype::isinstance(&tb, &vm.ctx.list_type()) { |
| 41 | + let elements = objsequence::get_elements(&tb).to_vec(); |
| 42 | + if let Some(top) = elements.get(0) { |
| 43 | + if objtype::isinstance(&top, &vm.ctx.tuple_type()) { |
| 44 | + let element = objsequence::get_elements(&top); |
| 45 | + |
| 46 | + if let Some(lineno) = objint::to_int(vm, &element[1], 10) |
| 47 | + .ok() |
| 48 | + .and_then(|lineno| lineno.to_u32()) |
| 49 | + { |
| 50 | + Reflect::set(&js_err, &"row".into(), &lineno.into()); |
| 51 | + } |
| 52 | + } |
| 53 | + } |
| 54 | + } |
| 55 | + } |
| 56 | + js_err |
12 | 57 | }
|
13 | 58 |
|
14 | 59 | pub fn js_py_typeerror(vm: &mut VirtualMachine, js_err: JsValue) -> PyObjectRef {
|
@@ -113,7 +158,7 @@ pub fn object_entries(obj: &Object) -> impl Iterator<Item = Result<(JsValue, JsV
|
113 | 158 | pub fn pyresult_to_jsresult(vm: &mut VirtualMachine, result: PyResult) -> Result<JsValue, JsValue> {
|
114 | 159 | result
|
115 | 160 | .map(|value| py_to_js(vm, value))
|
116 |
| - .map_err(|err| py_str_err(vm, &err).into()) |
| 161 | + .map_err(|err| py_err_to_js_err(vm, &err).into()) |
117 | 162 | }
|
118 | 163 |
|
119 | 164 | pub fn js_to_py(vm: &mut VirtualMachine, js_val: JsValue) -> PyObjectRef {
|
|
0 commit comments