1
+ use std:: cell:: RefCell ;
2
+
1
3
use js_sys:: { Array , ArrayBuffer , Object , Promise , Reflect , SyntaxError , Uint8Array } ;
2
4
use wasm_bindgen:: { closure:: Closure , prelude:: * , JsCast } ;
3
5
@@ -13,6 +15,9 @@ use rustpython_vm::{exceptions, py_serde};
13
15
use crate :: browser_module;
14
16
use crate :: vm_class:: { stored_vm_from_wasm, WASMVirtualMachine } ;
15
17
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
+
16
21
#[ wasm_bindgen( inline_js = r"
17
22
export class PyError extends Error {
18
23
constructor(info) {
@@ -149,6 +154,25 @@ pub fn pyresult_to_jsresult(vm: &VirtualMachine, result: PyResult) -> Result<JsV
149
154
. map_err ( |err| py_err_to_js_err ( vm, & err) )
150
155
}
151
156
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
+
152
176
pub fn js_to_py ( vm : & VirtualMachine , js_val : JsValue ) -> PyObjectRef {
153
177
if js_val. is_object ( ) {
154
178
if let Some ( promise) = js_val. dyn_ref :: < Promise > ( ) {
@@ -191,22 +215,8 @@ pub fn js_to_py(vm: &VirtualMachine, js_val: JsValue) -> PyObjectRef {
191
215
}
192
216
} else if js_val. is_function ( ) {
193
217
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)
210
220
} else if let Some ( err) = js_val. dyn_ref :: < js_sys:: Error > ( ) {
211
221
js_err_to_py_err ( vm, err) . into_object ( )
212
222
} else if js_val. is_undefined ( ) {
0 commit comments