Skip to content

Commit 3730ca2

Browse files
authored
Merge pull request #551 from coolreader18/store-rcs-in-stored-vm
[WASM] Keep a PyObjectWeakRef to the PyObjectRef being moved to a closure
2 parents 9e827cf + f1b156d commit 3730ca2

File tree

2 files changed

+33
-5
lines changed

2 files changed

+33
-5
lines changed

wasm/lib/src/convert.rs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,15 @@ pub fn py_to_js(vm: &mut VirtualMachine, py_obj: PyObjectRef) -> JsValue {
2222
let wasm_vm = WASMVirtualMachine {
2323
id: wasm_id.clone(),
2424
};
25-
let mut py_obj = Some(py_obj);
25+
let weak_py_obj = wasm_vm.push_held_rc(py_obj).unwrap();
26+
2627
let closure =
2728
move |args: Option<Array>, kwargs: Option<Object>| -> Result<JsValue, JsValue> {
2829
let py_obj = match wasm_vm.assert_valid() {
29-
Ok(_) => py_obj.clone().expect("py_obj to be valid if VM is valid"),
30+
Ok(_) => weak_py_obj
31+
.upgrade()
32+
.expect("weak_py_obj to be valid if VM is valid"),
3033
Err(err) => {
31-
py_obj = None;
3234
return Err(err);
3335
}
3436
};
@@ -57,7 +59,8 @@ pub fn py_to_js(vm: &mut VirtualMachine, py_obj: PyObjectRef) -> JsValue {
5759
as Box<dyn FnMut(Option<Array>, Option<Object>) -> Result<JsValue, JsValue>>);
5860
let func = closure.as_ref().clone();
5961

60-
// TODO: Come up with a way of managing closure handles
62+
// stores pretty much nothing, it's fine to leak this because if it gets dropped
63+
// the error message is worse
6164
closure.forget();
6265

6366
return func;

wasm/lib/src/vm_class.rs

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,16 @@ use std::collections::HashMap;
1313
use std::rc::{Rc, Weak};
1414
use wasm_bindgen::prelude::*;
1515

16+
pub trait HeldRcInner {}
17+
18+
impl<T> HeldRcInner for T {}
19+
1620
pub(crate) struct StoredVirtualMachine {
1721
pub vm: VirtualMachine,
1822
pub scope: ScopeRef,
23+
/// you can put a Rc in here, keep it as a Weak, and it'll be held only for
24+
/// as long as the StoredVM is alive
25+
held_rcs: Vec<Rc<dyn HeldRcInner>>,
1926
}
2027

2128
impl StoredVirtualMachine {
@@ -27,7 +34,11 @@ impl StoredVirtualMachine {
2734
setup_browser_module(&mut vm);
2835
}
2936
vm.wasm_id = Some(id);
30-
StoredVirtualMachine { vm, scope }
37+
StoredVirtualMachine {
38+
vm,
39+
scope,
40+
held_rcs: vec![],
41+
}
3142
}
3243
}
3344

@@ -211,6 +222,17 @@ impl WASMVirtualMachine {
211222
STORED_VMS.with(|cell| cell.borrow().contains_key(&self.id))
212223
}
213224

225+
pub(crate) fn push_held_rc<T: HeldRcInner + 'static>(
226+
&self,
227+
rc: Rc<T>,
228+
) -> Result<Weak<T>, JsValue> {
229+
self.with(|stored_vm| {
230+
let weak = Rc::downgrade(&rc);
231+
stored_vm.held_rcs.push(rc);
232+
weak
233+
})
234+
}
235+
214236
pub fn assert_valid(&self) -> Result<(), JsValue> {
215237
if self.valid() {
216238
Ok(())
@@ -234,6 +256,7 @@ impl WASMVirtualMachine {
234256
move |StoredVirtualMachine {
235257
ref mut vm,
236258
ref mut scope,
259+
..
237260
}| {
238261
let value = convert::js_to_py(vm, value);
239262
scope.locals.set_item(&vm.ctx, &name, value);
@@ -247,6 +270,7 @@ impl WASMVirtualMachine {
247270
move |StoredVirtualMachine {
248271
ref mut vm,
249272
ref mut scope,
273+
..
250274
}| {
251275
let print_fn: Box<Fn(&mut VirtualMachine, PyFuncArgs) -> PyResult> =
252276
if let Some(selector) = stdout.as_string() {
@@ -315,6 +339,7 @@ impl WASMVirtualMachine {
315339
|StoredVirtualMachine {
316340
ref mut vm,
317341
ref mut scope,
342+
..
318343
}| {
319344
source.push('\n');
320345
let code =

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy