Skip to content

Commit 2526c3a

Browse files
committed
fix: 🐛 correctly write at offset in FS adapter
1 parent b08d29a commit 2526c3a

File tree

3 files changed

+35
-3
lines changed

3 files changed

+35
-3
lines changed

src/crud/__tests__/matryoshka.test.ts

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,35 @@ onlyOnNode20('CRUD matryoshka', () => {
2525
});
2626

2727
describe('crud(fs(fsa(memfs)))', () => {
28+
test('can write at offset', async () => {
29+
const { fs } = memfs();
30+
await fs.promises.writeFile('/file1.txt', 'abc');
31+
const handle1 = await fs.promises.open('/file1.txt', 'r+');
32+
await handle1.write(Buffer.from('.'), 0, 1, 1);
33+
expect(await fs.promises.readFile('/file1.txt', 'utf8')).toBe('a.c');
34+
35+
const fsa = new NodeFileSystemDirectoryHandle(fs, '/', { mode: 'readwrite' });
36+
const file2 = await fsa.getFileHandle('file2.txt', {create: true});
37+
const writable1 = await file2.createWritable({keepExistingData: false});
38+
await writable1.write('abc');
39+
await writable1.close();
40+
const writable2 = await file2.createWritable({keepExistingData: true});
41+
await writable2.write({
42+
type: 'write',
43+
data: Buffer.from('.'),
44+
position: 1,
45+
size: 1,
46+
});
47+
await writable2.close();
48+
expect(await (await file2.getFile()).text()).toBe('a.c');
49+
50+
const fs2 = new FsaNodeFs(fsa);
51+
await fs2.promises.writeFile('/file3.txt', 'abc');
52+
const handle = await fs2.promises.open('/file3.txt', 'r+');
53+
await handle.write(Buffer.from('.'), 0, 1, 1);
54+
expect(await fs2.promises.readFile('/file3.txt', 'utf8')).toBe('a.c');
55+
});
56+
2857
testCrudfs(() => {
2958
const { fs } = memfs();
3059
const fsa = new NodeFileSystemDirectoryHandle(fs, '/', { mode: 'readwrite' });

src/fsa-to-node/FsaNodeFsOpenFile.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,9 @@ export class FsaNodeFsOpenFile {
3131

3232
public async write(data: ArrayBufferView, seek: number | null): Promise<void> {
3333
if (typeof seek !== 'number') seek = this.seek;
34-
const writer = await this.file.createWritable({ keepExistingData: this.keepExistingData });
34+
else this.keepExistingData = true;
35+
const keepExistingData = this.keepExistingData;
36+
const writer = await this.file.createWritable({ keepExistingData });
3537
await writer.write({
3638
type: 'write',
3739
data,

src/node/FileHandle.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,8 @@ export class FileHandle extends EventEmitter implements IFileHandle {
215215
length?: number,
216216
position?: number | null,
217217
): Promise<TFileHandleWriteResult> {
218-
const writePosition = position !== null && position !== undefined ? position : this.position;
218+
const useInternalPosition = typeof position !== 'number';
219+
const writePosition: number = useInternalPosition ? this.position : position;
219220

220221
const result = await promisify(this.fs, 'write', bytesWritten => ({ bytesWritten, buffer }))(
221222
this.fd,
@@ -226,7 +227,7 @@ export class FileHandle extends EventEmitter implements IFileHandle {
226227
);
227228

228229
// Update internal position only if position was null/undefined
229-
if (position === null || position === undefined) {
230+
if (useInternalPosition) {
230231
this.position += result.bytesWritten;
231232
}
232233

0 commit comments

Comments
 (0)