Skip to content

Commit bfd14b4

Browse files
committed
Support multiple js functions
1 parent 3eaa830 commit bfd14b4

File tree

2 files changed

+43
-41
lines changed

2 files changed

+43
-41
lines changed

wasm/lib/src/convert.rs

+27-22
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use crate::browser_module;
1616
use crate::vm_class::{stored_vm_from_wasm, WASMVirtualMachine};
1717

1818
// Currently WASM do not support multithreading. We should change this once it is enabled.
19-
thread_local!(static JS_FUNC: RefCell<Option<js_sys::Function>> = RefCell::new(None));
19+
thread_local!(static JS_FUNCS: RefCell<Vec<js_sys::Function>> = RefCell::new(vec![]));
2020

2121
#[wasm_bindgen(inline_js = r"
2222
export class PyError extends Error {
@@ -154,25 +154,6 @@ pub fn pyresult_to_jsresult(vm: &VirtualMachine, result: PyResult) -> Result<JsV
154154
.map_err(|err| py_err_to_js_err(vm, &err))
155155
}
156156

157-
fn js_func_to_py(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult {
158-
JS_FUNC.with(|func| {
159-
let this = Object::new();
160-
for (k, v) in args.kwargs {
161-
Reflect::set(&this, &k.into(), &py_to_js(vm, v)).expect("property to be settable");
162-
}
163-
let js_args = Array::new();
164-
for v in args.args {
165-
js_args.push(&py_to_js(vm, v));
166-
}
167-
func.borrow()
168-
.as_ref()
169-
.unwrap()
170-
.apply(&this, &js_args)
171-
.map(|val| js_to_py(vm, val))
172-
.map_err(|err| js_err_to_py_err(vm, &err))
173-
})
174-
}
175-
176157
pub fn js_to_py(vm: &VirtualMachine, js_val: JsValue) -> PyObjectRef {
177158
if js_val.is_object() {
178159
if let Some(promise) = js_val.dyn_ref::<Promise>() {
@@ -215,8 +196,32 @@ pub fn js_to_py(vm: &VirtualMachine, js_val: JsValue) -> PyObjectRef {
215196
}
216197
} else if js_val.is_function() {
217198
let func = js_sys::Function::from(js_val);
218-
JS_FUNC.with(|thread_func| thread_func.replace(Some(func.clone())));
219-
vm.ctx.new_method(js_func_to_py)
199+
let idx = JS_FUNCS.with(|funcs| {
200+
let mut funcs = funcs.borrow_mut();
201+
funcs.push(func);
202+
funcs.len() - 1
203+
});
204+
vm.ctx
205+
.new_method(move |vm: &VirtualMachine, args: PyFuncArgs| -> PyResult {
206+
JS_FUNCS.with(|funcs| {
207+
let this = Object::new();
208+
for (k, v) in args.kwargs {
209+
Reflect::set(&this, &k.into(), &py_to_js(vm, v))
210+
.expect("property to be settable");
211+
}
212+
let js_args = Array::new();
213+
for v in args.args {
214+
js_args.push(&py_to_js(vm, v));
215+
}
216+
funcs
217+
.borrow()
218+
.get(idx)
219+
.unwrap()
220+
.apply(&this, &js_args)
221+
.map(|val| js_to_py(vm, val))
222+
.map_err(|err| js_err_to_py_err(vm, &err))
223+
})
224+
})
220225
} else if let Some(err) = js_val.dyn_ref::<js_sys::Error>() {
221226
js_err_to_py_err(vm, err).into_object()
222227
} else if js_val.is_undefined() {

wasm/lib/src/vm_class.rs

+16-19
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,6 @@ use crate::js_module;
1919
use crate::wasm_builtins;
2020
use rustpython_compiler::mode::Mode;
2121

22-
// Currently WASM do not support multithreading. We should change this once it is enabled.
23-
thread_local!(static JS_FUNC: RefCell<Option<js_sys::Function>> = RefCell::new(None));
24-
2522
pub(crate) struct StoredVirtualMachine {
2623
pub vm: VirtualMachine,
2724
pub scope: RefCell<Scope>,
@@ -70,6 +67,7 @@ impl StoredVirtualMachine {
7067
// https://rustwasm.github.io/2018/10/24/multithreading-rust-and-wasm.html#atomic-instructions
7168
thread_local! {
7269
static STORED_VMS: RefCell<HashMap<String, Rc<StoredVirtualMachine>>> = RefCell::default();
70+
static JS_PRINT_FUNC: RefCell<Option<js_sys::Function>> = RefCell::new(None);
7371
}
7472

7573
pub fn get_vm_id(vm: &VirtualMachine) -> &str {
@@ -154,20 +152,6 @@ pub struct WASMVirtualMachine {
154152
pub(crate) id: String,
155153
}
156154

157-
fn stdout_js_func(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult {
158-
JS_FUNC.with(|func| {
159-
func.borrow()
160-
.as_ref()
161-
.unwrap()
162-
.call1(
163-
&JsValue::UNDEFINED,
164-
&wasm_builtins::format_print_args(vm, args)?.into(),
165-
)
166-
.map_err(|err| convert::js_py_typeerror(vm, err))?;
167-
Ok(vm.get_none())
168-
})
169-
}
170-
171155
#[wasm_bindgen(js_class = VirtualMachine)]
172156
impl WASMVirtualMachine {
173157
pub(crate) fn with_unchecked<F, R>(&self, f: F) -> R
@@ -246,8 +230,21 @@ impl WASMVirtualMachine {
246230
}
247231
} else if stdout.is_function() {
248232
let func = js_sys::Function::from(stdout);
249-
JS_FUNC.with(|thread_func| thread_func.replace(Some(func.clone())));
250-
vm.ctx.new_method(stdout_js_func)
233+
JS_PRINT_FUNC.with(|thread_func| thread_func.replace(Some(func.clone())));
234+
vm.ctx
235+
.new_method(move |vm: &VirtualMachine, args: PyFuncArgs| -> PyResult {
236+
JS_PRINT_FUNC.with(|func| {
237+
func.borrow()
238+
.as_ref()
239+
.unwrap()
240+
.call1(
241+
&JsValue::UNDEFINED,
242+
&wasm_builtins::format_print_args(vm, args)?.into(),
243+
)
244+
.map_err(|err| convert::js_py_typeerror(vm, err))?;
245+
Ok(vm.get_none())
246+
})
247+
})
251248
} else if stdout.is_null() {
252249
fn noop(vm: &VirtualMachine, _args: PyFuncArgs) -> PyResult {
253250
Ok(vm.get_none())

0 commit comments

Comments
 (0)