Compare commits

...

4 Commits

Author SHA1 Message Date
Jarred Sumner
464ddfa5a8 Merge branch 'main' into claude/implement-filehandle-readlines 2025-10-19 21:31:01 -07:00
Jarred Sumner
5bbeeb4d30 Update no-validate-exceptions.txt 2025-10-19 21:30:53 -07:00
autofix-ci[bot]
3c297a290d [autofix.ci] apply automated fixes 2025-10-18 23:15:19 +00:00
Claude Bot
68a0701dd5 Implement FileHandle.prototype.readLines
This implements the FileHandle.prototype.readLines() method in
src/js/node/fs.promises.ts, which was previously a stub throwing
"BUN TODO FileHandle.readLines".

The implementation creates a readline Interface with the file's
read stream as input and crlfDelay set to Infinity, matching
Node.js behavior from vendor/node/lib/internal/fs/promises.js.

Tests added:
- test/js/bun/fs/file-handle-readlines.test.ts: Comprehensive tests
  covering various scenarios (normal lines, empty lines, no trailing
  newline, empty files, and custom options)
- test/js/node/test/parallel/test-fs-promises-file-handle-readLines.mjs:
  Node.js compatibility test

All tests pass successfully.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-18 23:11:57 +00:00
4 changed files with 147 additions and 2 deletions

View File

@@ -413,8 +413,12 @@ function asyncWrap(fn: any, name: string) {
}
}
readLines(_options = undefined) {
throw new Error("BUN TODO FileHandle.readLines");
readLines(options = undefined) {
const { Interface } = require("node:readline");
return new Interface({
input: this.createReadStream(options),
crlfDelay: Infinity,
});
}
async stat(options) {

View File

@@ -0,0 +1,101 @@
import { afterAll, beforeAll, describe, expect, test } from "bun:test";
import { tempDirWithFiles } from "harness";
import { open, rm } from "node:fs/promises";
describe("FileHandle.readLines()", () => {
let tempDir: string;
beforeAll(() => {
tempDir = tempDirWithFiles("readlines", {
"test.txt": "line1\nline2\nline3",
"empty-lines.txt": "1\n\n2\n",
"no-newline.txt": "line1\nline2",
"empty.txt": "",
"with-encoding.txt": "line1\nline2",
});
});
afterAll(async () => {
await rm(tempDir, { recursive: true, force: true });
});
test("reads lines from a file", async () => {
const filePath = `${tempDir}/test.txt`;
const file = await open(filePath, "r");
try {
const lines = [];
for await (const line of file.readLines()) {
lines.push(line);
}
expect(lines).toEqual(["line1", "line2", "line3"]);
} finally {
await file.close();
}
});
test("handles empty lines", async () => {
const filePath = `${tempDir}/empty-lines.txt`;
const file = await open(filePath, "r");
try {
const lines = [];
for await (const line of file.readLines()) {
lines.push(line);
}
expect(lines).toEqual(["1", "", "2"]);
} finally {
await file.close();
}
});
test("handles files with no trailing newline", async () => {
const filePath = `${tempDir}/no-newline.txt`;
const file = await open(filePath, "r");
try {
const lines = [];
for await (const line of file.readLines()) {
lines.push(line);
}
expect(lines).toEqual(["line1", "line2"]);
} finally {
await file.close();
}
});
test("handles empty file", async () => {
const filePath = `${tempDir}/empty.txt`;
const file = await open(filePath, "r");
try {
const lines = [];
for await (const line of file.readLines()) {
lines.push(line);
}
expect(lines).toEqual([]);
} finally {
await file.close();
}
});
test("accepts options for createReadStream", async () => {
const filePath = `${tempDir}/with-encoding.txt`;
const file = await open(filePath, "r");
try {
const lines = [];
for await (const line of file.readLines({ encoding: "utf8" })) {
lines.push(line);
}
expect(lines).toEqual(["line1", "line2"]);
} finally {
await file.close();
}
});
});

View File

@@ -0,0 +1,39 @@
import '../common/index.mjs';
import tmpdir from '../common/tmpdir.js';
import assert from 'node:assert';
import { open, writeFile } from 'node:fs/promises';
tmpdir.refresh();
const filePath = tmpdir.resolve('file.txt');
await writeFile(filePath, '1\n\n2\n');
let file;
try {
file = await open(filePath);
let i = 0;
for await (const line of file.readLines()) {
switch (i++) {
case 0:
assert.strictEqual(line, '1');
break;
case 1:
assert.strictEqual(line, '');
break;
case 2:
assert.strictEqual(line, '2');
break;
default:
assert.fail();
break;
}
}
} finally {
await file?.close();
}

View File

@@ -25,6 +25,7 @@ test/js/node/test/parallel/test-whatwg-readablestream.mjs
test/js/node/test/parallel/test-worker.mjs
test/js/node/test/system-ca/test-native-root-certs.test.mjs
test/js/node/events/event-emitter.test.ts
test/js/node/test/parallel/test-fs-promises-file-handle-readLines.mjs
test/js/node/module/node-module-module.test.js
test/js/node/process/call-constructor.test.js
test/js/node/stubs.test.js