1+ use std:: cell:: RefCell ;
2+
13use js_sys:: { Array , ArrayBuffer , Object , Promise , Reflect , SyntaxError , Uint8Array } ;
24use wasm_bindgen:: { closure:: Closure , prelude:: * , JsCast } ;
35
@@ -13,6 +15,9 @@ use rustpython_vm::{exceptions, py_serde};
1315use crate :: browser_module;
1416use crate :: vm_class:: { stored_vm_from_wasm, WASMVirtualMachine } ;
1517
18+ // 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 ) ) ;
20+
1621#[ wasm_bindgen( inline_js = r"
1722export class PyError extends Error {
1823 constructor(info) {
@@ -149,6 +154,25 @@ pub fn pyresult_to_jsresult(vm: &VirtualMachine, result: PyResult) -> Result<JsV
149154 . map_err ( |err| py_err_to_js_err ( vm, & err) )
150155}
151156
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+
152176pub fn js_to_py ( vm : & VirtualMachine , js_val : JsValue ) -> PyObjectRef {
153177 if js_val. is_object ( ) {
154178 if let Some ( promise) = js_val. dyn_ref :: < Promise > ( ) {
@@ -191,22 +215,8 @@ pub fn js_to_py(vm: &VirtualMachine, js_val: JsValue) -> PyObjectRef {
191215 }
192216 } else if js_val. is_function ( ) {
193217 let func = js_sys:: Function :: from ( js_val) ;
194- vm. ctx
195- . new_method ( move |vm : & VirtualMachine , args : PyFuncArgs | -> PyResult {
196- let func = func. clone ( ) ;
197- let this = Object :: new ( ) ;
198- for ( k, v) in args. kwargs {
199- Reflect :: set ( & this, & k. into ( ) , & py_to_js ( vm, v) )
200- . expect ( "property to be settable" ) ;
201- }
202- let js_args = Array :: new ( ) ;
203- for v in args. args {
204- js_args. push ( & py_to_js ( vm, v) ) ;
205- }
206- func. apply ( & this, & js_args)
207- . map ( |val| js_to_py ( vm, val) )
208- . map_err ( |err| js_err_to_py_err ( vm, & err) )
209- } )
218+ JS_FUNC . with ( |thread_func| thread_func. replace ( Some ( func. clone ( ) ) ) ) ;
219+ vm. ctx . new_method ( js_func_to_py)
210220 } else if let Some ( err) = js_val. dyn_ref :: < js_sys:: Error > ( ) {
211221 js_err_to_py_err ( vm, err) . into_object ( )
212222 } else if js_val. is_undefined ( ) {
0 commit comments