mirror of
https://github.com/vercel-labs/scriptc.git
synced 2026-11-08 08:44:37 +08:00
Deliver a line to a single line listener without the listener snapshot (#2531)
This commit is contained in:
+6
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"order": [
|
||||
"<repo>/tests/corpus/readline-line-listener-changes.ts"
|
||||
],
|
||||
"diags": []
|
||||
}
|
||||
@@ -105,6 +105,17 @@ void scr_rl_emit(ScrRl *rl, int ev, ScrStr *line, ScrError *err) {
|
||||
RlList *l = &rl->ev[ev];
|
||||
size_t n = l->n;
|
||||
if (n == 0) return;
|
||||
/* One persistent line listener (the usual 'line' handler): no snapshot
|
||||
* and no once-listener pass. The retain keeps the closure alive if the
|
||||
* listener removes itself. */
|
||||
if (n == 1 && ev == RL_EV_LINE && !l->v[0].once && !l->v[0].iter) {
|
||||
RlEntry e = l->v[0];
|
||||
if (scr_exc_pending()) return;
|
||||
scr_closure_retain(e.cb);
|
||||
((ScrRlLineFn)e.fn)(e.cb, scr_str_retain(line));
|
||||
scr_closure_release(e.cb);
|
||||
return;
|
||||
}
|
||||
/* Most events have a listener or two: their snapshot stays on the stack. */
|
||||
RlEntry small[4];
|
||||
RlEntry *snap = n <= 4 ? small : malloc(n * sizeof *snap);
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
// 'line' listeners that change while a line is delivered: a listener added
|
||||
// by the only line listener starts with the next line, after which both
|
||||
// run in order; a once listener next to a persistent one runs for one line;
|
||||
// and no listener sees a line twice.
|
||||
import { createInterface } from "node:readline";
|
||||
import { Readable } from "node:stream";
|
||||
|
||||
const text = "a\nb\nc\nd\ne\nf\n";
|
||||
|
||||
const first = createInterface({ input: Readable.from([text]) });
|
||||
let seen = 0;
|
||||
const counting = (line: string): void => {
|
||||
seen++;
|
||||
console.log("counting", line);
|
||||
if (seen === 2) first.on("line", (later: string) => console.log("later", later));
|
||||
};
|
||||
first.on("line", counting);
|
||||
first.on("close", () => {
|
||||
console.log("first closed", seen);
|
||||
|
||||
const second = createInterface({ input: Readable.from([text]) });
|
||||
second.once("line", (line: string) => console.log("once", line));
|
||||
second.on("line", (line: string) => console.log("every", line));
|
||||
second.on("close", () => {
|
||||
console.log("second closed");
|
||||
|
||||
const third = createInterface({ input: Readable.from(["x\ny\n", "z\n"]) });
|
||||
const seenLines: string[] = [];
|
||||
third.on("line", (line: string) => seenLines.push(line));
|
||||
third.on("close", () => console.log("third", seenLines.join(",")));
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1 @@
|
||||
{ "plain": 4500, "san": 7400 }
|
||||
Reference in New Issue
Block a user