From 70fe76209b79b5280fd6c5641ef5814e8fa5ee0d Mon Sep 17 00:00:00 2001 From: robobun Date: Sat, 24 Jan 2026 15:37:29 -0800 Subject: [PATCH] fix(readline): use symbol key for _refreshLine in tab completer (#26412) --- src/js/node/readline.ts | 2 +- test/regression/issue/26411.test.ts | 40 +++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+), 1 deletion(-) create mode 100644 test/regression/issue/26411.test.ts diff --git a/src/js/node/readline.ts b/src/js/node/readline.ts index 81328b378f..a66af032e6 100644 --- a/src/js/node/readline.ts +++ b/src/js/node/readline.ts @@ -1534,7 +1534,7 @@ var _Interface = class Interface extends InterfaceConstructor { prefix + StringPrototypeSlice.$call(this.line, this.cursor, this.line.length); this.cursor = this.cursor - completeOn.length + prefix.length; - this._refreshLine(); + this[kRefreshLine](); return; } diff --git a/test/regression/issue/26411.test.ts b/test/regression/issue/26411.test.ts new file mode 100644 index 0000000000..37388ebb81 --- /dev/null +++ b/test/regression/issue/26411.test.ts @@ -0,0 +1,40 @@ +import { expect, test } from "bun:test"; +import { bunEnv, bunExe } from "harness"; + +// https://github.com/oven-sh/bun/issues/26411 +// Tab completion with node:readline/promises threw +// "TypeError: this._refreshLine is not a function" +test("tab completion works with node:readline/promises", async () => { + await using proc = Bun.spawn({ + cmd: [ + bunExe(), + "-e", + ` +import readline from "node:readline/promises"; +const rl = readline.createInterface({ + input: process.stdin, + output: process.stdout, + terminal: true, + completer: (line) => [["FOO", "FOOBAR"], line] +}); +rl.line = "foo"; +rl.cursor = 3; +setTimeout(() => { + rl.close(); + console.log("OK"); + process.exit(0); +}, 100); +rl.write("", { name: "tab" }); +`, + ], + env: bunEnv, + stdout: "pipe", + stderr: "pipe", + }); + + const [stdout, stderr, exitCode] = await Promise.all([proc.stdout.text(), proc.stderr.text(), proc.exited]); + + expect(stderr).not.toContain("this._refreshLine is not a function"); + expect(stdout).toContain("OK"); + expect(exitCode).toBe(0); +});