Fix markdown transient cache invalidation

This commit is contained in:
ben
2026-06-11 22:27:59 +08:00
parent 495758b517
commit db23b721b5
2 changed files with 34 additions and 4 deletions
+11 -4
View File
@@ -295,10 +295,7 @@ export class Markdown implements Component {
#cachedText?: string;
#cachedWidth?: number;
#cachedLines?: readonly string[];
/** When true, skip the module-level LRU (lookup and insert) for this instance's
* renders. Set for in-flight streaming partials whose text changes every frame —
* caching those churns the LRU with near-duplicate full-message snapshots. */
transientRenderCache = false;
#transientRenderCache = false;
constructor(
text: string,
@@ -326,6 +323,16 @@ export class Markdown implements Component {
this.#cachedWidth = undefined;
this.#cachedLines = undefined;
}
get transientRenderCache(): boolean {
return this.#transientRenderCache;
}
set transientRenderCache(value: boolean) {
const next = value === true;
if (this.#transientRenderCache === next) return;
this.#transientRenderCache = next;
this.invalidate();
}
render(width: number): readonly string[] {
// L1: per-instance cache — fastest path for repeated renders of the same
+23
View File
@@ -1279,6 +1279,29 @@ describe("Module-level LRU render cache", () => {
expect(plain).not.toContain("HIGHLIGHTED");
});
it("re-renders code-block highlighting when a transient instance becomes stable", () => {
clearRenderCache();
let highlightCallCount = 0;
const themeWithSpy = {
...defaultMarkdownTheme,
highlightCode: (_code: string, _lang?: string): string[] => {
highlightCallCount++;
return ["HIGHLIGHTED"];
},
};
const markdown = new Markdown("```ts\nconst streamed = true;\n```", 0, 0, themeWithSpy);
markdown.transientRenderCache = true;
const plain = stripVTControlCharacters(markdown.render(80).join("\n"));
expect(highlightCallCount).toBe(0);
expect(plain).toContain("const streamed = true;");
markdown.transientRenderCache = false;
const highlighted = stripVTControlCharacters(markdown.render(80).join("\n"));
expect(highlightCallCount).toBe(1);
expect(highlighted).toContain("HIGHLIGHTED");
});
it("skips nested list code-block highlighting for transient streaming renders", () => {
clearRenderCache();
let highlightCallCount = 0;