pub const CLOCK_JS: &str = "// The clock: `every \"250ms\"`, `every frame`, `after \"2s\"`.\n//\n// **There is no callback here, and that is the point.** Every function in\n// this file takes a number and returns a *read function* \u{2014} the same read\n// function `signal()` returns \u{2014} so what the emitter writes for a clock\n// declaration is one `const` and nothing else. The scheduler\'s callback\n// exists, but it is closed over inside this file and no program can reach\n// it: all it does is put a number in a cell. Everything downstream is the\n// `derived` and the bindings the language already had.\n//\n// That is the whole answer to \"how does a timer enter a dataflow graph\n// without an escape hatch\": it does not enter as control flow at all. It\n// is a source, like a text box, and the browser is its writer.\n//\n// **Its own module, for the reason `list.js` and `markup.js` are.** The\n// null-program size gate (`zdc-bench/tests/scaling.rs`) keeps a 2 kB\n// reserve against Swift\'s number, and the fix when a runtime addition eats\n// into it is to ship the addition only to the programs that use it rather\n// than to move the ceiling. A program with no clock links nothing here.\n\nimport { onCleanup, signal } from \'./signal.js\';\n\n/** `every \"<duration>\"` \u{2014} milliseconds elapsed, written every `ms`.\n *\n * The value is *elapsed time*, not a tick count, and not the wall clock.\n *\n * - Not a count, because a count answers \"how many\" and almost every use\n * wants \"how long\": a progress bar, a countdown and a carousel are all\n * arithmetic on a duration, and a count makes each of them divide by the\n * interval to get back what the timer already knew.\n * - Not `Date.now()`, because a signal holding the wall clock changes\n * every time it is written whether or not anything moved, and because\n * `static` and `server` placements are refused anyway \u{2014} so the one\n * question a wall clock answers (\"what time is it\") is the prelude\'s\n * `clock`, which is where it already lives.\n *\n * Measured from the same base every time rather than accumulated, so a\n * late tick does not shift every later one: `setInterval` drifts, and a\n * clock whose drift compounds is one that visibly disagrees with a second\n * clock beside it after a minute. */\nexport function everyMs(ms) {\n const [read, write] = signal(0);\n const start = stamp();\n const id = setInterval(() => write(stamp() - start), ms);\n onCleanup(() => clearInterval(id));\n return read;\n}\n\n/** `every frame` \u{2014} milliseconds elapsed, written once per repaint.\n *\n * The base is the *first* frame\'s timestamp rather than the time this was\n * called: `requestAnimationFrame` hands the callback a\n * `DOMHighResTimeStamp` measured from the document\'s time origin, so\n * subtracting a `stamp()` taken during module evaluation would start the\n * signal at however long the page took to load. Subtracting the first\n * frame starts it at zero, which is what an animation wants and what makes\n * two frame signals declared at different moments comparable.\n *\n * **A cancelled frame loop must not schedule another one.** `cancel`\n * cancels the frame already booked; the `live` flag is what stops the\n * callback that is *mid-flight* \u{2014} one already dequeued by the browser \u{2014}\n * from booking its successor after the dispose ran. Without it a disposed\n * loop survives roughly half the time, which is exactly the kind of leak\n * that never reproduces on the machine it is reported from. */\nexport function everyFrame() {\n const [read, write] = signal(0);\n let base = null;\n let live = true;\n let id = requestAnimationFrame(function step(now) {\n if (!live) return;\n if (base === null) base = now;\n write(now - base);\n id = requestAnimationFrame(step);\n });\n onCleanup(() => {\n live = false;\n cancelAnimationFrame(id);\n });\n return read;\n}\n\n/** `after \"<duration>\"` \u{2014} `false` until `ms` have passed, then `true`.\n *\n * One-shot, so there is nothing to keep alive afterwards: the timer clears\n * itself by firing. The `onCleanup` covers the other case \u{2014} a view thrown\n * away before the delay elapses, where the write would land in a cell\n * nothing reads and the browser would hold the closure until it did. */\nexport function afterMs(ms) {\n const [read, write] = signal(false);\n const id = setTimeout(() => write(true), ms);\n onCleanup(() => clearTimeout(id));\n return read;\n}\n\n/** A monotonic-ish millisecond reading.\n *\n * `performance.now()` where there is one, because it does not jump when\n * the system clock is corrected \u{2014} an NTP step or a user changing the time\n * would otherwise make an interval signal go backwards, and every\n * subtraction downstream of it negative. `Date.now()` is the fallback and\n * not the default. */\nfunction stamp() {\n return typeof performance !== \'undefined\' && performance.now\n ? performance.now()\n : Date.now();\n}\n";Expand description
The clock: every "250ms", every frame and after "2s".
Its own module for the same reason as the modules above, and the size
gate is the reason it is not in signal.js: a null program links
signal.js, so anything put there is shipped to every program forever.
It imports signal.js and nothing else — a clock writes a cell and
touches no DOM.