Download tests/test_reader_heading_cache.js from VoiceOfML/Search: direct link, hf CLI and curl.
- Browser
- Download file 3.04 kB
-
https://huggingface.co/spaces/VoiceOfML/Search/resolve/main/tests/test_reader_heading_cache.js
- Command line
-
hf download hf://spaces/VoiceOfML/Search/tests/test_reader_heading_cache.js
-
curl -L -o test_reader_heading_cache.js https://huggingface.co/spaces/VoiceOfML/Search/resolve/main/tests/test_reader_heading_cache.js
3.04 kB
| const fs = require('fs'); | |
| const vm = require('vm'); | |
| const assert = require('assert'); | |
| const path = require('path'); | |
| const root = process.argv[2] ? path.resolve(process.argv[2]) : path.resolve(__dirname, '..'); | |
| const source = require('./reader_source_contract').readReaderSource(root); | |
| const helper = source.match(/function createHeadingLocationCache\(root, entries\) \{[\s\S]*?\n\}/)[0]; | |
| const observers = [], listeners = new Map(); | |
| class Observer { | |
| constructor(callback) { this.callback = callback; this.records = []; this.closed = false; observers.push(this); } | |
| observe() {} | |
| disconnect() { this.closed = true; } | |
| takeRecords() { return this.records.splice(0); } | |
| } | |
| const add=(name,fn)=>{if(!listeners.has(name))listeners.set(name,new Set());listeners.get(name).add(fn);}; | |
| const remove=(name,fn)=>{listeners.get(name)?.delete(fn);if(!listeners.get(name)?.size)listeners.delete(name);}; | |
| const region = {clientWidth:400, scrollHeight:10000, | |
| addEventListener:add,removeEventListener:remove, | |
| ownerDocument:{defaultView:{getComputedStyle:node=>({position:node.position||'static'})}, | |
| fonts:{addEventListener:add,removeEventListener:remove}}}; | |
| const context = {MutationObserver:Observer, ResizeObserver:Observer, documentState:{zoom:100}}; | |
| vm.runInNewContext(helper, context); | |
| let reads = 0, scroll = 0; | |
| const entries = Array.from({length:1000}, (_,index)=>({target:{isConnected:true, | |
| getBoundingClientRect:()=>{reads++;return {top:index*10-scroll};}}})); | |
| const cache = context.createHeadingLocationCache(region, entries); | |
| assert.equal(cache.at(8,scroll),0); | |
| assert.equal(reads,1000); | |
| reads=0; | |
| for(let index=1;index<100;index++){scroll=index*10;assert.equal(cache.at(8,scroll),index);} | |
| assert.equal(reads,0); | |
| entries[99].target={isConnected:true,getBoundingClientRect:()=>{reads++;return {top:1005-scroll};}}; | |
| assert.equal(cache.at(8,scroll),98); | |
| assert.equal(reads,1000); | |
| reads=0;entries[98].target.isConnected=false; | |
| assert.equal(cache.at(8,scroll),97); | |
| assert.equal(reads,999); | |
| const unordered=[entries[500],entries[10],entries[200],entries[200]]; | |
| const alternative=context.createHeadingLocationCache(region,unordered); | |
| scroll=2000; | |
| assert.equal(alternative.at(0,scroll),3); | |
| scroll=0;assert.equal(alternative.at(0,scroll),1); | |
| for(const change of [()=>observers[0].records.push({}),()=>listeners.get('loadingdone').forEach(fn=>fn()), | |
| ()=>region.clientWidth++,()=>context.documentState.zoom++]) { | |
| reads=0;change();cache.at(8,scroll);assert.equal(reads,999); | |
| } | |
| cache.dispose();alternative.dispose(); | |
| const pinned=context.createHeadingLocationCache(region,[ | |
| {target:{isConnected:true,position:'fixed',getBoundingClientRect:()=>({top:0})}}, | |
| {target:{isConnected:true,getBoundingClientRect:()=>({top:500-scroll})}}]); | |
| scroll=0;assert.equal(pinned.at(8,scroll),0); | |
| scroll=510;assert.equal(pinned.at(8,scroll),0); | |
| pinned.dispose(); | |
| assert.ok(observers.every(observer=>observer.closed)); | |
| assert.equal(listeners.size,0); | |
| console.log('heading geometry reuse, unordered ties, mutation/layout invalidation and cleanup passed'); | |