OpenCode commited on
Commit
042d03e
·
1 Parent(s): bd462d7

Prioritize visible records within the viewport storage budget

Browse files
Files changed (2) hide show
  1. static/app.js +15 -2
  2. tests/test_position_window.py +20 -0
static/app.js CHANGED
@@ -290,8 +290,21 @@ function saveSearchViewport(position, view) {
290
  if (view.results[index]) records.push([index, cloneSearchResult(view.results[index]), VSCROLL.heights[index] || VSCROLL.estimatedHeight]);
291
  }
292
  const viewport = { key: position.key, savedAt: position.savedAt, anchorId: position.anchorId, index: position.index,
293
- total: view.total, estimatedHeight: VSCROLL.estimatedHeight, measurementKey: getHeightMeasurementKey(), records };
294
- if (new TextEncoder().encode(JSON.stringify(viewport)).byteLength > SEARCH_VIEWPORT_BYTES_MAX) return;
 
 
 
 
 
 
 
 
 
 
 
 
 
295
  searchViewportSnapshots.delete(viewport.key);
296
  searchViewportSnapshots.set(viewport.key, viewport);
297
  while (searchViewportSnapshots.size > SEARCH_VIEWPORT_MAX) searchViewportSnapshots.delete(searchViewportSnapshots.keys().next().value);
 
290
  if (view.results[index]) records.push([index, cloneSearchResult(view.results[index]), VSCROLL.heights[index] || VSCROLL.estimatedHeight]);
291
  }
292
  const viewport = { key: position.key, savedAt: position.savedAt, anchorId: position.anchorId, index: position.index,
293
+ total: view.total, estimatedHeight: VSCROLL.estimatedHeight, measurementKey: getHeightMeasurementKey(), records: [] };
294
+ // API records can include long URLs. Spend the budget on the visible screen
295
+ // first, then its nearest neighbors, rather than discarding the whole preview.
296
+ const visibleEnd = findVirtualIndex(DOM.resultsContainer.scrollTop + DOM.resultsContainer.clientHeight);
297
+ const distance = index => Math.max(position.index - index, index - visibleEnd, 0);
298
+ records.sort((a, b) => distance(a[0]) - distance(b[0]) || a[0] - b[0]);
299
+ const encoder = new TextEncoder();
300
+ let bytes = encoder.encode(JSON.stringify(viewport)).byteLength;
301
+ for (const record of records) {
302
+ const cost = encoder.encode(JSON.stringify(record)).byteLength + 1;
303
+ if (bytes + cost > SEARCH_VIEWPORT_BYTES_MAX) continue;
304
+ viewport.records.push(record); bytes += cost;
305
+ }
306
+ viewport.records.sort((a, b) => a[0] - b[0]);
307
+ if (!viewport.records.some(([index]) => index === position.index)) return;
308
  searchViewportSnapshots.delete(viewport.key);
309
  searchViewportSnapshots.set(viewport.key, viewport);
310
  while (searchViewportSnapshots.size > SEARCH_VIEWPORT_MAX) searchViewportSnapshots.delete(searchViewportSnapshots.keys().next().value);
tests/test_position_window.py CHANGED
@@ -212,3 +212,23 @@ class PositionWindowTests(unittest.TestCase):
212
  self.assertFalse(self.page.evaluate('!!positionRestore.preview'))
213
  self.page.evaluate('releaseWindow()')
214
  self.wait_anchor(49850)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
212
  self.assertFalse(self.page.evaluate('!!positionRestore.preview'))
213
  self.page.evaluate('releaseWindow()')
214
  self.wait_anchor(49850)
215
+
216
+ def test_large_api_records_prioritize_visible_content_within_storage_budget(self):
217
+ self.page.evaluate('''() => {
218
+ STATE.results.forEach(record=>record.Metadata='中'.repeat(900));
219
+ const original=fetchPositionPage;
220
+ fetchPositionPage=async (...args)=>{
221
+ const data=await original(...args);data.results.forEach(record=>record.Metadata='中'.repeat(900));return data;
222
+ };
223
+ }''')
224
+ self.persist_viewport()
225
+ self.assertTrue(self.page.evaluate('''() => {
226
+ const saved=searchViewportSnapshots.get(originalWindowKey);
227
+ return saved.records.length<80 && new TextEncoder().encode(JSON.stringify(saved)).byteLength<=SEARCH_VIEWPORT_BYTES_MAX;
228
+ }'''))
229
+ self.page.evaluate("STATE.query='paging-other';doSearch()")
230
+ self.page.wait_for_function('!STATE.isLoading')
231
+ self.page.evaluate("searchViewSnapshots.clear();searchViewportSnapshots.clear();windowStall=1;STATE.query='paging-original';doSearch()")
232
+ self.assert_cached_viewport()
233
+ self.page.evaluate('releaseWindow()')
234
+ self.wait_anchor(49850)