Skip to content

Commit c896bbd

Browse files
authored
Merge pull request #1164 from streamich/fix-fs-overwrite
Fix fs stream read buffer size check
2 parents 7097357 + d30a19c commit c896bbd

File tree

3 files changed

+51
-1
lines changed

3 files changed

+51
-1
lines changed

src/crud/__tests__/matryoshka.test.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import { fromStream } from '@jsonjoy.com/util/lib/streams/fromStream';
2+
import { bufferToUint8Array } from '@jsonjoy.com/util/lib/buffers/bufferToUint8Array';
13
import { memfs } from '../..';
24
import { onlyOnNode20 } from '../../__tests__/util';
35
import { NodeFileSystemDirectoryHandle } from '../../node-to-fsa';
@@ -6,6 +8,11 @@ import { NodeCrud } from '../../node-to-crud';
68
import { testCrudfs } from '../../crud/__tests__/testCrudfs';
79
import { FsaCrud } from '../../fsa-to-crud';
810

11+
const b = (str: string) => {
12+
const buf = Buffer.from(str);
13+
return new Uint8Array(buf.buffer, buf.byteOffset, buf.byteLength);
14+
};
15+
916
onlyOnNode20('CRUD matryoshka', () => {
1017
describe('crud(memfs)', () => {
1118
testCrudfs(() => {
@@ -54,6 +61,17 @@ onlyOnNode20('CRUD matryoshka', () => {
5461
expect(await fs2.promises.readFile('/file3.txt', 'utf8')).toBe('a.c');
5562
});
5663

64+
test('can read as stream', async () => {
65+
const { fs } = memfs();
66+
const fsa = new NodeFileSystemDirectoryHandle(fs, '/', { mode: 'readwrite' });
67+
const fs2 = new FsaNodeFs(fsa);
68+
await fs2.promises.writeFile('/foo', 'bar');
69+
const handle = await fs2.promises.open('/foo', 'r+');
70+
const stream = handle.readableWebStream();
71+
const blob = bufferToUint8Array((await fromStream(stream)) as any);
72+
expect(blob).toStrictEqual(b('bar'));
73+
});
74+
5775
testCrudfs(() => {
5876
const { fs } = memfs();
5977
const fsa = new NodeFileSystemDirectoryHandle(fs, '/', { mode: 'readwrite' });

src/crud/__tests__/testCrudfs.ts

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,33 @@ export const testCrudfs = (setup: Setup) => {
5252
});
5353
});
5454

55+
test('truncates overwritten resource', async () => {
56+
const { crud, snapshot } = setup();
57+
await crud.put(['a', 'b'], 'bar', b('abc'));
58+
await crud.put(['a', 'b'], 'bar', b('.'));
59+
expect(snapshot()).toStrictEqual({
60+
'/a/b/bar': '.',
61+
});
62+
});
63+
64+
test('can overwrite with empty file', async () => {
65+
const { crud, snapshot } = setup();
66+
await crud.put(['a', 'b'], 'bar', b('abc'));
67+
await crud.put(['a', 'b'], 'bar', b(''));
68+
expect(snapshot()).toStrictEqual({
69+
'/a/b/bar': '',
70+
});
71+
});
72+
73+
test('overwrites existing data', async () => {
74+
const { crud, snapshot } = setup();
75+
await crud.put(['a', 'b'], 'bar', b('abc'));
76+
await crud.put(['a', 'b'], 'bar', b('.'));
77+
expect(snapshot()).toStrictEqual({
78+
'/a/b/bar': '.',
79+
});
80+
});
81+
5582
test('can choose to throw if item already exists', async () => {
5683
const { crud } = setup();
5784
await crud.put(['a', 'b'], 'bar', b('abc'), { throwIf: 'exists' });

src/fsa-to-node/FsaNodeFs.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,12 @@ export class FsaNodeFs extends FsaNodeCore implements FsCallbackApi, FsSynchrono
9494
const openFile = await this.getFileByFd(fd, 'read');
9595
const file = await openFile.file.getFile();
9696
const src = await file.arrayBuffer();
97-
const slice = new Uint8Array(src, Number(position), Number(length));
97+
position = Number(position);
98+
length = Number(length);
99+
const slice =
100+
position > src.byteLength
101+
? new Uint8Array(0)
102+
: new Uint8Array(src, position, Math.min(length, src.byteLength - position));
98103
const dest = new Uint8Array(buffer.buffer, buffer.byteOffset + offset, slice.length);
99104
dest.set(slice, 0);
100105
return slice.length;

0 commit comments

Comments
 (0)