setMaxAtlasPages mutates a static that lives for the page's lifetime, so a
lowered cap silently leaked into every renderer built by later tests in the
same file (their GL texture and shader sampler arrays were sized at the tiny
cap, making tests order-dependent). Add resetMaxAtlasPages and call it in
afterEach wherever the cap is lowered on a shared page.
GlyphRenderer sizes its GL texture array and fragment-shader sampler array to
exactly TextureAtlas.maxAtlasPages at construction, but _createNewPage pushes
past that cap whenever a 4-page same-size merge is impossible (heterogeneous
sizes, e.g. 1024+512+512+512). The next render throws TypeError: Cannot read
properties of undefined (reading 'version') and rendering freezes — the
single-terminal breakage vector for long heavy-CLI sessions (vscode#322756).
The test builds the renderer with maxAtlasPages=4 (same code path as the
production 8/16/32 values), churns distinct glyphs, and asserts no pageerror,
pages.length <= texture capacity, and an intact pinned header. RED today:
4x TypeError from GlyphRenderer.render.
Two terminals with equal configs share one TextureAtlas (CharAtlasCache).
When the atlas merges pages it raises a consume-once clear-model flag
(TextureAtlas.beginFrame); only the first terminal to render consumes it and
rebuilds its vertex model. Every other terminal keeps stale texture-page
indexes/coords and draws wrong glyphs on its next partial render even though
its buffer is intact.
The test churns terminal A to force merges, then gives terminal B a tiny
partial update: B's untouched header row garbles (signature diff ~130/255 vs
tolerance 14) while B's buffer still reads HEADER_REF. A DOM-renderer control
runs the same workload without GPU acceleration and passes: the corruption is
exclusive to the WebGL path.
RED on current code by design; the fix lands separately.
generateColoredAsciiFlood emitted a trailing \r\n after its final cell, so a
flood whose last line lands on the bottom row scrolled the screen. In the
alt-buffer repro this destroyed the pinned header row in the BUFFER, making
the 255/255 signature diff a content change, not renderer corruption. The
single-terminal merge path is actually healthy: with the scroll removed the
same 30-chunk merge-heavy workload renders the header with zero drift.
- generateColoredAsciiFlood: no linefeed after the final cell
- WebglReproExperiment: now a green guard; asserts row-1 buffer text first so
a content bug can never masquerade as corruption again
- WebglVisual: accurate comments; erase rewritten lines so leftover prefill
text doesn't look like corruption
- WebglSingleTermStress: replace stale EXPECTED-RED comment (test passes)