test(terminal): prove empty glyph eviction preserves visible caches

This commit is contained in:
Neil
2026-09-19 17:54:30 -07:00
parent a628d201a5
commit fcd9306a43
5 changed files with 467 additions and 3 deletions
+3
View File
@@ -95,6 +95,9 @@ design-docs/
# and the tracked reference docs linked from AGENTS.md / README.md).
docs/**
!docs/
!docs/audits/
!docs/audits/webgl-empty-glyph-retention/
!docs/audits/webgl-empty-glyph-retention/**
# The deployable docs app is source, not local engineering notes.
!docs/site/
!docs/site/**
@@ -37,6 +37,24 @@ describe('vendored xterm WebGL runtime contract', () => {
}
})
it('keeps invisible glyph eviction separate from the visible glyph cache', () => {
const webgl = xtermManifest.packages.find((entry) => entry.name === '@xterm/addon-webgl')
for (const source of [
readProject(webgl.sourcePatch),
readInstalled('@xterm/addon-webgl', 'src/TextureAtlas.ts')
]) {
expect(source).toContain('emptyCacheMap.get(key, bg, fg, ext)')
expect(source).toContain('this._emptyGlyphCount >= Constants.EMPTY_GLYPH_CACHE_LIMIT')
expect(source).toContain('this._clearEmptyGlyphCache()')
}
for (const bundle of ['lib/addon-webgl.js', 'lib/addon-webgl.mjs']) {
const contents = readInstalled('@xterm/addon-webgl', bundle)
expect(contents, bundle).toContain('_emptyCacheMapCombined')
expect(contents, bundle).toContain('_clearEmptyGlyphCache')
expect(contents, bundle).toMatch(/_emptyGlyphCount>=4096/)
}
})
it('keeps the Orca-only WebGL hunks in the generated patch', () => {
const webgl = xtermManifest.packages.find((entry) => entry.name === '@xterm/addon-webgl')
const patch = readProject(webgl.patch)
@@ -38,7 +38,8 @@ two modes. It samples V8 heap after CDP collection and records bundle hashes in
[results.json](./results.json). Two terminals share one atlas. Assertions cover:
- Invisible entries stay at or below 4,096; the baseline accumulates 100,000.
- Visible glyph caches and the one texture page stay intact across overflow.
- After ASCII warmup finishes, visible cache and glyph counts stay exactly unchanged
across overflow, with no visible glyph rerasterized; the one texture page stays intact.
- Rendered pixels for the unaffected first cell of both terminals stay identical.
- The last 64 repeated variants cause no new rasterization.
- Explicit clear drops invisible metadata even when the atlas has no drawn glyphs.
@@ -48,7 +49,13 @@ run ends with 1,789 entries (93 visible and 1,696 invisible), with roughly 0.3 M
of heap growth. Exact heap samples vary; the bounded entry count is the invariant.
No Orca window was launched, and no browser window was shown.
Validation also passed 86 tests across the patch generator/runtime contract and
A follow-up [review-validation.json](./review-validation.json) reruns both installed
bundles and both output modes with the stronger warmup/count/rasterization checks
on Node 24.20.0. The original before/after measurements above remain in `results.json`.
The runtime contract test also guards the empty-glyph routing and cap in the source
patch, installed source, and both shipped bundles. Its three checks pass.
Original validation also passed 86 tests across the patch generator/runtime contract and
WebGL lifecycle/context/recovery suites, full typecheck, lint, and changed-code
quality. Test commands used `ORCA_BACKGROUND_LAUNCH=1`.
@@ -65,6 +65,21 @@ try {
await new Promise(requestAnimationFrame)
await new Promise(requestIdleCallback)
}, mode)
// The atlas warms ASCII in idle tasks; sample only after the final queued glyph exists.
await page.waitForFunction(() =>
Boolean(window.glyphAudit.first.addon._renderer._charAtlas._cacheMap.get(125, 0, 0, 0))
)
await page.evaluate(() => {
const atlas = window.glyphAudit.first.addon._renderer._charAtlas
const draw = atlas._drawToCache
window.glyphAudit.visibleRasterizations = 0
atlas._drawToCache = function (...args) {
if (args[0] !== 32 && args[0] !== ' \u200d') {
window.glyphAudit.visibleRasterizations++
}
return draw.apply(this, args)
}
})
const cdp = await page.context().newCDPSession(page)
const samples = []
for (const count of [0, 1000, 5000, 10000, 50000, 100000]) {
@@ -81,6 +96,7 @@ try {
second.addon._renderer.renderRows(0, 0)
window.glyphAudit.index = count
const atlas = first.addon._renderer._charAtlas
// This audit is tied to the pinned addon's private FourKeyMap storage.
const entries = (map) => {
let result = 0
for (const second of Object.values(map?._data._data ?? {})) {
@@ -106,6 +122,7 @@ try {
}
return {
updates: count,
visibleRasterizations: window.glyphAudit.visibleRasterizations,
firstCellPixels: pixels(first),
secondCellPixels: pixels(second),
regular: entries(atlas._cacheMap),
@@ -160,7 +177,12 @@ try {
if (phase === 'after') {
assert.ok(
samples.every(
(sample) => sample.empty <= 4096 && sample.regular + sample.combined < 200
(sample) =>
sample.empty <= 4096 &&
sample.regular === samples[0].regular &&
sample.combined === samples[0].combined &&
sample.glyphs === samples[0].glyphs &&
sample.visibleRasterizations === 0
)
)
assert.equal(checks.emptyAfterClear, 0)
@@ -0,0 +1,414 @@
{
"node": "v24.20.0",
"browser": "146.0.7680.0",
"results": [
{
"phase": "after",
"format": "cjs",
"mode": "space",
"sha256": "0667d4850345c52271515c6ffe434c40687c59db007ddd32aabc02f0118a1cad",
"samples": [
{
"updates": 0,
"visibleRasterizations": 0,
"firstCellPixels": 638013437,
"secondCellPixels": 395161943,
"regular": 93,
"combined": 0,
"empty": 0,
"pages": 1,
"glyphs": 93,
"layoutVersion": 0,
"shared": true,
"preserved": true,
"heap": 3336616
},
{
"updates": 1000,
"visibleRasterizations": 0,
"firstCellPixels": 638013437,
"secondCellPixels": 395161943,
"regular": 93,
"combined": 0,
"empty": 1000,
"pages": 1,
"glyphs": 93,
"layoutVersion": 0,
"shared": true,
"preserved": true,
"heap": 3808452
},
{
"updates": 5000,
"visibleRasterizations": 0,
"firstCellPixels": 638013437,
"secondCellPixels": 395161943,
"regular": 93,
"combined": 0,
"empty": 904,
"pages": 1,
"glyphs": 93,
"layoutVersion": 0,
"shared": true,
"preserved": true,
"heap": 3799644
},
{
"updates": 10000,
"visibleRasterizations": 0,
"firstCellPixels": 638013437,
"secondCellPixels": 395161943,
"regular": 93,
"combined": 0,
"empty": 1808,
"pages": 1,
"glyphs": 93,
"layoutVersion": 0,
"shared": true,
"preserved": true,
"heap": 3918852
},
{
"updates": 50000,
"visibleRasterizations": 0,
"firstCellPixels": 638013437,
"secondCellPixels": 395161943,
"regular": 93,
"combined": 0,
"empty": 848,
"pages": 1,
"glyphs": 93,
"layoutVersion": 0,
"shared": true,
"preserved": true,
"heap": 3519764
},
{
"updates": 100000,
"visibleRasterizations": 0,
"firstCellPixels": 638013437,
"secondCellPixels": 395161943,
"regular": 93,
"combined": 0,
"empty": 1696,
"pages": 1,
"glyphs": 93,
"layoutVersion": 0,
"shared": true,
"preserved": true,
"heap": 3632676
}
],
"checks": {
"rasterizations": 0,
"emptyAfterClear": 0
}
},
{
"phase": "after",
"format": "cjs",
"mode": "space-joiner",
"sha256": "0667d4850345c52271515c6ffe434c40687c59db007ddd32aabc02f0118a1cad",
"samples": [
{
"updates": 0,
"visibleRasterizations": 0,
"firstCellPixels": 638013437,
"secondCellPixels": 395161943,
"regular": 93,
"combined": 0,
"empty": 0,
"pages": 1,
"glyphs": 93,
"layoutVersion": 0,
"shared": true,
"preserved": true,
"heap": 3336388
},
{
"updates": 1000,
"visibleRasterizations": 0,
"firstCellPixels": 638013437,
"secondCellPixels": 395161943,
"regular": 93,
"combined": 0,
"empty": 1000,
"pages": 1,
"glyphs": 93,
"layoutVersion": 0,
"shared": true,
"preserved": true,
"heap": 3788324
},
{
"updates": 5000,
"visibleRasterizations": 0,
"firstCellPixels": 638013437,
"secondCellPixels": 395161943,
"regular": 93,
"combined": 0,
"empty": 904,
"pages": 1,
"glyphs": 93,
"layoutVersion": 0,
"shared": true,
"preserved": true,
"heap": 3817620
},
{
"updates": 10000,
"visibleRasterizations": 0,
"firstCellPixels": 638013437,
"secondCellPixels": 395161943,
"regular": 93,
"combined": 0,
"empty": 1808,
"pages": 1,
"glyphs": 93,
"layoutVersion": 0,
"shared": true,
"preserved": true,
"heap": 3937304
},
{
"updates": 50000,
"visibleRasterizations": 0,
"firstCellPixels": 638013437,
"secondCellPixels": 395161943,
"regular": 93,
"combined": 0,
"empty": 848,
"pages": 1,
"glyphs": 93,
"layoutVersion": 0,
"shared": true,
"preserved": true,
"heap": 3855688
},
{
"updates": 100000,
"visibleRasterizations": 0,
"firstCellPixels": 638013437,
"secondCellPixels": 395161943,
"regular": 93,
"combined": 0,
"empty": 1696,
"pages": 1,
"glyphs": 93,
"layoutVersion": 0,
"shared": true,
"preserved": true,
"heap": 3653104
}
],
"checks": {
"rasterizations": 0,
"emptyAfterClear": 0
}
},
{
"phase": "after",
"format": "esm",
"mode": "space",
"sha256": "1ff2a59921ed5d53c0958110dac290c8d9f8d4502ea631fac7fd8575227b30f0",
"samples": [
{
"updates": 0,
"visibleRasterizations": 0,
"firstCellPixels": 638013437,
"secondCellPixels": 395161943,
"regular": 93,
"combined": 0,
"empty": 0,
"pages": 1,
"glyphs": 93,
"layoutVersion": 0,
"shared": true,
"preserved": true,
"heap": 3295588
},
{
"updates": 1000,
"visibleRasterizations": 0,
"firstCellPixels": 638013437,
"secondCellPixels": 395161943,
"regular": 93,
"combined": 0,
"empty": 1000,
"pages": 1,
"glyphs": 93,
"layoutVersion": 0,
"shared": true,
"preserved": true,
"heap": 3768188
},
{
"updates": 5000,
"visibleRasterizations": 0,
"firstCellPixels": 638013437,
"secondCellPixels": 395161943,
"regular": 93,
"combined": 0,
"empty": 904,
"pages": 1,
"glyphs": 93,
"layoutVersion": 0,
"shared": true,
"preserved": true,
"heap": 3759512
},
{
"updates": 10000,
"visibleRasterizations": 0,
"firstCellPixels": 638013437,
"secondCellPixels": 395161943,
"regular": 93,
"combined": 0,
"empty": 1808,
"pages": 1,
"glyphs": 93,
"layoutVersion": 0,
"shared": true,
"preserved": true,
"heap": 3878776
},
{
"updates": 50000,
"visibleRasterizations": 0,
"firstCellPixels": 638013437,
"secondCellPixels": 395161943,
"regular": 93,
"combined": 0,
"empty": 848,
"pages": 1,
"glyphs": 93,
"layoutVersion": 0,
"shared": true,
"preserved": true,
"heap": 3798292
},
{
"updates": 100000,
"visibleRasterizations": 0,
"firstCellPixels": 638013437,
"secondCellPixels": 395161943,
"regular": 93,
"combined": 0,
"empty": 1696,
"pages": 1,
"glyphs": 93,
"layoutVersion": 0,
"shared": true,
"preserved": true,
"heap": 3668712
}
],
"checks": {
"rasterizations": 0,
"emptyAfterClear": 0
}
},
{
"phase": "after",
"format": "esm",
"mode": "space-joiner",
"sha256": "1ff2a59921ed5d53c0958110dac290c8d9f8d4502ea631fac7fd8575227b30f0",
"samples": [
{
"updates": 0,
"visibleRasterizations": 0,
"firstCellPixels": 638013437,
"secondCellPixels": 395161943,
"regular": 93,
"combined": 0,
"empty": 0,
"pages": 1,
"glyphs": 93,
"layoutVersion": 0,
"shared": true,
"preserved": true,
"heap": 3286928
},
{
"updates": 1000,
"visibleRasterizations": 0,
"firstCellPixels": 638013437,
"secondCellPixels": 395161943,
"regular": 93,
"combined": 0,
"empty": 1000,
"pages": 1,
"glyphs": 93,
"layoutVersion": 0,
"shared": true,
"preserved": true,
"heap": 3783224
},
{
"updates": 5000,
"visibleRasterizations": 0,
"firstCellPixels": 638013437,
"secondCellPixels": 395161943,
"regular": 93,
"combined": 0,
"empty": 904,
"pages": 1,
"glyphs": 93,
"layoutVersion": 0,
"shared": true,
"preserved": true,
"heap": 3777172
},
{
"updates": 10000,
"visibleRasterizations": 0,
"firstCellPixels": 638013437,
"secondCellPixels": 395161943,
"regular": 93,
"combined": 0,
"empty": 1808,
"pages": 1,
"glyphs": 93,
"layoutVersion": 0,
"shared": true,
"preserved": true,
"heap": 3896896
},
{
"updates": 50000,
"visibleRasterizations": 0,
"firstCellPixels": 638013437,
"secondCellPixels": 395161943,
"regular": 93,
"combined": 0,
"empty": 848,
"pages": 1,
"glyphs": 93,
"layoutVersion": 0,
"shared": true,
"preserved": true,
"heap": 3814948
},
{
"updates": 100000,
"visibleRasterizations": 0,
"firstCellPixels": 638013437,
"secondCellPixels": 395161943,
"regular": 93,
"combined": 0,
"empty": 1696,
"pages": 1,
"glyphs": 93,
"layoutVersion": 0,
"shared": true,
"preserved": true,
"heap": 3678164
}
],
"checks": {
"rasterizations": 0,
"emptyAfterClear": 0
}
}
]
}