Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions lib/codegen_deno.ml
Original file line number Diff line number Diff line change
Expand Up @@ -543,6 +543,13 @@ let () =
(* `new Date().toISOString()` — UTC ISO-8601 timestamp string. Distinct
from `dateNow()` which returns epoch millis as Int. *)
b "dateNowIso" (fun _ -> "(new Date().toISOString())");
(* `performance.now()` — high-resolution sub-millisecond timer. *)
b "performance_now" (fun _ -> "performance.now()");
(* Math.random + derived integer-range helpers (campaign #239 STEP
4-B / standards#327). Non-crypto PRNG. *)
b "math_random" (fun _ -> "Math.random()");
b "random_u32" (fun _ -> "((Math.random() * 4294967296) >>> 0)");
b "random_in_range" (fun a -> Printf.sprintf "(Math.floor(Math.random() * ((%s) - (%s))) + (%s))" (arg 1 a) (arg 0 a) (arg 0 a));
(* `Deno.args` — CLI argument vector (excludes argv[0]). *)
b "args" (fun _ -> "Deno.args");
(* `Deno.exit(code)` — terminate process. Never returns. *)
Expand Down
18 changes: 18 additions & 0 deletions tests/codegen-deno/random_smoke.affine
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// SPDX-License-Identifier: MPL-2.0
// campaign #239 STEP 4-B — randomness + perf.now smoke
//
// Exercises math_random / random_u32 / random_in_range bindings + the
// performance_now monotone-clock binding. The harness verifies
// distribution sanity (not crypto-grade): u32 spans a reasonable
// fraction of its range, random_in_range stays inside [lo, hi), and
// performance_now is non-decreasing.

use Deno::{ math_random, random_u32, random_in_range, performance_now };

pub fn draw_u32() -> Int = random_u32();

pub fn draw_unit() -> Float = math_random();

pub fn draw_in_range(lo: Int, hi: Int) -> Int = random_in_range(lo, hi);

pub fn perf_tick() -> Float = performance_now();
302 changes: 302 additions & 0 deletions tests/codegen-deno/random_smoke.deno.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

54 changes: 54 additions & 0 deletions tests/codegen-deno/random_smoke.harness.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
// SPDX-License-Identifier: MPL-2.0
// campaign #239 STEP 4-B — Node-ESM harness for random + perf.now bindings.

import assert from "node:assert/strict";

const {
draw_u32,
draw_unit,
draw_in_range,
perf_tick,
} = await import("./random_smoke.deno.js");

// math_random — every draw is in [0, 1).
for (let i = 0; i < 1000; i++) {
const x = draw_unit();
assert.ok(x >= 0 && x < 1, `math_random must be in [0, 1), got ${x}`);
}

// random_u32 — uniform sanity over 10000 draws: at least 1000 distinct
// values + all draws fit in u32. (A degenerate PRNG that always returned
// the same value would fail the distinct-count check; a buggy one that
// over-spilled u32 would fail the range check.)
const u32_draws = new Set();
for (let i = 0; i < 10000; i++) {
const v = draw_u32();
assert.ok(v >= 0 && v <= 0xFFFFFFFF, `random_u32 must fit in u32, got ${v}`);
u32_draws.add(v);
}
assert.ok(u32_draws.size >= 1000, `random_u32 distribution: only ${u32_draws.size} distinct values in 10000`);

// random_in_range — must stay in [lo, hi) for 1000 draws.
for (let i = 0; i < 1000; i++) {
const v = draw_in_range(0, 100);
assert.ok(v >= 0 && v < 100, `random_in_range(0, 100) must be in [0, 100), got ${v}`);
}

// random_in_range — non-zero lo / non-100 hi.
const window_draws = new Set();
for (let i = 0; i < 500; i++) {
const v = draw_in_range(50, 60);
assert.ok(v >= 50 && v < 60, `random_in_range(50, 60) must be in [50, 60), got ${v}`);
window_draws.add(v);
}
assert.ok(window_draws.size >= 5, `random_in_range(50, 60) should cover most of [50, 60); got ${window_draws.size} distinct values`);

// performance_now — monotone non-decreasing across consecutive calls.
const t0 = perf_tick();
const t1 = perf_tick();
const t2 = perf_tick();
assert.ok(t1 >= t0, `performance_now monotone: t1 (${t1}) >= t0 (${t0})`);
assert.ok(t2 >= t1, `performance_now monotone: t2 (${t2}) >= t1 (${t1})`);
assert.ok(typeof t0 === "number" && !isNaN(t0), "performance_now returns a finite number");

console.log("random_smoke.harness.mjs OK");
Loading