Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
4020ee7
Add a bare-bones VirtualMachine class to the WASM library
coolreader18 Jan 30, 2019
13b2f83
Fix vms.get()
coolreader18 Jan 30, 2019
f064bca
Add ids() function to VMStore and destroy() method to VirtualMachine
coolreader18 Jan 30, 2019
d0a4f9d
Make destroy() method public
coolreader18 Jan 30, 2019
b32b732
Run cargo fmt
coolreader18 Jan 30, 2019
136a476
Call assert_valid() in destroy()
coolreader18 Jan 31, 2019
f47864f
Return Ok(()) from destroy()
coolreader18 Jan 31, 2019
3bec226
Rename VMStore
coolreader18 Feb 5, 2019
f7c91c7
Add add_to_scope() method for WASM VM
coolreader18 Feb 5, 2019
de3762c
Add .run(); fix .addToScope(); add panic-catcher for debugging
coolreader18 Feb 5, 2019
a24cd83
Merge branch 'master' into wasm-vm-class
coolreader18 Feb 5, 2019
9b6516e
Allow closures to be passed from Python to JS if using a WASM VM
coolreader18 Feb 6, 2019
6851767
Fix RefCell borrowing errors
coolreader18 Feb 17, 2019
f55a8ea
Merge branch 'master' into wasm-vm-class
coolreader18 Feb 17, 2019
c83ff47
Fix error with new compile() and set_attr/item()
coolreader18 Feb 17, 2019
3e22c4f
Add print to default vm scope
coolreader18 Feb 17, 2019
a86069d
Store the WASM id in the VirtualMachine, add a (broken) fetch builtin
coolreader18 Feb 17, 2019
f00c3c8
Fix fetch builtin
coolreader18 Feb 17, 2019
00bc9e9
Convert fetch to use wasm_bindgen_futures
coolreader18 Feb 17, 2019
d0b4751
Remove the VM pointer from the map when it's dropped
coolreader18 Feb 17, 2019
7405c84
Add some more options to fetch()
coolreader18 Feb 17, 2019
b043f21
Fix js_py_typeerror
coolreader18 Feb 17, 2019
416f088
Convert `ArrayBuffer`s and `TypedArray`s to Python bytearrays
coolreader18 Feb 17, 2019
bead3f6
Fix conversion from ArrayBuffer, allow array_buffer in fetch
coolreader18 Feb 17, 2019
5244707
Add eval() method, rename run() to exec()
coolreader18 Feb 17, 2019
74e7131
Clean up some code
coolreader18 Feb 18, 2019
101ee77
Improve error messages
coolreader18 Feb 18, 2019
0d3d090
Convert pyEval to use a WASM VM, allowing closures and stuff
coolreader18 Feb 18, 2019
634571f
Remove WASM fetch builtin
coolreader18 Feb 18, 2019
8e5073e
Convert `bytes` and `bytearray`s to `Uint8Array`s
coolreader18 Feb 19, 2019
8c222af
Include details about thread_local! for WASM
coolreader18 Feb 21, 2019
9e17690
Use crate:: imports
coolreader18 Feb 22, 2019
65857e7
Merge
coolreader18 Feb 23, 2019
955d0b3
Merge branch 'master' into wasm-vm-class
coolreader18 Feb 23, 2019
7fa0a0c
Fix open in new make_module
coolreader18 Feb 23, 2019
09e2a7a
Add js_name for .set_stdout()
coolreader18 Feb 23, 2019
e0f222c
Don't hold on to a PyObjectRef from a python -> js closure
coolreader18 Feb 23, 2019
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
Next Next commit
Fix RefCell borrowing errors
  • Loading branch information
coolreader18 committed Feb 17, 2019
commit 68517676541b3d6a6ee3d1987f80ba86b24e81c2
55 changes: 26 additions & 29 deletions wasm/lib/src/convert.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use js_sys::{Array, Object, Reflect};
use rustpython_vm::pyobject::{self, PyFuncArgs, PyObjectRef, PyResult};
use rustpython_vm::VirtualMachine;
use vm_class::{StoredVirtualMachine, WASMVirtualMachine};
use vm_class::{AccessibleVM, WASMVirtualMachine};
use wasm_bindgen::{closure::Closure, prelude::*, JsCast};

