diff --git a/src/commands.mjs b/src/commands.mjs index 7cacf74..e5c2211 100644 --- a/src/commands.mjs +++ b/src/commands.mjs @@ -65,7 +65,11 @@ export function defaultCommands() { // handy extras say: (ctx, args) => ctx.out(` 💬 ${args.join(" ")}`), sleep: async (_ctx, args) => { - const ms = Number(args[0] || 0); + const raw = args[0] ?? 0; + const ms = Number(raw); + if (!Number.isFinite(ms) || ms < 0) { + throw new Error(`moshscript: sleep(ms) requires a finite non-negative number, got ${JSON.stringify(raw)}`); + } if (ms > 0) await new Promise((r) => setTimeout(r, ms)); }, stop: (ctx, args) => { diff --git a/test/commands.test.mjs b/test/commands.test.mjs index 0ad9f08..79d4fdf 100644 --- a/test/commands.test.mjs +++ b/test/commands.test.mjs @@ -34,3 +34,15 @@ test("notify() still accepts message arguments", async () => { assert.equal(ctx.lines.length, 1); assert.match(ctx.lines[0], /hello there/); }); + +test("sleep accepts zero milliseconds", async () => { + await defaultCommands().sleep({}, [0]); +}); + +test("sleep rejects non-finite and negative durations", async () => { + const sleep = defaultCommands().sleep; + + await assert.rejects(() => sleep({}, ["forever"]), /finite non-negative number/); + await assert.rejects(() => sleep({}, ["Infinity"]), /finite non-negative number/); + await assert.rejects(() => sleep({}, [-1]), /finite non-negative number/); +});