Skip to content

feat(core): expose per-spec strides on bindColumns meta#80

Merged
andymai merged 1 commit into
mainfrom
feat/bindcolumns-meta-strides
Jun 8, 2026
Merged

feat(core): expose per-spec strides on bindColumns meta#80
andymai merged 1 commit into
mainfrom
feat/bindcolumns-meta-strides

Conversation

@andymai
Copy link
Copy Markdown
Owner

@andymai andymai commented Jun 8, 2026

What

bindColumns hands a vec field's view through as the raw flat array — row r's axes live at [r*stride, (r+1)*stride). Callers had to hardcode the arity (pos[r*3]), a silent mis-index if a vec3 later becomes a vec4. The eachChunk cursor already exposes this via stride(def, field); bindColumns didn't — an inconsistency and a footgun.

meta now carries strides: readonly number[] (slots-per-row per spec, in spec order — 1 scalar, N for vecN):

const run = q.bindColumns([Transform, 'pos'], [Transform, 'w'], ([pos, w], meta) => {
  const s = meta.strides[0]  // 3 for vec3 'pos' — read ONCE, outside the loop
  return () => { for (let r = 0; r < meta.count; r++) pos[r * s] += 1 }
})

Def-invariant (vec arity is a field property), identity-stable per binding, read outside the hot loop — so the V8 closure specialization the API exists for is untouched.

Review

Independent review: clean, no issues. Verified col.layout.stride is the authoritative slots-per-row (parity with the cursor's stride()), meta stays monomorphic (single construction site), and no orphaned meta construction lacks the field.

Verification

pnpm test163 files / 1247 green (vec3 test now reads meta.strides instead of hardcoding; asserts [3, 1]) · typecheck:tests · typecheck:extras · docs:check.

Closes the last of the four deferred legs from the launch audit (topics-on-workers #73, react relations #75, gen-aware numeric #77/#79, and this).

A pinned vec column hands its raw flat view through — row r's axes at
[r*stride, (r+1)*stride) — so callers had to HARDCODE the arity (r*3), a
silent mis-index waiting to happen if a vec3 later becomes a vec4. The
eachChunk cursor already exposes the stride via stride(); bindColumns
didn't.

meta now carries strides: readonly number[] (slots-per-row per spec, in
spec order — 1 for a scalar, N for a vecN), so a caller reads
`const s = meta.strides[0]` ONCE outside the runner and indexes
`view[r*s + axis]` without hardcoding. It's def-invariant (the vec arity
is a field property, not an archetype one) and identity-stable per
binding, read outside the hot loop, so the closure specialization the API
exists for is untouched.

Closes the last of the four deferred legs from the launch audit.
@andymai andymai enabled auto-merge (squash) June 8, 2026 07:26
@andymai andymai merged commit a690bff into main Jun 8, 2026
8 checks passed
@andymai andymai deleted the feat/bindcolumns-meta-strides branch June 8, 2026 07:28
@greptile-apps
Copy link
Copy Markdown

greptile-apps Bot commented Jun 8, 2026

Greptile Summary

This PR exposes strides: readonly number[] on the BoundColumnsMeta object passed to bindColumns factories, letting callers read the slots-per-row for each spec without hardcoding the vec arity. The existing eachChunk cursor already surfaced this via stride(def, field); bindColumns now matches it.

  • packages/schema/src/index.ts: Adds strides to the BoundColumnsMeta interface (slots-per-row per spec, in spec order), with inline JSDoc linking to the QueryChunk.stride() equivalent.
  • packages/core/src/query/live-query.ts: Populates strides in makeBinding via cols.map((c) => c.layout.stride); the same meta object is reused on reinvoke, so the reference is identity-stable across column-growth rebinds.
  • Test + docs: The existing vec3 round-trip test now reads meta.strides[0] instead of hardcoding 3, and asserts [3, 1]; the performance guide gains a short vec-stride snippet.

Confidence Score: 5/5

Safe to merge — the change is additive, the new field is populated at the only construction site, and the meta object is correctly reused on reinvocation.

The strides array is derived from the same authoritative source (c.layout.stride) as the eachChunk cursor's stride(), it's created once per binding and preserved across reinvokes via the existing b.meta reference, and the updated test directly asserts the expected [3, 1] value. No existing behaviour is modified; the field is purely additive.

No files require special attention.

Important Files Changed

Filename Overview
packages/core/src/query/live-query.ts Adds strides array to makeBinding via cols.map(c => c.layout.stride); meta object is correctly reused on reinvoke, preserving identity stability across rebinds.
packages/schema/src/index.ts Adds strides field to BoundColumnsMeta interface with clear JSDoc; type is readonly number[], matching the runtime shape.
packages/core/test/bind-columns.test.ts Upgrades the vec3 round-trip test to use meta.strides[0] and asserts the [3, 1] value; correctly reads stride outside the returned runner closure.
website/guide/performance.md Adds a short vec-stride usage snippet (marked no-check) and prose explaining the meta.strides API; fits cleanly in the existing section.

Reviews (1): Last reviewed commit: "feat(core): expose per-spec strides on b..." | Re-trigger Greptile

@release-kun release-kun Bot mentioned this pull request Jun 8, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant