mirror of
https://github.com/RustPython/RustPython.git
synced 2026-10-29 03:04:38 +08:00
Merge pull request #2290 from RustPython/coolreader18/update-browser
Update the browser module
This commit is contained in:
11 files changed
+396
-229
No files matched your search
Generated
+46
-41
@@ -26,9 +26,9 @@ checksum = "aae1277d39aeec15cb388266ecc24b11c80469deae6067e17a1a7aa9e5c1f234"
|
||||
|
||||
[[package]]
|
||||
name = "aho-corasick"
|
||||
version = "0.7.13"
|
||||
version = "0.7.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "043164d8ba5c4c3035fec9bbee8647c0261d788f3474306f93bb65901cae0e86"
|
||||
checksum = "b476ce7103678b0c6d3d395dbbae31d48ff910bd28be979ba5d48c6351131d0d"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
@@ -140,7 +140,7 @@ checksum = "f1c85344eb535a31b62f0af37be84441ba9e7f0f4111eb0530f43d15e513fe57"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"cexpr",
|
||||
"cfg-if",
|
||||
"cfg-if 0.1.10",
|
||||
"clang-sys",
|
||||
"clap",
|
||||
"env_logger",
|
||||
@@ -288,6 +288,12 @@ version = "0.1.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "chrono"
|
||||
version = "0.4.19"
|
||||
@@ -482,7 +488,7 @@ version = "1.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ba125de2af0df55319f41944744ad91c71113bf74a4646efff39afe1f6842db1"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"cfg-if 0.1.10",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -492,7 +498,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c3c7c73a2d1e9fc0886a08b93e98eb643461230d5f1925e4036204d5f2e261a8"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"cfg-if",
|
||||
"cfg-if 0.1.10",
|
||||
"lazy_static 1.4.0",
|
||||
]
|
||||
|
||||
@@ -578,19 +584,19 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "dirs-next"
|
||||
version = "1.0.1"
|
||||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1cbcf9241d9e8d106295bd496bbe2e9cffd5fa098f2a8c9e2bbcbf09773c11a8"
|
||||
checksum = "cf36e65a80337bea855cd4ef9b8401ffce06a7baedf2e85ec467b1ac3f6e82b6"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"cfg-if 1.0.0",
|
||||
"dirs-sys-next",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dirs-sys-next"
|
||||
version = "0.1.0"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9c60f7b8a8953926148223260454befb50c751d3c50e1c178c4fd1ace4083c9a"
|
||||
checksum = "99de365f605554ae33f115102a02057d4fc18b01f3284d6870be0938743cfe7d"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"redox_users",
|
||||
@@ -603,7 +609,7 @@ version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8f69635ffdfbaea44241d7cca30a5e3a2e1c892613a6a8ad8ef03deeb6803480"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"cfg-if 0.1.10",
|
||||
"libc",
|
||||
"socket2",
|
||||
"winapi",
|
||||
@@ -730,7 +736,7 @@ version = "1.0.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "da80be589a72651dcda34d8b35bcdc9b7254ad06325611074d9cc0fbb19f60ee"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"cfg-if 0.1.10",
|
||||
"crc32fast",
|
||||
"libc",
|
||||
"libz-sys",
|
||||
@@ -789,7 +795,7 @@ version = "0.1.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fc587bc0ec293155d5bfa6b9891ec18a1e330c234f896ea47fbada4cadbe47e6"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"cfg-if 0.1.10",
|
||||
"libc",
|
||||
"wasi 0.9.0+wasi-snapshot-preview1",
|
||||
"wasm-bindgen",
|
||||
@@ -853,7 +859,7 @@ version = "0.1.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "63312a18f7ea8760cdd0a7c5aac1a619752a246b833545e3e36d1f81f7cd9e66"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"cfg-if 0.1.10",
|
||||
"js-sys",
|
||||
"wasm-bindgen",
|
||||
"web-sys",
|
||||
@@ -959,16 +965,16 @@ checksum = "db65c6da02e61f55dae90a0ae427b2a5f6b3e8db09f58d10efab23af92592616"
|
||||
dependencies = [
|
||||
"arrayvec",
|
||||
"bitflags",
|
||||
"cfg-if",
|
||||
"cfg-if 0.1.10",
|
||||
"ryu",
|
||||
"static_assertions",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.76"
|
||||
version = "0.2.79"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "755456fae044e6fa1ebbbd1b3e902ae19e73097ed4ed87bb79934a867c007bc3"
|
||||
checksum = "2448f6066e80e3bfc792e9c98bf705b4b0fc6e8ef5b43e5889aff0eaa9c58743"
|
||||
|
||||
[[package]]
|
||||
name = "libffi"
|
||||
@@ -1030,7 +1036,7 @@ version = "0.4.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4fabed175da42fed1fa0746b0ea71f412aa9d35e76e95e59b192c64b9dc2bf8b"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"cfg-if 0.1.10",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1117,7 +1123,7 @@ checksum = "83450fe6a6142ddd95fb064b746083fc4ef1705fe81f64a64e1d4b39f54a1055"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"cc",
|
||||
"cfg-if",
|
||||
"cfg-if 0.1.10",
|
||||
"libc",
|
||||
]
|
||||
|
||||
@@ -1246,7 +1252,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8d575eff3665419f9b83678ff2815858ad9d11567e082f5ac1814baba4e2bcb4"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"cfg-if",
|
||||
"cfg-if 0.1.10",
|
||||
"foreign-types",
|
||||
"lazy_static 1.4.0",
|
||||
"libc",
|
||||
@@ -1299,7 +1305,7 @@ version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c361aa727dd08437f2f1447be8b59a33b0edd15e0fcee698f935613d9efbca9b"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"cfg-if 0.1.10",
|
||||
"cloudabi",
|
||||
"instant",
|
||||
"libc",
|
||||
@@ -1354,9 +1360,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "pkg-config"
|
||||
version = "0.3.18"
|
||||
version = "0.3.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d36492546b6af1463394d46f0c834346f31548646f6ba10849802c9c9a27ac33"
|
||||
checksum = "3831453b3449ceb48b6d9c7ad7c96d5ea673e9b470a1dc578c2ce6521230884c"
|
||||
|
||||
[[package]]
|
||||
name = "pmutil"
|
||||
@@ -1512,9 +1518,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "1.4.0"
|
||||
version = "1.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "36f45b719a674bf4b828ff318906d6c133264c793eff7a41e30074a45b5099e2"
|
||||
checksum = "8963b85b8ce3074fecffde43b4b0dded83ce2f367dc8d363afc56679f3ee820b"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
@@ -1533,9 +1539,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "regex-syntax"
|
||||
version = "0.6.19"
|
||||
version = "0.6.20"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c17be88d9eaa858870aa5e48cc406c206e4600e983fc4f06bbe5750d93d09761"
|
||||
checksum = "8cab7a364d15cde1e505267766a2d3c4e22a843e1a601f0fa7564c0f82ced11c"
|
||||
|
||||
[[package]]
|
||||
name = "region"
|
||||
@@ -1599,7 +1605,7 @@ dependencies = [
|
||||
name = "rustpython"
|
||||
version = "0.1.2"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"cfg-if 0.1.10",
|
||||
"clap",
|
||||
"cpython",
|
||||
"dirs-next",
|
||||
@@ -1633,7 +1639,7 @@ dependencies = [
|
||||
name = "rustpython-common"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"cfg-if 0.1.10",
|
||||
"derive_more",
|
||||
"hexf-parse",
|
||||
"lexical-core",
|
||||
@@ -1725,7 +1731,7 @@ dependencies = [
|
||||
"bstr",
|
||||
"byteorder",
|
||||
"caseless",
|
||||
"cfg-if",
|
||||
"cfg-if 0.1.10",
|
||||
"chrono",
|
||||
"crc",
|
||||
"crc32fast",
|
||||
@@ -1810,7 +1816,6 @@ dependencies = [
|
||||
name = "rustpython_wasm"
|
||||
version = "0.1.2"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"js-sys",
|
||||
"parking_lot",
|
||||
"rustpython-compiler",
|
||||
@@ -1829,7 +1834,7 @@ version = "6.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6f0d5e7b0219a3eadd5439498525d4765c59b7c993ef0c12244865cd2d988413"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"cfg-if 0.1.10",
|
||||
"dirs-next",
|
||||
"libc",
|
||||
"log",
|
||||
@@ -1881,9 +1886,9 @@ checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.116"
|
||||
version = "1.0.117"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "96fe57af81d28386a513cbc6858332abc6117cfdb5999647c6444b8f43a370a5"
|
||||
checksum = "b88fa983de7720629c9387e9f517353ed404164b1e482c970a90c1a4aaf7dc1a"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
@@ -1902,9 +1907,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.116"
|
||||
version = "1.0.117"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f630a6370fd8e457873b4bd2ffdae75408bc291ba72be773772a4c2a065d9ae8"
|
||||
checksum = "cbd1ae72adb44aab48f325a02444a5fc079349a8d804c1fc922aed3f7454c74e"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -1913,9 +1918,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
version = "1.0.58"
|
||||
version = "1.0.59"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a230ea9107ca2220eea9d46de97eddcb04cd00e92d13dda78e478dd33fa82bd4"
|
||||
checksum = "dcac07dbffa1c65e7f816ab9eba78eb142c6d44410f4eeba1e26e4f5dfa56b95"
|
||||
dependencies = [
|
||||
"itoa",
|
||||
"ryu",
|
||||
@@ -1983,7 +1988,7 @@ version = "0.3.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b1fa70dc5c8104ec096f4fe7ede7a221d35ae13dcd19ba1ad9a81d2cab9a1c44"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"cfg-if 0.1.10",
|
||||
"libc",
|
||||
"redox_syscall",
|
||||
"winapi",
|
||||
@@ -2399,7 +2404,7 @@ version = "0.2.68"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1ac64ead5ea5f05873d7c12b545865ca2b8d28adfc50a49b84770a3a97265d42"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"cfg-if 0.1.10",
|
||||
"wasm-bindgen-macro",
|
||||
]
|
||||
|
||||
@@ -2424,7 +2429,7 @@ version = "0.4.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b7866cab0aa01de1edf8b5d7936938a7e397ee50ce24119aef3e1eaa3b6171da"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"cfg-if 0.1.10",
|
||||
"js-sys",
|
||||
"wasm-bindgen",
|
||||
"web-sys",
|
||||
|
||||
@@ -502,7 +502,7 @@ impl ToTokens for GetSetNursery {
|
||||
class.set_str_attr(
|
||||
#name,
|
||||
::rustpython_vm::pyobject::PyObject::new(
|
||||
::rustpython_vm::builtins::getset::PyGetSet::#constructor(#name.into(), &Self::#getter #setter),
|
||||
::rustpython_vm::builtins::PyGetSet::#constructor(#name.into(), &Self::#getter #setter),
|
||||
ctx.types.getset_type.clone(), None)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -29,6 +29,7 @@ pub use function::PyFunction;
|
||||
pub(crate) mod generator;
|
||||
pub use generator::PyGenerator;
|
||||
pub(crate) mod getset;
|
||||
pub use getset::PyGetSet;
|
||||
pub(crate) mod int;
|
||||
pub use int::{PyInt, PyIntRef};
|
||||
pub(crate) mod iter;
|
||||
|
||||
@@ -72,6 +72,10 @@ impl PyBaseException {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn get_arg(&self, idx: usize) -> Option<PyObjectRef> {
|
||||
self.args.read().borrow_value().get(idx).cloned()
|
||||
}
|
||||
|
||||
#[pyproperty]
|
||||
pub fn args(&self) -> PyTupleRef {
|
||||
self.args.read().clone()
|
||||
@@ -641,7 +645,7 @@ fn none_getter(_obj: PyObjectRef, vm: &VirtualMachine) -> PyNoneRef {
|
||||
}
|
||||
|
||||
fn make_arg_getter(idx: usize) -> impl Fn(PyBaseExceptionRef) -> Option<PyObjectRef> {
|
||||
move |exc| exc.args.read().borrow_value().get(idx).cloned()
|
||||
move |exc| exc.get_arg(idx)
|
||||
}
|
||||
|
||||
fn key_error_str(exc: PyBaseExceptionRef, vm: &VirtualMachine) -> PyStrRef {
|
||||
|
||||
@@ -352,6 +352,10 @@ impl<T> Args<T> {
|
||||
pub fn into_vec(self) -> Vec<T> {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn iter(&self) -> std::slice::Iter<T> {
|
||||
self.0.iter()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> From<Vec<T>> for Args<T> {
|
||||
|
||||
+6
-6
@@ -2079,27 +2079,27 @@ mod posix {
|
||||
|
||||
#[pyfunction(name = "WIFSIGNALED")]
|
||||
fn wifsignaled(status: i32) -> bool {
|
||||
unsafe { libc::WIFSIGNALED(status) }
|
||||
libc::WIFSIGNALED(status)
|
||||
}
|
||||
#[pyfunction(name = "WIFSTOPPED")]
|
||||
fn wifstopped(status: i32) -> bool {
|
||||
unsafe { libc::WIFSTOPPED(status) }
|
||||
libc::WIFSTOPPED(status)
|
||||
}
|
||||
#[pyfunction(name = "WIFEXITED")]
|
||||
fn wifexited(status: i32) -> bool {
|
||||
unsafe { libc::WIFEXITED(status) }
|
||||
libc::WIFEXITED(status)
|
||||
}
|
||||
#[pyfunction(name = "WTERMSIG")]
|
||||
fn wtermsig(status: i32) -> i32 {
|
||||
unsafe { libc::WTERMSIG(status) }
|
||||
libc::WTERMSIG(status)
|
||||
}
|
||||
#[pyfunction(name = "WSTOPSIG")]
|
||||
fn wstopsig(status: i32) -> i32 {
|
||||
unsafe { libc::WSTOPSIG(status) }
|
||||
libc::WSTOPSIG(status)
|
||||
}
|
||||
#[pyfunction(name = "WEXITSTATUS")]
|
||||
fn wexitstatus(status: i32) -> i32 {
|
||||
unsafe { libc::WEXITSTATUS(status) }
|
||||
libc::WEXITSTATUS(status)
|
||||
}
|
||||
|
||||
#[pyfunction]
|
||||
|
||||
@@ -19,7 +19,6 @@ rustpython-compiler = { path = "../../compiler" }
|
||||
rustpython-parser = { path = "../../parser" }
|
||||
# no threading feature for rustpython-vm -- doesn't much matter anyway, but it might be more optimized
|
||||
rustpython-vm = { path = "../../vm", default-features = false, features = ["compile-parse"] }
|
||||
cfg-if = "0.1.2"
|
||||
wasm-bindgen = "0.2"
|
||||
wasm-bindgen-futures = "0.4"
|
||||
serde-wasm-bindgen = "0.1"
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
from _browser import *
|
||||
|
||||
from _js import JsValue
|
||||
from _js import JSValue, Promise
|
||||
from _window import window
|
||||
|
||||
|
||||
jsstr = window.new_from_str
|
||||
jsclosure = window.new_closure
|
||||
|
||||
|
||||
_alert = window.get_prop("alert")
|
||||
|
||||
@@ -1,20 +1,18 @@
|
||||
use js_sys::Promise;
|
||||
use std::future::Future;
|
||||
use wasm_bindgen::prelude::*;
|
||||
use wasm_bindgen::JsCast;
|
||||
use wasm_bindgen_futures::{future_to_promise, JsFuture};
|
||||
use wasm_bindgen_futures::JsFuture;
|
||||
|
||||
use rustpython_vm::builtins::{PyDictRef, PyStrRef, PyTypeRef};
|
||||
use rustpython_vm::common::rc::PyRc;
|
||||
use rustpython_vm::function::OptionalArg;
|
||||
use rustpython_vm::import::import_file;
|
||||
use rustpython_vm::pyobject::{
|
||||
BorrowValue, IntoPyObject, PyCallable, PyClassImpl, PyObject, PyObjectRef, PyRef, PyResult,
|
||||
PyValue,
|
||||
BorrowValue, IntoPyObject, PyCallable, PyClassImpl, PyObject, PyObjectRef, PyResult, PyValue,
|
||||
};
|
||||
use rustpython_vm::VirtualMachine;
|
||||
|
||||
use crate::{convert, vm_class::weak_vm, wasm_builtins::window};
|
||||
use crate::{convert, js_module::PyPromise, vm_class::weak_vm, wasm_builtins::window};
|
||||
|
||||
enum FetchResponseFormat {
|
||||
Json,
|
||||
@@ -155,100 +153,6 @@ fn browser_cancel_animation_frame(id: i32, vm: &VirtualMachine) -> PyResult<()>
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[pyclass(module = "browser", name = "Promise")]
|
||||
#[derive(Debug)]
|
||||
pub struct PyPromise {
|
||||
value: Promise,
|
||||
}
|
||||
pub type PyPromiseRef = PyRef<PyPromise>;
|
||||
|
||||
impl PyValue for PyPromise {
|
||||
fn class(vm: &VirtualMachine) -> PyTypeRef {
|
||||
vm.class("browser", "Promise")
|
||||
}
|
||||
}
|
||||
|
||||
#[pyimpl]
|
||||
impl PyPromise {
|
||||
pub fn new(value: Promise) -> PyPromise {
|
||||
PyPromise { value }
|
||||
}
|
||||
pub fn from_future<F>(future: F) -> PyPromise
|
||||
where
|
||||
F: Future<Output = Result<JsValue, JsValue>> + 'static,
|
||||
{
|
||||
PyPromise::new(future_to_promise(future))
|
||||
}
|
||||
pub fn value(&self) -> Promise {
|
||||
self.value.clone()
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
fn then(
|
||||
&self,
|
||||
on_fulfill: PyCallable,
|
||||
on_reject: OptionalArg<PyCallable>,
|
||||
vm: &VirtualMachine,
|
||||
) -> PyPromiseRef {
|
||||
let weak_vm = weak_vm(vm);
|
||||
let prom = JsFuture::from(self.value.clone());
|
||||
|
||||
let ret_future = async move {
|
||||
let stored_vm = &weak_vm
|
||||
.upgrade()
|
||||
.expect("that the vm is valid when the promise resolves");
|
||||
let res = prom.await;
|
||||
match res {
|
||||
Ok(val) => stored_vm.interp.enter(move |vm| {
|
||||
let args = if val.is_null() {
|
||||
vec![]
|
||||
} else {
|
||||
vec![convert::js_to_py(vm, val)]
|
||||
};
|
||||
let res = vm.invoke(&on_fulfill.into_object(), args);
|
||||
convert::pyresult_to_jsresult(vm, res)
|
||||
}),
|
||||
Err(err) => {
|
||||
if let OptionalArg::Present(on_reject) = on_reject {
|
||||
stored_vm.interp.enter(move |vm| {
|
||||
let err = convert::js_to_py(vm, err);
|
||||
let res = vm.invoke(&on_reject.into_object(), (err,));
|
||||
convert::pyresult_to_jsresult(vm, res)
|
||||
})
|
||||
} else {
|
||||
Err(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
PyPromise::from_future(ret_future).into_ref(vm)
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
fn catch(&self, on_reject: PyCallable, vm: &VirtualMachine) -> PyPromiseRef {
|
||||
let weak_vm = weak_vm(vm);
|
||||
let prom = JsFuture::from(self.value.clone());
|
||||
|
||||
let ret_future = async move {
|
||||
let err = match prom.await {
|
||||
Ok(x) => return Ok(x),
|
||||
Err(e) => e,
|
||||
};
|
||||
let stored_vm = weak_vm
|
||||
.upgrade()
|
||||
.expect("that the vm is valid when the promise resolves");
|
||||
stored_vm.interp.enter(move |vm| {
|
||||
let err = convert::js_to_py(vm, err);
|
||||
let res = vm.invoke(&on_reject.into_object(), (err,));
|
||||
convert::pyresult_to_jsresult(vm, res)
|
||||
})
|
||||
};
|
||||
|
||||
PyPromise::from_future(ret_future).into_ref(vm)
|
||||
}
|
||||
}
|
||||
|
||||
#[pyclass(module = "browser", name)]
|
||||
#[derive(Debug)]
|
||||
struct Document {
|
||||
@@ -347,8 +251,6 @@ fn browser_load_module(module: PyStrRef, path: PyStrRef, vm: &VirtualMachine) ->
|
||||
pub fn make_module(vm: &VirtualMachine) -> PyObjectRef {
|
||||
let ctx = &vm.ctx;
|
||||
|
||||
let promise = PyPromise::make_class(ctx);
|
||||
|
||||
let document_class = Document::make_class(ctx);
|
||||
|
||||
let document = PyObject::new(
|
||||
@@ -361,11 +263,10 @@ pub fn make_module(vm: &VirtualMachine) -> PyObjectRef {
|
||||
|
||||
let element = Element::make_class(ctx);
|
||||
|
||||
py_module!(vm, "browser", {
|
||||
py_module!(vm, "_browser", {
|
||||
"fetch" => ctx.new_function(browser_fetch),
|
||||
"request_animation_frame" => ctx.new_function(browser_request_animation_frame),
|
||||
"cancel_animation_frame" => ctx.new_function(browser_cancel_animation_frame),
|
||||
"Promise" => promise,
|
||||
"Document" => document_class,
|
||||
"document" => document,
|
||||
"Element" => element,
|
||||
|
||||
+62
-41
@@ -12,7 +12,7 @@ use rustpython_vm::pyobject::{
|
||||
use rustpython_vm::VirtualMachine;
|
||||
use rustpython_vm::{exceptions, py_serde};
|
||||
|
||||
use crate::browser_module;
|
||||
use crate::js_module;
|
||||
use crate::vm_class::{stored_vm_from_wasm, WASMVirtualMachine};
|
||||
|
||||
#[wasm_bindgen(inline_js = r"
|
||||
@@ -35,10 +35,25 @@ extern "C" {
|
||||
}
|
||||
|
||||
pub fn py_err_to_js_err(vm: &VirtualMachine, py_err: &PyBaseExceptionRef) -> JsValue {
|
||||
let res = serde_wasm_bindgen::to_value(&exceptions::SerializeException::new(vm, py_err));
|
||||
match res {
|
||||
Ok(err_info) => PyError::new(err_info).into(),
|
||||
Err(e) => e.into(),
|
||||
let jserr = vm.try_class("_js", "JSError").ok();
|
||||
let js_arg = if jserr.map_or(false, |jserr| py_err.isinstance(&jserr)) {
|
||||
py_err.get_arg(0)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let js_arg = js_arg
|
||||
.as_ref()
|
||||
.and_then(|x| x.payload::<js_module::PyJsValue>());
|
||||
match js_arg {
|
||||
Some(val) => val.value.clone(),
|
||||
None => {
|
||||
let res =
|
||||
serde_wasm_bindgen::to_value(&exceptions::SerializeException::new(vm, py_err));
|
||||
match res {
|
||||
Ok(err_info) => PyError::new(err_info).into(),
|
||||
Err(e) => e.into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -74,37 +89,42 @@ pub fn py_to_js(vm: &VirtualMachine, py_obj: PyObjectRef) -> JsValue {
|
||||
};
|
||||
let weak_py_obj = wasm_vm.push_held_rc(py_obj).unwrap();
|
||||
|
||||
let closure =
|
||||
move |args: Option<Array>, kwargs: Option<Object>| -> Result<JsValue, JsValue> {
|
||||
let py_obj = match wasm_vm.assert_valid() {
|
||||
Ok(_) => weak_py_obj
|
||||
.upgrade()
|
||||
.expect("weak_py_obj to be valid if VM is valid"),
|
||||
Err(err) => {
|
||||
return Err(err);
|
||||
}
|
||||
};
|
||||
stored_vm_from_wasm(&wasm_vm).interp.enter(move |vm| {
|
||||
let mut py_func_args = FuncArgs::default();
|
||||
if let Some(ref args) = args {
|
||||
for arg in args.values() {
|
||||
py_func_args.args.push(js_to_py(vm, arg?));
|
||||
}
|
||||
}
|
||||
if let Some(ref kwargs) = kwargs {
|
||||
for pair in object_entries(kwargs) {
|
||||
let (key, val) = pair?;
|
||||
py_func_args
|
||||
.kwargs
|
||||
.insert(js_sys::JsString::from(key).into(), js_to_py(vm, val));
|
||||
}
|
||||
}
|
||||
let result = vm.invoke(&py_obj, py_func_args);
|
||||
pyresult_to_jsresult(vm, result)
|
||||
})
|
||||
let closure = move |args: Option<Box<[JsValue]>>,
|
||||
kwargs: Option<Object>|
|
||||
-> Result<JsValue, JsValue> {
|
||||
let py_obj = match wasm_vm.assert_valid() {
|
||||
Ok(_) => weak_py_obj
|
||||
.upgrade()
|
||||
.expect("weak_py_obj to be valid if VM is valid"),
|
||||
Err(err) => {
|
||||
return Err(err);
|
||||
}
|
||||
};
|
||||
stored_vm_from_wasm(&wasm_vm).interp.enter(move |vm| {
|
||||
let args = match args {
|
||||
Some(args) => Vec::from(args)
|
||||
.into_iter()
|
||||
.map(|arg| js_to_py(vm, arg))
|
||||
.collect::<Vec<_>>(),
|
||||
None => Vec::new(),
|
||||
};
|
||||
let mut py_func_args = FuncArgs::from(args);
|
||||
if let Some(ref kwargs) = kwargs {
|
||||
for pair in object_entries(kwargs) {
|
||||
let (key, val) = pair?;
|
||||
py_func_args
|
||||
.kwargs
|
||||
.insert(js_sys::JsString::from(key).into(), js_to_py(vm, val));
|
||||
}
|
||||
}
|
||||
let result = vm.invoke(&py_obj, py_func_args);
|
||||
pyresult_to_jsresult(vm, result)
|
||||
})
|
||||
};
|
||||
let closure = Closure::wrap(Box::new(closure)
|
||||
as Box<dyn FnMut(Option<Array>, Option<Object>) -> Result<JsValue, JsValue>>);
|
||||
as Box<
|
||||
dyn FnMut(Option<Box<[JsValue]>>, Option<Object>) -> Result<JsValue, JsValue>,
|
||||
>);
|
||||
let func = closure.as_ref().clone();
|
||||
|
||||
// stores pretty much nothing, it's fine to leak this because if it gets dropped
|
||||
@@ -115,8 +135,8 @@ pub fn py_to_js(vm: &VirtualMachine, py_obj: PyObjectRef) -> JsValue {
|
||||
}
|
||||
}
|
||||
// the browser module might not be injected
|
||||
if vm.try_class("browser", "Promise").is_ok() {
|
||||
if let Some(py_prom) = py_obj.payload::<browser_module::PyPromise>() {
|
||||
if vm.try_class("_js", "Promise").is_ok() {
|
||||
if let Some(py_prom) = py_obj.payload::<js_module::PyPromise>() {
|
||||
return py_prom.value().into();
|
||||
}
|
||||
}
|
||||
@@ -157,7 +177,7 @@ pub fn js_to_py(vm: &VirtualMachine, js_val: JsValue) -> PyObjectRef {
|
||||
if let Some(promise) = js_val.dyn_ref::<Promise>() {
|
||||
// the browser module might not be injected
|
||||
if vm.try_class("browser", "Promise").is_ok() {
|
||||
return browser_module::PyPromise::new(promise.clone())
|
||||
return js_module::PyPromise::new(promise.clone())
|
||||
.into_ref(vm)
|
||||
.into_object();
|
||||
}
|
||||
@@ -205,10 +225,11 @@ pub fn js_to_py(vm: &VirtualMachine, js_val: JsValue) -> PyObjectRef {
|
||||
Reflect::set(&this, &k.into(), &py_to_js(vm, v))
|
||||
.expect("property to be settable");
|
||||
}
|
||||
let js_args = Array::new();
|
||||
for v in args.args {
|
||||
js_args.push(&py_to_js(vm, v));
|
||||
}
|
||||
let js_args = args
|
||||
.args
|
||||
.into_iter()
|
||||
.map(|v| py_to_js(vm, v))
|
||||
.collect::<Array>();
|
||||
func.apply(&this, &js_args)
|
||||
.map(|val| js_to_py(vm, val))
|
||||
.map_err(|err| js_err_to_py_err(vm, &err))
|
||||
|
||||
+265
-34
@@ -1,14 +1,21 @@
|
||||
use js_sys::{Array, Object, Reflect};
|
||||
use crate::convert;
|
||||
use crate::vm_class::{stored_vm_from_wasm, WASMVirtualMachine};
|
||||
use crate::weak_vm;
|
||||
use js_sys::{Array, Object, Promise, Reflect};
|
||||
use std::{cell, fmt, future};
|
||||
use wasm_bindgen::{closure::Closure, prelude::*, JsCast};
|
||||
use wasm_bindgen_futures::{future_to_promise, JsFuture};
|
||||
|
||||
use rustpython_vm::builtins::{PyFloatRef, PyStrRef, PyTypeRef};
|
||||
use rustpython_vm::common::rc::PyRc;
|
||||
use rustpython_vm::exceptions::PyBaseExceptionRef;
|
||||
use rustpython_vm::function::Args;
|
||||
use rustpython_vm::function::{Args, OptionalArg};
|
||||
use rustpython_vm::pyobject::{
|
||||
BorrowValue, PyClassImpl, PyObjectRef, PyRef, PyResult, PyValue, TryFromObject,
|
||||
BorrowValue, IntoPyObject, PyCallable, PyClassImpl, PyObjectRef, PyRef, PyResult, PyValue,
|
||||
TryFromObject,
|
||||
};
|
||||
use rustpython_vm::types::create_type;
|
||||
use rustpython_vm::VirtualMachine;
|
||||
use wasm_bindgen::{prelude::*, JsCast};
|
||||
|
||||
#[wasm_bindgen(inline_js = "
|
||||
export function has_prop(target, prop) { return prop in Object(target); }
|
||||
@@ -16,6 +23,13 @@ export function get_prop(target, prop) { return target[prop]; }
|
||||
export function set_prop(target, prop, value) { target[prop] = value; }
|
||||
export function type_of(a) { return typeof a; }
|
||||
export function instance_of(lhs, rhs) { return lhs instanceof rhs; }
|
||||
export function call_func(func, args) { return func(...args); }
|
||||
export function call_method(obj, method, args) { return obj[method](...args) }
|
||||
export function wrap_closure(closure) {
|
||||
return function pyfunction(...args) {
|
||||
closure(this, args)
|
||||
}
|
||||
}
|
||||
")]
|
||||
extern "C" {
|
||||
#[wasm_bindgen(catch)]
|
||||
@@ -28,22 +42,30 @@ extern "C" {
|
||||
fn type_of(a: &JsValue) -> String;
|
||||
#[wasm_bindgen(catch)]
|
||||
fn instance_of(lhs: &JsValue, rhs: &JsValue) -> Result<bool, JsValue>;
|
||||
#[wasm_bindgen(catch)]
|
||||
fn call_func(func: &JsValue, args: &Array) -> Result<JsValue, JsValue>;
|
||||
#[wasm_bindgen(catch)]
|
||||
fn call_method(obj: &JsValue, method: &JsValue, args: &Array) -> Result<JsValue, JsValue>;
|
||||
#[wasm_bindgen]
|
||||
fn wrap_closure(closure: &JsValue) -> JsValue;
|
||||
}
|
||||
|
||||
#[pyclass(module = "_js", name = "JsValue")]
|
||||
#[pyclass(module = "_js", name = "JSValue")]
|
||||
#[derive(Debug)]
|
||||
pub struct PyJsValue {
|
||||
value: JsValue,
|
||||
pub(crate) value: JsValue,
|
||||
}
|
||||
type PyJsValueRef = PyRef<PyJsValue>;
|
||||
|
||||
// TODO: Fix this when threading is supported in WASM.
|
||||
unsafe impl Send for PyJsValue {}
|
||||
unsafe impl Sync for PyJsValue {}
|
||||
|
||||
impl PyValue for PyJsValue {
|
||||
fn class(vm: &VirtualMachine) -> PyTypeRef {
|
||||
vm.class("_js", "JsValue")
|
||||
vm.class("_js", "JSValue")
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<JsValue> for PyJsValue {
|
||||
fn as_ref(&self) -> &JsValue {
|
||||
&self.value
|
||||
}
|
||||
}
|
||||
|
||||
@@ -98,6 +120,11 @@ impl PyJsValue {
|
||||
PyJsValue::new(n.to_f64())
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
fn new_closure(&self, obj: PyObjectRef, vm: &VirtualMachine) -> JsClosure {
|
||||
JsClosure::new(obj, vm)
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
fn new_object(&self, opts: NewObjectOptions, vm: &VirtualMachine) -> PyResult<PyJsValue> {
|
||||
let value = if let Some(proto) = opts.prototype {
|
||||
@@ -148,15 +175,23 @@ impl PyJsValue {
|
||||
.value
|
||||
.dyn_ref::<js_sys::Function>()
|
||||
.ok_or_else(|| vm.new_type_error("JS value is not callable".to_owned()))?;
|
||||
let this = opts
|
||||
.this
|
||||
.map(|this| this.value.clone())
|
||||
.unwrap_or(JsValue::UNDEFINED);
|
||||
let js_args = Array::new();
|
||||
for arg in args {
|
||||
js_args.push(&arg.value);
|
||||
}
|
||||
Reflect::apply(func, &this, &js_args)
|
||||
let js_args = args.iter().map(|x| x.as_ref()).collect::<Array>();
|
||||
let res = match opts.this {
|
||||
Some(this) => Reflect::apply(func, &this.value, &js_args),
|
||||
None => call_func(func, &js_args),
|
||||
};
|
||||
res.map(PyJsValue::new).map_err(|err| new_js_error(vm, err))
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
fn call_method(
|
||||
&self,
|
||||
name: JsProperty,
|
||||
args: Args<PyJsValueRef>,
|
||||
vm: &VirtualMachine,
|
||||
) -> PyResult<PyJsValue> {
|
||||
let js_args = args.iter().map(|x| x.as_ref()).collect::<Array>();
|
||||
call_method(&self.value, &name.into_jsvalue(), &js_args)
|
||||
.map(PyJsValue::new)
|
||||
.map_err(|err| new_js_error(vm, err))
|
||||
}
|
||||
@@ -176,10 +211,7 @@ impl PyJsValue {
|
||||
.prototype
|
||||
.as_ref()
|
||||
.and_then(|proto| proto.value.dyn_ref::<js_sys::Function>());
|
||||
let js_args = Array::new();
|
||||
for arg in args {
|
||||
js_args.push(&arg.value);
|
||||
}
|
||||
let js_args = args.iter().map(|x| x.as_ref()).collect::<Array>();
|
||||
let constructed_result = if let Some(proto) = proto {
|
||||
Reflect::construct_with_new_target(ctor, &js_args, &proto)
|
||||
} else {
|
||||
@@ -211,9 +243,9 @@ impl PyJsValue {
|
||||
type_of(&self.value)
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
/// Checks that `typeof self == "object" && self !== null`. Use instead
|
||||
/// of `value.typeof() == "object"`
|
||||
#[pymethod]
|
||||
fn is_object(&self) -> bool {
|
||||
self.value.is_object()
|
||||
}
|
||||
@@ -241,22 +273,221 @@ struct NewObjectOptions {
|
||||
prototype: Option<PyJsValueRef>,
|
||||
}
|
||||
|
||||
type ClosureType = Closure<dyn Fn(JsValue, Box<[JsValue]>) -> Result<JsValue, JsValue>>;
|
||||
|
||||
#[pyclass(module = "_js", name = "JSClosure")]
|
||||
struct JsClosure {
|
||||
closure: cell::RefCell<Option<(ClosureType, PyJsValueRef)>>,
|
||||
destroyed: cell::Cell<bool>,
|
||||
detached: cell::Cell<bool>,
|
||||
}
|
||||
|
||||
impl fmt::Debug for JsClosure {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
f.pad("JsClosure")
|
||||
}
|
||||
}
|
||||
|
||||
impl PyValue for JsClosure {
|
||||
fn class(vm: &VirtualMachine) -> PyTypeRef {
|
||||
vm.class("_js", "JSClosure")
|
||||
}
|
||||
}
|
||||
|
||||
#[pyimpl]
|
||||
impl JsClosure {
|
||||
fn new(obj: PyObjectRef, vm: &VirtualMachine) -> Self {
|
||||
let wasm_vm = WASMVirtualMachine {
|
||||
id: vm.wasm_id.clone().unwrap(),
|
||||
};
|
||||
let weak_py_obj = wasm_vm.push_held_rc(obj).unwrap();
|
||||
let f = move |this: JsValue, args: Box<[JsValue]>| {
|
||||
let py_obj = match wasm_vm.assert_valid() {
|
||||
Ok(_) => weak_py_obj
|
||||
.upgrade()
|
||||
.expect("weak_py_obj to be valid if VM is valid"),
|
||||
Err(err) => {
|
||||
return Err(err);
|
||||
}
|
||||
};
|
||||
stored_vm_from_wasm(&wasm_vm).interp.enter(move |vm| {
|
||||
let mut pyargs = vec![PyJsValue::new(this).into_object(vm)];
|
||||
pyargs.extend(
|
||||
Vec::from(args)
|
||||
.into_iter()
|
||||
.map(|arg| PyJsValue::new(arg).into_object(vm)),
|
||||
);
|
||||
let res = vm.invoke(&py_obj, pyargs);
|
||||
convert::pyresult_to_jsresult(vm, res)
|
||||
})
|
||||
};
|
||||
let closure = Closure::wrap(Box::new(f) as _);
|
||||
let wrapped = PyJsValue::new(wrap_closure(closure.as_ref())).into_ref(vm);
|
||||
JsClosure {
|
||||
closure: Some((closure, wrapped)).into(),
|
||||
destroyed: false.into(),
|
||||
detached: false.into(),
|
||||
}
|
||||
}
|
||||
|
||||
#[pyproperty]
|
||||
fn value(&self) -> Option<PyJsValueRef> {
|
||||
self.closure
|
||||
.borrow()
|
||||
.as_ref()
|
||||
.map(|(_, jsval)| jsval.clone())
|
||||
}
|
||||
#[pyproperty]
|
||||
fn destroyed(&self) -> bool {
|
||||
self.destroyed.get()
|
||||
}
|
||||
#[pyproperty]
|
||||
fn detached(&self) -> bool {
|
||||
self.detached.get()
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
fn destroy(&self, vm: &VirtualMachine) -> PyResult<()> {
|
||||
let (closure, _) = self.closure.replace(None).ok_or_else(|| {
|
||||
vm.new_value_error(
|
||||
"can't destroy closure has already been destroyed or detached".to_owned(),
|
||||
)
|
||||
})?;
|
||||
drop(closure);
|
||||
self.destroyed.set(true);
|
||||
Ok(())
|
||||
}
|
||||
#[pymethod]
|
||||
fn detach(&self, vm: &VirtualMachine) -> PyResult<PyJsValueRef> {
|
||||
let (closure, jsval) = self.closure.replace(None).ok_or_else(|| {
|
||||
vm.new_value_error(
|
||||
"can't detach closure has already been detached or destroyed".to_owned(),
|
||||
)
|
||||
})?;
|
||||
closure.forget();
|
||||
self.detached.set(true);
|
||||
Ok(jsval)
|
||||
}
|
||||
}
|
||||
|
||||
#[pyclass(module = "browser", name = "Promise")]
|
||||
#[derive(Debug)]
|
||||
pub struct PyPromise {
|
||||
value: Promise,
|
||||
}
|
||||
pub type PyPromiseRef = PyRef<PyPromise>;
|
||||
|
||||
impl PyValue for PyPromise {
|
||||
fn class(vm: &VirtualMachine) -> PyTypeRef {
|
||||
vm.class("browser", "Promise")
|
||||
}
|
||||
}
|
||||
|
||||
#[pyimpl]
|
||||
impl PyPromise {
|
||||
pub fn new(value: Promise) -> PyPromise {
|
||||
PyPromise { value }
|
||||
}
|
||||
pub fn from_future<F>(future: F) -> PyPromise
|
||||
where
|
||||
F: future::Future<Output = Result<JsValue, JsValue>> + 'static,
|
||||
{
|
||||
PyPromise::new(future_to_promise(future))
|
||||
}
|
||||
pub fn value(&self) -> Promise {
|
||||
self.value.clone()
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
fn then(
|
||||
&self,
|
||||
on_fulfill: PyCallable,
|
||||
on_reject: OptionalArg<PyCallable>,
|
||||
vm: &VirtualMachine,
|
||||
) -> PyPromiseRef {
|
||||
let weak_vm = weak_vm(vm);
|
||||
let prom = JsFuture::from(self.value.clone());
|
||||
|
||||
let ret_future = async move {
|
||||
let stored_vm = &weak_vm
|
||||
.upgrade()
|
||||
.expect("that the vm is valid when the promise resolves");
|
||||
let res = prom.await;
|
||||
match res {
|
||||
Ok(val) => stored_vm.interp.enter(move |vm| {
|
||||
let args = if val.is_null() {
|
||||
vec![]
|
||||
} else {
|
||||
vec![convert::js_to_py(vm, val)]
|
||||
};
|
||||
let res = vm.invoke(&on_fulfill.into_object(), args);
|
||||
convert::pyresult_to_jsresult(vm, res)
|
||||
}),
|
||||
Err(err) => {
|
||||
if let OptionalArg::Present(on_reject) = on_reject {
|
||||
stored_vm.interp.enter(move |vm| {
|
||||
let err = convert::js_to_py(vm, err);
|
||||
let res = vm.invoke(&on_reject.into_object(), (err,));
|
||||
convert::pyresult_to_jsresult(vm, res)
|
||||
})
|
||||
} else {
|
||||
Err(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
PyPromise::from_future(ret_future).into_ref(vm)
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
fn catch(&self, on_reject: PyCallable, vm: &VirtualMachine) -> PyPromiseRef {
|
||||
let weak_vm = weak_vm(vm);
|
||||
let prom = JsFuture::from(self.value.clone());
|
||||
|
||||
let ret_future = async move {
|
||||
let err = match prom.await {
|
||||
Ok(x) => return Ok(x),
|
||||
Err(e) => e,
|
||||
};
|
||||
let stored_vm = weak_vm
|
||||
.upgrade()
|
||||
.expect("that the vm is valid when the promise resolves");
|
||||
stored_vm.interp.enter(move |vm| {
|
||||
let err = convert::js_to_py(vm, err);
|
||||
let res = vm.invoke(&on_reject.into_object(), (err,));
|
||||
convert::pyresult_to_jsresult(vm, res)
|
||||
})
|
||||
};
|
||||
|
||||
PyPromise::from_future(ret_future).into_ref(vm)
|
||||
}
|
||||
}
|
||||
|
||||
fn new_js_error(vm: &VirtualMachine, err: JsValue) -> PyBaseExceptionRef {
|
||||
let exc = vm.new_exception_msg(vm.class("_js", "JsError"), format!("{:?}", err));
|
||||
vm.set_attr(
|
||||
exc.as_object(),
|
||||
"js_value",
|
||||
PyJsValue::new(err).into_ref(vm),
|
||||
vm.new_exception(
|
||||
vm.class("_js", "JSError"),
|
||||
vec![PyJsValue::new(err).into_pyobject(vm)],
|
||||
)
|
||||
.unwrap();
|
||||
exc
|
||||
}
|
||||
|
||||
pub fn make_module(vm: &VirtualMachine) -> PyObjectRef {
|
||||
let ctx = &vm.ctx;
|
||||
|
||||
let js_error = create_type(
|
||||
"JSError",
|
||||
&ctx.types.type_type,
|
||||
ctx.exceptions.exception_type.clone(),
|
||||
);
|
||||
extend_class!(ctx, &js_error, {
|
||||
"value" => ctx.new_readonly_getset("value", |exc: PyBaseExceptionRef| exc.get_arg(0)),
|
||||
});
|
||||
|
||||
py_module!(vm, "_js", {
|
||||
"JsError" => create_type("JsError", &ctx.types.type_type, ctx.exceptions.exception_type.clone()),
|
||||
"JsValue" => PyJsValue::make_class(ctx),
|
||||
"JSError" => js_error,
|
||||
"JSValue" => PyJsValue::make_class(ctx),
|
||||
"JSClosure" => JsClosure::make_class(ctx),
|
||||
"Promise" => PyPromise::make_class(ctx),
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user