diff options
author | William Perron <hey@wperron.io> | 2020-10-15 21:06:31 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-10-15 21:06:31 -0400 |
commit | 943b0980c7ff97cb6096291efa5e3d5dbfe10805 (patch) | |
tree | d258b1c9fa317db819c3d95e6616635fd70c2489 | |
parent | bbe4474d39aecfabed52bd080e73d34978b6481b (diff) |
feat(cli/ops): add the sleep_sync op (#7974)
-rw-r--r-- | cli/dts/lib.deno.unstable.d.ts | 11 | ||||
-rw-r--r-- | cli/ops/timers.rs | 18 | ||||
-rw-r--r-- | cli/rt/11_timers.js | 5 | ||||
-rw-r--r-- | cli/rt/90_deno_ns.js | 1 | ||||
-rw-r--r-- | cli/tests/unit/timers_test.ts | 52 |
5 files changed, 87 insertions, 0 deletions
diff --git a/cli/dts/lib.deno.unstable.d.ts b/cli/dts/lib.deno.unstable.d.ts index 2dcd94f75..4269d4b74 100644 --- a/cli/dts/lib.deno.unstable.d.ts +++ b/cli/dts/lib.deno.unstable.d.ts @@ -1312,6 +1312,17 @@ declare namespace Deno { atime: number | Date, mtime: number | Date, ): Promise<void>; + + /** *UNSTABLE**: new API, yet to be vetted. + * + * SleepSync puts the main thread to sleep synchronously for a given amount of + * time in milliseconds. + * + * ```ts + * Deno.sleepSync(10); + * ``` + */ + export function sleepSync(millis: number): Promise<void>; } declare function fetch( diff --git a/cli/ops/timers.rs b/cli/ops/timers.rs index 74edc7267..841cdf289 100644 --- a/cli/ops/timers.rs +++ b/cli/ops/timers.rs @@ -25,6 +25,7 @@ use std::cell::RefCell; use std::future::Future; use std::pin::Pin; use std::rc::Rc; +use std::thread::sleep; use std::time::Duration; use std::time::Instant; @@ -77,6 +78,7 @@ pub fn init(rt: &mut deno_core::JsRuntime) { super::reg_json_sync(rt, "op_global_timer_start", op_global_timer_start); super::reg_json_async(rt, "op_global_timer", op_global_timer); super::reg_json_sync(rt, "op_now", op_now); + super::reg_json_sync(rt, "op_sleep_sync", op_sleep_sync); } fn op_global_timer_stop( @@ -157,3 +159,19 @@ fn op_now( "subsecNanos": subsec_nanos, })) } + +#[derive(Deserialize)] +struct SleepArgs { + millis: u64, +} + +fn op_sleep_sync( + state: &mut OpState, + args: Value, + _zero_copy: &mut [ZeroCopyBuf], +) -> Result<Value, AnyError> { + super::check_unstable(state, "Deno.sleepSync"); + let args: SleepArgs = serde_json::from_value(args)?; + sleep(Duration::from_millis(args.millis)); + Ok(json!({})) +} diff --git a/cli/rt/11_timers.js b/cli/rt/11_timers.js index 8f6a7e049..c762c59d8 100644 --- a/cli/rt/11_timers.js +++ b/cli/rt/11_timers.js @@ -20,6 +20,10 @@ return core.jsonOpSync("op_now"); } + function sleepSync(millis = 0) { + return core.jsonOpSync("op_sleep_sync", { millis }); + } + // Derived from https://github.com/vadimg/js_bintrees. MIT Licensed. class RBNode { @@ -545,5 +549,6 @@ opStopGlobalTimer, opStartGlobalTimer, opNow, + sleepSync, }; })(this); diff --git a/cli/rt/90_deno_ns.js b/cli/rt/90_deno_ns.js index 3a41e6bd1..7e8598923 100644 --- a/cli/rt/90_deno_ns.js +++ b/cli/rt/90_deno_ns.js @@ -80,6 +80,7 @@ __bootstrap.denoNs = { listen: __bootstrap.net.listen, connectTls: __bootstrap.tls.connectTls, listenTls: __bootstrap.tls.listenTls, + sleepSync: __bootstrap.timers.sleepSync, }; __bootstrap.denoNsUnstable = { diff --git a/cli/tests/unit/timers_test.ts b/cli/tests/unit/timers_test.ts index b304d8946..2d69ddb44 100644 --- a/cli/tests/unit/timers_test.ts +++ b/cli/tests/unit/timers_test.ts @@ -380,3 +380,55 @@ unitTest(async function timerIgnoresDateOverride(): Promise<void> { } assertEquals(hasThrown, 1); }); + +unitTest({ perms: { hrtime: true } }, function sleepSync(): void { + const start = performance.now(); + Deno.sleepSync(10); + const after = performance.now(); + assert(after - start >= 10); +}); + +unitTest( + { perms: { hrtime: true } }, + async function sleepSyncShorterPromise(): Promise<void> { + const perf = performance; + const short = 5; + const long = 10; + + const start = perf.now(); + const p = sleepAsync(short).then(() => { + const after = perf.now(); + // pending promises should resolve after the main thread comes out of sleep + assert(after - start >= long); + }); + Deno.sleepSync(long); + + await p; + }, +); + +unitTest( + { perms: { hrtime: true } }, + async function sleepSyncLongerPromise(): Promise<void> { + const perf = performance; + const short = 5; + const long = 10; + + const start = perf.now(); + const p = sleepAsync(long).then(() => { + const after = perf.now(); + // sleeping for less than the duration of a promise should have no impact + // on the resolution of that promise + assert(after - start >= long); + }); + Deno.sleepSync(short); + + await p; + }, +); + +function sleepAsync(delay: number): Promise<void> { + return new Promise((resolve) => { + setTimeout(() => resolve(), delay); + }); +} |