From e2c92c69b5710241df9c7fb8aa1a20caa166f366 Mon Sep 17 00:00:00 2001 From: argosphil Date: Sat, 17 Feb 2024 02:32:37 +0000 Subject: [PATCH] fix: make sure Bun.sleep(Date) doesn't resolve prematurely (#8950) * fix: make sure Bun.sleep(Date) doesn't return prematurely Fixes #8834. This makes Bun.sleep(new Date(x)) fulfill its promise only when Date.now() >= x. * resolve test now #8834 is fixed 11 ms is in fact the right limit. --------- Co-authored-by: John-David Dalton --- src/bun.js/bindings/BunObject.cpp | 4 ++-- test/js/web/timers/setTimeout.test.js | 12 +++++++++--- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/src/bun.js/bindings/BunObject.cpp b/src/bun.js/bindings/BunObject.cpp index e94a00bbbd..6145e3d2b0 100644 --- a/src/bun.js/bindings/BunObject.cpp +++ b/src/bun.js/bindings/BunObject.cpp @@ -352,8 +352,8 @@ JSC_DEFINE_HOST_FUNCTION(functionBunSleep, if (millisecondsValue.inherits()) { auto now = MonotonicTime::now(); - auto milliseconds = jsCast(millisecondsValue)->internalNumber() - now.approximateWallTime().secondsSinceEpoch().milliseconds(); - millisecondsValue = JSC::jsNumber(milliseconds > 0 ? milliseconds : 0); + double milliseconds = jsCast(millisecondsValue)->internalNumber() - now.approximateWallTime().secondsSinceEpoch().milliseconds(); + millisecondsValue = JSC::jsNumber(milliseconds > 0 ? std::ceil(milliseconds) : 0); } if (!millisecondsValue.isNumber()) { diff --git a/test/js/web/timers/setTimeout.test.js b/test/js/web/timers/setTimeout.test.js index 8dcc1aa67d..5ef9970e18 100644 --- a/test/js/web/timers/setTimeout.test.js +++ b/test/js/web/timers/setTimeout.test.js @@ -152,9 +152,15 @@ it("Bun.sleep works with a Date object", async () => { var ten_ms = new Date(); ten_ms.setMilliseconds(ten_ms.getMilliseconds() + 12); await Bun.sleep(ten_ms); - // TODO: Fix https://github.com/oven-sh/bun/issues/8834 - // This should be .toBeGreaterThan(11), or maybe even 12 - expect(performance.now() - now).toBeGreaterThan(10); + expect(performance.now() - now).toBeGreaterThan(11); +}); + +it("Bun.sleep(Date) fulfills after Date", async () => { + let ten_ms = new Date(); + ten_ms.setMilliseconds(ten_ms.getMilliseconds() + 12); + await Bun.sleep(ten_ms); + let now = new Date(); + expect(+now).toBeGreaterThanOrEqual(+ten_ms); }); it("node.js timers/promises setTimeout propagates exceptions", async () => {