From 7a2fced74c8aa1a80b7077b99707869dbac2f72c Mon Sep 17 00:00:00 2001 From: Vadim Dalecky Date: Mon, 19 Jun 2023 10:48:05 +0200 Subject: [PATCH] =?UTF-8?q?feat:=20=F0=9F=8E=B8=20implement=20writeSync()?= =?UTF-8?q?=20method?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- demo/fsa/main.ts | 7 +++++ src/fsa-to-node/FsaNodeFs.ts | 15 +++++++++- src/fsa-to-node/types.ts | 5 ++++ src/fsa-to-node/worker/FsaNodeSyncWorker.ts | 5 ++++ src/node/constants.ts | 4 --- src/node/util.ts | 33 +++++++++++++++++++++ src/volume.ts | 30 ++----------------- 7 files changed, 66 insertions(+), 33 deletions(-) diff --git a/demo/fsa/main.ts b/demo/fsa/main.ts index 764f47491..f42265849 100644 --- a/demo/fsa/main.ts +++ b/demo/fsa/main.ts @@ -92,6 +92,13 @@ const demo = async (dir: fsa.IFileSystemDirectoryHandle) => { const bytesRead = fs.readSync(readHandle.fd, buf, 0, 3, 0); strictEqual(bytesRead, 3); strictEqual(buf.toString('utf8'), 'wor'); + + console.log('writeSync() - can write into an open file'); + const writeHandle = await fs.promises.open('/cool.txt', 'a'); + const bytesWritten = fs.writeSync(writeHandle.fd, Buffer.from('W'), 0, 1, 0); + await writeHandle.close(); + strictEqual(bytesWritten, 1); + strictEqual(fs.readFileSync('/cool.txt', 'utf8'), 'Worlds!'); }; const main = async () => { diff --git a/src/fsa-to-node/FsaNodeFs.ts b/src/fsa-to-node/FsaNodeFs.ts index 3d23896e3..bfe480f96 100644 --- a/src/fsa-to-node/FsaNodeFs.ts +++ b/src/fsa-to-node/FsaNodeFs.ts @@ -34,6 +34,7 @@ import { validateCallback, validateFd, isFd, + getWriteSyncArgs, } from '../node/util'; import { pathToLocation, testDirectoryIsWritable } from './util'; import { ERRSTR, MODE } from '../node/constants'; @@ -974,8 +975,20 @@ export class FsaNodeFs extends FsaNodeCore implements FsCallbackApi, FsSynchrono return uint8.length; }; + public readonly writeSync: FsSynchronousApi['writeSync'] = ( + fd: number, + a: string | Buffer | ArrayBufferView | DataView, + b?: number, + c?: number | BufferEncoding, + d?: number, + ): number => { + const [, buf, offset, length, position] = getWriteSyncArgs(fd, a, b, c, d) + const filename = this.getFileName(fd); + const data = new Uint8Array(buf.buffer, buf.byteOffset + offset, length); + return this.getSyncAdapter().call('write', [filename, data, position || null]); + }; + public readonly openSync: FsSynchronousApi['openSync'] = notSupported; - public readonly writeSync: FsSynchronousApi['writeSync'] = notSupported; public readonly chmodSync: FsSynchronousApi['chmodSync'] = noop; public readonly chownSync: FsSynchronousApi['chownSync'] = noop; diff --git a/src/fsa-to-node/types.ts b/src/fsa-to-node/types.ts index 817e090d8..87663ad5c 100644 --- a/src/fsa-to-node/types.ts +++ b/src/fsa-to-node/types.ts @@ -26,6 +26,11 @@ export interface FsaNodeSyncAdapterApi { position: number, length: number, ]): Uint8Array; + write(req: [ + filename: string, + data: Uint8Array, + position: number | null, + ]): number; } export interface FsaNodeSyncAdapter { diff --git a/src/fsa-to-node/worker/FsaNodeSyncWorker.ts b/src/fsa-to-node/worker/FsaNodeSyncWorker.ts index 6ba1b99a3..2163c4a67 100644 --- a/src/fsa-to-node/worker/FsaNodeSyncWorker.ts +++ b/src/fsa-to-node/worker/FsaNodeSyncWorker.ts @@ -183,5 +183,10 @@ export class FsaNodeSyncWorker { if (bytesRead < length) uint8 = uint8.slice(0, bytesRead); return uint8; }, + write: async ([filename, data, position]): Promise => { + const handle = await this.fs.promises.open(filename, 'a'); + const {bytesWritten} = await handle.write(data, 0, data.length, position || undefined); + return bytesWritten; + }, }; } diff --git a/src/node/constants.ts b/src/node/constants.ts index 5e71a1023..25341d20e 100644 --- a/src/node/constants.ts +++ b/src/node/constants.ts @@ -34,10 +34,6 @@ const { O_TRUNC, O_APPEND, O_SYNC, - O_DIRECTORY, - F_OK, - COPYFILE_EXCL, - COPYFILE_FICLONE_FORCE, } = constants; // List of file `flags` as defined by Node. diff --git a/src/node/util.ts b/src/node/util.ts index e4144ac5c..87754abbd 100644 --- a/src/node/util.ts +++ b/src/node/util.ts @@ -244,6 +244,39 @@ export const getWriteArgs = ( return [fd, tipa === 'string', buf, offset, length!, position, cb]; }; +export const getWriteSyncArgs = ( + fd: number, + a: string | Buffer | ArrayBufferView | DataView, + b?: number, + c?: number | BufferEncoding, + d?: number, +): [fd: number, buf: Buffer, offset: number, length?: number, position?: number] => { + validateFd(fd); + let encoding: BufferEncoding | undefined; + let offset: number | undefined; + let length: number | undefined; + let position: number | undefined; + const isBuffer = typeof a !== 'string'; + if (isBuffer) { + offset = (b || 0) | 0; + length = c as number; + position = d; + } else { + position = b; + encoding = c as BufferEncoding; + } + const buf: Buffer = dataToBuffer(a, encoding); + if (isBuffer) { + if (typeof length === 'undefined') { + length = buf.length; + } + } else { + offset = 0; + length = buf.length; + } + return [fd, buf, offset || 0, length, position]; +}; + export function bufferToEncoding(buffer: Buffer, encoding?: TEncodingExtended): misc.TDataOut { if (!encoding || encoding === 'buffer') return buffer; else return buffer.toString(encoding); diff --git a/src/volume.ts b/src/volume.ts index 6bb6bc8ab..a62fcbba1 100644 --- a/src/volume.ts +++ b/src/volume.ts @@ -48,6 +48,7 @@ import { dataToBuffer, getWriteArgs, bufferToEncoding, + getWriteSyncArgs, } from './node/util'; import type { PathLike, symlink } from 'fs'; import { WritevCallback } from './node/types/callback'; @@ -907,34 +908,7 @@ export class Volume { c?: number | BufferEncoding, d?: number, ): number { - validateFd(fd); - - let encoding: BufferEncoding | undefined; - let offset: number | undefined; - let length: number | undefined; - let position: number | undefined; - - const isBuffer = typeof a !== 'string'; - if (isBuffer) { - offset = (b || 0) | 0; - length = c as number; - position = d; - } else { - position = b; - encoding = c as BufferEncoding; - } - - const buf: Buffer = dataToBuffer(a, encoding); - - if (isBuffer) { - if (typeof length === 'undefined') { - length = buf.length; - } - } else { - offset = 0; - length = buf.length; - } - + const [, buf, offset, length, position] = getWriteSyncArgs(fd, a, b, c, d) return this.writeBase(fd, buf, offset, length, position); }