use crate::is_v8_bool;
use crate::is_v8_int;
use crate::js;
use crate::js::JsFuture;
use crate::js::JsRuntime;
use crate::js::TimerId;
use crate::js::converter::*;
use crate::js::pending;
use crate::prelude::*;
use std::rc::Rc;
struct TimeoutFuture {
cb: Rc<v8::Global<v8::Function>>,
params: Rc<Vec<v8::Global<v8::Value>>>,
}
impl JsFuture for TimeoutFuture {
fn run(&mut self, scope: &mut v8::PinScope) {
trace!("|TimeoutFuture|");
let undefined = v8::undefined(scope).into();
let callback = v8::Local::new(scope, (*self.cb).clone());
let args: Vec<v8::Local<v8::Value>> = self
.params
.iter()
.map(|arg| v8::Local::new(scope, arg))
.collect();
v8::tc_scope!(let tc_scope, scope);
callback.call(tc_scope, undefined, &args);
if tc_scope.has_caught() {
let exception = tc_scope.exception().unwrap();
let exception = v8::Global::new(tc_scope, exception);
let state_rc = JsRuntime::state(tc_scope);
state_rc
.borrow_mut()
.exceptions
.capture_exception(exception);
}
}
}
pub fn create_timer<'s>(
scope: &mut v8::PinScope<'s, '_>,
args: v8::FunctionCallbackArguments<'s>,
mut rv: v8::ReturnValue,
) {
debug_assert!(args.length() == 3);
debug_assert!(args.get(0).is_function());
let callback = v8::Local::<v8::Function>::try_from(args.get(0)).unwrap();
let callback = Rc::new(v8::Global::new(scope, callback));
debug_assert!(is_v8_int!(args.get(1)));
let delay = u32::from_v8(scope, args.get(1).to_integer(scope).unwrap());
debug_assert!(is_v8_bool!(args.get(2)));
let repeated = bool::from_v8(scope, args.get(2).to_boolean(scope));
let params = vec![];
let params = Rc::new(params);
let state_rc = JsRuntime::state(scope);
let timer_cb = {
let state_rc = state_rc.clone();
move || {
let fut = TimeoutFuture {
cb: Rc::clone(&callback),
params: Rc::clone(¶ms),
};
let mut state = state_rc.borrow_mut();
state.pending_futures.push(Box::new(fut));
}
};
let mut state = state_rc.borrow_mut();
let timer_id = js::TimerId::next();
pending::create_timer(
&mut state,
timer_id,
delay,
repeated,
Box::new(timer_cb),
);
rv.set_int32(timer_id.into());
trace!(
"|create_timer| timer_id:{:?}, delay:{:?}, repeated:{:?}",
timer_id, delay, repeated
);
}
pub fn clear_timer<'s>(
scope: &mut v8::PinScope<'s, '_>,
args: v8::FunctionCallbackArguments<'s>,
_: v8::ReturnValue,
) {
debug_assert!(args.length() == 1);
debug_assert!(is_v8_int!(args.get(0)));
let timer_id =
TimerId::from_v8(scope, args.get(0).to_integer(scope).unwrap());
let state_rc = JsRuntime::state(scope);
let mut state = state_rc.borrow_mut();
pending::remove_timer(&mut state, timer_id);
trace!("|clear_timer| timer_id:{:?}", timer_id);
}