diff --git a/Cargo.lock b/Cargo.lock index 52474001f..67b1b5a1c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1368,8 +1368,6 @@ dependencies = [ "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", "js-sys 0.3.28 (registry+https://github.com/rust-lang/crates.io-index)", - "num-bigint 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "rustpython-compiler 0.1.1", "rustpython-parser 0.1.1", "rustpython-vm 0.1.1", diff --git a/wasm/lib/Cargo.toml b/wasm/lib/Cargo.toml index 48a9b0738..c96b2a58c 100644 --- a/wasm/lib/Cargo.toml +++ b/wasm/lib/Cargo.toml @@ -25,8 +25,6 @@ serde-wasm-bindgen = "0.1" serde = "1.0" js-sys = "0.3" futures = "0.1" -num-traits = "0.2" -num-bigint = { version = "0.2.3", features = ["serde"] } [dependencies.web-sys] version = "0.3" diff --git a/wasm/lib/src/browser_module.rs b/wasm/lib/src/browser_module.rs index 86c0d93f9..84aeb3c8c 100644 --- a/wasm/lib/src/browser_module.rs +++ b/wasm/lib/src/browser_module.rs @@ -1,15 +1,12 @@ use futures::Future; use js_sys::Promise; -use num_traits::cast::ToPrimitive; use wasm_bindgen::prelude::*; use wasm_bindgen::JsCast; use wasm_bindgen_futures::{future_to_promise, JsFuture}; use rustpython_vm::function::{OptionalArg, PyFuncArgs}; use rustpython_vm::import::import_file; -use rustpython_vm::obj::{ - objdict::PyDictRef, objint::PyIntRef, objstr::PyStringRef, objtype::PyClassRef, -}; +use rustpython_vm::obj::{objdict::PyDictRef, objstr::PyStringRef, objtype::PyClassRef}; use rustpython_vm::pyobject::{ PyCallable, PyClassImpl, PyObject, PyObjectRef, PyRef, PyResult, PyValue, }; @@ -148,14 +145,7 @@ fn browser_request_animation_frame(func: PyCallable, vm: &VirtualMachine) -> PyR Ok(vm.ctx.new_int(id)) } -fn browser_cancel_animation_frame(id: PyIntRef, vm: &VirtualMachine) -> PyResult { - let id = id.as_bigint().to_i32().ok_or_else(|| { - vm.new_exception( - vm.ctx.exceptions.value_error.clone(), - "Integer too large to convert to i32 for animationFrame id".into(), - ) - })?; - +fn browser_cancel_animation_frame(id: i32, vm: &VirtualMachine) -> PyResult { window() .cancel_animation_frame(id) .map_err(|err| convert::js_py_typeerror(vm, err))?; @@ -308,7 +298,7 @@ impl Element { fn set_attr(&self, attr: PyStringRef, value: PyStringRef, vm: &VirtualMachine) -> PyResult<()> { self.elem .set_attribute(attr.as_str(), value.as_str()) - .map_err(|err| convert::js_to_py(vm, err)) + .map_err(|err| convert::js_py_typeerror(vm, err)) } } diff --git a/wasm/lib/src/convert.rs b/wasm/lib/src/convert.rs index 1bba54629..789f6cb39 100644 --- a/wasm/lib/src/convert.rs +++ b/wasm/lib/src/convert.rs @@ -1,20 +1,18 @@ use js_sys::{Array, ArrayBuffer, Object, Promise, Reflect, Uint8Array}; -use num_traits::cast::ToPrimitive; use serde_wasm_bindgen; use wasm_bindgen::{closure::Closure, prelude::*, JsCast}; +use rustpython_vm::exceptions::PyBaseExceptionRef; use rustpython_vm::function::PyFuncArgs; -use rustpython_vm::obj::{objbytes, objint, objsequence, objtype}; +use rustpython_vm::obj::{objbytes, objtype}; use rustpython_vm::py_serde; use rustpython_vm::pyobject::{ItemProtocol, PyObjectRef, PyResult, PyValue}; use rustpython_vm::VirtualMachine; -use num_bigint::BigInt; - use crate::browser_module; use crate::vm_class::{stored_vm_from_wasm, WASMVirtualMachine}; -pub fn py_err_to_js_err(vm: &VirtualMachine, py_err: &PyObjectRef) -> JsValue { +pub fn py_err_to_js_err(vm: &VirtualMachine, py_err: &PyBaseExceptionRef) -> 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) { @@ -24,11 +22,11 @@ pub fn py_err_to_js_err(vm: &VirtualMachine, py_err: &PyObjectRef) -> JsValue { } }; } - let msg = match vm.to_pystr(py_err) { + let msg = match vm.to_str(py_err.as_object()) { Ok(msg) => msg, Err(_) => return js_sys::Error::new("error getting error").into(), }; - let js_err = map_exceptions!(py_err,& msg, { + let js_err = map_exceptions!(py_err, msg.as_str(), { // 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, @@ -38,31 +36,36 @@ pub fn py_err_to_js_err(vm: &VirtualMachine, py_err: &PyObjectRef) -> JsValue { &vm.ctx.exceptions.name_error => js_sys::ReferenceError::new, &vm.ctx.exceptions.syntax_error => js_sys::SyntaxError::new, }); - if let Ok(tb) = vm.get_attribute(py_err.clone(), "__traceback__") { - if objtype::isinstance(&tb, &vm.ctx.list_type()) { - let elements = objsequence::get_elements_list(&tb).to_vec(); - if let Some(top) = elements.get(0) { - if objtype::isinstance(&top, &vm.ctx.tuple_type()) { - let element = objsequence::get_elements_tuple(&top); - - if let Some(lineno) = objint::to_int(vm, &element[1], &BigInt::from(10)) - .ok() - .and_then(|lineno| lineno.to_u32()) - { - let _ = Reflect::set(&js_err, &"row".into(), &lineno.into()); - } - } - } - } + if let Some(tb) = py_err.traceback() { + let _ = Reflect::set(&js_err, &"row".into(), &(tb.lineno as u32).into()); } js_err } -pub fn js_py_typeerror(vm: &VirtualMachine, js_err: JsValue) -> PyObjectRef { +pub fn js_py_typeerror(vm: &VirtualMachine, js_err: JsValue) -> PyBaseExceptionRef { let msg = js_err.unchecked_into::().to_string(); vm.new_type_error(msg.into()) } +pub fn js_err_to_py_err(vm: &VirtualMachine, js_err: &JsValue) -> PyBaseExceptionRef { + match js_err.dyn_ref::() { + Some(err) => { + let exc_type = match String::from(err.name()).as_str() { + "TypeError" => &vm.ctx.exceptions.type_error, + "ReferenceError" => &vm.ctx.exceptions.name_error, + "SyntaxError" => &vm.ctx.exceptions.syntax_error, + _ => &vm.ctx.exceptions.exception_type, + } + .clone(); + vm.new_exception(exc_type, err.message().into()) + } + None => vm.new_exception( + vm.ctx.exceptions.exception_type.clone(), + format!("{:?}", js_err), + ), + } +} + pub fn py_to_js(vm: &VirtualMachine, py_obj: PyObjectRef) -> JsValue { if let Some(ref wasm_id) = vm.wasm_id { if objtype::isinstance(&py_obj, &vm.ctx.function_type()) { @@ -207,17 +210,10 @@ pub fn js_to_py(vm: &VirtualMachine, js_val: JsValue) -> PyObjectRef { } func.apply(&this, &js_args) .map(|val| js_to_py(vm, val)) - .map_err(|err| js_to_py(vm, err)) + .map_err(|err| js_err_to_py_err(vm, &err)) }) } else if let Some(err) = js_val.dyn_ref::() { - let exc_type = match String::from(err.name()).as_str() { - "TypeError" => &vm.ctx.exceptions.type_error, - "ReferenceError" => &vm.ctx.exceptions.name_error, - "SyntaxError" => &vm.ctx.exceptions.syntax_error, - _ => &vm.ctx.exceptions.exception_type, - } - .clone(); - vm.new_exception(exc_type, err.message().into()) + js_err_to_py_err(vm, err).into_object() } else if js_val.is_undefined() { // Because `JSON.stringify(undefined)` returns undefined vm.get_none() diff --git a/wasm/lib/src/js_module.rs b/wasm/lib/src/js_module.rs index 9622613f7..0ffcf2f6a 100644 --- a/wasm/lib/src/js_module.rs +++ b/wasm/lib/src/js_module.rs @@ -1,4 +1,5 @@ use js_sys::{Array, Object, Reflect}; +use rustpython_vm::exceptions::PyBaseExceptionRef; use rustpython_vm::function::Args; use rustpython_vm::obj::{objfloat::PyFloatRef, objstr::PyStringRef, objtype::PyClassRef}; use rustpython_vm::pyobject::{PyClassImpl, PyObjectRef, PyRef, PyResult, PyValue, TryFromObject}; @@ -233,10 +234,14 @@ struct NewObjectOptions { prototype: Option, } -fn new_js_error(vm: &VirtualMachine, err: JsValue) -> PyObjectRef { +fn new_js_error(vm: &VirtualMachine, err: JsValue) -> PyBaseExceptionRef { let exc = vm.new_exception(vm.class("_js", "JsError"), format!("{:?}", err)); - vm.set_attr(&exc, "js_value", PyJsValue::new(err).into_ref(vm)) - .unwrap(); + vm.set_attr( + exc.as_object(), + "js_value", + PyJsValue::new(err).into_ref(vm), + ) + .unwrap(); exc } diff --git a/wasm/lib/src/vm_class.rs b/wasm/lib/src/vm_class.rs index 3f9a318fa..57c9e0c7c 100644 --- a/wasm/lib/src/vm_class.rs +++ b/wasm/lib/src/vm_class.rs @@ -232,7 +232,7 @@ impl WASMVirtualMachine { &JsValue::UNDEFINED, &wasm_builtins::format_print_args(vm, args)?.into(), ) - .map_err(|err| convert::js_to_py(vm, err))?; + .map_err(|err| convert::js_py_typeerror(vm, err))?; Ok(vm.get_none()) }) } else if stdout.is_null() {