diff options
author | 2023-01-31 17:51:36 -0800 | |
---|---|---|
committer | 2023-01-31 17:51:36 -0800 | |
commit | b09896f06ec81e606a7f7e344d2ac45a5e1ffd39 (patch) | |
tree | c7efa26435eaa873859719f81d78e0cf5c1c7441 | |
parent | b7816f3175362271d4569d64e33a193998268cab (diff) | |
download | bun-b09896f06ec81e606a7f7e344d2ac45a5e1ffd39.tar.gz bun-b09896f06ec81e606a7f7e344d2ac45a5e1ffd39.tar.zst bun-b09896f06ec81e606a7f7e344d2ac45a5e1ffd39.zip |
mostly fix `node:timers`
-rw-r--r-- | packages/bun-types/timers.d.ts | 15 | ||||
-rw-r--r-- | src/bun.js/node_timers.exports.js | 88 | ||||
-rw-r--r-- | test/bun.js/node-timers.test.ts | 26 |
3 files changed, 105 insertions, 24 deletions
diff --git a/packages/bun-types/timers.d.ts b/packages/bun-types/timers.d.ts index 522ae6a18..c09c5b30c 100644 --- a/packages/bun-types/timers.d.ts +++ b/packages/bun-types/timers.d.ts @@ -10,11 +10,18 @@ */ declare module "timers" { + class Timer { + ref(): void; + unref(): void; + hasRef(): boolean; + } + const _exported: { - clearTimeout: typeof clearTimeout; - clearInterval: typeof clearInterval; - setTimeout: typeof setTimeout; - setInterval: typeof setInterval; + clearTimeout: (timer: Timer | number) => void; + clearInterval: (timer: Timer | number) => void; + setInterval: (cb: CallableFunction, msDelay: number, ...args: any[]) => Timer; + setTimeout: (cb: CallableFunction, msDelay: number, ...args: any[]) => Timer; + setImmediate: (cb: CallableFunction, ...args: any[]) => Timer; }; export = _exported; } diff --git a/src/bun.js/node_timers.exports.js b/src/bun.js/node_timers.exports.js index d46916ac5..d1f3e81e7 100644 --- a/src/bun.js/node_timers.exports.js +++ b/src/bun.js/node_timers.exports.js @@ -1,3 +1,7 @@ +// This implementation isn't 100% correct +// Ref/unref does not impact whether the process is kept alive + +var clear = Symbol("clear"); class Timeout { #id; #refCount = 1; @@ -17,6 +21,15 @@ class Timeout { return this.#refCount > 0; } + [clear]() { + this.#refCount = 0; + var clearFunction = this.#clearFunction; + if (clearFunction) { + this.#clearFunction = null; + clearFunction(this.#id); + } + } + unref() { this.#refCount -= 1; var clearFunction = this.#clearFunction; @@ -26,23 +39,78 @@ class Timeout { } } } -export const setInterval = globalThis.setInterval; -export const setImmediate = globalThis.queueMicrotask; -export const setTimeout = globalThis.setTimeout; -export const clearInterval = globalThis.clearInterval; +var { + setTimeout: setTimeout_, + setImmediate: setImmediate_, + clearTimeout: clearTimeout_, + setInterval: setInterval_, + clearInterval: clearInterval_, +} = globalThis; -// not implemented -export const clearImmediate = () => {}; +export function setImmediate(callback, ...args) { + if (typeof callback !== "function") { + throw new TypeError("callback must be a function"); + } + var cleared = false; + function clearImmediate(id) { + cleared = true; + } + + const wrapped = function (callback, args) { + if (cleared) { + return; + } + cleared = true; + try { + callback(...args); + } catch (e) { + reportError(e); + } finally { + } + }; -export const clearTimeout = globalThis.clearTimeout; -export const queueMicrotask = globalThis.queueMicrotask; + return new Timeout(setImmediate_(wrapped, callback, args), clearImmediate); +} + +export function setTimeout(callback, delay, ...args) { + if (typeof callback !== "function") { + throw new TypeError("callback must be a function"); + } + + return new Timeout(setTimeout_.apply(globalThis, arguments), clearTimeout_); +} + +export function setInterval(callback, delay, ...args) { + if (typeof callback !== "function") { + throw new TypeError("callback must be a function"); + } + + return new Timeout(setInterval_.apply(globalThis, arguments), clearInterval_); +} + +export function clearTimeout(id) { + if (id && typeof id === "object" && id[clear]) { + id[clear](); + return; + } + + clearTimeout_(id); +} + +export function clearInterval(id) { + if (id && typeof id === "object" && id[clear]) { + id[clear](); + return; + } + + clearInterval_(id); +} export default { setInterval, - queueMicrotask, setImmediate, setTimeout, clearInterval, - clearImmediate, clearTimeout, + [Symbol.for("CommonJS")]: 0, }; diff --git a/test/bun.js/node-timers.test.ts b/test/bun.js/node-timers.test.ts index f1a8ae802..e6fa48010 100644 --- a/test/bun.js/node-timers.test.ts +++ b/test/bun.js/node-timers.test.ts @@ -1,11 +1,17 @@ -import { test } from "bun:test"; -import { setTimeout } from "node:timers"; +import { describe, test } from "bun:test"; +import { setTimeout, clearTimeout, setInterval, setImmediate } from "node:timers"; -// not implemented yet -// test("unref is possible", () => { -// const timer = setTimeout(() => { -// throw new Error("should not be called"); -// }, 1000); -// timer.unref(); -// clearTimeout(timer); -// }); +for (const fn of [setTimeout, setInterval, setImmediate]) { + describe(fn.name, () => { + test("unref is possible", done => { + const timer = fn(() => { + done(new Error("should not be called")); + }, 1); + fn(() => { + done(); + }, 2); + timer.unref(); + if (fn !== setImmediate) clearTimeout(timer); + }); + }); +} |