Download codex-rs/code-mode-runtime/src/runtime/timers.rs from SaylorTwift/codex: direct link, hf CLI and curl.
- Browser
- Download file 3.72 kB
-
https://huggingface.co/SaylorTwift/codex/resolve/main/codex-rs/code-mode-runtime/src/runtime/timers.rs
- Command line
-
hf download hf://SaylorTwift/codex/codex-rs/code-mode-runtime/src/runtime/timers.rs
-
curl -L -o timers.rs https://huggingface.co/SaylorTwift/codex/resolve/main/codex-rs/code-mode-runtime/src/runtime/timers.rs
3.72 kB
| use std::time::Duration; | |
| use tokio_util::task::AbortOnDropHandle; | |
| use super::RuntimeCommand; | |
| use super::RuntimeState; | |
| use super::value::value_to_error_text; | |
| pub(super) struct ScheduledTimeout { | |
| callback: v8::Global<v8::Function>, | |
| // Clearing the timeout or dropping the isolate also cancels its sleep. | |
| _task: AbortOnDropHandle<()>, | |
| } | |
| pub(super) fn schedule_timeout( | |
| scope: &mut v8::PinScope<'_, '_>, | |
| args: v8::FunctionCallbackArguments, | |
| ) -> Result<u64, String> { | |
| let callback = args.get(0); | |
| if !callback.is_function() { | |
| return Err("setTimeout expects a function callback".to_string()); | |
| } | |
| let callback = v8::Local::<v8::Function>::try_from(callback) | |
| .map_err(|_| "setTimeout expects a function callback".to_string())?; | |
| let delay_ms = args | |
| .get(1) | |
| .number_value(scope) | |
| .map(normalize_delay_ms) | |
| .unwrap_or(0); | |
| let callback = v8::Global::new(scope, callback); | |
| let state = scope | |
| .get_slot_mut::<RuntimeState>() | |
| .ok_or_else(|| "runtime state unavailable".to_string())?; | |
| let timeout_id = state.next_timeout_id; | |
| state.next_timeout_id = state.next_timeout_id.saturating_add(1); | |
| let runtime_command_tx = state.runtime_command_tx.clone(); | |
| let sleep = tokio::time::sleep(Duration::from_millis(delay_ms)); | |
| let task = tokio::spawn(async move { | |
| sleep.await; | |
| let _ = runtime_command_tx.send(RuntimeCommand::TimeoutFired { id: timeout_id }); | |
| }); | |
| state.pending_timeouts.insert( | |
| timeout_id, | |
| ScheduledTimeout { | |
| callback, | |
| _task: AbortOnDropHandle::new(task), | |
| }, | |
| ); | |
| Ok(timeout_id) | |
| } | |
| pub(super) fn clear_timeout( | |
| scope: &mut v8::PinScope<'_, '_>, | |
| args: v8::FunctionCallbackArguments, | |
| ) -> Result<(), String> { | |
| let Some(timeout_id) = timeout_id_from_args(scope, args)? else { | |
| return Ok(()); | |
| }; | |
| let Some(state) = scope.get_slot_mut::<RuntimeState>() else { | |
| return Err("runtime state unavailable".to_string()); | |
| }; | |
| state.pending_timeouts.remove(&timeout_id); | |
| Ok(()) | |
| } | |
| pub(super) fn invoke_timeout_callback( | |
| scope: &mut v8::PinScope<'_, '_>, | |
| timeout_id: u64, | |
| ) -> Result<(), String> { | |
| let callback = { | |
| let state = scope | |
| .get_slot_mut::<RuntimeState>() | |
| .ok_or_else(|| "runtime state unavailable".to_string())?; | |
| state.pending_timeouts.remove(&timeout_id) | |
| }; | |
| let Some(callback) = callback else { | |
| return Ok(()); | |
| }; | |
| let tc = std::pin::pin!(v8::TryCatch::new(scope)); | |
| let mut tc = tc.init(); | |
| let callback = v8::Local::new(&tc, &callback.callback); | |
| let receiver = v8::undefined(&tc).into(); | |
| let _ = callback.call(&tc, receiver, &[]); | |
| if tc.has_caught() { | |
| return Err(tc | |
| .exception() | |
| .map(|exception| value_to_error_text(&mut tc, exception)) | |
| .unwrap_or_else(|| "unknown code mode exception".to_string())); | |
| } | |
| Ok(()) | |
| } | |
| fn timeout_id_from_args( | |
| scope: &mut v8::PinScope<'_, '_>, | |
| args: v8::FunctionCallbackArguments, | |
| ) -> Result<Option<u64>, String> { | |
| if args.length() == 0 || args.get(0).is_null_or_undefined() { | |
| return Ok(None); | |
| } | |
| let Some(timeout_id) = args.get(0).number_value(scope) else { | |
| return Err("clearTimeout expects a numeric timeout id".to_string()); | |
| }; | |
| if !timeout_id.is_finite() || timeout_id <= 0.0 { | |
| return Ok(None); | |
| } | |
| Ok(Some(timeout_id.trunc().min(u64::MAX as f64) as u64)) | |
| } | |
| fn normalize_delay_ms(delay_ms: f64) -> u64 { | |
| if !delay_ms.is_finite() || delay_ms <= 0.0 { | |
| 0 | |
| } else { | |
| delay_ms.trunc().min(u64::MAX as f64) as u64 | |
| } | |
| } | |