Part of #239, follow-up to #242 (STEP 3) and pre-req for #243 (STEP 4 per-repo ports).
Why this is needed
The STEP 4 triage on #243 found that bofig's property tests (tests/property/graph_properties_test.ts, 377L) generate test inputs with:
function randomId(prefix: string = "node"): string {
return `${prefix}_${Math.floor(Math.random() * 1000000)}`;
}
Math.random() is not bound in AffineScript's Deno-ESM surface today. Same pattern likely recurs in any future property-test port that uses generator-driven fuzzing rather than fixed-seed inputs.
Required surface
Minimum viable randomness:
| Extern |
Lowers to |
Notes |
math_random() -> Float |
Math.random() |
[0, 1). JS PRNG, non-crypto. |
random_u32() -> Int |
(Math.random() * 0x100000000) >>> 0 |
Convenience: uniform u32. |
random_in_range(lo: Int, hi: Int) -> Int |
Math.floor(Math.random() * (hi - lo)) + lo |
Uniform [lo, hi). |
If property tests need crypto-grade randomness later (e.g. cryptographic key generation), file a separate crypto_random_bytes binding sub-issue under #239 — it's a different host call (crypto.getRandomValues) and a different threat model.
Time bindings the same triage flagged as occasional needs:
| Extern |
Lowers to |
Notes |
performance_now() -> Float |
performance.now() |
High-res timer (sub-ms). Existing dateNow() -> Int millis is fine for coarse timings; bench tests want sub-ms resolution. |
Out of scope
- Seeded RNG (
@std/random) — defer until a property-test port actually needs determinism.
sleep / setTimeout — separate effect surface; not blocking STEP 4 tests.
Acceptance
- Externs ship in
stdlib/Deno.affine with docstrings.
tests/codegen-deno/random_smoke.{affine,deno.js,harness.mjs} exercises distribution sanity (random_u32 returns ≥ 1000 distinct values in 10000 draws; random_in_range(0, 100) stays in [0, 100) over 1000 draws; performance_now returns a monotone non-decreasing number across two calls).
dune runtest green; tools/run_codegen_deno_tests.sh green.
Refs
Part of #239, follow-up to #242 (STEP 3) and pre-req for #243 (STEP 4 per-repo ports).
Why this is needed
The STEP 4 triage on #243 found that bofig's property tests (
tests/property/graph_properties_test.ts, 377L) generate test inputs with:Math.random()is not bound in AffineScript's Deno-ESM surface today. Same pattern likely recurs in any future property-test port that uses generator-driven fuzzing rather than fixed-seed inputs.Required surface
Minimum viable randomness:
math_random() -> FloatMath.random()[0, 1). JS PRNG, non-crypto.random_u32() -> Int(Math.random() * 0x100000000) >>> 0random_in_range(lo: Int, hi: Int) -> IntMath.floor(Math.random() * (hi - lo)) + lo[lo, hi).If property tests need crypto-grade randomness later (e.g. cryptographic key generation), file a separate
crypto_random_bytesbinding sub-issue under #239 — it's a different host call (crypto.getRandomValues) and a different threat model.Time bindings the same triage flagged as occasional needs:
performance_now() -> Floatperformance.now()dateNow()-> Int millis is fine for coarse timings; bench tests want sub-ms resolution.Out of scope
@std/random) — defer until a property-test port actually needs determinism.sleep/setTimeout— separate effect surface; not blocking STEP 4 tests.Acceptance
stdlib/Deno.affinewith docstrings.tests/codegen-deno/random_smoke.{affine,deno.js,harness.mjs}exercises distribution sanity (random_u32returns ≥ 1000 distinct values in 10000 draws;random_in_range(0, 100)stays in[0, 100)over 1000 draws;performance_nowreturns a monotone non-decreasing number across two calls).dune runtestgreen;tools/run_codegen_deno_tests.shgreen.Refs