summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWilliam Perron <hey@wperron.io>2020-10-15 21:06:31 -0400
committerGitHub <noreply@github.com>2020-10-15 21:06:31 -0400
commit943b0980c7ff97cb6096291efa5e3d5dbfe10805 (patch)
treed258b1c9fa317db819c3d95e6616635fd70c2489
parentbbe4474d39aecfabed52bd080e73d34978b6481b (diff)
feat(cli/ops): add the sleep_sync op (#7974)
-rw-r--r--cli/dts/lib.deno.unstable.d.ts11
-rw-r--r--cli/ops/timers.rs18
-rw-r--r--cli/rt/11_timers.js5
-rw-r--r--cli/rt/90_deno_ns.js1
-rw-r--r--cli/tests/unit/timers_test.ts52
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);
+ });
+}