diff --git a/js/deno.ts b/js/deno.ts index 3bbda69e8f..92ba5301d3 100644 --- a/js/deno.ts +++ b/js/deno.ts @@ -15,4 +15,5 @@ export { ErrorKind, DenoError } from "./errors"; export { libdeno } from "./libdeno"; export { arch, platform } from "./platform"; export { trace } from "./trace"; +export { setGlobalTimeout } from "./timers"; export const args: string[] = []; diff --git a/js/timers.ts b/js/timers.ts index 42be96d91b..03badfd467 100644 --- a/js/timers.ts +++ b/js/timers.ts @@ -19,6 +19,15 @@ interface Timer { delay: number; // milliseconds } +export function setGlobalTimeout(timeout: number) { + const builder = new flatbuffers.Builder(); + fbs.SetTimeout.startSetTimeout(builder); + fbs.SetTimeout.addTimeout(builder, timeout); + const msg = fbs.SetTimeout.endSetTimeout(builder); + const res = sendSync(builder, fbs.Any.SetTimeout, msg); + assert(res == null); +} + function startTimer( id: number, cb: TimerCallback, diff --git a/js/timers_test.ts b/js/timers_test.ts index af172e9765..e5fe2d4784 100644 --- a/js/timers_test.ts +++ b/js/timers_test.ts @@ -1,4 +1,5 @@ import { test, assertEqual } from "./test_util.ts"; +import { setGlobalTimeout } from "deno"; function deferred() { let resolve; @@ -95,3 +96,7 @@ test(async function intervalCancelInvalidSilentFail() { // Should silently fail (no panic) clearInterval(2147483647); }); + +test(async function SetGlobalTimeoutSmoke() { + setGlobalTimeout(50); +}); diff --git a/src/handlers.rs b/src/handlers.rs index c914df36d0..42becc0b09 100644 --- a/src/handlers.rs +++ b/src/handlers.rs @@ -45,6 +45,7 @@ pub fn msg_from_js(state: Arc, bytes: &[u8]) -> (bool, Box) { msg::Any::Start => handle_start, msg::Any::CodeFetch => handle_code_fetch, msg::Any::CodeCache => handle_code_cache, + msg::Any::SetTimeout => handle_set_timeout, msg::Any::Environ => handle_env, msg::Any::FetchReq => handle_fetch_req, msg::Any::TimerStart => handle_timer_start, @@ -236,6 +237,15 @@ fn handle_code_cache(state: Arc, base: &msg::Base) -> Box { }())) } +fn handle_set_timeout(state: Arc, base: &msg::Base) -> Box { + let msg = base.msg_as_set_timeout().unwrap(); + let val = msg.timeout() as isize; + state + .timeout + .swap(val, std::sync::atomic::Ordering::Relaxed); + ok_future(empty_buf()) +} + fn handle_set_env(state: Arc, base: &msg::Base) -> Box { let msg = base.msg_as_set_env().unwrap(); let key = msg.key().unwrap(); diff --git a/src/isolate.rs b/src/isolate.rs index 64bec5ddf1..30e90be5cf 100644 --- a/src/isolate.rs +++ b/src/isolate.rs @@ -16,6 +16,7 @@ use std; use std::collections::HashMap; use std::ffi::CStr; use std::ffi::CString; +use std::sync::atomic::AtomicIsize; use std::sync::mpsc; use std::sync::Arc; use std::sync::Mutex; @@ -48,6 +49,7 @@ pub struct Isolate { // Isolate cannot be passed between threads but IsolateState can. So any state that // needs to be accessed outside the main V8 thread should be inside IsolateState. pub struct IsolateState { + pub timeout: AtomicIsize, pub dir: deno_dir::DenoDir, pub timers: Mutex>>, pub argv: Vec, @@ -85,6 +87,7 @@ impl Isolate { rx, ntasks: 0, state: Arc::new(IsolateState { + timeout: AtomicIsize::new(-1), dir: deno_dir::DenoDir::new(flags.reload, None).unwrap(), timers: Mutex::new(HashMap::new()), argv: argv_rest, diff --git a/src/msg.fbs b/src/msg.fbs index 6358668b7e..52eba8ca63 100644 --- a/src/msg.fbs +++ b/src/msg.fbs @@ -4,6 +4,7 @@ union Any { CodeFetch, CodeFetchRes, CodeCache, + SetTimeout, Exit, TimerStart, TimerReady, @@ -115,6 +116,10 @@ table CodeCache { output_code: string; } +table SetTimeout { + timeout: int; +} + table Exit { code: int; }