import assert from 'node:assert/strict'; import fs from 'node:fs/promises'; import path from 'node:path'; import { pathToFileURL } from 'node:url'; import { createHash } from 'node:crypto'; import { chromium } from 'playwright'; import { describePage } from './browser-worker.mjs'; // Compare against an explicitly saved pre-change evaluate function, never a // production/RPC switch. All fixtures are synthetic and network is blocked. const baselinePath = process.argv[2]; assert.ok(baselinePath, 'Pass the saved baseline module path'); const { describeBaseline } = await import(pathToFileURL(path.resolve(baselinePath)).href); const runDirectory = path.resolve('.tmp', `observation-cache-${Date.now()}`); await fs.mkdir(runDirectory, { recursive: true }); const report = { browser: process.platform === 'win32' ? 'msedge' : 'chromium', real_platform_requests: 0, baseline_sha256: createHash('sha256').update(await fs.readFile(path.resolve(baselinePath))).digest('hex'), comparisons: [], performance: [] }; const browser = await chromium.launch({ headless: true, ...(process.platform === 'win32' ? { channel: 'msedge' } : {}) }); try { const page = await browser.newPage({ viewport: { width: 1120, height: 760 } }); await page.route('**/*', route => route.abort()); const cards = Array.from({ length: 230 }, (_, index) => `
Author ${index}
Question ${index}

Ordinary renovation sample ${index}

Nested ${index}
`).join(''); await page.setContent(`Observation equivalence

Fixture

${cards}

Clipped ordinary text

Clipped away content

Ordinary heading

Fresh text

Contact 13800138000

Transparent content

Concealed content

SENSITIVE_ANCESTOR

SENSITIVE_FORM

Offscreen retained loaded text

