// Streaming invariant check: for every file, several fixed chunk sizes must give the whole-input output and errors.
// Usage: node stream-sweep.mjs
[maxSmall=1024] [shard/shards]
// Chunk sizes 1 and 2 only for files up to maxSmall chars; run shards 0/4..3/4 in parallel for a big tree.
import fs from "node:fs";
import path from "node:path";
process.env.TYPESTRIP_ERASE_WASM ??= "build/erase.wasm";
const root = new URL("../..", import.meta.url).pathname.replace(/\/$/, "");
const { transformSync } = await import(root + "/src/index.js");
const dir = process.argv[2];
const maxSmall = Number(process.argv[3] ?? 1024);
const [shard, shards] = (process.argv[4] ?? "0/1").split("/").map(Number);
function* walk(d) {
let entries;
try { entries = fs.readdirSync(d, { withFileTypes: true }); } catch { return; }
for (const e of entries) {
if (e.name.startsWith(".")) continue;
const full = path.join(d, e.name);
if (e.isDirectory()) yield* walk(full);
else if (/\.[cm]?ts$/.test(e.name)) yield full;
}
}
function* parts(src, n) {
for (let i = 0; i < src.length; i += n) yield src.slice(i, i + n);
}
function streamed(src, n) {
const errs = [];
let out = "";
for (const piece of transformSync(parts(src, n), { onError: (e) => errs.push(e.start) })) out += piece;
return { out, errs: errs.join() };
}
const seen = new Set();
let files = 0, bad = 0, index = 0;
const t0 = performance.now();
for (const f of walk(dir)) {
let src;
try { src = fs.readFileSync(f, "utf8"); } catch { continue; }
if (seen.has(src)) continue;
seen.add(src);
if (index++ % shards !== shard) continue;
const we = [];
let whole;
try { whole = transformSync(src, { onError: (e) => we.push(e.start) }); } catch { continue; }
files++;
const sizes = src.length <= maxSmall ? [1, 2, 7, 61, 509, 4093] : [7, 61, 509, 4093];
for (const n of sizes) {
let r;
try { r = streamed(src, n); } catch (e) { console.log(`THREW chunk ${n}: ${f}`); bad++; break; }
if (r.out !== whole || r.errs !== we.join()) {
let j = 0;
while (r.out[j] === whole[j]) j++;
console.log(`DIFF chunk ${n}: ${f} at ${j}${r.out === whole ? " (errors only)" : ""}`);
bad++;
break;
}
}
}
console.log(`${files} files, ${bad} streaming divergences in ${((performance.now() - t0) / 1000).toFixed(0)}s`);