mirror of
https://github.com/QwenLM/qwen-code.git
synced 2026-08-18 21:25:00 +00:00
fix(core): jsonl write([]) should leave an empty file, not a stray newline (#7533)
write() built its content with join('\n') and then appended a trailing
newline. For an empty array the join produces '', so the file ends up as
a single '\n': one byte, no records.
That makes the module's own accessors contradict each other — exists()
tests size > 0 and returns true, while read() skips blank lines and
returns []. Clearing a JSONL file therefore leaves something that reports
as non-empty but has nothing in it.
Terminate each record instead of joining with separators. The output for
a non-empty array is byte-identical; an empty array now writes nothing.
Co-authored-by: Shaojin Wen <shaojin.wensj@alibaba-inc.com>
This commit is contained in:
parent
abc9666f77
commit
baaedfbf7d
2 changed files with 24 additions and 2 deletions
|
|
@ -20,6 +20,7 @@ import {
|
|||
_recoverObjectsFromLine,
|
||||
_resetEnsuredDirsCacheForTest,
|
||||
countLines,
|
||||
exists,
|
||||
parseLineTolerant,
|
||||
read,
|
||||
readLines,
|
||||
|
|
@ -354,6 +355,24 @@ describe('writeLine / writeLineSync / write', () => {
|
|||
// branch is never exercised. A regression that dropped that branch would
|
||||
// make write() fail with ENOENT only when callers target a brand-new
|
||||
// subdirectory.
|
||||
it('write() with an empty array leaves a genuinely empty file', async () => {
|
||||
const file = path.join(
|
||||
tmpRoot,
|
||||
`we-${Math.random().toString(36).slice(2)}.jsonl`,
|
||||
);
|
||||
await writeLine(file, { v: 1 });
|
||||
expect(exists(file)).toBe(true);
|
||||
|
||||
// Clearing the file must not leave a stray newline behind: a 1-byte file
|
||||
// makes exists() (size > 0) disagree with read() (no records).
|
||||
write(file, []);
|
||||
|
||||
expect(fs.readFileSync(file, 'utf8')).toBe('');
|
||||
expect(fs.statSync(file).size).toBe(0);
|
||||
expect(await read(file)).toEqual([]);
|
||||
expect(exists(file)).toBe(false);
|
||||
});
|
||||
|
||||
it('write() creates parent dirs when missing', () => {
|
||||
const nested = path.join(tmpRoot, 'a', 'b', 'c', 'file.jsonl');
|
||||
write(nested, [{ x: 1 }]);
|
||||
|
|
|
|||
|
|
@ -323,13 +323,16 @@ export function writeLineSync(filePath: string, data: unknown): void {
|
|||
* Each object will be written as a separate line.
|
||||
*/
|
||||
export function write(filePath: string, data: unknown[]): void {
|
||||
const lines = data.map((item) => JSON.stringify(item)).join('\n');
|
||||
// Terminate each record rather than joining with separators: joining an
|
||||
// empty array yields '' and the trailing newline then writes a 1-byte file
|
||||
// that read() reports as empty but exists() reports as non-empty.
|
||||
const lines = data.map((item) => `${JSON.stringify(item)}\n`).join('');
|
||||
// Ensure directory exists before writing
|
||||
const dir = path.dirname(filePath);
|
||||
if (!fs.existsSync(dir)) {
|
||||
fs.mkdirSync(dir, { recursive: true });
|
||||
}
|
||||
atomicWriteFileSync(filePath, `${lines}\n`, { encoding: 'utf8' });
|
||||
atomicWriteFileSync(filePath, lines, { encoding: 'utf8' });
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue