|
1 | 1 | use crate::{convert, vm_class::AccessibleVM, wasm_builtins::window};
|
2 | 2 | use futures::{future, Future};
|
3 | 3 | use js_sys::Promise;
|
4 |
| -use rustpython_vm::obj::objstr; |
| 4 | +use rustpython_vm::obj::{objint, objstr}; |
5 | 5 | use rustpython_vm::pyobject::{PyContext, PyFuncArgs, PyObjectRef, PyResult, TypeProtocol};
|
6 | 6 | use rustpython_vm::VirtualMachine;
|
7 | 7 | use wasm_bindgen::{prelude::*, JsCast};
|
@@ -125,11 +125,68 @@ fn browser_fetch(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
125 | 125 | Ok(vm.get_none())
|
126 | 126 | }
|
127 | 127 |
|
| 128 | +fn browser_request_animation_frame(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { |
| 129 | + arg_check!(vm, args, required = [(func, Some(vm.ctx.function_type()))]); |
| 130 | + |
| 131 | + use std::{cell::RefCell, rc::Rc}; |
| 132 | + |
| 133 | + // this basic setup for request_animation_frame taken from: |
| 134 | + // https://rustwasm.github.io/wasm-bindgen/examples/request-animation-frame.html |
| 135 | + |
| 136 | + let f = Rc::new(RefCell::new(None)); |
| 137 | + let g = f.clone(); |
| 138 | + |
| 139 | + let func = func.clone(); |
| 140 | + |
| 141 | + let acc_vm = AccessibleVM::from_vm(vm); |
| 142 | + |
| 143 | + *g.borrow_mut() = Some(Closure::wrap(Box::new(move |time: f64| { |
| 144 | + let vm = &mut acc_vm |
| 145 | + .upgrade() |
| 146 | + .expect("that the vm is valid from inside of request_animation_frame"); |
| 147 | + let func = func.clone(); |
| 148 | + let args = PyFuncArgs { |
| 149 | + args: vec![vm.ctx.new_float(time)], |
| 150 | + kwargs: vec![], |
| 151 | + }; |
| 152 | + let _ = vm.invoke(func, args); |
| 153 | + |
| 154 | + let closure = f.borrow_mut().take(); |
| 155 | + drop(closure); |
| 156 | + }) as Box<Fn(f64)>)); |
| 157 | + |
| 158 | + let id = window() |
| 159 | + .request_animation_frame(&js_sys::Function::from( |
| 160 | + g.borrow().as_ref().unwrap().as_ref().clone(), |
| 161 | + )) |
| 162 | + .map_err(|err| convert::js_py_typeerror(vm, err))?; |
| 163 | + |
| 164 | + Ok(vm.ctx.new_int(id)) |
| 165 | +} |
| 166 | + |
| 167 | +fn browser_cancel_animation_frame(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { |
| 168 | + arg_check!(vm, args, required = [(id, Some(vm.ctx.int_type()))]); |
| 169 | + |
| 170 | + // fine because |
| 171 | + let id = objint::get_value(id) |
| 172 | + .to_string() |
| 173 | + .parse() |
| 174 | + .expect("bigint.to_string() to be parsable as i32"); |
| 175 | + |
| 176 | + window() |
| 177 | + .cancel_animation_frame(id) |
| 178 | + .map_err(|err| convert::js_py_typeerror(vm, err))?; |
| 179 | + |
| 180 | + Ok(vm.get_none()) |
| 181 | +} |
| 182 | + |
128 | 183 | const BROWSER_NAME: &str = "browser";
|
129 | 184 |
|
130 | 185 | pub fn mk_module(ctx: &PyContext) -> PyObjectRef {
|
131 | 186 | py_module!(ctx, BROWSER_NAME, {
|
132 |
| - "fetch" => ctx.new_rustfunc(browser_fetch) |
| 187 | + "fetch" => ctx.new_rustfunc(browser_fetch), |
| 188 | + "request_animation_frame" => ctx.new_rustfunc(browser_request_animation_frame), |
| 189 | + "cancel_animation_frame" => ctx.new_rustfunc(browser_cancel_animation_frame), |
133 | 190 | })
|
134 | 191 | }
|
135 | 192 |
|
|
0 commit comments