Changelog
All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
0.1.1 - 2026-05-29
Added
fireImmediatelyconfig field —scope:every(interval, fn, { fireImmediately = false })skips the first-frame execution. Defaults totrue(existing behavior unchanged).Typesmodule —HandleConfig,ScopeConfig,Scope,Handle, andProfileEntryare now exported from a dedicatedTypesmodule for external consumers.
Changed
setTimeScalenegative guard — passing a negative scale now clamps to0and emits awarn()instead of silently producing undefined behavior.
0.1.0 - 2026-05-28
Added
- Scopes —
chrono.scope(config?)creates independent lifecycle containers for scheduled work. scope:after(delay, fn, config?)— one-shot delayed execution.scope:every(interval, fn, config?)— repeating interval with immediate first run.scope:frame(fn, config?)— per-frame callback viaRunService.Heartbeatwith wall-clockdt.scope:tick(hz, fn, config?)— fixed-rate simulation loop, fires multiple times per frame to catch up.- Handles — all scheduling methods return a
Handlewithcancel(),pause(),resume(),setInterval(),isPaused(),isCancelled(). - Scope pause/resume —
scope:pause()freezes all timers;framestill fires withdt = 0. No backlog on resume. - Time-scale —
scope:setTimeScale(scale)for slow motion / fast-forward. Affectsafter,every,tick— notframe. maxCatchup— optional cap on tick fires per frame via config:scope:tick(60, fn, { maxCatchup = 4 }). Discards excess accumulation after a hitch.- Error isolation — callback errors are caught with
pcalland never propagate to other tasks or scopes. onErrorhandler — configurable per scope:chrono.scope({ onError = function(err, name) ... end }). Errors are silently swallowed when no handler is set.- Profiler —
chrono.profile()returns per-taskcount,avgMs,maxMs,p99Ms,totalMs. Ring-buffer backed (128 samples) for bounded memory. chrono.reset_profiler()— clears all profiler data.chrono.pause_all()/chrono.resume_all()— freeze or unfreeze every active scope in one call.- Trove compatibility — scopes expose
Destroy()as an alias fordestroy(). - Nested task safety — tasks created during callback execution are deferred to the next frame.
- Self-cancellation — a task can safely cancel itself or destroy its parent scope mid-callback.