Four SPA hot-path fixes, each shipping with a vitest benchmark gate
(verbatim BEFORE replica + equivalence + perf assertion) so CI
re-verifies the win on every run:
- fetchFolderListing invoked onPage after EVERY 200-row page with the
whole accumulated listing, and the files view re-sorts everything per
emission — O(N²/page) main-thread work on large folders. Page one and
the final page always emit; intermediates coalesce to one per 150 ms.
25×200 load: 30.9 → 4.0 ms (7.8x), 65 000 → 5 200 sorted elements.
- selected/favoriteIds/sharedIds (files) and favoriteIds (recent) were
$state<Set>s copied whole on every toggle. Now one SvelteSet each,
mutated in place (the useSelection pattern): 1 000 toggles @ N=5 000
771.9 → 1.9 ms (399x); one-toggle fan-out across 40 mounted rows
40 → 3 re-runs when refining a select-all.
- batchDelete/moveInto awaited one request per item serially and
probed listing.folders.find per id (O(N·M)). Now an id index built
once + mapLimit(6) fan-out, failure semantics preserved: 100-item
delete @ 5 ms RTT 525 → 89 ms (5.9x), 38 825 → 500 probes.
- t() re-split its dotted key and walked the nested dict on every call,
and interpolate regex-scanned strings without placeholders. Resolved
values now memoize per (dict, key) in a WeakMap + a {{ guard:
20k mixed calls 22.7 → 8.6 ms (2.63x).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017aJu9ghvuT8WqC31ZEGTBA