pub fn py_str_err(vm: &mut VirtualMachine, py_err: &PyObjectRef) -> String {
Expand All @@ -16,39 +16,36 @@ pub fn py_to_js(
) -> JsValue {
if let Some(wasm_vm) = wasm_vm {
if rustpython_vm::obj::objtype::isinstance(&py_obj, &vm.ctx.function_type()) {
let closure = Closure::wrap(Box::new(
let closure =
move |args: Option<Array>, kwargs: Option<Object>| -> Result<JsValue, JsValue> {
let py_obj = py_obj.clone();
let wasm_vm = wasm_vm.clone();
wasm_vm.assert_valid()?;
let wasm_vm_clone = wasm_vm.clone();
wasm_vm.with_unchecked(move |StoredVirtualMachine { ref mut vm, .. }| {
let vm: &mut VirtualMachine = vm;
let mut py_func_args = rustpython_vm::pyobject::PyFuncArgs::default();
if let Some(ref args) = args {
for arg in args.values() {
py_func_args.args.push(js_to_py(
vm,
arg?,
Some(wasm_vm_clone.clone()),
));
}
let acc_vm = AccessibleVM::from(wasm_vm.clone());
let vm = acc_vm
.upgrade()
.expect("acc. VM to be invalid when WASM vm is valid");
let mut py_func_args = rustpython_vm::pyobject::PyFuncArgs::default();
if let Some(ref args) = args {
for arg in args.values() {
py_func_args
.args
.push(js_to_py(vm, arg?, Some(wasm_vm.clone())));
}
if let Some(ref kwargs) = kwargs {
for pair in object_entries(kwargs) {
let (key, val) = pair?;
py_func_args.kwargs.push((
js_sys::JsString::from(key).into(),
js_to_py(vm, val, Some(wasm_vm_clone.clone())),
));
}
}
if let Some(ref kwargs) = kwargs {
for pair in object_entries(kwargs) {
let (key, val) = pair?;
py_func_args.kwargs.push((
js_sys::JsString::from(key).into(),
js_to_py(vm, val, Some(wasm_vm.clone())),
));
}
let result = vm.invoke(py_obj.clone(), py_func_args);
pyresult_to_jsresult(vm, result, Some(wasm_vm_clone.clone()))
})
},
)
as Box<Fn(Option<Array>, Option<Object>) -> Result<JsValue, JsValue>>);
}
let result = vm.invoke(py_obj.clone(), py_func_args);
pyresult_to_jsresult(vm, result, Some(wasm_vm.clone()))
};
let closure = Closure::wrap(Box::new(closure)
as Box<dyn Fn(Option<Array>, Option<Object>) -> Result<JsValue, JsValue>>);
let func = closure.as_ref().clone();

// TODO: Come up with a way of managing closure handles
Expand Down
74 changes: 67 additions & 7 deletions wasm/lib/src/vm_class.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
use convert;
use js_sys::TypeError;
use rustpython_vm::{compile, pyobject::PyObjectRef, VirtualMachine};
use rustpython_vm::{
compile,
pyobject::{PyObjectRef, PyRef},
VirtualMachine,
};
use std::cell::RefCell;
use std::collections::HashMap;
use std::rc::Rc;
use std::rc::{Rc, Weak};
use wasm_bindgen::prelude::*;

pub(crate) struct StoredVirtualMachine {
Expand All @@ -22,7 +26,8 @@ impl StoredVirtualMachine {

// It's fine that it's thread local, since WASM doesn't even have threads yet
thread_local! {
Comment thread
coolreader18 marked this conversation as resolved.
static STORED_VMS: Rc<RefCell<HashMap<String, StoredVirtualMachine>>> = Rc::default();
static STORED_VMS: PyRef<HashMap<String, PyRef<StoredVirtualMachine>>> = Rc::default();
static ACTIVE_VMS: PyRef<HashMap<String, *mut VirtualMachine>> = Rc::default();
}

#[wasm_bindgen(js_name = vmStore)]
Expand All @@ -34,7 +39,10 @@ impl VMStore {
STORED_VMS.with(|cell| {
let mut vms = cell.borrow_mut();
if !vms.contains_key(&id) {
vms.insert(id.clone(), StoredVirtualMachine::new());
vms.insert(
id.clone(),
Rc::new(RefCell::new(StoredVirtualMachine::new())),
);
}
});
WASMVirtualMachine { id }
Expand All @@ -53,7 +61,18 @@ impl VMStore {

pub fn destroy(id: String) {
STORED_VMS.with(|cell| {
cell.borrow_mut().remove(&id);
use std::collections::hash_map::Entry;
match cell.borrow_mut().entry(id) {
Entry::Occupied(o) => {
let (_k, stored_vm) = o.remove_entry();
// for f in stored_vm.drop_handlers.iter() {
// f();
// }
// deallocate the VM
drop(stored_vm);
}
Entry::Vacant(_v) => {}
}
});
}

Expand All @@ -62,6 +81,47 @@ impl VMStore {
}
}

pub(crate) struct AccessibleVM {
weak: Weak<RefCell<StoredVirtualMachine>>,
id: String,
}

impl AccessibleVM {
pub fn from_id(id: String) -> AccessibleVM {
let weak = STORED_VMS
.with(|cell| Rc::downgrade(cell.borrow().get(&id).expect("WASM VM to be valid")));
AccessibleVM { weak, id }
}

pub fn upgrade(&self) -> Option<&mut VirtualMachine> {
let vm_cell = self.weak.upgrade()?;
match vm_cell.try_borrow_mut() {
Ok(mut vm) => {
ACTIVE_VMS.with(|cell| {
cell.borrow_mut().insert(self.id.clone(), &mut vm.vm);
});
}
Err(_) => {}
};
Some(ACTIVE_VMS.with(|cell| {
let vms = cell.borrow();
let ptr = vms.get(&self.id).expect("id to be in ACTIVE_VMS");
unsafe { &mut **ptr }
}))
}
}

impl From<WASMVirtualMachine> for AccessibleVM {
fn from(vm: WASMVirtualMachine) -> AccessibleVM {
AccessibleVM::from_id(vm.id)
}
}
impl From<&WASMVirtualMachine> for AccessibleVM {
fn from(vm: &WASMVirtualMachine) -> AccessibleVM {
AccessibleVM::from_id(vm.id.clone())
}
}

#[wasm_bindgen(js_name = VirtualMachine)]
#[derive(Clone)]
pub struct WASMVirtualMachine {
Expand All @@ -76,8 +136,8 @@ impl WASMVirtualMachine {
{
STORED_VMS.with(|cell| {
let mut vms = cell.borrow_mut();
let stored_vm = vms.get_mut(&self.id).unwrap();
f(stored_vm)
let mut stored_vm = vms.get_mut(&self.id).unwrap().borrow_mut();
f(&mut stored_vm)
})
}

Expand Down