Lazy execution
Iterators, async generators, visitors and incremental pipeline operators.
Eager arrays remain the default. Lazy consumption is an explicit terminal contract:
const query = JIT.query(Users)
.filter((q) => q.eq("active", true))
.select("id", "name")
.take(10);
query.compile();
query.compileIterator();
query.compileAsyncIterator();
query.compileVisitor();
query.lazy().compile();Supported incremental operators include flatMap, take/takeWhile, drop/dropWhile,
unique, chunk, window, pairwise, scan and groupAdjacentBy.
Consecutive filters, projections and control operators share one generated stage. Array
inputs use an indexed loop. The direct visitor backend calls the consumer without an
iterator object or { value, done } protocol.
const visit = JIT.query(Users)
.filter((q) => q.eq("active", true))
.select("id")
.compileVisitor();
visit(users, sendToQueue);orderBy remains available but explain("generator") marks it as a materialization
barrier because global ordering must observe every accepted item.
Latest one-million-row local benchmark: visitor 3.81 ms / 760 B heap for 800k projected results; handwritten generator 15.21 ms / 7.75 MiB.
State and memory
Lazy does not automatically mean constant memory. unique retains a Set,
orderBy materializes all accepted values and groupBy needs all groups.
chunk, window, pairwise and groupAdjacentBy keep bounded/current state.
Use .explain() to make these costs visible.
Safe windows
window(n) emits independent arrays. JIT does not expose a reused mutable view
by default because consumers commonly retain windows. The allocation is an
explicit correctness tradeoff; a future ephemeral-view API would require a
different contract.
Visitor fallback
Filter/select/control pipelines receive direct visitor source. Pipelines with
cardinality-changing stages use the iterator backend as a correctness fallback.
Generated source and explain() reveal which strategy was selected.
Async guidance
Async iterators are for already asynchronous sources. Do not wrap an in-memory
array in async iteration for style: promise scheduling and async generator
protocols cost more than a synchronous indexed loop. Async scan updates are
awaited and downstream consumption provides natural backpressure.