diff options
| author | Adam <[email protected]> | 2026-01-06 04:18:20 -0600 |
|---|---|---|
| committer | Adam <[email protected]> | 2026-01-06 08:18:49 -0600 |
| commit | 3f463bc9168abd907be9ae582e161ff89c3a27c9 (patch) | |
| tree | 5b4aad62e698be847dccb6e93b80ac2c3f84844f /packages/app/src/context/layout-scroll.test.ts | |
| parent | 0b02f6d22f793387322d96f937cfc1c8eee9bfbb (diff) | |
| download | opencode-3f463bc9168abd907be9ae582e161ff89c3a27c9.tar.gz opencode-3f463bc9168abd907be9ae582e161ff89c3a27c9.zip | |
fix(app): scroll store performance
Diffstat (limited to 'packages/app/src/context/layout-scroll.test.ts')
| -rw-r--r-- | packages/app/src/context/layout-scroll.test.ts | 73 |
1 files changed, 73 insertions, 0 deletions
diff --git a/packages/app/src/context/layout-scroll.test.ts b/packages/app/src/context/layout-scroll.test.ts new file mode 100644 index 000000000..b7962c411 --- /dev/null +++ b/packages/app/src/context/layout-scroll.test.ts @@ -0,0 +1,73 @@ +import { describe, expect, test } from "bun:test" +import { createRoot } from "solid-js" +import { createStore } from "solid-js/store" +import { makePersisted, type SyncStorage } from "@solid-primitives/storage" +import { createScrollPersistence } from "./layout-scroll" + +describe("createScrollPersistence", () => { + test("debounces persisted scroll writes", async () => { + const key = "layout-scroll.test" + const data = new Map<string, string>() + const writes: string[] = [] + const stats = { flushes: 0 } + + const storage = { + getItem: (k: string) => data.get(k) ?? null, + setItem: (k: string, v: string) => { + data.set(k, v) + if (k === key) writes.push(v) + }, + removeItem: (k: string) => { + data.delete(k) + }, + } as SyncStorage + + await new Promise<void>((resolve, reject) => { + createRoot((dispose) => { + const [raw, setRaw] = createStore({ + sessionView: {} as Record<string, { scroll: Record<string, { x: number; y: number }> }>, + }) + + const [store, setStore] = makePersisted([raw, setRaw], { name: key, storage }) + + const scroll = createScrollPersistence({ + debounceMs: 30, + getSnapshot: (sessionKey) => store.sessionView[sessionKey]?.scroll, + onFlush: (sessionKey, next) => { + stats.flushes += 1 + + const current = store.sessionView[sessionKey] + if (!current) { + setStore("sessionView", sessionKey, { scroll: next }) + return + } + setStore("sessionView", sessionKey, "scroll", (prev) => ({ ...(prev ?? {}), ...next })) + }, + }) + + const run = async () => { + await new Promise((r) => setTimeout(r, 0)) + writes.length = 0 + + for (const i of Array.from({ length: 100 }, (_, n) => n)) { + scroll.setScroll("session", "review", { x: 0, y: i }) + } + + await new Promise((r) => setTimeout(r, 120)) + + expect(stats.flushes).toBeGreaterThanOrEqual(1) + expect(writes.length).toBeGreaterThanOrEqual(1) + expect(writes.length).toBeLessThanOrEqual(2) + } + + void run() + .then(resolve) + .catch(reject) + .finally(() => { + scroll.dispose() + dispose() + }) + }) + }) + }) +}) |
