Skip to content

Commit 157204c

Browse files
committed
Clean up the wasm crate
1 parent 8535ba9 commit 157204c

File tree

4 files changed

+89
-123
lines changed

4 files changed

+89
-123
lines changed

derive/src/from_args.rs

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ impl ArgAttribute {
109109
}
110110
}
111111

112-
fn generate_field(field: &Field) -> TokenStream2 {
112+
fn generate_field(field: &Field, rp_path: &syn::Path) -> TokenStream2 {
113113
let mut pyarg_attrs = field
114114
.attrs
115115
.iter()
@@ -132,24 +132,24 @@ fn generate_field(field: &Field) -> TokenStream2 {
132132

133133
let name = &field.ident;
134134
let middle = quote! {
135-
.map(|x| crate::pyobject::TryFromObject::try_from_object(vm, x)).transpose()?
135+
.map(|x| #rp_path::pyobject::TryFromObject::try_from_object(vm, x)).transpose()?
136136
};
137137
let ending = if let Some(default) = attr.default {
138138
quote! {
139139
.unwrap_or_else(|| #default)
140140
}
141141
} else if attr.optional {
142142
quote! {
143-
.map(crate::function::OptionalArg::Present)
144-
.unwrap_or(crate::function::OptionalArg::Missing)
143+
.map(#rp_path::function::OptionalArg::Present)
144+
.unwrap_or(#rp_path::function::OptionalArg::Missing)
145145
}
146146
} else {
147147
let err = match attr.kind {
148148
ParameterKind::PositionalOnly | ParameterKind::PositionalOrKeyword => quote! {
149-
crate::function::ArgumentError::TooFewArgs
149+
#rp_path::function::ArgumentError::TooFewArgs
150150
},
151151
ParameterKind::KeywordOnly => quote! {
152-
crate::function::ArgumentError::RequiredKeywordArgument(tringify!(#name))
152+
#rp_path::function::ArgumentError::RequiredKeywordArgument(tringify!(#name))
153153
},
154154
};
155155
quote! {
@@ -181,7 +181,10 @@ pub fn impl_from_args(input: DeriveInput) -> TokenStream2 {
181181
let fields = match input.data {
182182
Data::Struct(ref data) => {
183183
match data.fields {
184-
Fields::Named(ref fields) => fields.named.iter().map(generate_field),
184+
Fields::Named(ref fields) => fields
185+
.named
186+
.iter()
187+
.map(|field| generate_field(field, &rp_path)),
185188
Fields::Unnamed(_) | Fields::Unit => unimplemented!(), // TODO: better error message
186189
}
187190
}
@@ -192,9 +195,9 @@ pub fn impl_from_args(input: DeriveInput) -> TokenStream2 {
192195
quote! {
193196
impl #rp_path::function::FromArgs for #name {
194197
fn from_args(
195-
vm: &crate::vm::VirtualMachine,
196-
args: &mut crate::function::PyFuncArgs
197-
) -> Result<Self, crate::function::ArgumentError> {
198+
vm: &#rp_path::VirtualMachine,
199+
args: &mut #rp_path::function::PyFuncArgs
200+
) -> Result<Self, #rp_path::function::ArgumentError> {
198201
Ok(#name { #(#fields)* })
199202
}
200203
}

wasm/lib/src/browser_module.rs

Lines changed: 56 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,13 @@ use wasm_bindgen_futures::{future_to_promise, JsFuture};
77

88
use rustpython_vm::function::{OptionalArg, PyFuncArgs};
99
use rustpython_vm::obj::{
10-
objdict::PyDictRef,
11-
objfunction::PyFunction,
12-
objint,
13-
objstr::{self, PyStringRef},
10+
objdict::PyDictRef, objfunction::PyFunctionRef, objint::PyIntRef, objstr::PyStringRef,
1411
objtype::PyClassRef,
1512
};
16-
use rustpython_vm::pyobject::{PyObject, PyObjectRef, PyRef, PyResult, PyValue, TypeProtocol};
13+
use rustpython_vm::pyobject::{PyObject, PyObjectRef, PyRef, PyResult, PyValue};
1714
use rustpython_vm::VirtualMachine;
1815

19-
use crate::{convert, vm_class::AccessibleVM, wasm_builtins::window};
16+
use crate::{convert, vm_class::weak_vm, wasm_builtins::window};
2017

2118
enum FetchResponseFormat {
2219
Json,
@@ -42,50 +39,62 @@ impl FetchResponseFormat {
4239
}
4340
}
4441

45-
fn browser_fetch(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult {
46-
arg_check!(vm, args, required = [(url, Some(vm.ctx.str_type()))]);
42+
#[derive(FromArgs)]
43+
struct FetchArgs {
44+
#[pyarg(keyword_only, default = "None")]
45+
response_format: Option<PyStringRef>,
46+
#[pyarg(keyword_only, default = "None")]
47+
method: Option<PyStringRef>,
48+
#[pyarg(keyword_only, default = "None")]
49+
headers: Option<PyDictRef>,
50+
#[pyarg(keyword_only, default = "None")]
51+
body: Option<PyObjectRef>,
52+
#[pyarg(keyword_only, default = "None")]
53+
content_type: Option<PyStringRef>,
54+
}
4755

48-
let response_format =
49-
args.get_optional_kwarg_with_type("response_format", vm.ctx.str_type(), vm)?;
50-
let method = args.get_optional_kwarg_with_type("method", vm.ctx.str_type(), vm)?;
51-
let headers = args.get_optional_kwarg_with_type("headers", vm.ctx.dict_type(), vm)?;
52-
let body = args.get_optional_kwarg("body");
53-
let content_type = args.get_optional_kwarg_with_type("content_type", vm.ctx.str_type(), vm)?;
56+
fn browser_fetch(url: PyStringRef, args: FetchArgs, vm: &VirtualMachine) -> PyResult {
57+
let FetchArgs {
58+
response_format,
59+
method,
60+
headers,
61+
body,
62+
content_type,
63+
} = args;
5464

5565
let response_format = match response_format {
56-
Some(s) => FetchResponseFormat::from_str(vm, &objstr::get_value(&s))?,
66+
Some(s) => FetchResponseFormat::from_str(vm, s.as_str())?,
5767
None => FetchResponseFormat::Text,
5868
};
5969

6070
let mut opts = web_sys::RequestInit::new();
6171

6272
match method {
63-
Some(s) => opts.method(&objstr::get_value(&s)),
73+
Some(s) => opts.method(s.as_str()),
6474
None => opts.method("GET"),
6575
};
6676

6777
if let Some(body) = body {
6878
opts.body(Some(&convert::py_to_js(vm, body)));
6979
}
7080

71-
let request = web_sys::Request::new_with_str_and_init(&objstr::get_value(url), &opts)
81+
let request = web_sys::Request::new_with_str_and_init(url.as_str(), &opts)
7282
.map_err(|err| convert::js_py_typeerror(vm, err))?;
7383

7484
if let Some(headers) = headers {
7585
let h = request.headers();
76-
let headers: PyDictRef = headers.downcast().unwrap();
7786
for (key, value) in headers.get_key_value_pairs() {
78-
let key = &vm.to_str(&key)?.value;
79-
let value = &vm.to_str(&value)?.value;
80-
h.set(key, value)
87+
let key = vm.to_str(&key)?;
88+
let value = vm.to_str(&value)?;
89+
h.set(key.as_str(), value.as_str())
8190
.map_err(|err| convert::js_py_typeerror(vm, err))?;
8291
}
8392
}
8493

8594
if let Some(content_type) = content_type {
8695
request
8796
.headers()
88-
.set("Content-Type", &objstr::get_value(&content_type))
97+
.set("Content-Type", content_type.as_str())
8998
.map_err(|err| convert::js_py_typeerror(vm, err))?;
9099
}
91100

@@ -104,9 +113,7 @@ fn browser_fetch(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult {
104113
Ok(PyPromise::from_future(future).into_ref(vm).into_object())
105114
}
106115

107-
fn browser_request_animation_frame(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult {
108-
arg_check!(vm, args, required = [(func, Some(vm.ctx.function_type()))]);
109-
116+
fn browser_request_animation_frame(func: PyFunctionRef, vm: &VirtualMachine) -> PyResult {
110117
use std::{cell::RefCell, rc::Rc};
111118

112119
// this basic setup for request_animation_frame taken from:
@@ -115,18 +122,16 @@ fn browser_request_animation_frame(vm: &VirtualMachine, args: PyFuncArgs) -> PyR
115122
let f = Rc::new(RefCell::new(None));
116123
let g = f.clone();
117124

118-
let func = func.clone();
119-
120-
let acc_vm = AccessibleVM::from(vm);
125+
let weak_vm = weak_vm(vm);
121126

122127
*g.borrow_mut() = Some(Closure::wrap(Box::new(move |time: f64| {
123-
let stored_vm = acc_vm
128+
let stored_vm = weak_vm
124129
.upgrade()
125130
.expect("that the vm is valid from inside of request_animation_frame");
126131
let vm = &stored_vm.vm;
127132
let func = func.clone();
128133
let args = vec![vm.ctx.new_float(time)];
129-
let _ = vm.invoke(func, args);
134+
let _ = vm.invoke(func.into_object(), args);
130135

131136
let closure = f.borrow_mut().take();
132137
drop(closure);
@@ -141,10 +146,8 @@ fn browser_request_animation_frame(vm: &VirtualMachine, args: PyFuncArgs) -> PyR
141146
Ok(vm.ctx.new_int(id))
142147
}
143148

144-
fn browser_cancel_animation_frame(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult {
145-
arg_check!(vm, args, required = [(id, Some(vm.ctx.int_type()))]);
146-
147-
let id = objint::get_value(id).to_i32().ok_or_else(|| {
149+
fn browser_cancel_animation_frame(id: PyIntRef, vm: &VirtualMachine) -> PyResult {
150+
let id = id.as_bigint().to_i32().ok_or_else(|| {
148151
vm.new_exception(
149152
vm.ctx.exceptions.value_error.clone(),
150153
"Integer too large to convert to i32 for animationFrame id".into(),
@@ -186,14 +189,14 @@ impl PyPromise {
186189

187190
fn then(
188191
zelf: PyPromiseRef,
189-
on_fulfill: PyRef<PyFunction>,
190-
on_reject: OptionalArg<PyRef<PyFunction>>,
192+
on_fulfill: PyFunctionRef,
193+
on_reject: OptionalArg<PyFunctionRef>,
191194
vm: &VirtualMachine,
192195
) -> PyPromiseRef {
193-
let acc_vm = AccessibleVM::from(vm);
196+
let weak_vm = weak_vm(vm);
194197

195198
let ret_future = JsFuture::from(zelf.value.clone()).then(move |res| {
196-
let stored_vm = &acc_vm
199+
let stored_vm = &weak_vm
197200
.upgrade()
198201
.expect("that the vm is valid when the promise resolves");
199202
let vm = &stored_vm.vm;
@@ -217,16 +220,12 @@ impl PyPromise {
217220
PyPromise::from_future(ret_future).into_ref(vm)
218221
}
219222

220-
fn catch(
221-
zelf: PyPromiseRef,
222-
on_reject: PyRef<PyFunction>,
223-
vm: &VirtualMachine,
224-
) -> PyPromiseRef {
225-
let acc_vm = AccessibleVM::from(vm);
223+
fn catch(zelf: PyPromiseRef, on_reject: PyFunctionRef, vm: &VirtualMachine) -> PyPromiseRef {
224+
let weak_vm = weak_vm(vm);
226225

227226
let ret_future = JsFuture::from(zelf.value.clone()).then(move |res| {
228227
res.or_else(|err| {
229-
let stored_vm = acc_vm
228+
let stored_vm = weak_vm
230229
.upgrade()
231230
.expect("that the vm is valid when the promise resolves");
232231
let vm = &stored_vm.vm;
@@ -303,41 +302,31 @@ impl Element {
303302
}
304303
}
305304

306-
fn browser_alert(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult {
307-
arg_check!(vm, args, required = [(message, Some(vm.ctx.str_type()))]);
308-
305+
fn browser_alert(message: PyStringRef, vm: &VirtualMachine) -> PyResult {
309306
window()
310-
.alert_with_message(&objstr::get_value(message))
307+
.alert_with_message(message.as_str())
311308
.expect("alert() not to fail");
312309

313310
Ok(vm.get_none())
314311
}
315312

316-
fn browser_confirm(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult {
317-
arg_check!(vm, args, required = [(message, Some(vm.ctx.str_type()))]);
318-
313+
fn browser_confirm(message: PyStringRef, vm: &VirtualMachine) -> PyResult {
319314
let result = window()
320-
.confirm_with_message(&objstr::get_value(message))
315+
.confirm_with_message(message.as_str())
321316
.expect("confirm() not to fail");
322317

323318
Ok(vm.new_bool(result))
324319
}
325320

326-
fn browser_prompt(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult {
327-
arg_check!(
328-
vm,
329-
args,
330-
required = [(message, Some(vm.ctx.str_type()))],
331-
optional = [(default, Some(vm.ctx.str_type()))]
332-
);
333-
334-
let result = if let Some(default) = default {
335-
window().prompt_with_message_and_default(
336-
&objstr::get_value(message),
337-
&objstr::get_value(default),
338-
)
321+
fn browser_prompt(
322+
message: PyStringRef,
323+
default: OptionalArg<PyStringRef>,
324+
vm: &VirtualMachine,
325+
) -> PyResult {
326+
let result = if let OptionalArg::Present(default) = default {
327+
window().prompt_with_message_and_default(message.as_str(), default.as_str())
339328
} else {
340-
window().prompt_with_message(&objstr::get_value(message))
329+
window().prompt_with_message(message.as_str())
341330
};
342331

343332
let result = match result.expect("prompt() not to fail") {

wasm/lib/src/convert.rs

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use rustpython_vm::pyobject::{DictProtocol, PyObjectRef, PyResult, PyValue};
88
use rustpython_vm::VirtualMachine;
99

1010
use crate::browser_module;
11-
use crate::vm_class::{AccessibleVM, WASMVirtualMachine};
11+
use crate::vm_class::{stored_vm_from_wasm, WASMVirtualMachine};
1212

1313
pub fn py_err_to_js_err(vm: &VirtualMachine, py_err: &PyObjectRef) -> JsValue {
1414
macro_rules! map_exceptions {
@@ -81,11 +81,7 @@ pub fn py_to_js(vm: &VirtualMachine, py_obj: PyObjectRef) -> JsValue {
8181
return Err(err);
8282
}
8383
};
84-
let acc_vm = AccessibleVM::from(wasm_vm.clone());
85-
let stored_vm = acc_vm
86-
.upgrade()
87-
.expect("acc. VM to be invalid when WASM vm is valid");
88-
let vm = &stored_vm.vm;
84+
let vm = &stored_vm_from_wasm(&wasm_vm).vm;
8985
let mut py_func_args = PyFuncArgs::default();
9086
if let Some(ref args) = args {
9187
for arg in args.values() {

wasm/lib/src/vm_class.rs

Lines changed: 18 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,24 @@ impl StoredVirtualMachine {
4343
// probably gets compiled down to a normal-ish static varible, like Atomic* types do:
4444
// https://rustwasm.github.io/2018/10/24/multithreading-rust-and-wasm.html#atomic-instructions
4545
thread_local! {
46-
static STORED_VMS: RefCell<HashMap<String, Rc<StoredVirtualMachine>>> =
47-
RefCell::default();
46+
static STORED_VMS: RefCell<HashMap<String, Rc<StoredVirtualMachine>>> = RefCell::default();
47+
}
48+
49+
pub(crate) fn stored_vm_from_wasm(wasm_vm: &WASMVirtualMachine) -> Rc<StoredVirtualMachine> {
50+
STORED_VMS.with(|cell| {
51+
cell.borrow()
52+
.get(&wasm_vm.id)
53+
.expect("VirtualMachine is not valid")
54+
.clone()
55+
})
56+
}
57+
pub(crate) fn weak_vm(vm: &VirtualMachine) -> Weak<StoredVirtualMachine> {
58+
let id = vm
59+
.wasm_id
60+
.as_ref()
61+
.expect("VirtualMachine inside of WASM crate should have wasm_id set");
62+
STORED_VMS
63+
.with(|cell| Rc::downgrade(cell.borrow().get(id).expect("VirtualMachine is not valid")))
4864
}
4965

5066
#[wasm_bindgen(js_name = vmStore)]
@@ -104,44 +120,6 @@ impl VMStore {
104120
}
105121
}
106122

107-
#[derive(Clone)]
108-
pub(crate) struct AccessibleVM {
109-
weak: Weak<StoredVirtualMachine>,
110-
id: String,
111-
}
112-
113-
impl AccessibleVM {
114-
pub fn from_id(id: String) -> AccessibleVM {
115-
let weak = STORED_VMS
116-
.with(|cell| Rc::downgrade(cell.borrow().get(&id).expect("WASM VM to be valid")));
117-
AccessibleVM { weak, id }
118-
}
119-
120-
pub fn upgrade(&self) -> Option<Rc<StoredVirtualMachine>> {
121-
self.weak.upgrade()
122-
}
123-
}
124-
125-
impl From<WASMVirtualMachine> for AccessibleVM {
126-
fn from(vm: WASMVirtualMachine) -> AccessibleVM {
127-
AccessibleVM::from_id(vm.id)
128-
}
129-
}
130-
impl From<&WASMVirtualMachine> for AccessibleVM {
131-
fn from(vm: &WASMVirtualMachine) -> AccessibleVM {
132-
AccessibleVM::from_id(vm.id.clone())
133-
}
134-
}
135-
impl From<&VirtualMachine> for AccessibleVM {
136-
fn from(vm: &VirtualMachine) -> AccessibleVM {
137-
AccessibleVM::from_id(
138-
vm.wasm_id
139-
.clone()
140-
.expect("VM passed to from::<VirtualMachine>() to have wasm_id be Some()"),
141-
)
142-
}
143-
}
144-
145123
#[wasm_bindgen(js_name = VirtualMachine)]
146124
#[derive(Clone)]
147125
pub struct WASMVirtualMachine {

0 commit comments

Comments
 (0)