pub(crate) fn get_external_references() -> Vec<v8::ExternalReference> {
vec![
v8::ExternalReference {
function: v8::MapFnTo::map_fn_to(set_timeout),
},
v8::ExternalReference {
function: v8::MapFnTo::map_fn_to(set_interval),
},
v8::ExternalReference {
function: v8::MapFnTo::map_fn_to(clear_timer),
},
]
}
pub(crate) fn register_bindings(scope: &mut v8::PinScope, bindings: v8::Local<v8::Object>) {
let name = v8::String::new(scope, "setTimeout").unwrap();
let value = v8::Function::new(scope, set_timeout).unwrap();
bindings.set(scope, name.into(), value.into());
let name = v8::String::new(scope, "setInterval").unwrap();
let value = v8::Function::new(scope, set_interval).unwrap();
bindings.set(scope, name.into(), value.into());
let name = v8::String::new(scope, "clearTimer").unwrap();
let value = v8::Function::new(scope, clear_timer).unwrap();
bindings.set(scope, name.into(), value.into());
}
#[inline]
fn set_timeout(
scope: &mut v8::PinScope,
args: v8::FunctionCallbackArguments,
mut rv: v8::ReturnValue,
) {
let callback_obj = args.get(0);
let callback = match crate::error::try_get_function_result(callback_obj) {
Ok(f) => f,
Err(msg) => {
crate::error::throw_type_error(scope, msg);
return;
}
};
let delay_obj = args.get(1);
let delay_ms = if delay_obj.is_undefined() || delay_obj.is_null() {
0
} else {
delay_obj.integer_value(scope).unwrap_or(0).max(0) as u64
};
let callback_global = v8::Global::new(scope, callback);
let state = crate::IsolateState::get(scope);
let state_borrow = state.borrow();
let timer_id = {
let mut next_id = state_borrow.next_timer_id.borrow_mut();
let id = crate::event_loop::TimerId(*next_id);
*next_id += 1;
id
};
state_borrow
.timers_to_add
.borrow_mut()
.push(crate::event_loop::PendingTimer::Timeout {
id: timer_id,
callback: callback_global,
delay_ms,
});
let timer_id_value = v8::Number::new(scope, timer_id.0 as f64);
rv.set(timer_id_value.into());
}
#[inline]
fn set_interval(
scope: &mut v8::PinScope,
args: v8::FunctionCallbackArguments,
mut rv: v8::ReturnValue,
) {
let callback_obj = args.get(0);
let callback = match crate::error::try_get_function_result(callback_obj) {
Ok(f) => f,
Err(msg) => {
crate::error::throw_type_error(scope, msg);
return;
}
};
let interval_obj = args.get(1);
let interval_ms = if interval_obj.is_undefined() || interval_obj.is_null() {
0
} else {
interval_obj.integer_value(scope).unwrap_or(0).max(0) as u64
};
let callback_global = v8::Global::new(scope, callback);
let state = crate::IsolateState::get(scope);
let state_borrow = state.borrow();
let timer_id = {
let mut next_id = state_borrow.next_timer_id.borrow_mut();
let id = crate::event_loop::TimerId(*next_id);
*next_id += 1;
id
};
state_borrow
.timers_to_add
.borrow_mut()
.push(crate::event_loop::PendingTimer::Interval {
id: timer_id,
callback: callback_global,
interval_ms,
});
let timer_id_value = v8::Number::new(scope, timer_id.0 as f64);
rv.set(timer_id_value.into());
}
#[inline]
fn clear_timer(
scope: &mut v8::PinScope,
args: v8::FunctionCallbackArguments,
_rv: v8::ReturnValue,
) {
let timer_id_obj = args.get(0);
if let Some(timer_id_num) = timer_id_obj.number_value(scope) {
let timer_id = crate::event_loop::TimerId(timer_id_num as u64);
let state = crate::IsolateState::get(scope);
state.borrow().timers_to_clear.borrow_mut().push(timer_id);
}
}