Visible overlay
`); await page.evaluate(() => { const costs = () => ({ computed_style: 0, bounding_rect: 0, query_selector: 0, query_selector_all: 0, element_from_point: 0 }); window.observationCosts = costs(); window.resetObservationCosts = () => { window.observationCosts = costs(); }; const wrap = (owner, name, cost) => { const original = owner[name]; owner[name] = function (...args) { window.observationCosts[cost] += 1; return original.apply(this, args); }; }; wrap(window, 'getComputedStyle', 'computed_style'); wrap(Element.prototype, 'getBoundingClientRect', 'bounding_rect'); for (const owner of [Document.prototype, Element.prototype]) { wrap(owner, 'querySelector', 'query_selector'); wrap(owner, 'querySelectorAll', 'query_selector_all'); } wrap(Document.prototype, 'elementFromPoint', 'element_from_point'); }); async function sample(read, request) { await page.evaluate(() => window.resetObservationCosts()); const started = performance.now(); const value = await read(page, request); const duration_ms = performance.now() - started; return { value, duration_ms, costs: await page.evaluate(() => window.observationCosts) }; } async function compare(name, mutate, request = null) { if (mutate) await page.evaluate(mutate); const baseline = await sample(describeBaseline, request), optimized = await sample(describePage, request); assert.deepEqual(optimized.value, baseline.value, name); report.comparisons.push({ name, exact: true, elements: optimized.value.elements.length, ...(optimized.value.masks ? { masks: optimized.value.masks.length } : {}) }); return { baseline, optimized }; } const initial = await compare('initial full observation with overlay, clipping, sensitive subtrees and output caps'); assert.ok(!initial.optimized.value.text.includes('SENSITIVE_ANCESTOR')); assert.ok(!initial.optimized.value.text.includes('SENSITIVE_FORM')); assert.ok(!initial.optimized.value.text.includes('13800138000')); assert.ok(initial.optimized.value.masks.includes('#phone-leaf')); assert.ok(initial.optimized.value.elements.length <= 120); assert.equal(initial.optimized.value.viewport.scroll_y, 0); await compare('canonical metadata', null, { selector: '#search-field', requireCanonical: true }); await compare('collection metadata', null, { selector: '#scroller a.name', collection: true }); await compare('noncanonical metadata rejected', null, { selector: 'input[type=search]', requireCanonical: true }); await compare('sensitive metadata rejected', null, { selector: '#sensitive-child' }); await compare('bounded metadata rejects more than 500 nodes', () => { const root = document.createElement('div'); root.id = 'many'; root.innerHTML = 'X'.repeat(501); document.body.append(root); }, { selector: '.many-node', collection: true }); await compare('remove large fixture and overlay; text and source attributes change', () => { document.querySelector('#many').remove(); document.querySelector('#overlay').remove(); document.querySelector('#mutable').textContent = 'Changed source after previous call'; document.querySelector('#search-field').setAttribute('placeholder', 'Find content'); document.querySelector('#search-field').setAttribute('name', 'query'); }); await compare('scroll root changes viewport and current scroll metadata', () => { document.querySelector('#scroller').scrollTop = 630; }); const scrolled = await compare('metadata refreshed after root scroll', null, { selector: '#scroller', requireCanonical: true }); assert.equal(scrolled.optimized.value.elements[0].scroll_y.scroll_top, 630); await compare('window scroll changes clipping', () => window.scrollTo(0, 460)); await compare('style changes are not cached across calls', () => { window.scrollTo(0, 0); document.querySelector('#hidden-parent').classList.remove('hidden'); document.querySelector('#opacity').style.opacity = '1'; document.querySelector('#concealed').style.visibility = 'visible'; document.querySelector('#ordinary').style.visibility = 'collapse'; document.querySelector('#scroller').style.height = '240px'; }); await compare('ancestor sensitivity changes are not cached across calls', () => { document.querySelector('#ordinary').style.visibility = 'visible'; document.querySelector('#sensitive-ancestor').setAttribute('aria-label', 'Ordinary section'); document.querySelector('#private-field').setAttribute('type', 'text'); document.querySelector('#private-form label').firstChild.textContent = 'Ordinary'; document.querySelector('#private-form').id = 'ordinary-form'; document.querySelector('#private-text').textContent = 'Now ordinary form'; }); await compare('new private field causes current form exclusion', () => { const form = document.querySelector('#ordinary-form'); const field = document.createElement('input'); field.autocomplete = 'one-time-code'; form.append(field); }); await compare('disabled field and changed sensitive field label', () => { document.querySelector('#search-field').disabled = true; document.querySelector('#search-field').setAttribute('aria-label', 'verification code'); }); await compare('delete and recreate nodes with same IDs and different geometry', () => { document.querySelector('#scroller').remove(); const section = document.createElement('section'); section.id = 'scroller'; section.style.height = '300px'; section.innerHTML = '
New author
New source
'; document.querySelector('#main').prepend(section); }); await compare('metadata refreshed after node replacement', null, { selector: '#scroller', requireCanonical: true }); const duplicate = await compare('duplicate target metadata preserves ambiguity', () => { const other = document.querySelector('#scroller').cloneNode(true); document.querySelector('#main').append(other); }, { selector: '#scroller', requireCanonical: true }); assert.equal(duplicate.optimized.value.elements[0].unique, false); assert.equal(duplicate.optimized.value.elements[0].count, 2); await page.evaluate(async () => { document.body.innerHTML = '

Media observation

Ordinary image and video

'; const pixel = 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///ywAAAAAAQABAAACAUwAOw=='; const images = [...document.images]; await Promise.all(images.map(image => new Promise(resolve => { image.onload = image.onerror = resolve; image.src = pixel; }))); window.scrollTo(0, 0); }); const media = await compare('media hints preserve loaded state, avatar exclusion and hidden media exclusion'); const hints = media.optimized.value.elements.find(element => element.selector === '#media-root').read_hints; assert.ok(hints.some(hint => hint.selector === '#content-image' && hint.media_kind === 'image' && hint.loaded === true)); assert.ok(hints.some(hint => hint.selector === '#content-video' && hint.media_kind === 'video' && hint.loaded === false)); assert.ok(!hints.some(hint => hint.selector === '#avatar-image' || hint.selector === '#hidden-image')); const long = await compare('raw walk reuse preserves normalization and per-root text truncation', () => { document.body.innerHTML = '

Tail must be truncated only at the outer root

'; document.querySelector('#long-text').textContent = ' \n Leading whitespace\t' + '中文 Long text '.repeat(1600) + ' 13800138000'; }); assert.equal(long.optimized.value.text.length, 16000); assert.ok(long.optimized.value.text.startsWith('Leading whitespace 中文 Long text')); const limited = await compare('candidate/control/read limits and order remain identical in a dense visible page', () => { document.body.innerHTML = '
'; const root = document.querySelector('#dense-root'); root.innerHTML = Array.from({ length: 130 }, (_, index) => `
Read ${index}
`).join('') + Array.from({ length: 40 }, (_, index) => ``).join('') + Array.from({ length: 25 }, (_, index) => ``).join(''); }); assert.ok(limited.optimized.value.elements.length <= 120); assert.equal(limited.optimized.value.elements.filter(element => !element.collection && element.kind === 'fill').length, 16); assert.equal(limited.optimized.value.elements.filter(element => !element.collection && element.tag === 'button').length, 24); assert.equal(limited.optimized.value.elements.filter(element => !element.collection && element.kind === 'read').length, 48); // Measure deterministic DOM work on the large unmodified fixture as well as // elapsed time. Elapsed time is reported, never used as a flaky pass threshold. report.performance.push({ name: 'initial_large_fixture', baseline_ms: initial.baseline.duration_ms, optimized_ms: initial.optimized.duration_ms, baseline_costs: initial.baseline.costs, optimized_costs: initial.optimized.costs }); for (const name of ['computed_style', 'bounding_rect', 'element_from_point']) { assert.ok(initial.optimized.costs[name] < initial.baseline.costs[name], `${name} must reuse current-call observations`); } assert.equal(initial.optimized.costs.query_selector_all, initial.baseline.costs.query_selector_all, 'Candidate discovery queries are unchanged'); report.status = 'passed'; } catch (error) { report.status = 'failed'; report.error = { name: error.name, message: error.message.slice(0, 2000) }; throw error; } finally { await browser.close(); await fs.writeFile(path.join(runDirectory, 'report.json'), JSON.stringify(report, null, 2) + '\n'); console.log(JSON.stringify({ report: path.join(runDirectory, 'report.json'), status: report.status, comparisons: report.comparisons.length, real_platform_requests: 0 })); }