@datakable/core 2.0.3 → 2.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. package/dist/features/search/search-index.cjs +108 -81
  2. package/dist/features/search/search-index.cjs.map +1 -1
  3. package/dist/features/search/search-index.js +109 -82
  4. package/dist/features/search/search-index.js.map +1 -1
  5. package/dist/features/search/search.cjs +2 -1
  6. package/dist/features/search/search.cjs.map +1 -1
  7. package/dist/features/search/search.js +6 -2
  8. package/dist/features/search/search.js.map +1 -1
  9. package/dist/features/sorting/ranks.cjs +117 -50
  10. package/dist/features/sorting/ranks.cjs.map +1 -1
  11. package/dist/features/sorting/ranks.js +117 -50
  12. package/dist/features/sorting/ranks.js.map +1 -1
  13. package/dist/features/sorting/sorting.cjs +32 -8
  14. package/dist/features/sorting/sorting.cjs.map +1 -1
  15. package/dist/features/sorting/sorting.js +32 -8
  16. package/dist/features/sorting/sorting.js.map +1 -1
  17. package/dist/pipeline/column-cache.cjs +6 -2
  18. package/dist/pipeline/column-cache.cjs.map +1 -1
  19. package/dist/pipeline/column-cache.js +6 -2
  20. package/dist/pipeline/column-cache.js.map +1 -1
  21. package/dist/pipeline/release.cjs +34 -0
  22. package/dist/pipeline/release.cjs.map +1 -0
  23. package/dist/pipeline/release.js +8 -0
  24. package/dist/pipeline/release.js.map +1 -0
  25. package/dist/pipeline/runner.cjs +15 -1
  26. package/dist/pipeline/runner.cjs.map +1 -1
  27. package/dist/pipeline/runner.js +15 -1
  28. package/dist/pipeline/runner.js.map +1 -1
  29. package/dist/table/create-table.cjs +3 -0
  30. package/dist/table/create-table.cjs.map +1 -1
  31. package/dist/table/create-table.js +3 -0
  32. package/dist/table/create-table.js.map +1 -1
  33. package/dist/version.cjs +1 -1
  34. package/dist/version.cjs.map +1 -1
  35. package/dist/version.js +1 -1
  36. package/dist/version.js.map +1 -1
  37. package/package.json +3 -3
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/pipeline/column-cache.ts"],"sourcesContent":["import { describeReturn, expectedReturn, formatSlot, slotDiagnostics } from '../catalog/slots'\nimport { defaultFormat } from '../column/format'\nimport { getValue } from '../column/get-value'\nimport { keepDiagnostics } from '../diagnostics/catalog'\nimport '../diagnostics/process-guard'\nimport type { Emit } from '../diagnostics/types'\nimport { CellFailures, type CellSlot, runCells } from '../intercept/cell-batch'\nimport { type ContextBase, createContextPool } from '../intercept/context'\nimport type { InterceptorRuntime } from '../intercept/runtime'\nimport { pipelineDiagnostics } from './codes'\nimport type { ColumnLike, ResolvedColumn } from './columns'\nimport { allRows } from './indices'\nimport { runJob } from './slice'\nimport type { ColumnValues } from './types'\n\nkeepDiagnostics(pipelineDiagnostics, slotDiagnostics)\n\nexport interface ColumnCacheHost {\n readonly runtime: InterceptorRuntime\n readonly emit: Emit\n base(): ContextBase\n /**\n * The §6.6 status rule's counter (pipeline/status-rule.ts): `emit` increments it for a diagnostic\n * the rule counts. An entry whose read incremented it is flagged, and every later read of that\n * entry increments it again (its cells still hold the fallback values).\n */\n readonly flags?: { count: number }\n}\n\n/**\n * Internal member of the pipeline's run context (not on the public `RowModelContext`): a column's\n * formatted values as a time-sliced job (search, #40); `undefined` for an unknown column.\n */\nexport interface SlicedFormatting {\n readonly formattedSliced?: (\n id: string,\n ) => Generator<undefined, readonly string[] | undefined, undefined>\n}\n\nexport interface ColumnCache {\n /**\n * The values of `column` for every row of `data` (index = row index). An all-number column is a\n * `Float64Array` with `NaN` for `null` / `undefined`; any other column a plain array.\n */\n values(data: readonly unknown[], column: ResolvedColumn): ColumnValues\n /** `format` (or the default formatter) applied to {@link values}: what the user sees. */\n formatted(data: readonly unknown[], column: ResolvedColumn): readonly string[]\n /**\n * {@link formatted} as a time-sliced job (§9.1, #40): the cells are formatted in batches of a few\n * milliseconds with a `yield` between them (one `column:batch` per batch, never per cell).\n */\n formattedSliced(\n data: readonly unknown[],\n column: ResolvedColumn,\n ): Generator<undefined, readonly string[], undefined>\n /**\n * Runs `body` as one `column:batch` over `rows` (pooled ctx, `where` = `columns[i].<field>`):\n * interceptors see one dispatch per column, never one per cell. `body` loops over the cells\n * with an inline `try/catch` and reports its own failures.\n */\n batch(\n column: ResolvedColumn,\n slot: CellSlot,\n field: string,\n rows: Uint32Array,\n body: () => void,\n ): void\n}\n\ninterface Entry {\n values?: ColumnValues\n /** Numeric columns: 1 = `null`, 2 = `undefined` per row. Absent when there are none. */\n nullish?: Uint8Array | undefined\n formatted?: readonly string[]\n /** Reading `values` / `formatted` reported a diagnostic the status rule counts. */\n flaggedValues?: boolean\n flaggedFormatted?: boolean\n}\n\nconst NULL = 1\nconst UNDEFINED = 2\n\n/** The nullish kinds of each cached numeric column that has any (see {@link nullishOf}). */\nconst nullishKinds = new WeakMap<Float64Array, Uint8Array>()\n\n/**\n * Which rows of a cached all-number column (`values` from the column cache) hold `null` /\n * `undefined` (non-zero) rather than a real `NaN`: both are stored as `NaN`. `undefined` when no\n * row does. Lets search format such a column on the fly (`''` / `'NaN'`) instead of caching a\n * string per row (#27).\n */\nexport function nullishOf(values: Float64Array): Uint8Array | undefined {\n return nullishKinds.get(values)\n}\n\nfunction allStrings(values: readonly unknown[]): boolean {\n for (let i = 0; i < values.length; i++) if (typeof values[i] !== 'string') return false\n return true\n}\n\nconst typeName = (v: unknown) => (Array.isArray(v) ? 'array' : typeof v)\n\n/** Rows per batch of a sliced format (#40): small, so the slicer's clock check comes often. */\nconst STEP = 512\n\n/** Distinct strings {@link share} remembers per column: enough for categories, tags, flags. */\nconst SHARED = 1024\n\n/**\n * Repeated formatted strings of a column share one copy (§9.3 memory, #27): each formatted cell is\n * a fresh string, so a column of tags or categories would keep one per row. Only the first\n * {@link SHARED} distinct strings are remembered; once per column, after formatting.\n */\nfunction share(cells: string[]) {\n const seen = new Map<string, string>()\n for (let r = 0; r < cells.length; r++) {\n const s = cells[r] as string\n const hit = seen.get(s)\n if (hit !== undefined) cells[r] = hit\n else if (seen.size < SHARED) seen.set(s, s)\n }\n}\n\n/**\n * The lazy column cache (§9.1): a column is read only when a step asks for it, once per data\n * reference, in one `column:batch` per column (never per cell, §3.4). Entries live in a `WeakMap`\n * keyed by the data reference, then by the column definition, so new data or a changed column\n * releases them.\n */\nexport function createColumnCache(host: ColumnCacheHost): ColumnCache {\n const byData = new WeakMap<readonly unknown[], WeakMap<ColumnLike, Entry>>()\n const pool = createContextPool()\n const failures = new CellFailures()\n\n function entry(data: readonly unknown[], column: ResolvedColumn): Entry {\n let cols = byData.get(data)\n if (!cols) {\n cols = new WeakMap()\n byData.set(data, cols)\n }\n let e = cols.get(column.def)\n if (!e) {\n e = {}\n cols.set(column.def, e)\n }\n return e\n }\n\n /** One `column:batch` (pooled ctx); `where` = `columns[i].<field>`, never row data. */\n function batch(\n column: ResolvedColumn,\n slot: CellSlot,\n field: string,\n rows: Uint32Array,\n body: () => void,\n ) {\n const ctx = pool.acquire(\n 'column:batch',\n { column: column.id, slot, rows },\n `columns[${column.index}].${field}`,\n host.base(),\n )\n try {\n void host.runtime.run('column:batch', ctx, (): undefined => {\n try {\n body()\n } finally {\n failures.reset()\n }\n })\n } finally {\n pool.release(ctx)\n }\n }\n\n function readValues(data: readonly unknown[], column: ResolvedColumn, e: Entry): ColumnValues {\n const n = data.length\n const rows = allRows(data)\n const out: unknown[] = new Array(n).fill(undefined)\n const field = column.path ? 'key' : 'accessor'\n batch(column, 'accessor', field, rows, () => {\n const path = column.path\n const accessor = column.accessor\n if (path) {\n let cur = 0\n const onError = (error: unknown) => failures.add(cur, error)\n runCells(\n rows,\n (r) => {\n cur = r\n return getValue(data[r], path, onError)\n },\n out,\n undefined,\n failures,\n )\n } else if (accessor) {\n runCells(rows, (r) => accessor(data[r]), out, undefined, failures)\n }\n failures.report(host.emit, column.index, column.id, 'accessor', undefined, field)\n })\n return toNumeric(out, e) ?? out\n }\n\n /** A `Float64Array` when every non-nullish value is a number (and there is one); else nothing. */\n function toNumeric(values: unknown[], e: Entry): Float64Array | undefined {\n let numbers = 0\n let nullish = 0\n for (let i = 0; i < values.length; i++) {\n const v = values[i]\n if (typeof v === 'number') numbers++\n else if (v === null || v === undefined) nullish++\n else return undefined\n }\n if (numbers === 0) return undefined\n const out = new Float64Array(values.length)\n const kinds = nullish > 0 ? new Uint8Array(values.length) : undefined\n for (let i = 0; i < values.length; i++) {\n const v = values[i]\n if (typeof v === 'number') out[i] = v\n else {\n out[i] = Number.NaN\n if (kinds) kinds[i] = v === null ? NULL : UNDEFINED\n }\n }\n e.nullish = kinds\n if (kinds) nullishKinds.set(out, kinds)\n return out\n }\n\n const flags = host.flags\n\n function values(data: readonly unknown[], column: ResolvedColumn): ColumnValues {\n const e = entry(data, column)\n if (e.values) {\n if (flags && e.flaggedValues) flags.count++\n return e.values\n }\n const before = flags?.count ?? 0\n e.values = readValues(data, column, e)\n if (flags && flags.count > before) e.flaggedValues = true\n return e.values\n }\n\n /**\n * Formats `column` once per data reference, in one `column:batch`; `sliced` (#40): in batches of\n * {@link STEP} rows with a `yield` between them, so the slicer can end the task on time (a slow\n * formatter, e.g. dates, is never one long task). Failures and slot-contract breaks are counted\n * over the whole column and reported once.\n */\n function* formatting(\n data: readonly unknown[],\n column: ResolvedColumn,\n sliced: boolean,\n ): Generator<undefined, readonly string[], undefined> {\n let e = entry(data, column)\n if (e.formatted) {\n if (flags && e.flaggedFormatted) flags.count++\n return e.formatted\n }\n const before = flags?.count ?? 0\n const vals = values(data, column)\n if (sliced) yield // reading the values is a task of its own\n const kinds = e.nullish\n // The raw value: nullish numbers read back as null / undefined, not NaN.\n const valueAt = (r: number): unknown => {\n const k = kinds?.[r]\n return k ? (k === NULL ? null : undefined) : vals[r]\n }\n const n = data.length\n const rows = allRows(data)\n const format = column.format\n // Job-local counts: a sliced column spans several batches.\n const failed = new CellFailures()\n const bad = (process.env.NODE_ENV !== \"production\") ? new CellFailures() : undefined\n const unrendered = new CellFailures()\n let firstBad: unknown\n let firstType = ''\n let cur = 0\n // A column with `cell` renders itself: its formatted value only feeds search.\n const onUnrenderable = column.hasCell\n ? undefined\n : (v: unknown) => {\n if (unrendered.count === 0) firstType = typeName(v)\n unrendered.add(cur, undefined)\n }\n const cell = format\n ? (r: number) => {\n const s = format(valueAt(r))\n if (typeof s === 'string') return s\n // Slot contract (dev): counted only on this non-string path; coerced either way.\n if ((process.env.NODE_ENV !== \"production\") && bad) {\n if (bad.count === 0) firstBad = s\n bad.add(r, undefined)\n }\n return defaultFormat(s)\n }\n : (r: number) => {\n cur = r\n return defaultFormat(valueAt(r), onUnrenderable)\n }\n // Values that are all strings already format to themselves: no copy (§9.3 memory).\n const strings = !format && !(vals instanceof Float64Array) && allStrings(vals)\n let out: string[] | undefined = strings ? undefined : new Array(n).fill('')\n for (let from = 0; from < n; from += STEP) {\n const part = sliced && !strings ? rows.subarray(from, from + STEP) : rows\n // An interceptor may skip a batch: its cells keep the slot fallback ('').\n batch(column, 'format', 'format', part, () => {\n if (strings) out = vals as string[]\n else runCells(part, cell, out as string[], '', failed)\n })\n if (part === rows || from + STEP >= n) break\n yield\n }\n out ??= new Array<string>(n).fill('')\n failed.report(host.emit, column.index, column.id, 'format')\n if ((process.env.NODE_ENV !== \"production\") && bad && bad.count > 0) {\n host.emit('DK_CALLBACK_BAD_RETURN', {\n slot: `columns[${column.index}].format`,\n column: column.id,\n expected: expectedReturn(formatSlot),\n received: describeReturn(firstBad),\n count: bad.count,\n rows: Array.from(bad.sample()),\n fallback: formatSlot.fallback,\n })\n }\n if (unrendered.count > 0) {\n host.emit('DK_UNRENDERABLE_VALUE', {\n column: column.id,\n index: column.index,\n count: unrendered.count,\n rows: Array.from(unrendered.sample()),\n valueType: firstType,\n })\n }\n if (out !== vals) share(out)\n // A synchronous read may have cached the column while a sliced job ran.\n e = entry(data, column)\n if (!e.formatted) {\n e.formatted = out\n if (flags && flags.count > before) e.flaggedFormatted = true\n }\n return e.formatted\n }\n\n function formatted(data: readonly unknown[], column: ResolvedColumn): readonly string[] {\n return runJob(() => formatting(data, column, false))\n }\n\n return {\n values,\n formatted,\n formattedSliced: (data, column) => formatting(data, column, true),\n batch,\n }\n}\n"],"mappings":";AAAA,SAAS,gBAAgB,gBAAgB,YAAY,uBAAuB;AAC5E,SAAS,qBAAqB;AAC9B,SAAS,gBAAgB;AACzB,SAAS,uBAAuB;AAChC,OAAO;AAEP,SAAS,cAA6B,gBAAgB;AACtD,SAA2B,yBAAyB;AAEpD,SAAS,2BAA2B;AAEpC,SAAS,eAAe;AACxB,SAAS,cAAc;AAGvB,gBAAgB,qBAAqB,eAAe;AAgEpD,IAAM,OAAO;AACb,IAAM,YAAY;AAGlB,IAAM,eAAe,oBAAI,QAAkC;AAQpD,SAAS,UAAU,QAA8C;AACtE,SAAO,aAAa,IAAI,MAAM;AAChC;AAEA,SAAS,WAAW,QAAqC;AACvD,WAAS,IAAI,GAAG,IAAI,OAAO,QAAQ,IAAK,KAAI,OAAO,OAAO,CAAC,MAAM,SAAU,QAAO;AAClF,SAAO;AACT;AAEA,IAAM,WAAW,CAAC,MAAgB,MAAM,QAAQ,CAAC,IAAI,UAAU,OAAO;AAGtE,IAAM,OAAO;AAGb,IAAM,SAAS;AAOf,SAAS,MAAM,OAAiB;AAC9B,QAAM,OAAO,oBAAI,IAAoB;AACrC,WAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;AACrC,UAAM,IAAI,MAAM,CAAC;AACjB,UAAM,MAAM,KAAK,IAAI,CAAC;AACtB,QAAI,QAAQ,OAAW,OAAM,CAAC,IAAI;AAAA,aACzB,KAAK,OAAO,OAAQ,MAAK,IAAI,GAAG,CAAC;AAAA,EAC5C;AACF;AAQO,SAAS,kBAAkB,MAAoC;AACpE,QAAM,SAAS,oBAAI,QAAwD;AAC3E,QAAM,OAAO,kBAAkB;AAC/B,QAAM,WAAW,IAAI,aAAa;AAElC,WAAS,MAAM,MAA0B,QAA+B;AACtE,QAAI,OAAO,OAAO,IAAI,IAAI;AAC1B,QAAI,CAAC,MAAM;AACT,aAAO,oBAAI,QAAQ;AACnB,aAAO,IAAI,MAAM,IAAI;AAAA,IACvB;AACA,QAAI,IAAI,KAAK,IAAI,OAAO,GAAG;AAC3B,QAAI,CAAC,GAAG;AACN,UAAI,CAAC;AACL,WAAK,IAAI,OAAO,KAAK,CAAC;AAAA,IACxB;AACA,WAAO;AAAA,EACT;AAGA,WAAS,MACP,QACA,MACA,OACA,MACA,MACA;AACA,UAAM,MAAM,KAAK;AAAA,MACf;AAAA,MACA,EAAE,QAAQ,OAAO,IAAI,MAAM,KAAK;AAAA,MAChC,WAAW,OAAO,KAAK,KAAK,KAAK;AAAA,MACjC,KAAK,KAAK;AAAA,IACZ;AACA,QAAI;AACF,WAAK,KAAK,QAAQ,IAAI,gBAAgB,KAAK,MAAiB;AAC1D,YAAI;AACF,eAAK;AAAA,QACP,UAAE;AACA,mBAAS,MAAM;AAAA,QACjB;AAAA,MACF,CAAC;AAAA,IACH,UAAE;AACA,WAAK,QAAQ,GAAG;AAAA,IAClB;AAAA,EACF;AAEA,WAAS,WAAW,MAA0B,QAAwB,GAAwB;AAC5F,UAAM,IAAI,KAAK;AACf,UAAM,OAAO,QAAQ,IAAI;AACzB,UAAM,MAAiB,IAAI,MAAM,CAAC,EAAE,KAAK,MAAS;AAClD,UAAM,QAAQ,OAAO,OAAO,QAAQ;AACpC,UAAM,QAAQ,YAAY,OAAO,MAAM,MAAM;AAC3C,YAAM,OAAO,OAAO;AACpB,YAAM,WAAW,OAAO;AACxB,UAAI,MAAM;AACR,YAAI,MAAM;AACV,cAAM,UAAU,CAAC,UAAmB,SAAS,IAAI,KAAK,KAAK;AAC3D;AAAA,UACE;AAAA,UACA,CAAC,MAAM;AACL,kBAAM;AACN,mBAAO,SAAS,KAAK,CAAC,GAAG,MAAM,OAAO;AAAA,UACxC;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,QACF;AAAA,MACF,WAAW,UAAU;AACnB,iBAAS,MAAM,CAAC,MAAM,SAAS,KAAK,CAAC,CAAC,GAAG,KAAK,QAAW,QAAQ;AAAA,MACnE;AACA,eAAS,OAAO,KAAK,MAAM,OAAO,OAAO,OAAO,IAAI,YAAY,QAAW,KAAK;AAAA,IAClF,CAAC;AACD,WAAO,UAAU,KAAK,CAAC,KAAK;AAAA,EAC9B;AAGA,WAAS,UAAUA,SAAmB,GAAoC;AACxE,QAAI,UAAU;AACd,QAAI,UAAU;AACd,aAAS,IAAI,GAAG,IAAIA,QAAO,QAAQ,KAAK;AACtC,YAAM,IAAIA,QAAO,CAAC;AAClB,UAAI,OAAO,MAAM,SAAU;AAAA,eAClB,MAAM,QAAQ,MAAM,OAAW;AAAA,UACnC,QAAO;AAAA,IACd;AACA,QAAI,YAAY,EAAG,QAAO;AAC1B,UAAM,MAAM,IAAI,aAAaA,QAAO,MAAM;AAC1C,UAAM,QAAQ,UAAU,IAAI,IAAI,WAAWA,QAAO,MAAM,IAAI;AAC5D,aAAS,IAAI,GAAG,IAAIA,QAAO,QAAQ,KAAK;AACtC,YAAM,IAAIA,QAAO,CAAC;AAClB,UAAI,OAAO,MAAM,SAAU,KAAI,CAAC,IAAI;AAAA,WAC/B;AACH,YAAI,CAAC,IAAI,OAAO;AAChB,YAAI,MAAO,OAAM,CAAC,IAAI,MAAM,OAAO,OAAO;AAAA,MAC5C;AAAA,IACF;AACA,MAAE,UAAU;AACZ,QAAI,MAAO,cAAa,IAAI,KAAK,KAAK;AACtC,WAAO;AAAA,EACT;AAEA,QAAM,QAAQ,KAAK;AAEnB,WAAS,OAAO,MAA0B,QAAsC;AAC9E,UAAM,IAAI,MAAM,MAAM,MAAM;AAC5B,QAAI,EAAE,QAAQ;AACZ,UAAI,SAAS,EAAE,cAAe,OAAM;AACpC,aAAO,EAAE;AAAA,IACX;AACA,UAAM,SAAS,OAAO,SAAS;AAC/B,MAAE,SAAS,WAAW,MAAM,QAAQ,CAAC;AACrC,QAAI,SAAS,MAAM,QAAQ,OAAQ,GAAE,gBAAgB;AACrD,WAAO,EAAE;AAAA,EACX;AAQA,YAAU,WACR,MACA,QACA,QACoD;AACpD,QAAI,IAAI,MAAM,MAAM,MAAM;AAC1B,QAAI,EAAE,WAAW;AACf,UAAI,SAAS,EAAE,iBAAkB,OAAM;AACvC,aAAO,EAAE;AAAA,IACX;AACA,UAAM,SAAS,OAAO,SAAS;AAC/B,UAAM,OAAO,OAAO,MAAM,MAAM;AAChC,QAAI,OAAQ;AACZ,UAAM,QAAQ,EAAE;AAEhB,UAAM,UAAU,CAAC,MAAuB;AACtC,YAAM,IAAI,QAAQ,CAAC;AACnB,aAAO,IAAK,MAAM,OAAO,OAAO,SAAa,KAAK,CAAC;AAAA,IACrD;AACA,UAAM,IAAI,KAAK;AACf,UAAM,OAAO,QAAQ,IAAI;AACzB,UAAM,SAAS,OAAO;AAEtB,UAAM,SAAS,IAAI,aAAa;AAChC,UAAM,MAAO,QAAQ,IAAI,aAAa,eAAgB,IAAI,aAAa,IAAI;AAC3E,UAAM,aAAa,IAAI,aAAa;AACpC,QAAI;AACJ,QAAI,YAAY;AAChB,QAAI,MAAM;AAEV,UAAM,iBAAiB,OAAO,UAC1B,SACA,CAAC,MAAe;AACd,UAAI,WAAW,UAAU,EAAG,aAAY,SAAS,CAAC;AAClD,iBAAW,IAAI,KAAK,MAAS;AAAA,IAC/B;AACJ,UAAM,OAAO,SACT,CAAC,MAAc;AACb,YAAM,IAAI,OAAO,QAAQ,CAAC,CAAC;AAC3B,UAAI,OAAO,MAAM,SAAU,QAAO;AAElC,UAAK,QAAQ,IAAI,aAAa,gBAAiB,KAAK;AAClD,YAAI,IAAI,UAAU,EAAG,YAAW;AAChC,YAAI,IAAI,GAAG,MAAS;AAAA,MACtB;AACA,aAAO,cAAc,CAAC;AAAA,IACxB,IACA,CAAC,MAAc;AACb,YAAM;AACN,aAAO,cAAc,QAAQ,CAAC,GAAG,cAAc;AAAA,IACjD;AAEJ,UAAM,UAAU,CAAC,UAAU,EAAE,gBAAgB,iBAAiB,WAAW,IAAI;AAC7E,QAAI,MAA4B,UAAU,SAAY,IAAI,MAAM,CAAC,EAAE,KAAK,EAAE;AAC1E,aAAS,OAAO,GAAG,OAAO,GAAG,QAAQ,MAAM;AACzC,YAAM,OAAO,UAAU,CAAC,UAAU,KAAK,SAAS,MAAM,OAAO,IAAI,IAAI;AAErE,YAAM,QAAQ,UAAU,UAAU,MAAM,MAAM;AAC5C,YAAI,QAAS,OAAM;AAAA,YACd,UAAS,MAAM,MAAM,KAAiB,IAAI,MAAM;AAAA,MACvD,CAAC;AACD,UAAI,SAAS,QAAQ,OAAO,QAAQ,EAAG;AACvC;AAAA,IACF;AACA,YAAQ,IAAI,MAAc,CAAC,EAAE,KAAK,EAAE;AACpC,WAAO,OAAO,KAAK,MAAM,OAAO,OAAO,OAAO,IAAI,QAAQ;AAC1D,QAAK,QAAQ,IAAI,aAAa,gBAAiB,OAAO,IAAI,QAAQ,GAAG;AACnE,WAAK,KAAK,0BAA0B;AAAA,QAClC,MAAM,WAAW,OAAO,KAAK;AAAA,QAC7B,QAAQ,OAAO;AAAA,QACf,UAAU,eAAe,UAAU;AAAA,QACnC,UAAU,eAAe,QAAQ;AAAA,QACjC,OAAO,IAAI;AAAA,QACX,MAAM,MAAM,KAAK,IAAI,OAAO,CAAC;AAAA,QAC7B,UAAU,WAAW;AAAA,MACvB,CAAC;AAAA,IACH;AACA,QAAI,WAAW,QAAQ,GAAG;AACxB,WAAK,KAAK,yBAAyB;AAAA,QACjC,QAAQ,OAAO;AAAA,QACf,OAAO,OAAO;AAAA,QACd,OAAO,WAAW;AAAA,QAClB,MAAM,MAAM,KAAK,WAAW,OAAO,CAAC;AAAA,QACpC,WAAW;AAAA,MACb,CAAC;AAAA,IACH;AACA,QAAI,QAAQ,KAAM,OAAM,GAAG;AAE3B,QAAI,MAAM,MAAM,MAAM;AACtB,QAAI,CAAC,EAAE,WAAW;AAChB,QAAE,YAAY;AACd,UAAI,SAAS,MAAM,QAAQ,OAAQ,GAAE,mBAAmB;AAAA,IAC1D;AACA,WAAO,EAAE;AAAA,EACX;AAEA,WAAS,UAAU,MAA0B,QAA2C;AACtF,WAAO,OAAO,MAAM,WAAW,MAAM,QAAQ,KAAK,CAAC;AAAA,EACrD;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,iBAAiB,CAAC,MAAM,WAAW,WAAW,MAAM,QAAQ,IAAI;AAAA,IAChE;AAAA,EACF;AACF;","names":["values"]}
1
+ {"version":3,"sources":["../../src/pipeline/column-cache.ts"],"sourcesContent":["import { describeReturn, expectedReturn, formatSlot, slotDiagnostics } from '../catalog/slots'\nimport { defaultFormat } from '../column/format'\nimport { getValue } from '../column/get-value'\nimport { keepDiagnostics } from '../diagnostics/catalog'\nimport '../diagnostics/process-guard'\nimport type { Emit } from '../diagnostics/types'\nimport { CellFailures, type CellSlot, runCells } from '../intercept/cell-batch'\nimport { type ContextBase, createContextPool } from '../intercept/context'\nimport type { InterceptorRuntime } from '../intercept/runtime'\nimport { pipelineDiagnostics } from './codes'\nimport type { ColumnLike, ResolvedColumn } from './columns'\nimport { allRows } from './indices'\nimport { runJob } from './slice'\nimport type { ColumnValues } from './types'\n\nkeepDiagnostics(pipelineDiagnostics, slotDiagnostics)\n\nexport interface ColumnCacheHost {\n readonly runtime: InterceptorRuntime\n readonly emit: Emit\n base(): ContextBase\n /**\n * The §6.6 status rule's counter (pipeline/status-rule.ts): `emit` increments it for a diagnostic\n * the rule counts. An entry whose read incremented it is flagged, and every later read of that\n * entry increments it again (its cells still hold the fallback values).\n */\n readonly flags?: { count: number }\n}\n\n/**\n * Internal member of the pipeline's run context (not on the public `RowModelContext`): a column's\n * formatted values as a time-sliced job (search, #40); `undefined` for an unknown column.\n */\nexport interface SlicedFormatting {\n readonly formattedSliced?: (\n id: string,\n ) => Generator<undefined, readonly string[] | undefined, undefined>\n}\n\nexport interface ColumnCache {\n /**\n * The values of `column` for every row of `data` (index = row index). An all-number column is a\n * `Float64Array` with `NaN` for `null` / `undefined`; any other column a plain array.\n */\n values(data: readonly unknown[], column: ResolvedColumn): ColumnValues\n /** `format` (or the default formatter) applied to {@link values}: what the user sees. */\n formatted(data: readonly unknown[], column: ResolvedColumn): readonly string[]\n /**\n * {@link formatted} as a time-sliced job (§9.1, #40): the cells are formatted in batches of a few\n * milliseconds with a `yield` between them (one `column:batch` per batch, never per cell).\n */\n formattedSliced(\n data: readonly unknown[],\n column: ResolvedColumn,\n ): Generator<undefined, readonly string[], undefined>\n /**\n * Runs `body` as one `column:batch` over `rows` (pooled ctx, `where` = `columns[i].<field>`):\n * interceptors see one dispatch per column, never one per cell. `body` loops over the cells\n * with an inline `try/catch` and reports its own failures.\n */\n batch(\n column: ResolvedColumn,\n slot: CellSlot,\n field: string,\n rows: Uint32Array,\n body: () => void,\n ): void\n /** Drops every entry (`destroy()`, #98). */\n release(): void\n /** Development only, for tests (#98): an entry of `data` is cached. */\n holds?(data: readonly unknown[]): boolean\n}\n\ninterface Entry {\n values?: ColumnValues\n /** Numeric columns: 1 = `null`, 2 = `undefined` per row. Absent when there are none. */\n nullish?: Uint8Array | undefined\n formatted?: readonly string[]\n /** Reading `values` / `formatted` reported a diagnostic the status rule counts. */\n flaggedValues?: boolean\n flaggedFormatted?: boolean\n}\n\nconst NULL = 1\nconst UNDEFINED = 2\n\n/** The nullish kinds of each cached numeric column that has any (see {@link nullishOf}). */\nconst nullishKinds = new WeakMap<Float64Array, Uint8Array>()\n\n/**\n * Which rows of a cached all-number column (`values` from the column cache) hold `null` /\n * `undefined` (non-zero) rather than a real `NaN`: both are stored as `NaN`. `undefined` when no\n * row does. Lets search format such a column on the fly (`''` / `'NaN'`) instead of caching a\n * string per row (#27).\n */\nexport function nullishOf(values: Float64Array): Uint8Array | undefined {\n return nullishKinds.get(values)\n}\n\nfunction allStrings(values: readonly unknown[]): boolean {\n for (let i = 0; i < values.length; i++) if (typeof values[i] !== 'string') return false\n return true\n}\n\nconst typeName = (v: unknown) => (Array.isArray(v) ? 'array' : typeof v)\n\n/** Rows per batch of a sliced format (#40): small, so the slicer's clock check comes often. */\nconst STEP = 512\n\n/** Distinct strings {@link share} remembers per column: enough for categories, tags, flags. */\nconst SHARED = 1024\n\n/**\n * Repeated formatted strings of a column share one copy (§9.3 memory, #27): each formatted cell is\n * a fresh string, so a column of tags or categories would keep one per row. Only the first\n * {@link SHARED} distinct strings are remembered; once per column, after formatting.\n */\nfunction share(cells: string[]) {\n const seen = new Map<string, string>()\n for (let r = 0; r < cells.length; r++) {\n const s = cells[r] as string\n const hit = seen.get(s)\n if (hit !== undefined) cells[r] = hit\n else if (seen.size < SHARED) seen.set(s, s)\n }\n}\n\n/**\n * The lazy column cache (§9.1): a column is read only when a step asks for it, once per data\n * reference, in one `column:batch` per column (never per cell, §3.4). Entries live in a `WeakMap`\n * keyed by the data reference, then by the column definition, so new data or a changed column\n * releases them.\n */\nexport function createColumnCache(host: ColumnCacheHost): ColumnCache {\n let byData = new WeakMap<readonly unknown[], WeakMap<ColumnLike, Entry>>()\n const pool = createContextPool()\n const failures = new CellFailures()\n\n function entry(data: readonly unknown[], column: ResolvedColumn): Entry {\n let cols = byData.get(data)\n if (!cols) {\n cols = new WeakMap()\n byData.set(data, cols)\n }\n let e = cols.get(column.def)\n if (!e) {\n e = {}\n cols.set(column.def, e)\n }\n return e\n }\n\n /** One `column:batch` (pooled ctx); `where` = `columns[i].<field>`, never row data. */\n function batch(\n column: ResolvedColumn,\n slot: CellSlot,\n field: string,\n rows: Uint32Array,\n body: () => void,\n ) {\n const ctx = pool.acquire(\n 'column:batch',\n { column: column.id, slot, rows },\n `columns[${column.index}].${field}`,\n host.base(),\n )\n try {\n void host.runtime.run('column:batch', ctx, (): undefined => {\n try {\n body()\n } finally {\n failures.reset()\n }\n })\n } finally {\n pool.release(ctx)\n }\n }\n\n function readValues(data: readonly unknown[], column: ResolvedColumn, e: Entry): ColumnValues {\n const n = data.length\n const rows = allRows(data)\n const out: unknown[] = new Array(n).fill(undefined)\n const field = column.path ? 'key' : 'accessor'\n batch(column, 'accessor', field, rows, () => {\n const path = column.path\n const accessor = column.accessor\n if (path) {\n let cur = 0\n const onError = (error: unknown) => failures.add(cur, error)\n runCells(\n rows,\n (r) => {\n cur = r\n return getValue(data[r], path, onError)\n },\n out,\n undefined,\n failures,\n )\n } else if (accessor) {\n runCells(rows, (r) => accessor(data[r]), out, undefined, failures)\n }\n failures.report(host.emit, column.index, column.id, 'accessor', undefined, field)\n })\n return toNumeric(out, e) ?? out\n }\n\n /** A `Float64Array` when every non-nullish value is a number (and there is one); else nothing. */\n function toNumeric(values: unknown[], e: Entry): Float64Array | undefined {\n let numbers = 0\n let nullish = 0\n for (let i = 0; i < values.length; i++) {\n const v = values[i]\n if (typeof v === 'number') numbers++\n else if (v === null || v === undefined) nullish++\n else return undefined\n }\n if (numbers === 0) return undefined\n const out = new Float64Array(values.length)\n const kinds = nullish > 0 ? new Uint8Array(values.length) : undefined\n for (let i = 0; i < values.length; i++) {\n const v = values[i]\n if (typeof v === 'number') out[i] = v\n else {\n out[i] = Number.NaN\n if (kinds) kinds[i] = v === null ? NULL : UNDEFINED\n }\n }\n e.nullish = kinds\n if (kinds) nullishKinds.set(out, kinds)\n return out\n }\n\n const flags = host.flags\n\n function values(data: readonly unknown[], column: ResolvedColumn): ColumnValues {\n const e = entry(data, column)\n if (e.values) {\n if (flags && e.flaggedValues) flags.count++\n return e.values\n }\n const before = flags?.count ?? 0\n e.values = readValues(data, column, e)\n if (flags && flags.count > before) e.flaggedValues = true\n return e.values\n }\n\n /**\n * Formats `column` once per data reference, in one `column:batch`; `sliced` (#40): in batches of\n * {@link STEP} rows with a `yield` between them, so the slicer can end the task on time (a slow\n * formatter, e.g. dates, is never one long task). Failures and slot-contract breaks are counted\n * over the whole column and reported once.\n */\n function* formatting(\n data: readonly unknown[],\n column: ResolvedColumn,\n sliced: boolean,\n ): Generator<undefined, readonly string[], undefined> {\n let e = entry(data, column)\n if (e.formatted) {\n if (flags && e.flaggedFormatted) flags.count++\n return e.formatted\n }\n const before = flags?.count ?? 0\n const vals = values(data, column)\n if (sliced) yield // reading the values is a task of its own\n const kinds = e.nullish\n // The raw value: nullish numbers read back as null / undefined, not NaN.\n const valueAt = (r: number): unknown => {\n const k = kinds?.[r]\n return k ? (k === NULL ? null : undefined) : vals[r]\n }\n const n = data.length\n const rows = allRows(data)\n const format = column.format\n // Job-local counts: a sliced column spans several batches.\n const failed = new CellFailures()\n const bad = (process.env.NODE_ENV !== \"production\") ? new CellFailures() : undefined\n const unrendered = new CellFailures()\n let firstBad: unknown\n let firstType = ''\n let cur = 0\n // A column with `cell` renders itself: its formatted value only feeds search.\n const onUnrenderable = column.hasCell\n ? undefined\n : (v: unknown) => {\n if (unrendered.count === 0) firstType = typeName(v)\n unrendered.add(cur, undefined)\n }\n const cell = format\n ? (r: number) => {\n const s = format(valueAt(r))\n if (typeof s === 'string') return s\n // Slot contract (dev): counted only on this non-string path; coerced either way.\n if ((process.env.NODE_ENV !== \"production\") && bad) {\n if (bad.count === 0) firstBad = s\n bad.add(r, undefined)\n }\n return defaultFormat(s)\n }\n : (r: number) => {\n cur = r\n return defaultFormat(valueAt(r), onUnrenderable)\n }\n // Values that are all strings already format to themselves: no copy (§9.3 memory).\n const strings = !format && !(vals instanceof Float64Array) && allStrings(vals)\n let out: string[] | undefined = strings ? undefined : new Array(n).fill('')\n for (let from = 0; from < n; from += STEP) {\n const part = sliced && !strings ? rows.subarray(from, from + STEP) : rows\n // An interceptor may skip a batch: its cells keep the slot fallback ('').\n batch(column, 'format', 'format', part, () => {\n if (strings) out = vals as string[]\n else runCells(part, cell, out as string[], '', failed)\n })\n if (part === rows || from + STEP >= n) break\n yield\n }\n out ??= new Array<string>(n).fill('')\n failed.report(host.emit, column.index, column.id, 'format')\n if ((process.env.NODE_ENV !== \"production\") && bad && bad.count > 0) {\n host.emit('DK_CALLBACK_BAD_RETURN', {\n slot: `columns[${column.index}].format`,\n column: column.id,\n expected: expectedReturn(formatSlot),\n received: describeReturn(firstBad),\n count: bad.count,\n rows: Array.from(bad.sample()),\n fallback: formatSlot.fallback,\n })\n }\n if (unrendered.count > 0) {\n host.emit('DK_UNRENDERABLE_VALUE', {\n column: column.id,\n index: column.index,\n count: unrendered.count,\n rows: Array.from(unrendered.sample()),\n valueType: firstType,\n })\n }\n if (out !== vals) share(out)\n // A synchronous read may have cached the column while a sliced job ran.\n e = entry(data, column)\n if (!e.formatted) {\n e.formatted = out\n if (flags && flags.count > before) e.flaggedFormatted = true\n }\n return e.formatted\n }\n\n function formatted(data: readonly unknown[], column: ResolvedColumn): readonly string[] {\n return runJob(() => formatting(data, column, false))\n }\n\n return {\n values,\n formatted,\n formattedSliced: (data, column) => formatting(data, column, true),\n batch,\n release: () => {\n byData = new WeakMap()\n },\n ...((process.env.NODE_ENV !== \"production\") ? { holds: (data: readonly unknown[]) => byData.has(data) } : {}),\n }\n}\n"],"mappings":"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","names":["values"]}
@@ -0,0 +1,34 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/pipeline/release.ts
21
+ var release_exports = {};
22
+ __export(release_exports, {
23
+ PROBE: () => PROBE,
24
+ RELEASE: () => RELEASE
25
+ });
26
+ module.exports = __toCommonJS(release_exports);
27
+ var RELEASE = /* @__PURE__ */ Symbol();
28
+ var PROBE = /* @__PURE__ */ Symbol();
29
+ // Annotate the CommonJS export names for ESM import in node:
30
+ 0 && (module.exports = {
31
+ PROBE,
32
+ RELEASE
33
+ });
34
+ //# sourceMappingURL=release.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/pipeline/release.ts"],"sourcesContent":["/**\n * Internal (#98), not exported: a feature's `[RELEASE]()` drops its per-instance caches. The table\n * calls it on `destroy()`, so a destroyed table still referenced (a ref, a store, StrictMode's\n * double mount) does not keep them.\n */\nexport const RELEASE = /* @__PURE__ */ Symbol()\n\n/** Development only, for tests (#98): `[PROBE]()` returns what a feature / the table still holds. */\nexport const PROBE = /* @__PURE__ */ Symbol()\n\nexport interface Releasable {\n [RELEASE]?: () => void\n [PROBE]?: () => Record<string, unknown>\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAKO,IAAM,UAA0B,uBAAO;AAGvC,IAAM,QAAwB,uBAAO;","names":[]}
@@ -0,0 +1,8 @@
1
+ // src/pipeline/release.ts
2
+ var RELEASE = /* @__PURE__ */ Symbol();
3
+ var PROBE = /* @__PURE__ */ Symbol();
4
+ export {
5
+ PROBE,
6
+ RELEASE
7
+ };
8
+ //# sourceMappingURL=release.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/pipeline/release.ts"],"sourcesContent":["/**\n * Internal (#98), not exported: a feature's `[RELEASE]()` drops its per-instance caches. The table\n * calls it on `destroy()`, so a destroyed table still referenced (a ref, a store, StrictMode's\n * double mount) does not keep them.\n */\nexport const RELEASE = /* @__PURE__ */ Symbol()\n\n/** Development only, for tests (#98): `[PROBE]()` returns what a feature / the table still holds. */\nexport const PROBE = /* @__PURE__ */ Symbol()\n\nexport interface Releasable {\n [RELEASE]?: () => void\n [PROBE]?: () => Record<string, unknown>\n}\n"],"mappings":";AAKO,IAAM,UAA0B,uBAAO;AAGvC,IAAM,QAAwB,uBAAO;","names":[]}
@@ -333,7 +333,21 @@ function createPipeline(host) {
333
333
  current: () => model,
334
334
  lastRun: () => lastRun,
335
335
  replayContext,
336
- dispose: () => slicer?.cancel()
336
+ dispose: () => {
337
+ slicer?.cancel();
338
+ cache?.release();
339
+ memo.clear();
340
+ keys = void 0;
341
+ last = void 0;
342
+ },
343
+ ...process.env.NODE_ENV !== "production" ? {
344
+ probe: () => ({
345
+ memo: memo.size,
346
+ keys: keys !== void 0,
347
+ last: last !== void 0,
348
+ cached: cache?.holds?.(host.getData()) === true
349
+ })
350
+ } : {}
337
351
  };
338
352
  }
339
353
  // Annotate the CommonJS export names for ESM import in node:
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/pipeline/runner.ts"],"sourcesContent":["import { getValue } from '../column/get-value'\nimport { keepDiagnostics } from '../diagnostics/catalog'\nimport '../diagnostics/process-guard'\nimport { SLICED, sliceTimer } from '../diagnostics/trace-store'\nimport type { Emit, Trigger } from '../diagnostics/types'\nimport { featureDiagnostics } from '../feature/codes'\nimport type { FeatureRuntime } from '../feature/runtime'\nimport type { AnyFeature, RowModelContext } from '../feature/types'\nimport { matchCellIssues } from '../ingest/cell-issues'\nimport { type KeyOf, resolveRowKeys } from '../ingest/row-key'\nimport { CellFailures } from '../intercept/cell-batch'\nimport { errorName } from '../intercept/classify'\nimport { type ContextBase, createContext } from '../intercept/context'\nimport { FALLBACK } from '../intercept/fallbacks'\nimport type { InterceptorRuntime } from '../intercept/runtime'\nimport type { TableState } from '../table/types'\nimport type { ColumnCache, SlicedFormatting } from './column-cache'\nimport { type ResolvedColumn, type ResolvedColumns, resolveColumns } from './columns'\nimport { checkStep, indexPrint, stepDiagnostics } from './dev-checks'\nimport { allRows } from './indices'\nimport { lazyRows, Row, type RowIssue, type RowSource } from './row'\nimport type { Slicer } from './slice'\nimport { inStepDiagnosticSetsError } from './status-rule'\nimport type { RowModel, RowModelStatus } from './types'\n\nkeepDiagnostics(featureDiagnostics, stepDiagnostics)\n\nconst EMPTY: readonly never[] = []\nconst NO_EMIT = (() => undefined) as Emit\n\n/** What `createTable` gives the runner. */\nexport interface PipelineHost {\n readonly runtime: InterceptorRuntime\n /**\n * What the features brought (`runtimeFor`): the column cache and time-slicing of their steps.\n * Always set when a feature has a `rowModel`; a table without features runs no step.\n */\n readonly featureRuntime?: FeatureRuntime | undefined\n readonly emit: Emit\n /** Installed features in pipeline (stage) order. */\n readonly features: readonly AnyFeature[]\n /** `options.features` in the listed order: `where` = `features[<listed index>].rowModel`. */\n readonly listed: readonly AnyFeature[]\n base(): ContextBase\n /** Starts a pipeline run: increments and returns the run id. */\n nextRun(): number\n getData(): readonly unknown[]\n getState(): TableState\n getColumns(): readonly unknown[] | undefined\n getRowKey(): unknown\n /** `RowModel.isInitialLoad`: no data applied yet (§6.6). */\n isInitialLoad(): boolean\n /**\n * The table's status outside the pipeline (`'validating'`, `'error'` after a failed ingest, …);\n * a step failing in this run makes the row model `'error'` regardless.\n */\n status(): RowModelStatus\n /** Schema issues of a flagged row by data index (`invalidRows: 'flag'`); else `undefined`. */\n issues(index: number): readonly RowIssue[] | undefined\n /** `schema` + `invalidRows: 'flag'` (read once): steps get `RowModelContext.flagged`. */\n readonly flagMode?: boolean\n /**\n * Time-sliced work (§9.1, `RowModelContext.slice`) ended: recompute the row model and notify,\n * under the trigger of the run that started it. Without it nothing is sliced.\n */\n refresh?(trigger: Trigger): void\n}\n\nexport interface Pipeline<T> {\n /** Runs `pipeline:run` and returns the row model (the previous object when nothing changed). */\n run(): RowModel<T>\n /** The last row model, if the pipeline ran. */\n current(): RowModel<T> | undefined\n /** The last run (`explain`, §8.4); `undefined` before the first. */\n lastRun(): RunRecord | undefined\n /**\n * A `rowModel` context over the current data and columns for replaying a step on chosen rows\n * (`explainRow`, §8.4): diagnostics are dropped and `batch` runs its body directly (no\n * interceptors), so a replay reports nothing and changes nothing.\n */\n replayContext(name: string): RowModelContext\n /** Cancels time-sliced work in progress (`destroy()`). */\n dispose(): void\n}\n\n/**\n * One step of the last run (`explain` / `explainRow`, §8.4): references to the index arrays the\n * step memo holds anyway, never copies. `cached`: served from the memo; `failed`: the step threw or\n * returned a bad output and passed its input through.\n */\nexport interface RunRecord {\n readonly run: number\n readonly trigger: Trigger\n /** The client steps that ran, in order (fewer when `pipeline:run` itself failed). */\n readonly steps: readonly StepRecord[]\n}\n\nexport interface StepRecord {\n readonly feature: AnyFeature\n readonly input: Uint32Array\n readonly output: Uint32Array\n readonly cached: boolean\n readonly failed: boolean\n}\n\ninterface StepMemo {\n input: Uint32Array\n state: unknown\n columns: readonly unknown[]\n output: Uint32Array\n}\n\ninterface Built<T> {\n model: RowModel<T>\n data: readonly unknown[]\n indices: Uint32Array\n columns: readonly unknown[]\n rowKey: unknown\n}\n\n/**\n * The index-based pipeline (§3.3, §9.1): each step consumes and produces a `Uint32Array` of row\n * indices, is memoised on (input reference, own slice, columns), and `Row` objects are created only\n * for the final (visible) indices, each when it is first read.\n */\nexport function createPipeline<T>(host: PipelineHost): Pipeline<T> {\n /**\n * In-step diagnostics the §6.6 status rule counts (`inStepDiagnosticSetsError`), ever reported:\n * a step whose run moved it makes the row model `'error'` and is not memoised.\n */\n const flags = { count: 0 }\n /** `emit` for steps and the column cache: counts through the status rule. */\n const stepEmit = ((code, details, options) => {\n if (inStepDiagnosticSetsError(code)) flags.count++\n host.emit(code, details, options)\n }) as Emit\n const rt = host.featureRuntime\n // Only steps (and explainRow's replay of them) read the cache: they exist only with a runtime.\n const cache = rt?.createColumnCache({\n runtime: host.runtime,\n emit: stepEmit,\n base: () => host.base(),\n flags,\n }) as ColumnCache\n // A server-mode feature (§7.1) only holds state: the server ran its step.\n const steps = host.features.filter(\n (f) => f.stage !== 'none' && f.mode !== 'server' && typeof f.rowModel === 'function',\n )\n const where = new Map(steps.map((f) => [f, `features[${host.listed.indexOf(f)}].rowModel`]))\n const memo = new Map<AnyFeature, StepMemo>()\n const sources = new WeakMap<ResolvedColumns, RowSource>()\n const keyFailures = new CellFailures()\n /** The first `rowKey` error of the current build (its `cause`). */\n let keyError: unknown\n const keyFailed = (index: number, e: unknown) => {\n if (keyFailures.count === 0) keyError = e\n keyFailures.add(index, e)\n }\n let last: Built<T> | undefined\n /** Row keys resolved over all rows (§5.2), per (data, rowKey) reference. */\n let keys: { data: readonly unknown[]; rowKey: unknown; keyOf: KeyOf } | undefined\n let model: RowModel<T> | undefined\n /** The last run (replaced per run; a few references per step). */\n let lastRun: RunRecord | undefined\n /** Steps of the current run waiting on time-sliced work (§9.1): the row model is 'pending'. */\n let waiting = 0\n const refresh = host.refresh\n const slicer: Slicer | undefined = rt?.createSlicer({\n emit: stepEmit,\n // Not during SSR, and not for the first row model (the hydrated client matches the server).\n enabled: () => refresh !== undefined && last !== undefined && host.base().phase === 'client',\n trigger: () => host.base().trigger,\n done: (trigger) => refresh?.(trigger),\n timed: (feature, ms) => sliceTimer.current?.(host.base(), feature, ms),\n })\n\n /** `Row.getValue` failures: one emit per failing cell, built only when a cell fails. */\n function reportCell(col: ResolvedColumn, index: number, e: unknown, field: string) {\n const name = errorName(e)\n host.emit(\n 'DK_CALLBACK_FAILED',\n {\n slot: `columns[${col.index}].${field}`,\n column: col.id,\n rows: [index],\n count: 1,\n fallback: 'cell-undefined',\n ...(name === undefined ? {} : { errorName: name }),\n },\n { cause: e },\n )\n }\n // A key-path read error, captured by a closure made once (Row.getValue is per cell: no\n // allocation per call).\n let pathFailed = false\n let pathError: unknown\n const onPathError = (e: unknown) => {\n pathFailed = true\n pathError = e\n }\n\n function rowSource(cols: ResolvedColumns): RowSource {\n let s = sources.get(cols)\n if (s) return s\n s = {\n value(index, original, id) {\n const col = cols.byId.get(id)\n if (!col) return undefined\n if (col.path) {\n const v = getValue(original, col.path, onPathError)\n if (pathFailed) {\n const e = pathError\n pathFailed = false\n pathError = undefined\n reportCell(col, index, e, 'key')\n }\n return v\n }\n if (!col.accessor) return undefined\n try {\n return col.accessor(original)\n } catch (e) {\n reportCell(col, index, e, 'accessor')\n return undefined\n }\n },\n issues: (index) => host.issues(index),\n cellIssues(issues, id) {\n const col = cols.byId.get(id)\n return col ? matchCellIssues(issues, col.path) : EMPTY\n },\n }\n sources.set(cols, s)\n return s\n }\n\n function reportKeyFailures() {\n if (keyFailures.count === 0) return\n const name = errorName(keyError)\n host.emit(\n 'DK_CALLBACK_FAILED',\n {\n slot: 'rowKey',\n rows: Array.from(keyFailures.sample()),\n count: keyFailures.count,\n fallback: 'row-key-index',\n ...(name === undefined ? {} : { errorName: name }),\n },\n { cause: keyError },\n )\n keyFailures.reset()\n keyError = undefined\n }\n\n function build(\n data: readonly unknown[],\n indices: Uint32Array,\n columns: readonly unknown[],\n filteredCount: number,\n status: RowModelStatus,\n ): RowModel<T> {\n const rowKey = host.getRowKey()\n const isInitialLoad = host.isInitialLoad()\n const prev = last\n if (\n prev &&\n prev.indices === indices &&\n prev.data === data &&\n prev.columns === columns &&\n prev.rowKey === rowKey &&\n prev.model.status === status &&\n prev.model.isInitialLoad === isInitialLoad\n ) {\n return prev.model\n }\n const source = rowSource(resolveColumns(columns))\n keyFailures.reset()\n if (keys?.data !== data || keys.rowKey !== rowKey) {\n keys = { data, rowKey, keyOf: resolveRowKeys(data, rowKey, host.emit, keyFailed) }\n }\n const keyOf = keys.keyOf\n reportKeyFailures()\n // A data array whose rows cannot be read fails this run (the last good row model is kept),\n // not a later read of `rows[i]`.\n for (let i = 0; i < indices.length; i++) void data[indices[i] as number]\n // Rows are built when read (§9.3: no Row per visible row up front). The key scan above read\n // every key; one that throws only now is reported now.\n const rows = lazyRows(indices.length, (i) => {\n const r = indices[i] as number\n const original = data[r] as T\n const row = new Row<T>(source, r, keyOf(original, r), original)\n reportKeyFailures()\n return row\n })\n const m: RowModel<T> = { rows, filteredCount, totalCount: data.length, status, isInitialLoad }\n last = { model: m, data, indices, columns, rowKey }\n return m\n }\n\n function run(): RowModel<T> {\n host.nextRun()\n const data = host.getData()\n const columns = host.getColumns() ?? EMPTY\n const cols = resolveColumns(columns)\n const state = host.getState()\n let failed = false\n let result: RowModel<T> | undefined\n const records: StepRecord[] = []\n const { run: runId, trigger } = host.base()\n lastRun = { run: runId, trigger, steps: records }\n\n const rowModelContext = (name: string): RowModelContext & SlicedFormatting => ({\n name,\n data,\n emit: stepEmit,\n ...(host.flagMode ? { flagged: (i: number) => host.issues(i) } : {}),\n run: host.base().run,\n columns,\n getColumnValues: (id) => {\n const col = cols.byId.get(id)\n return col ? cache.values(data, col) : undefined\n },\n getFormattedValues: (id) => {\n const col = cols.byId.get(id)\n return col ? cache.formatted(data, col) : undefined\n },\n *formattedSliced(id) {\n const col = cols.byId.get(id)\n return col ? yield* cache.formattedSliced(data, col) : undefined\n },\n batch: (id, slot, rows, body) => {\n const col = cols.byId.get(id)\n if (col) cache.batch(col, slot, slot, rows, body)\n return col !== undefined\n },\n slice: (key, job) => {\n const r = (slicer as Slicer).run(key, job, name)\n if (r === undefined) waiting++\n return r\n },\n })\n\n function step(f: AnyFeature, input: Uint32Array): Uint32Array {\n const slice = state[f.name]\n const m = memo.get(f)\n if (m && m.input === input && Object.is(m.state, slice) && m.columns === columns) {\n records.push({ feature: f, input, output: m.output, cached: true, failed: false })\n return m.output\n }\n let ok = false\n const flagged = flags.count\n const waited = waiting\n const ctx = createContext(\n 'pipeline:step',\n { stage: f.stage, feature: f.name, indices: input },\n where.get(f) as string,\n host.base(),\n )\n const output = host.runtime.run('pipeline:step', ctx, () => {\n let out: unknown\n // Dev check (§3.4 devChecks): a bounded fingerprint of the input before rowModel runs.\n const before = (process.env.NODE_ENV !== \"production\") ? indexPrint(input) : 0\n try {\n out = (f.rowModel as NonNullable<AnyFeature['rowModel']>)(\n input,\n slice,\n rowModelContext(f.name),\n )\n } catch (e) {\n const name = errorName(e)\n host.emit(\n 'DK_FEATURE_FAILED',\n {\n feature: f.name,\n hook: 'rowModel',\n fallback: 'step-passthrough',\n ...(name === undefined ? {} : { errorName: name }),\n },\n { cause: e },\n )\n return input\n }\n // The tracer adds the time of this sliced work to the step (#61).\n if (waiting > waited) ctx.meta.set(SLICED, true)\n // Dev: a mutated input warns; a bad output passes the input through, not memoised.\n if ((process.env.NODE_ENV !== \"production\") && !checkStep(stepEmit, f.name, input, before, out, data.length)) return input\n ok = true\n return out instanceof Uint32Array ? out : input\n })\n // A counted in-step diagnostic (status rule): 'error' with the step's output, re-run next time.\n // A step waiting on sliced work returned a stand-in: re-run next time too.\n if (ok && flags.count === flagged) {\n if (waiting === waited) memo.set(f, { input, state: slice, columns, output })\n else memo.delete(f)\n } else {\n failed = true\n memo.delete(f)\n }\n records.push({ feature: f, input, output, cached: false, failed: !ok })\n return output\n }\n\n const ctx = createContext('pipeline:run', { rowCount: data.length }, 'features', host.base())\n // The last good row model (§3.4): its indices; the runner keeps the matching rows below.\n if (last) ctx.meta.set(FALLBACK, last.indices)\n waiting = 0\n slicer?.begin()\n try {\n void host.runtime.run('pipeline:run', ctx, () => {\n let indices = allRows(data)\n let filteredCount = -1\n for (const f of steps) {\n if (f.stage === 'paginate' && filteredCount < 0) filteredCount = indices.length\n indices = step(f, indices)\n }\n if (filteredCount < 0) filteredCount = indices.length\n // Sliced work in progress is 'pending', below every other status (§6.6 precedence).\n const outside = host.status()\n const status = failed ? 'error' : waiting > 0 && outside === 'idle' ? 'pending' : outside\n result = build(data, indices, columns, filteredCount, status)\n return indices\n })\n } finally {\n // Sliced work no step asked for in this run is stale: cancelled.\n slicer?.end()\n if (result) model = result\n else {\n // pipeline:run failed: the boundary reported it, or a strict throw is leaving the run\n // (#43). Either way the last good rows with status 'error', never an empty 'idle' model.\n const isInitialLoad = host.isInitialLoad()\n model = last\n ? { ...last.model, status: 'error', isInitialLoad }\n : { rows: EMPTY, filteredCount: 0, totalCount: 0, status: 'error', isInitialLoad }\n }\n }\n return model\n }\n\n function replayContext(name: string): RowModelContext {\n const data = host.getData()\n const columns = host.getColumns() ?? EMPTY\n const cols = resolveColumns(columns)\n return {\n name,\n data,\n emit: NO_EMIT,\n ...(host.flagMode ? { flagged: (i: number) => host.issues(i) } : {}),\n run: host.base().run,\n columns,\n getColumnValues: (id) => {\n const col = cols.byId.get(id)\n return col ? cache.values(data, col) : undefined\n },\n getFormattedValues: (id) => {\n const col = cols.byId.get(id)\n return col ? cache.formatted(data, col) : undefined\n },\n batch: (id, _slot, _rows, body) => {\n if (!cols.byId.has(id)) return false\n body()\n return true\n },\n }\n }\n\n return {\n run,\n current: () => model,\n lastRun: () => lastRun,\n replayContext,\n dispose: () => slicer?.cancel(),\n }\n}\n"],"mappings":"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","names":["ctx"]}
1
+ {"version":3,"sources":["../../src/pipeline/runner.ts"],"sourcesContent":["import { getValue } from '../column/get-value'\nimport { keepDiagnostics } from '../diagnostics/catalog'\nimport '../diagnostics/process-guard'\nimport { SLICED, sliceTimer } from '../diagnostics/trace-store'\nimport type { Emit, Trigger } from '../diagnostics/types'\nimport { featureDiagnostics } from '../feature/codes'\nimport type { FeatureRuntime } from '../feature/runtime'\nimport type { AnyFeature, RowModelContext } from '../feature/types'\nimport { matchCellIssues } from '../ingest/cell-issues'\nimport { type KeyOf, resolveRowKeys } from '../ingest/row-key'\nimport { CellFailures } from '../intercept/cell-batch'\nimport { errorName } from '../intercept/classify'\nimport { type ContextBase, createContext } from '../intercept/context'\nimport { FALLBACK } from '../intercept/fallbacks'\nimport type { InterceptorRuntime } from '../intercept/runtime'\nimport type { TableState } from '../table/types'\nimport type { ColumnCache, SlicedFormatting } from './column-cache'\nimport { type ResolvedColumn, type ResolvedColumns, resolveColumns } from './columns'\nimport { checkStep, indexPrint, stepDiagnostics } from './dev-checks'\nimport { allRows } from './indices'\nimport { lazyRows, Row, type RowIssue, type RowSource } from './row'\nimport type { Slicer } from './slice'\nimport { inStepDiagnosticSetsError } from './status-rule'\nimport type { RowModel, RowModelStatus } from './types'\n\nkeepDiagnostics(featureDiagnostics, stepDiagnostics)\n\nconst EMPTY: readonly never[] = []\nconst NO_EMIT = (() => undefined) as Emit\n\n/** What `createTable` gives the runner. */\nexport interface PipelineHost {\n readonly runtime: InterceptorRuntime\n /**\n * What the features brought (`runtimeFor`): the column cache and time-slicing of their steps.\n * Always set when a feature has a `rowModel`; a table without features runs no step.\n */\n readonly featureRuntime?: FeatureRuntime | undefined\n readonly emit: Emit\n /** Installed features in pipeline (stage) order. */\n readonly features: readonly AnyFeature[]\n /** `options.features` in the listed order: `where` = `features[<listed index>].rowModel`. */\n readonly listed: readonly AnyFeature[]\n base(): ContextBase\n /** Starts a pipeline run: increments and returns the run id. */\n nextRun(): number\n getData(): readonly unknown[]\n getState(): TableState\n getColumns(): readonly unknown[] | undefined\n getRowKey(): unknown\n /** `RowModel.isInitialLoad`: no data applied yet (§6.6). */\n isInitialLoad(): boolean\n /**\n * The table's status outside the pipeline (`'validating'`, `'error'` after a failed ingest, …);\n * a step failing in this run makes the row model `'error'` regardless.\n */\n status(): RowModelStatus\n /** Schema issues of a flagged row by data index (`invalidRows: 'flag'`); else `undefined`. */\n issues(index: number): readonly RowIssue[] | undefined\n /** `schema` + `invalidRows: 'flag'` (read once): steps get `RowModelContext.flagged`. */\n readonly flagMode?: boolean\n /**\n * Time-sliced work (§9.1, `RowModelContext.slice`) ended: recompute the row model and notify,\n * under the trigger of the run that started it. Without it nothing is sliced.\n */\n refresh?(trigger: Trigger): void\n}\n\nexport interface Pipeline<T> {\n /** Runs `pipeline:run` and returns the row model (the previous object when nothing changed). */\n run(): RowModel<T>\n /** The last row model, if the pipeline ran. */\n current(): RowModel<T> | undefined\n /** The last run (`explain`, §8.4); `undefined` before the first. */\n lastRun(): RunRecord | undefined\n /**\n * A `rowModel` context over the current data and columns for replaying a step on chosen rows\n * (`explainRow`, §8.4): diagnostics are dropped and `batch` runs its body directly (no\n * interceptors), so a replay reports nothing and changes nothing.\n */\n replayContext(name: string): RowModelContext\n /**\n * `destroy()`: cancels time-sliced work in progress and releases the column cache, the step memo\n * and the row keys (#98). {@link current} stays readable.\n */\n dispose(): void\n /** Development only, for tests (#98): what the runner still holds. */\n probe?(): { memo: number; keys: boolean; last: boolean; cached: boolean }\n}\n\n/**\n * One step of the last run (`explain` / `explainRow`, §8.4): references to the index arrays the\n * step memo holds anyway, never copies. `cached`: served from the memo; `failed`: the step threw or\n * returned a bad output and passed its input through.\n */\nexport interface RunRecord {\n readonly run: number\n readonly trigger: Trigger\n /** The client steps that ran, in order (fewer when `pipeline:run` itself failed). */\n readonly steps: readonly StepRecord[]\n}\n\nexport interface StepRecord {\n readonly feature: AnyFeature\n readonly input: Uint32Array\n readonly output: Uint32Array\n readonly cached: boolean\n readonly failed: boolean\n}\n\ninterface StepMemo {\n input: Uint32Array\n state: unknown\n columns: readonly unknown[]\n output: Uint32Array\n}\n\ninterface Built<T> {\n model: RowModel<T>\n data: readonly unknown[]\n indices: Uint32Array\n columns: readonly unknown[]\n rowKey: unknown\n}\n\n/**\n * The index-based pipeline (§3.3, §9.1): each step consumes and produces a `Uint32Array` of row\n * indices, is memoised on (input reference, own slice, columns), and `Row` objects are created only\n * for the final (visible) indices, each when it is first read.\n */\nexport function createPipeline<T>(host: PipelineHost): Pipeline<T> {\n /**\n * In-step diagnostics the §6.6 status rule counts (`inStepDiagnosticSetsError`), ever reported:\n * a step whose run moved it makes the row model `'error'` and is not memoised.\n */\n const flags = { count: 0 }\n /** `emit` for steps and the column cache: counts through the status rule. */\n const stepEmit = ((code, details, options) => {\n if (inStepDiagnosticSetsError(code)) flags.count++\n host.emit(code, details, options)\n }) as Emit\n const rt = host.featureRuntime\n // Only steps (and explainRow's replay of them) read the cache: they exist only with a runtime.\n const cache = rt?.createColumnCache({\n runtime: host.runtime,\n emit: stepEmit,\n base: () => host.base(),\n flags,\n }) as ColumnCache\n // A server-mode feature (§7.1) only holds state: the server ran its step.\n const steps = host.features.filter(\n (f) => f.stage !== 'none' && f.mode !== 'server' && typeof f.rowModel === 'function',\n )\n const where = new Map(steps.map((f) => [f, `features[${host.listed.indexOf(f)}].rowModel`]))\n const memo = new Map<AnyFeature, StepMemo>()\n const sources = new WeakMap<ResolvedColumns, RowSource>()\n const keyFailures = new CellFailures()\n /** The first `rowKey` error of the current build (its `cause`). */\n let keyError: unknown\n const keyFailed = (index: number, e: unknown) => {\n if (keyFailures.count === 0) keyError = e\n keyFailures.add(index, e)\n }\n let last: Built<T> | undefined\n /** Row keys resolved over all rows (§5.2), per (data, rowKey) reference. */\n let keys: { data: readonly unknown[]; rowKey: unknown; keyOf: KeyOf } | undefined\n let model: RowModel<T> | undefined\n /** The last run (replaced per run; a few references per step). */\n let lastRun: RunRecord | undefined\n /** Steps of the current run waiting on time-sliced work (§9.1): the row model is 'pending'. */\n let waiting = 0\n const refresh = host.refresh\n const slicer: Slicer | undefined = rt?.createSlicer({\n emit: stepEmit,\n // Not during SSR, and not for the first row model (the hydrated client matches the server).\n enabled: () => refresh !== undefined && last !== undefined && host.base().phase === 'client',\n trigger: () => host.base().trigger,\n done: (trigger) => refresh?.(trigger),\n timed: (feature, ms) => sliceTimer.current?.(host.base(), feature, ms),\n })\n\n /** `Row.getValue` failures: one emit per failing cell, built only when a cell fails. */\n function reportCell(col: ResolvedColumn, index: number, e: unknown, field: string) {\n const name = errorName(e)\n host.emit(\n 'DK_CALLBACK_FAILED',\n {\n slot: `columns[${col.index}].${field}`,\n column: col.id,\n rows: [index],\n count: 1,\n fallback: 'cell-undefined',\n ...(name === undefined ? {} : { errorName: name }),\n },\n { cause: e },\n )\n }\n // A key-path read error, captured by a closure made once (Row.getValue is per cell: no\n // allocation per call).\n let pathFailed = false\n let pathError: unknown\n const onPathError = (e: unknown) => {\n pathFailed = true\n pathError = e\n }\n\n function rowSource(cols: ResolvedColumns): RowSource {\n let s = sources.get(cols)\n if (s) return s\n s = {\n value(index, original, id) {\n const col = cols.byId.get(id)\n if (!col) return undefined\n if (col.path) {\n const v = getValue(original, col.path, onPathError)\n if (pathFailed) {\n const e = pathError\n pathFailed = false\n pathError = undefined\n reportCell(col, index, e, 'key')\n }\n return v\n }\n if (!col.accessor) return undefined\n try {\n return col.accessor(original)\n } catch (e) {\n reportCell(col, index, e, 'accessor')\n return undefined\n }\n },\n issues: (index) => host.issues(index),\n cellIssues(issues, id) {\n const col = cols.byId.get(id)\n return col ? matchCellIssues(issues, col.path) : EMPTY\n },\n }\n sources.set(cols, s)\n return s\n }\n\n function reportKeyFailures() {\n if (keyFailures.count === 0) return\n const name = errorName(keyError)\n host.emit(\n 'DK_CALLBACK_FAILED',\n {\n slot: 'rowKey',\n rows: Array.from(keyFailures.sample()),\n count: keyFailures.count,\n fallback: 'row-key-index',\n ...(name === undefined ? {} : { errorName: name }),\n },\n { cause: keyError },\n )\n keyFailures.reset()\n keyError = undefined\n }\n\n function build(\n data: readonly unknown[],\n indices: Uint32Array,\n columns: readonly unknown[],\n filteredCount: number,\n status: RowModelStatus,\n ): RowModel<T> {\n const rowKey = host.getRowKey()\n const isInitialLoad = host.isInitialLoad()\n const prev = last\n if (\n prev &&\n prev.indices === indices &&\n prev.data === data &&\n prev.columns === columns &&\n prev.rowKey === rowKey &&\n prev.model.status === status &&\n prev.model.isInitialLoad === isInitialLoad\n ) {\n return prev.model\n }\n const source = rowSource(resolveColumns(columns))\n keyFailures.reset()\n if (keys?.data !== data || keys.rowKey !== rowKey) {\n keys = { data, rowKey, keyOf: resolveRowKeys(data, rowKey, host.emit, keyFailed) }\n }\n const keyOf = keys.keyOf\n reportKeyFailures()\n // A data array whose rows cannot be read fails this run (the last good row model is kept),\n // not a later read of `rows[i]`.\n for (let i = 0; i < indices.length; i++) void data[indices[i] as number]\n // Rows are built when read (§9.3: no Row per visible row up front). The key scan above read\n // every key; one that throws only now is reported now.\n const rows = lazyRows(indices.length, (i) => {\n const r = indices[i] as number\n const original = data[r] as T\n const row = new Row<T>(source, r, keyOf(original, r), original)\n reportKeyFailures()\n return row\n })\n const m: RowModel<T> = { rows, filteredCount, totalCount: data.length, status, isInitialLoad }\n last = { model: m, data, indices, columns, rowKey }\n return m\n }\n\n function run(): RowModel<T> {\n host.nextRun()\n const data = host.getData()\n const columns = host.getColumns() ?? EMPTY\n const cols = resolveColumns(columns)\n const state = host.getState()\n let failed = false\n let result: RowModel<T> | undefined\n const records: StepRecord[] = []\n const { run: runId, trigger } = host.base()\n lastRun = { run: runId, trigger, steps: records }\n\n const rowModelContext = (name: string): RowModelContext & SlicedFormatting => ({\n name,\n data,\n emit: stepEmit,\n ...(host.flagMode ? { flagged: (i: number) => host.issues(i) } : {}),\n run: host.base().run,\n columns,\n getColumnValues: (id) => {\n const col = cols.byId.get(id)\n return col ? cache.values(data, col) : undefined\n },\n getFormattedValues: (id) => {\n const col = cols.byId.get(id)\n return col ? cache.formatted(data, col) : undefined\n },\n *formattedSliced(id) {\n const col = cols.byId.get(id)\n return col ? yield* cache.formattedSliced(data, col) : undefined\n },\n batch: (id, slot, rows, body) => {\n const col = cols.byId.get(id)\n if (col) cache.batch(col, slot, slot, rows, body)\n return col !== undefined\n },\n slice: (key, job) => {\n const r = (slicer as Slicer).run(key, job, name)\n if (r === undefined) waiting++\n return r\n },\n })\n\n function step(f: AnyFeature, input: Uint32Array): Uint32Array {\n const slice = state[f.name]\n const m = memo.get(f)\n if (m && m.input === input && Object.is(m.state, slice) && m.columns === columns) {\n records.push({ feature: f, input, output: m.output, cached: true, failed: false })\n return m.output\n }\n let ok = false\n const flagged = flags.count\n const waited = waiting\n const ctx = createContext(\n 'pipeline:step',\n { stage: f.stage, feature: f.name, indices: input },\n where.get(f) as string,\n host.base(),\n )\n const output = host.runtime.run('pipeline:step', ctx, () => {\n let out: unknown\n // Dev check (§3.4 devChecks): a bounded fingerprint of the input before rowModel runs.\n const before = (process.env.NODE_ENV !== \"production\") ? indexPrint(input) : 0\n try {\n out = (f.rowModel as NonNullable<AnyFeature['rowModel']>)(\n input,\n slice,\n rowModelContext(f.name),\n )\n } catch (e) {\n const name = errorName(e)\n host.emit(\n 'DK_FEATURE_FAILED',\n {\n feature: f.name,\n hook: 'rowModel',\n fallback: 'step-passthrough',\n ...(name === undefined ? {} : { errorName: name }),\n },\n { cause: e },\n )\n return input\n }\n // The tracer adds the time of this sliced work to the step (#61).\n if (waiting > waited) ctx.meta.set(SLICED, true)\n // Dev: a mutated input warns; a bad output passes the input through, not memoised.\n if ((process.env.NODE_ENV !== \"production\") && !checkStep(stepEmit, f.name, input, before, out, data.length)) return input\n ok = true\n return out instanceof Uint32Array ? out : input\n })\n // A counted in-step diagnostic (status rule): 'error' with the step's output, re-run next time.\n // A step waiting on sliced work returned a stand-in: re-run next time too.\n if (ok && flags.count === flagged) {\n if (waiting === waited) memo.set(f, { input, state: slice, columns, output })\n else memo.delete(f)\n } else {\n failed = true\n memo.delete(f)\n }\n records.push({ feature: f, input, output, cached: false, failed: !ok })\n return output\n }\n\n const ctx = createContext('pipeline:run', { rowCount: data.length }, 'features', host.base())\n // The last good row model (§3.4): its indices; the runner keeps the matching rows below.\n if (last) ctx.meta.set(FALLBACK, last.indices)\n waiting = 0\n slicer?.begin()\n try {\n void host.runtime.run('pipeline:run', ctx, () => {\n let indices = allRows(data)\n let filteredCount = -1\n for (const f of steps) {\n if (f.stage === 'paginate' && filteredCount < 0) filteredCount = indices.length\n indices = step(f, indices)\n }\n if (filteredCount < 0) filteredCount = indices.length\n // Sliced work in progress is 'pending', below every other status (§6.6 precedence).\n const outside = host.status()\n const status = failed ? 'error' : waiting > 0 && outside === 'idle' ? 'pending' : outside\n result = build(data, indices, columns, filteredCount, status)\n return indices\n })\n } finally {\n // Sliced work no step asked for in this run is stale: cancelled.\n slicer?.end()\n if (result) model = result\n else {\n // pipeline:run failed: the boundary reported it, or a strict throw is leaving the run\n // (#43). Either way the last good rows with status 'error', never an empty 'idle' model.\n const isInitialLoad = host.isInitialLoad()\n model = last\n ? { ...last.model, status: 'error', isInitialLoad }\n : { rows: EMPTY, filteredCount: 0, totalCount: 0, status: 'error', isInitialLoad }\n }\n }\n return model\n }\n\n function replayContext(name: string): RowModelContext {\n const data = host.getData()\n const columns = host.getColumns() ?? EMPTY\n const cols = resolveColumns(columns)\n return {\n name,\n data,\n emit: NO_EMIT,\n ...(host.flagMode ? { flagged: (i: number) => host.issues(i) } : {}),\n run: host.base().run,\n columns,\n getColumnValues: (id) => {\n const col = cols.byId.get(id)\n return col ? cache.values(data, col) : undefined\n },\n getFormattedValues: (id) => {\n const col = cols.byId.get(id)\n return col ? cache.formatted(data, col) : undefined\n },\n batch: (id, _slot, _rows, body) => {\n if (!cols.byId.has(id)) return false\n body()\n return true\n },\n }\n }\n\n return {\n run,\n current: () => model,\n lastRun: () => lastRun,\n replayContext,\n dispose: () => {\n slicer?.cancel()\n cache?.release()\n memo.clear()\n keys = undefined\n last = undefined\n },\n ...((process.env.NODE_ENV !== \"production\")\n ? {\n probe: () => ({\n memo: memo.size,\n keys: keys !== undefined,\n last: last !== undefined,\n cached: cache?.holds?.(host.getData()) === true,\n }),\n }\n : {}),\n }\n}\n"],"mappings":"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","names":["ctx"]}
@@ -309,7 +309,21 @@ function createPipeline(host) {
309
309
  current: () => model,
310
310
  lastRun: () => lastRun,
311
311
  replayContext,
312
- dispose: () => slicer?.cancel()
312
+ dispose: () => {
313
+ slicer?.cancel();
314
+ cache?.release();
315
+ memo.clear();
316
+ keys = void 0;
317
+ last = void 0;
318
+ },
319
+ ...process.env.NODE_ENV !== "production" ? {
320
+ probe: () => ({
321
+ memo: memo.size,
322
+ keys: keys !== void 0,
323
+ last: last !== void 0,
324
+ cached: cache?.holds?.(host.getData()) === true
325
+ })
326
+ } : {}
313
327
  };
314
328
  }
315
329
  export {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/pipeline/runner.ts"],"sourcesContent":["import { getValue } from '../column/get-value'\nimport { keepDiagnostics } from '../diagnostics/catalog'\nimport '../diagnostics/process-guard'\nimport { SLICED, sliceTimer } from '../diagnostics/trace-store'\nimport type { Emit, Trigger } from '../diagnostics/types'\nimport { featureDiagnostics } from '../feature/codes'\nimport type { FeatureRuntime } from '../feature/runtime'\nimport type { AnyFeature, RowModelContext } from '../feature/types'\nimport { matchCellIssues } from '../ingest/cell-issues'\nimport { type KeyOf, resolveRowKeys } from '../ingest/row-key'\nimport { CellFailures } from '../intercept/cell-batch'\nimport { errorName } from '../intercept/classify'\nimport { type ContextBase, createContext } from '../intercept/context'\nimport { FALLBACK } from '../intercept/fallbacks'\nimport type { InterceptorRuntime } from '../intercept/runtime'\nimport type { TableState } from '../table/types'\nimport type { ColumnCache, SlicedFormatting } from './column-cache'\nimport { type ResolvedColumn, type ResolvedColumns, resolveColumns } from './columns'\nimport { checkStep, indexPrint, stepDiagnostics } from './dev-checks'\nimport { allRows } from './indices'\nimport { lazyRows, Row, type RowIssue, type RowSource } from './row'\nimport type { Slicer } from './slice'\nimport { inStepDiagnosticSetsError } from './status-rule'\nimport type { RowModel, RowModelStatus } from './types'\n\nkeepDiagnostics(featureDiagnostics, stepDiagnostics)\n\nconst EMPTY: readonly never[] = []\nconst NO_EMIT = (() => undefined) as Emit\n\n/** What `createTable` gives the runner. */\nexport interface PipelineHost {\n readonly runtime: InterceptorRuntime\n /**\n * What the features brought (`runtimeFor`): the column cache and time-slicing of their steps.\n * Always set when a feature has a `rowModel`; a table without features runs no step.\n */\n readonly featureRuntime?: FeatureRuntime | undefined\n readonly emit: Emit\n /** Installed features in pipeline (stage) order. */\n readonly features: readonly AnyFeature[]\n /** `options.features` in the listed order: `where` = `features[<listed index>].rowModel`. */\n readonly listed: readonly AnyFeature[]\n base(): ContextBase\n /** Starts a pipeline run: increments and returns the run id. */\n nextRun(): number\n getData(): readonly unknown[]\n getState(): TableState\n getColumns(): readonly unknown[] | undefined\n getRowKey(): unknown\n /** `RowModel.isInitialLoad`: no data applied yet (§6.6). */\n isInitialLoad(): boolean\n /**\n * The table's status outside the pipeline (`'validating'`, `'error'` after a failed ingest, …);\n * a step failing in this run makes the row model `'error'` regardless.\n */\n status(): RowModelStatus\n /** Schema issues of a flagged row by data index (`invalidRows: 'flag'`); else `undefined`. */\n issues(index: number): readonly RowIssue[] | undefined\n /** `schema` + `invalidRows: 'flag'` (read once): steps get `RowModelContext.flagged`. */\n readonly flagMode?: boolean\n /**\n * Time-sliced work (§9.1, `RowModelContext.slice`) ended: recompute the row model and notify,\n * under the trigger of the run that started it. Without it nothing is sliced.\n */\n refresh?(trigger: Trigger): void\n}\n\nexport interface Pipeline<T> {\n /** Runs `pipeline:run` and returns the row model (the previous object when nothing changed). */\n run(): RowModel<T>\n /** The last row model, if the pipeline ran. */\n current(): RowModel<T> | undefined\n /** The last run (`explain`, §8.4); `undefined` before the first. */\n lastRun(): RunRecord | undefined\n /**\n * A `rowModel` context over the current data and columns for replaying a step on chosen rows\n * (`explainRow`, §8.4): diagnostics are dropped and `batch` runs its body directly (no\n * interceptors), so a replay reports nothing and changes nothing.\n */\n replayContext(name: string): RowModelContext\n /** Cancels time-sliced work in progress (`destroy()`). */\n dispose(): void\n}\n\n/**\n * One step of the last run (`explain` / `explainRow`, §8.4): references to the index arrays the\n * step memo holds anyway, never copies. `cached`: served from the memo; `failed`: the step threw or\n * returned a bad output and passed its input through.\n */\nexport interface RunRecord {\n readonly run: number\n readonly trigger: Trigger\n /** The client steps that ran, in order (fewer when `pipeline:run` itself failed). */\n readonly steps: readonly StepRecord[]\n}\n\nexport interface StepRecord {\n readonly feature: AnyFeature\n readonly input: Uint32Array\n readonly output: Uint32Array\n readonly cached: boolean\n readonly failed: boolean\n}\n\ninterface StepMemo {\n input: Uint32Array\n state: unknown\n columns: readonly unknown[]\n output: Uint32Array\n}\n\ninterface Built<T> {\n model: RowModel<T>\n data: readonly unknown[]\n indices: Uint32Array\n columns: readonly unknown[]\n rowKey: unknown\n}\n\n/**\n * The index-based pipeline (§3.3, §9.1): each step consumes and produces a `Uint32Array` of row\n * indices, is memoised on (input reference, own slice, columns), and `Row` objects are created only\n * for the final (visible) indices, each when it is first read.\n */\nexport function createPipeline<T>(host: PipelineHost): Pipeline<T> {\n /**\n * In-step diagnostics the §6.6 status rule counts (`inStepDiagnosticSetsError`), ever reported:\n * a step whose run moved it makes the row model `'error'` and is not memoised.\n */\n const flags = { count: 0 }\n /** `emit` for steps and the column cache: counts through the status rule. */\n const stepEmit = ((code, details, options) => {\n if (inStepDiagnosticSetsError(code)) flags.count++\n host.emit(code, details, options)\n }) as Emit\n const rt = host.featureRuntime\n // Only steps (and explainRow's replay of them) read the cache: they exist only with a runtime.\n const cache = rt?.createColumnCache({\n runtime: host.runtime,\n emit: stepEmit,\n base: () => host.base(),\n flags,\n }) as ColumnCache\n // A server-mode feature (§7.1) only holds state: the server ran its step.\n const steps = host.features.filter(\n (f) => f.stage !== 'none' && f.mode !== 'server' && typeof f.rowModel === 'function',\n )\n const where = new Map(steps.map((f) => [f, `features[${host.listed.indexOf(f)}].rowModel`]))\n const memo = new Map<AnyFeature, StepMemo>()\n const sources = new WeakMap<ResolvedColumns, RowSource>()\n const keyFailures = new CellFailures()\n /** The first `rowKey` error of the current build (its `cause`). */\n let keyError: unknown\n const keyFailed = (index: number, e: unknown) => {\n if (keyFailures.count === 0) keyError = e\n keyFailures.add(index, e)\n }\n let last: Built<T> | undefined\n /** Row keys resolved over all rows (§5.2), per (data, rowKey) reference. */\n let keys: { data: readonly unknown[]; rowKey: unknown; keyOf: KeyOf } | undefined\n let model: RowModel<T> | undefined\n /** The last run (replaced per run; a few references per step). */\n let lastRun: RunRecord | undefined\n /** Steps of the current run waiting on time-sliced work (§9.1): the row model is 'pending'. */\n let waiting = 0\n const refresh = host.refresh\n const slicer: Slicer | undefined = rt?.createSlicer({\n emit: stepEmit,\n // Not during SSR, and not for the first row model (the hydrated client matches the server).\n enabled: () => refresh !== undefined && last !== undefined && host.base().phase === 'client',\n trigger: () => host.base().trigger,\n done: (trigger) => refresh?.(trigger),\n timed: (feature, ms) => sliceTimer.current?.(host.base(), feature, ms),\n })\n\n /** `Row.getValue` failures: one emit per failing cell, built only when a cell fails. */\n function reportCell(col: ResolvedColumn, index: number, e: unknown, field: string) {\n const name = errorName(e)\n host.emit(\n 'DK_CALLBACK_FAILED',\n {\n slot: `columns[${col.index}].${field}`,\n column: col.id,\n rows: [index],\n count: 1,\n fallback: 'cell-undefined',\n ...(name === undefined ? {} : { errorName: name }),\n },\n { cause: e },\n )\n }\n // A key-path read error, captured by a closure made once (Row.getValue is per cell: no\n // allocation per call).\n let pathFailed = false\n let pathError: unknown\n const onPathError = (e: unknown) => {\n pathFailed = true\n pathError = e\n }\n\n function rowSource(cols: ResolvedColumns): RowSource {\n let s = sources.get(cols)\n if (s) return s\n s = {\n value(index, original, id) {\n const col = cols.byId.get(id)\n if (!col) return undefined\n if (col.path) {\n const v = getValue(original, col.path, onPathError)\n if (pathFailed) {\n const e = pathError\n pathFailed = false\n pathError = undefined\n reportCell(col, index, e, 'key')\n }\n return v\n }\n if (!col.accessor) return undefined\n try {\n return col.accessor(original)\n } catch (e) {\n reportCell(col, index, e, 'accessor')\n return undefined\n }\n },\n issues: (index) => host.issues(index),\n cellIssues(issues, id) {\n const col = cols.byId.get(id)\n return col ? matchCellIssues(issues, col.path) : EMPTY\n },\n }\n sources.set(cols, s)\n return s\n }\n\n function reportKeyFailures() {\n if (keyFailures.count === 0) return\n const name = errorName(keyError)\n host.emit(\n 'DK_CALLBACK_FAILED',\n {\n slot: 'rowKey',\n rows: Array.from(keyFailures.sample()),\n count: keyFailures.count,\n fallback: 'row-key-index',\n ...(name === undefined ? {} : { errorName: name }),\n },\n { cause: keyError },\n )\n keyFailures.reset()\n keyError = undefined\n }\n\n function build(\n data: readonly unknown[],\n indices: Uint32Array,\n columns: readonly unknown[],\n filteredCount: number,\n status: RowModelStatus,\n ): RowModel<T> {\n const rowKey = host.getRowKey()\n const isInitialLoad = host.isInitialLoad()\n const prev = last\n if (\n prev &&\n prev.indices === indices &&\n prev.data === data &&\n prev.columns === columns &&\n prev.rowKey === rowKey &&\n prev.model.status === status &&\n prev.model.isInitialLoad === isInitialLoad\n ) {\n return prev.model\n }\n const source = rowSource(resolveColumns(columns))\n keyFailures.reset()\n if (keys?.data !== data || keys.rowKey !== rowKey) {\n keys = { data, rowKey, keyOf: resolveRowKeys(data, rowKey, host.emit, keyFailed) }\n }\n const keyOf = keys.keyOf\n reportKeyFailures()\n // A data array whose rows cannot be read fails this run (the last good row model is kept),\n // not a later read of `rows[i]`.\n for (let i = 0; i < indices.length; i++) void data[indices[i] as number]\n // Rows are built when read (§9.3: no Row per visible row up front). The key scan above read\n // every key; one that throws only now is reported now.\n const rows = lazyRows(indices.length, (i) => {\n const r = indices[i] as number\n const original = data[r] as T\n const row = new Row<T>(source, r, keyOf(original, r), original)\n reportKeyFailures()\n return row\n })\n const m: RowModel<T> = { rows, filteredCount, totalCount: data.length, status, isInitialLoad }\n last = { model: m, data, indices, columns, rowKey }\n return m\n }\n\n function run(): RowModel<T> {\n host.nextRun()\n const data = host.getData()\n const columns = host.getColumns() ?? EMPTY\n const cols = resolveColumns(columns)\n const state = host.getState()\n let failed = false\n let result: RowModel<T> | undefined\n const records: StepRecord[] = []\n const { run: runId, trigger } = host.base()\n lastRun = { run: runId, trigger, steps: records }\n\n const rowModelContext = (name: string): RowModelContext & SlicedFormatting => ({\n name,\n data,\n emit: stepEmit,\n ...(host.flagMode ? { flagged: (i: number) => host.issues(i) } : {}),\n run: host.base().run,\n columns,\n getColumnValues: (id) => {\n const col = cols.byId.get(id)\n return col ? cache.values(data, col) : undefined\n },\n getFormattedValues: (id) => {\n const col = cols.byId.get(id)\n return col ? cache.formatted(data, col) : undefined\n },\n *formattedSliced(id) {\n const col = cols.byId.get(id)\n return col ? yield* cache.formattedSliced(data, col) : undefined\n },\n batch: (id, slot, rows, body) => {\n const col = cols.byId.get(id)\n if (col) cache.batch(col, slot, slot, rows, body)\n return col !== undefined\n },\n slice: (key, job) => {\n const r = (slicer as Slicer).run(key, job, name)\n if (r === undefined) waiting++\n return r\n },\n })\n\n function step(f: AnyFeature, input: Uint32Array): Uint32Array {\n const slice = state[f.name]\n const m = memo.get(f)\n if (m && m.input === input && Object.is(m.state, slice) && m.columns === columns) {\n records.push({ feature: f, input, output: m.output, cached: true, failed: false })\n return m.output\n }\n let ok = false\n const flagged = flags.count\n const waited = waiting\n const ctx = createContext(\n 'pipeline:step',\n { stage: f.stage, feature: f.name, indices: input },\n where.get(f) as string,\n host.base(),\n )\n const output = host.runtime.run('pipeline:step', ctx, () => {\n let out: unknown\n // Dev check (§3.4 devChecks): a bounded fingerprint of the input before rowModel runs.\n const before = (process.env.NODE_ENV !== \"production\") ? indexPrint(input) : 0\n try {\n out = (f.rowModel as NonNullable<AnyFeature['rowModel']>)(\n input,\n slice,\n rowModelContext(f.name),\n )\n } catch (e) {\n const name = errorName(e)\n host.emit(\n 'DK_FEATURE_FAILED',\n {\n feature: f.name,\n hook: 'rowModel',\n fallback: 'step-passthrough',\n ...(name === undefined ? {} : { errorName: name }),\n },\n { cause: e },\n )\n return input\n }\n // The tracer adds the time of this sliced work to the step (#61).\n if (waiting > waited) ctx.meta.set(SLICED, true)\n // Dev: a mutated input warns; a bad output passes the input through, not memoised.\n if ((process.env.NODE_ENV !== \"production\") && !checkStep(stepEmit, f.name, input, before, out, data.length)) return input\n ok = true\n return out instanceof Uint32Array ? out : input\n })\n // A counted in-step diagnostic (status rule): 'error' with the step's output, re-run next time.\n // A step waiting on sliced work returned a stand-in: re-run next time too.\n if (ok && flags.count === flagged) {\n if (waiting === waited) memo.set(f, { input, state: slice, columns, output })\n else memo.delete(f)\n } else {\n failed = true\n memo.delete(f)\n }\n records.push({ feature: f, input, output, cached: false, failed: !ok })\n return output\n }\n\n const ctx = createContext('pipeline:run', { rowCount: data.length }, 'features', host.base())\n // The last good row model (§3.4): its indices; the runner keeps the matching rows below.\n if (last) ctx.meta.set(FALLBACK, last.indices)\n waiting = 0\n slicer?.begin()\n try {\n void host.runtime.run('pipeline:run', ctx, () => {\n let indices = allRows(data)\n let filteredCount = -1\n for (const f of steps) {\n if (f.stage === 'paginate' && filteredCount < 0) filteredCount = indices.length\n indices = step(f, indices)\n }\n if (filteredCount < 0) filteredCount = indices.length\n // Sliced work in progress is 'pending', below every other status (§6.6 precedence).\n const outside = host.status()\n const status = failed ? 'error' : waiting > 0 && outside === 'idle' ? 'pending' : outside\n result = build(data, indices, columns, filteredCount, status)\n return indices\n })\n } finally {\n // Sliced work no step asked for in this run is stale: cancelled.\n slicer?.end()\n if (result) model = result\n else {\n // pipeline:run failed: the boundary reported it, or a strict throw is leaving the run\n // (#43). Either way the last good rows with status 'error', never an empty 'idle' model.\n const isInitialLoad = host.isInitialLoad()\n model = last\n ? { ...last.model, status: 'error', isInitialLoad }\n : { rows: EMPTY, filteredCount: 0, totalCount: 0, status: 'error', isInitialLoad }\n }\n }\n return model\n }\n\n function replayContext(name: string): RowModelContext {\n const data = host.getData()\n const columns = host.getColumns() ?? EMPTY\n const cols = resolveColumns(columns)\n return {\n name,\n data,\n emit: NO_EMIT,\n ...(host.flagMode ? { flagged: (i: number) => host.issues(i) } : {}),\n run: host.base().run,\n columns,\n getColumnValues: (id) => {\n const col = cols.byId.get(id)\n return col ? cache.values(data, col) : undefined\n },\n getFormattedValues: (id) => {\n const col = cols.byId.get(id)\n return col ? cache.formatted(data, col) : undefined\n },\n batch: (id, _slot, _rows, body) => {\n if (!cols.byId.has(id)) return false\n body()\n return true\n },\n }\n }\n\n return {\n run,\n current: () => model,\n lastRun: () => lastRun,\n replayContext,\n dispose: () => slicer?.cancel(),\n }\n}\n"],"mappings":"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","names":["ctx"]}
1
+ {"version":3,"sources":["../../src/pipeline/runner.ts"],"sourcesContent":["import { getValue } from '../column/get-value'\nimport { keepDiagnostics } from '../diagnostics/catalog'\nimport '../diagnostics/process-guard'\nimport { SLICED, sliceTimer } from '../diagnostics/trace-store'\nimport type { Emit, Trigger } from '../diagnostics/types'\nimport { featureDiagnostics } from '../feature/codes'\nimport type { FeatureRuntime } from '../feature/runtime'\nimport type { AnyFeature, RowModelContext } from '../feature/types'\nimport { matchCellIssues } from '../ingest/cell-issues'\nimport { type KeyOf, resolveRowKeys } from '../ingest/row-key'\nimport { CellFailures } from '../intercept/cell-batch'\nimport { errorName } from '../intercept/classify'\nimport { type ContextBase, createContext } from '../intercept/context'\nimport { FALLBACK } from '../intercept/fallbacks'\nimport type { InterceptorRuntime } from '../intercept/runtime'\nimport type { TableState } from '../table/types'\nimport type { ColumnCache, SlicedFormatting } from './column-cache'\nimport { type ResolvedColumn, type ResolvedColumns, resolveColumns } from './columns'\nimport { checkStep, indexPrint, stepDiagnostics } from './dev-checks'\nimport { allRows } from './indices'\nimport { lazyRows, Row, type RowIssue, type RowSource } from './row'\nimport type { Slicer } from './slice'\nimport { inStepDiagnosticSetsError } from './status-rule'\nimport type { RowModel, RowModelStatus } from './types'\n\nkeepDiagnostics(featureDiagnostics, stepDiagnostics)\n\nconst EMPTY: readonly never[] = []\nconst NO_EMIT = (() => undefined) as Emit\n\n/** What `createTable` gives the runner. */\nexport interface PipelineHost {\n readonly runtime: InterceptorRuntime\n /**\n * What the features brought (`runtimeFor`): the column cache and time-slicing of their steps.\n * Always set when a feature has a `rowModel`; a table without features runs no step.\n */\n readonly featureRuntime?: FeatureRuntime | undefined\n readonly emit: Emit\n /** Installed features in pipeline (stage) order. */\n readonly features: readonly AnyFeature[]\n /** `options.features` in the listed order: `where` = `features[<listed index>].rowModel`. */\n readonly listed: readonly AnyFeature[]\n base(): ContextBase\n /** Starts a pipeline run: increments and returns the run id. */\n nextRun(): number\n getData(): readonly unknown[]\n getState(): TableState\n getColumns(): readonly unknown[] | undefined\n getRowKey(): unknown\n /** `RowModel.isInitialLoad`: no data applied yet (§6.6). */\n isInitialLoad(): boolean\n /**\n * The table's status outside the pipeline (`'validating'`, `'error'` after a failed ingest, …);\n * a step failing in this run makes the row model `'error'` regardless.\n */\n status(): RowModelStatus\n /** Schema issues of a flagged row by data index (`invalidRows: 'flag'`); else `undefined`. */\n issues(index: number): readonly RowIssue[] | undefined\n /** `schema` + `invalidRows: 'flag'` (read once): steps get `RowModelContext.flagged`. */\n readonly flagMode?: boolean\n /**\n * Time-sliced work (§9.1, `RowModelContext.slice`) ended: recompute the row model and notify,\n * under the trigger of the run that started it. Without it nothing is sliced.\n */\n refresh?(trigger: Trigger): void\n}\n\nexport interface Pipeline<T> {\n /** Runs `pipeline:run` and returns the row model (the previous object when nothing changed). */\n run(): RowModel<T>\n /** The last row model, if the pipeline ran. */\n current(): RowModel<T> | undefined\n /** The last run (`explain`, §8.4); `undefined` before the first. */\n lastRun(): RunRecord | undefined\n /**\n * A `rowModel` context over the current data and columns for replaying a step on chosen rows\n * (`explainRow`, §8.4): diagnostics are dropped and `batch` runs its body directly (no\n * interceptors), so a replay reports nothing and changes nothing.\n */\n replayContext(name: string): RowModelContext\n /**\n * `destroy()`: cancels time-sliced work in progress and releases the column cache, the step memo\n * and the row keys (#98). {@link current} stays readable.\n */\n dispose(): void\n /** Development only, for tests (#98): what the runner still holds. */\n probe?(): { memo: number; keys: boolean; last: boolean; cached: boolean }\n}\n\n/**\n * One step of the last run (`explain` / `explainRow`, §8.4): references to the index arrays the\n * step memo holds anyway, never copies. `cached`: served from the memo; `failed`: the step threw or\n * returned a bad output and passed its input through.\n */\nexport interface RunRecord {\n readonly run: number\n readonly trigger: Trigger\n /** The client steps that ran, in order (fewer when `pipeline:run` itself failed). */\n readonly steps: readonly StepRecord[]\n}\n\nexport interface StepRecord {\n readonly feature: AnyFeature\n readonly input: Uint32Array\n readonly output: Uint32Array\n readonly cached: boolean\n readonly failed: boolean\n}\n\ninterface StepMemo {\n input: Uint32Array\n state: unknown\n columns: readonly unknown[]\n output: Uint32Array\n}\n\ninterface Built<T> {\n model: RowModel<T>\n data: readonly unknown[]\n indices: Uint32Array\n columns: readonly unknown[]\n rowKey: unknown\n}\n\n/**\n * The index-based pipeline (§3.3, §9.1): each step consumes and produces a `Uint32Array` of row\n * indices, is memoised on (input reference, own slice, columns), and `Row` objects are created only\n * for the final (visible) indices, each when it is first read.\n */\nexport function createPipeline<T>(host: PipelineHost): Pipeline<T> {\n /**\n * In-step diagnostics the §6.6 status rule counts (`inStepDiagnosticSetsError`), ever reported:\n * a step whose run moved it makes the row model `'error'` and is not memoised.\n */\n const flags = { count: 0 }\n /** `emit` for steps and the column cache: counts through the status rule. */\n const stepEmit = ((code, details, options) => {\n if (inStepDiagnosticSetsError(code)) flags.count++\n host.emit(code, details, options)\n }) as Emit\n const rt = host.featureRuntime\n // Only steps (and explainRow's replay of them) read the cache: they exist only with a runtime.\n const cache = rt?.createColumnCache({\n runtime: host.runtime,\n emit: stepEmit,\n base: () => host.base(),\n flags,\n }) as ColumnCache\n // A server-mode feature (§7.1) only holds state: the server ran its step.\n const steps = host.features.filter(\n (f) => f.stage !== 'none' && f.mode !== 'server' && typeof f.rowModel === 'function',\n )\n const where = new Map(steps.map((f) => [f, `features[${host.listed.indexOf(f)}].rowModel`]))\n const memo = new Map<AnyFeature, StepMemo>()\n const sources = new WeakMap<ResolvedColumns, RowSource>()\n const keyFailures = new CellFailures()\n /** The first `rowKey` error of the current build (its `cause`). */\n let keyError: unknown\n const keyFailed = (index: number, e: unknown) => {\n if (keyFailures.count === 0) keyError = e\n keyFailures.add(index, e)\n }\n let last: Built<T> | undefined\n /** Row keys resolved over all rows (§5.2), per (data, rowKey) reference. */\n let keys: { data: readonly unknown[]; rowKey: unknown; keyOf: KeyOf } | undefined\n let model: RowModel<T> | undefined\n /** The last run (replaced per run; a few references per step). */\n let lastRun: RunRecord | undefined\n /** Steps of the current run waiting on time-sliced work (§9.1): the row model is 'pending'. */\n let waiting = 0\n const refresh = host.refresh\n const slicer: Slicer | undefined = rt?.createSlicer({\n emit: stepEmit,\n // Not during SSR, and not for the first row model (the hydrated client matches the server).\n enabled: () => refresh !== undefined && last !== undefined && host.base().phase === 'client',\n trigger: () => host.base().trigger,\n done: (trigger) => refresh?.(trigger),\n timed: (feature, ms) => sliceTimer.current?.(host.base(), feature, ms),\n })\n\n /** `Row.getValue` failures: one emit per failing cell, built only when a cell fails. */\n function reportCell(col: ResolvedColumn, index: number, e: unknown, field: string) {\n const name = errorName(e)\n host.emit(\n 'DK_CALLBACK_FAILED',\n {\n slot: `columns[${col.index}].${field}`,\n column: col.id,\n rows: [index],\n count: 1,\n fallback: 'cell-undefined',\n ...(name === undefined ? {} : { errorName: name }),\n },\n { cause: e },\n )\n }\n // A key-path read error, captured by a closure made once (Row.getValue is per cell: no\n // allocation per call).\n let pathFailed = false\n let pathError: unknown\n const onPathError = (e: unknown) => {\n pathFailed = true\n pathError = e\n }\n\n function rowSource(cols: ResolvedColumns): RowSource {\n let s = sources.get(cols)\n if (s) return s\n s = {\n value(index, original, id) {\n const col = cols.byId.get(id)\n if (!col) return undefined\n if (col.path) {\n const v = getValue(original, col.path, onPathError)\n if (pathFailed) {\n const e = pathError\n pathFailed = false\n pathError = undefined\n reportCell(col, index, e, 'key')\n }\n return v\n }\n if (!col.accessor) return undefined\n try {\n return col.accessor(original)\n } catch (e) {\n reportCell(col, index, e, 'accessor')\n return undefined\n }\n },\n issues: (index) => host.issues(index),\n cellIssues(issues, id) {\n const col = cols.byId.get(id)\n return col ? matchCellIssues(issues, col.path) : EMPTY\n },\n }\n sources.set(cols, s)\n return s\n }\n\n function reportKeyFailures() {\n if (keyFailures.count === 0) return\n const name = errorName(keyError)\n host.emit(\n 'DK_CALLBACK_FAILED',\n {\n slot: 'rowKey',\n rows: Array.from(keyFailures.sample()),\n count: keyFailures.count,\n fallback: 'row-key-index',\n ...(name === undefined ? {} : { errorName: name }),\n },\n { cause: keyError },\n )\n keyFailures.reset()\n keyError = undefined\n }\n\n function build(\n data: readonly unknown[],\n indices: Uint32Array,\n columns: readonly unknown[],\n filteredCount: number,\n status: RowModelStatus,\n ): RowModel<T> {\n const rowKey = host.getRowKey()\n const isInitialLoad = host.isInitialLoad()\n const prev = last\n if (\n prev &&\n prev.indices === indices &&\n prev.data === data &&\n prev.columns === columns &&\n prev.rowKey === rowKey &&\n prev.model.status === status &&\n prev.model.isInitialLoad === isInitialLoad\n ) {\n return prev.model\n }\n const source = rowSource(resolveColumns(columns))\n keyFailures.reset()\n if (keys?.data !== data || keys.rowKey !== rowKey) {\n keys = { data, rowKey, keyOf: resolveRowKeys(data, rowKey, host.emit, keyFailed) }\n }\n const keyOf = keys.keyOf\n reportKeyFailures()\n // A data array whose rows cannot be read fails this run (the last good row model is kept),\n // not a later read of `rows[i]`.\n for (let i = 0; i < indices.length; i++) void data[indices[i] as number]\n // Rows are built when read (§9.3: no Row per visible row up front). The key scan above read\n // every key; one that throws only now is reported now.\n const rows = lazyRows(indices.length, (i) => {\n const r = indices[i] as number\n const original = data[r] as T\n const row = new Row<T>(source, r, keyOf(original, r), original)\n reportKeyFailures()\n return row\n })\n const m: RowModel<T> = { rows, filteredCount, totalCount: data.length, status, isInitialLoad }\n last = { model: m, data, indices, columns, rowKey }\n return m\n }\n\n function run(): RowModel<T> {\n host.nextRun()\n const data = host.getData()\n const columns = host.getColumns() ?? EMPTY\n const cols = resolveColumns(columns)\n const state = host.getState()\n let failed = false\n let result: RowModel<T> | undefined\n const records: StepRecord[] = []\n const { run: runId, trigger } = host.base()\n lastRun = { run: runId, trigger, steps: records }\n\n const rowModelContext = (name: string): RowModelContext & SlicedFormatting => ({\n name,\n data,\n emit: stepEmit,\n ...(host.flagMode ? { flagged: (i: number) => host.issues(i) } : {}),\n run: host.base().run,\n columns,\n getColumnValues: (id) => {\n const col = cols.byId.get(id)\n return col ? cache.values(data, col) : undefined\n },\n getFormattedValues: (id) => {\n const col = cols.byId.get(id)\n return col ? cache.formatted(data, col) : undefined\n },\n *formattedSliced(id) {\n const col = cols.byId.get(id)\n return col ? yield* cache.formattedSliced(data, col) : undefined\n },\n batch: (id, slot, rows, body) => {\n const col = cols.byId.get(id)\n if (col) cache.batch(col, slot, slot, rows, body)\n return col !== undefined\n },\n slice: (key, job) => {\n const r = (slicer as Slicer).run(key, job, name)\n if (r === undefined) waiting++\n return r\n },\n })\n\n function step(f: AnyFeature, input: Uint32Array): Uint32Array {\n const slice = state[f.name]\n const m = memo.get(f)\n if (m && m.input === input && Object.is(m.state, slice) && m.columns === columns) {\n records.push({ feature: f, input, output: m.output, cached: true, failed: false })\n return m.output\n }\n let ok = false\n const flagged = flags.count\n const waited = waiting\n const ctx = createContext(\n 'pipeline:step',\n { stage: f.stage, feature: f.name, indices: input },\n where.get(f) as string,\n host.base(),\n )\n const output = host.runtime.run('pipeline:step', ctx, () => {\n let out: unknown\n // Dev check (§3.4 devChecks): a bounded fingerprint of the input before rowModel runs.\n const before = (process.env.NODE_ENV !== \"production\") ? indexPrint(input) : 0\n try {\n out = (f.rowModel as NonNullable<AnyFeature['rowModel']>)(\n input,\n slice,\n rowModelContext(f.name),\n )\n } catch (e) {\n const name = errorName(e)\n host.emit(\n 'DK_FEATURE_FAILED',\n {\n feature: f.name,\n hook: 'rowModel',\n fallback: 'step-passthrough',\n ...(name === undefined ? {} : { errorName: name }),\n },\n { cause: e },\n )\n return input\n }\n // The tracer adds the time of this sliced work to the step (#61).\n if (waiting > waited) ctx.meta.set(SLICED, true)\n // Dev: a mutated input warns; a bad output passes the input through, not memoised.\n if ((process.env.NODE_ENV !== \"production\") && !checkStep(stepEmit, f.name, input, before, out, data.length)) return input\n ok = true\n return out instanceof Uint32Array ? out : input\n })\n // A counted in-step diagnostic (status rule): 'error' with the step's output, re-run next time.\n // A step waiting on sliced work returned a stand-in: re-run next time too.\n if (ok && flags.count === flagged) {\n if (waiting === waited) memo.set(f, { input, state: slice, columns, output })\n else memo.delete(f)\n } else {\n failed = true\n memo.delete(f)\n }\n records.push({ feature: f, input, output, cached: false, failed: !ok })\n return output\n }\n\n const ctx = createContext('pipeline:run', { rowCount: data.length }, 'features', host.base())\n // The last good row model (§3.4): its indices; the runner keeps the matching rows below.\n if (last) ctx.meta.set(FALLBACK, last.indices)\n waiting = 0\n slicer?.begin()\n try {\n void host.runtime.run('pipeline:run', ctx, () => {\n let indices = allRows(data)\n let filteredCount = -1\n for (const f of steps) {\n if (f.stage === 'paginate' && filteredCount < 0) filteredCount = indices.length\n indices = step(f, indices)\n }\n if (filteredCount < 0) filteredCount = indices.length\n // Sliced work in progress is 'pending', below every other status (§6.6 precedence).\n const outside = host.status()\n const status = failed ? 'error' : waiting > 0 && outside === 'idle' ? 'pending' : outside\n result = build(data, indices, columns, filteredCount, status)\n return indices\n })\n } finally {\n // Sliced work no step asked for in this run is stale: cancelled.\n slicer?.end()\n if (result) model = result\n else {\n // pipeline:run failed: the boundary reported it, or a strict throw is leaving the run\n // (#43). Either way the last good rows with status 'error', never an empty 'idle' model.\n const isInitialLoad = host.isInitialLoad()\n model = last\n ? { ...last.model, status: 'error', isInitialLoad }\n : { rows: EMPTY, filteredCount: 0, totalCount: 0, status: 'error', isInitialLoad }\n }\n }\n return model\n }\n\n function replayContext(name: string): RowModelContext {\n const data = host.getData()\n const columns = host.getColumns() ?? EMPTY\n const cols = resolveColumns(columns)\n return {\n name,\n data,\n emit: NO_EMIT,\n ...(host.flagMode ? { flagged: (i: number) => host.issues(i) } : {}),\n run: host.base().run,\n columns,\n getColumnValues: (id) => {\n const col = cols.byId.get(id)\n return col ? cache.values(data, col) : undefined\n },\n getFormattedValues: (id) => {\n const col = cols.byId.get(id)\n return col ? cache.formatted(data, col) : undefined\n },\n batch: (id, _slot, _rows, body) => {\n if (!cols.byId.has(id)) return false\n body()\n return true\n },\n }\n }\n\n return {\n run,\n current: () => model,\n lastRun: () => lastRun,\n replayContext,\n dispose: () => {\n slicer?.cancel()\n cache?.release()\n memo.clear()\n keys = undefined\n last = undefined\n },\n ...((process.env.NODE_ENV !== \"production\")\n ? {\n probe: () => ({\n memo: memo.size,\n keys: keys !== undefined,\n last: last !== undefined,\n cached: cache?.holds?.(host.getData()) === true,\n }),\n }\n : {}),\n }\n}\n"],"mappings":"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","names":["ctx"]}
@@ -41,6 +41,7 @@ var import_classify = require("../intercept/classify.cjs");
41
41
  var import_context = require("../intercept/context.cjs");
42
42
  var import_fallbacks = require("../intercept/fallbacks.cjs");
43
43
  var import_runtime2 = require("../intercept/runtime.cjs");
44
+ var import_release = require("../pipeline/release.cjs");
44
45
  var import_runner = require("../pipeline/runner.cjs");
45
46
  var import_fetcher = require("../source/fetcher.cjs");
46
47
  var import_server_brand = require("../source/server-brand.cjs");
@@ -391,6 +392,7 @@ function createTable(initialOptions) {
391
392
  });
392
393
  }
393
394
  });
395
+ if (process.env.NODE_ENV !== "production") table[import_release.PROBE] = () => runner.probe?.() ?? {};
394
396
  const explainHost = {
395
397
  table,
396
398
  features: pipeline,
@@ -608,6 +610,7 @@ function createTable(initialOptions) {
608
610
  ingestSeq++;
609
611
  listeners.clear();
610
612
  runner.dispose();
613
+ for (const f of pipeline) f[import_release.RELEASE]?.();
611
614
  if (process.env.NODE_ENV !== "production") feedback?.dispose();
612
615
  }
613
616
  });