diff --git a/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/readline-close-in-line-listener.ts.json b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/readline-close-in-line-listener.ts.json new file mode 100644 index 000000000..0ea441125 --- /dev/null +++ b/packages/compiler/test/ts7/baselines/order-parity/tests/corpus/readline-close-in-line-listener.ts.json @@ -0,0 +1,6 @@ +{ + "order": [ + "/tests/corpus/readline-close-in-line-listener.ts" + ], + "diags": [] +} diff --git a/packages/runtime/src/scr_readline.c b/packages/runtime/src/scr_readline.c index 94becf5d7..dc6216018 100644 --- a/packages/runtime/src/scr_readline.c +++ b/packages/runtime/src/scr_readline.c @@ -350,8 +350,10 @@ static void scr_rl_feed_text(ScrRl *rl, const char *p, size_t n) { } rl->line_len = 0; if (start < n) scr_rl_buf_append(rl, p + start, n - start); + /* Node delivers every line the chunk split, also after a line listener + * closes the interface; an exception a listener throws ends the chunk. */ for (size_t i = 0; i < n_lines; i++) { - if (rl->closed || scr_exc_pending()) { + if (scr_exc_pending()) { scr_str_release(lines[i]); continue; } diff --git a/tests/corpus/readline-close-in-line-listener.ts b/tests/corpus/readline-close-in-line-listener.ts new file mode 100644 index 000000000..c86242cab --- /dev/null +++ b/tests/corpus/readline-close-in-line-listener.ts @@ -0,0 +1,23 @@ +// A 'line' listener that closes the interface: the 'close' event runs at +// once, the rest of the lines already split from the same chunk are still +// delivered, as in Node, and later chunks are not read. +import { createInterface } from "node:readline"; +import { Readable } from "node:stream"; + +const first = createInterface({ input: Readable.from(["x\ny\nz\n", "after\n"]) }); +first.on("line", (line: string) => { + console.log("line", line); + if (line === "y") first.close(); +}); +first.on("close", () => console.log("closed")); + +// Two listeners; the second closes on the first line of a chunk of three. +const second = createInterface({ input: Readable.from(["a\nb\nc"]) }); +const order: string[] = []; +second.on("line", (line: string) => order.push(`one:${line}`)); +second.on("line", (line: string) => { + order.push(`two:${line}`); + if (line === "a") second.close(); +}); +second.on("close", () => order.push("close")); +setTimeout(() => console.log(order.join(" ")), 20); diff --git a/tests/harness/corpus-costs/readline-close-in-line-listener.ts.json b/tests/harness/corpus-costs/readline-close-in-line-listener.ts.json new file mode 100644 index 000000000..5ac0e468a --- /dev/null +++ b/tests/harness/corpus-costs/readline-close-in-line-listener.ts.json @@ -0,0 +1 @@ +{ "plain": 4600, "san": 6500 }