diff --git a/packages/shared/src/terminalOutput.test.ts b/packages/shared/src/terminalOutput.test.ts index 8870d422b763d..c83bee3553cda 100644 --- a/packages/shared/src/terminalOutput.test.ts +++ b/packages/shared/src/terminalOutput.test.ts @@ -103,10 +103,15 @@ describe("appendTerminalOutput edge cases from review", () => { describe("appendTerminalOutput under adversarial output", () => { it("gives the same result however the output is split into chunks", () => { - const input = "abcdef\rX\u001b[31mred\u001b[0m\nnext line\r\u001b[2Kdone\n"; - const whole = feed([input], 3).text; - for (let cut = 1; cut < input.length; cut += 1) { - expect(feed([input.slice(0, cut), input.slice(cut)], 3).text).toBe(whole); + const input = + "abcdef\rX\u001b[31mred\u001b[0m\nnext line\r\u001b[2Kdone\n" + + "\u001b[1;31mbold red\u001b[mplain\u001b[38:2::12:34:56mrgb\u001b[0m\n" + + "\u001b[1;31mbold red again\u001b[mplain again\u001b[38:2::12:34:56mrgb again\u001b[0m"; + for (const maxChars of [3, 1_024]) { + const whole = feed([input], maxChars).text; + for (let cut = 1; cut < input.length; cut += 1) { + expect(feed([input.slice(0, cut), input.slice(cut)], maxChars).text).toBe(whole); + } } expect(feed(["abcdef", "\rX"], 3).text).toBe(feed(["abcdef\rX"], 3).text); }); diff --git a/packages/shared/src/terminalOutput.ts b/packages/shared/src/terminalOutput.ts index 9172554e07336..02f08c2a05d5d 100644 --- a/packages/shared/src/terminalOutput.ts +++ b/packages/shared/src/terminalOutput.ts @@ -389,22 +389,22 @@ class Terminal { csi(params: string, final: string): void { if (/^[?>=]/u.test(params)) return; // Mode switches (cursor visibility, bracketed paste). + if (final === "m") { + const key = `${this.pen}|${params}`; + let pen = penTransitions.get(key); + if (pen === undefined) { + const attributes = parsePen(this.pen); + applySgr(attributes, params === "" ? [] : csiParams(params)); + pen = formatPen(attributes); + if (penTransitions.size >= 512) penTransitions.clear(); + penTransitions.set(key, pen); + } + this.pen = pen; + return; + } const numbers = params === "" ? [] : csiParams(params); const count = Math.max(1, numbers[0] || 1); switch (final) { - case "m": { - const key = `${this.pen}|${params}`; - let pen = penTransitions.get(key); - if (pen === undefined) { - const attributes = parsePen(this.pen); - applySgr(attributes, numbers); - pen = formatPen(attributes); - if (penTransitions.size >= 512) penTransitions.clear(); - penTransitions.set(key, pen); - } - this.pen = pen; - return; - } case "A": return this.moveTo(this.row - count, this.col); case "B":