From 47620641e7455a0f9df82d17ad0405693e4427a4 Mon Sep 17 00:00:00 2001 From: Asher Gomez Date: Wed, 24 Jan 2024 11:07:06 +1100 Subject: [PATCH] feat: `FsFile.sync()` and `FsFile.syncSync()` (#22017) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This change: 1. Implements `Deno.FsFile.sync()` and `Deno.FsFile.syncSync()`. 2. Deprecates `Deno.fsync()` and `Deno.fsyncSync()` for removal in Deno v2, in favour of the above corresponding methods. Related #21995 --------- Co-authored-by: Bartek IwaƄczuk --- cli/js/40_testing.js | 2 +- cli/tests/unit/files_test.ts | 36 +++++++++++++++++++++++++ cli/tsc/dts/lib.deno.ns.d.ts | 42 +++++++++++++++++++++++++++++ ext/fs/30_fs.js | 18 +++++++++++++ ext/node/polyfills/_fs/_fs_fsync.ts | 5 ++-- 5 files changed, 100 insertions(+), 3 deletions(-) diff --git a/cli/js/40_testing.js b/cli/js/40_testing.js index eb75a4d436..23a8da71ba 100644 --- a/cli/js/40_testing.js +++ b/cli/js/40_testing.js @@ -101,7 +101,7 @@ const OP_DETAILS = { "op_flock_async": ["lock a file", "awaiting the result of a `Deno.flock` call"], "op_fs_events_poll": ["get the next file system event", "breaking out of a for await loop looping over `Deno.FsEvents`"], "op_fstat_async": ["get file metadata", "awaiting the result of a `Deno.File#fstat` call"], - "op_fsync_async": ["flush pending data operations for a file to disk", "awaiting the result of a `Deno.fsync` call"], + "op_fsync_async": ["flush pending data operations for a file to disk", "awaiting the result of a `file.fsync` call"], "op_ftruncate_async": ["truncate a file", "awaiting the result of a `Deno.ftruncate` call"], "op_funlock_async": ["unlock a file", "awaiting the result of a `Deno.funlock` call"], "op_futime_async": ["change file timestamps", "awaiting the result of a `Deno.futime` call"], diff --git a/cli/tests/unit/files_test.ts b/cli/tests/unit/files_test.ts index d02471b077..b38a798d79 100644 --- a/cli/tests/unit/files_test.ts +++ b/cli/tests/unit/files_test.ts @@ -860,3 +860,39 @@ Deno.test( await Deno.remove(filename); }, ); + +Deno.test( + { permissions: { read: true, write: true } }, + function fsFileSyncSyncSuccess() { + const filename = Deno.makeTempDirSync() + "/test_fsyncSync.txt"; + const file = Deno.openSync(filename, { + read: true, + write: true, + create: true, + }); + const size = 64; + file.truncateSync(size); + file.syncSync(); + assertEquals(file.statSync().size, size); + file.close(); + Deno.removeSync(filename); + }, +); + +Deno.test( + { permissions: { read: true, write: true } }, + async function fsFileSyncSuccess() { + const filename = (await Deno.makeTempDir()) + "/test_fsync.txt"; + const file = await Deno.open(filename, { + read: true, + write: true, + create: true, + }); + const size = 64; + await file.truncate(size); + await file.sync(); + assertEquals((await file.stat()).size, size); + file.close(); + await Deno.remove(filename); + }, +); diff --git a/cli/tsc/dts/lib.deno.ns.d.ts b/cli/tsc/dts/lib.deno.ns.d.ts index e32b90b414..2b82fa1523 100644 --- a/cli/tsc/dts/lib.deno.ns.d.ts +++ b/cli/tsc/dts/lib.deno.ns.d.ts @@ -2168,6 +2168,9 @@ declare namespace Deno { * console.log(await Deno.readTextFile("my_file.txt")); // H * ``` * + * @deprecated Use `file.sync()` instead. {@linkcode Deno.fsync} will be + * removed in v2.0.0. + * * @category I/O */ export function fsync(rid: number): Promise; @@ -2187,6 +2190,9 @@ declare namespace Deno { * console.log(Deno.readTextFileSync("my_file.txt")); // H * ``` * + * @deprecated Use `file.syncSync()` instead. {@linkcode Deno.fsyncSync} will + * be removed in v2.0.0. + * * @category I/O */ export function fsyncSync(rid: number): void; @@ -2530,6 +2536,42 @@ declare namespace Deno { * ``` */ statSync(): FileInfo; + /** + * Flushes any pending data and metadata operations of the given file + * stream to disk. + * + * ```ts + * const file = await Deno.open( + * "my_file.txt", + * { read: true, write: true, create: true }, + * ); + * await file.write(new TextEncoder().encode("Hello World")); + * await file.truncate(1); + * await file.sync(); + * console.log(await Deno.readTextFile("my_file.txt")); // H + * ``` + * + * @category I/O + */ + sync(): Promise; + /** + * Synchronously flushes any pending data and metadata operations of the given + * file stream to disk. + * + * ```ts + * const file = Deno.openSync( + * "my_file.txt", + * { read: true, write: true, create: true }, + * ); + * file.writeSync(new TextEncoder().encode("Hello World")); + * file.truncateSync(1); + * file.syncSync(); + * console.log(Deno.readTextFileSync("my_file.txt")); // H + * ``` + * + * @category I/O + */ + syncSync(): void; /** * Flushes any pending data operations of the given file stream to disk. * ```ts diff --git a/ext/fs/30_fs.js b/ext/fs/30_fs.js index 3c888f1f12..6923741eea 100644 --- a/ext/fs/30_fs.js +++ b/ext/fs/30_fs.js @@ -576,10 +576,20 @@ async function fdatasync(rid) { } function fsyncSync(rid) { + internals.warnOnDeprecatedApi( + "Deno.fsyncSync()", + new Error().stack, + "Use `file.syncSync()` instead.", + ); op_fs_fsync_sync(rid); } async function fsync(rid) { + internals.warnOnDeprecatedApi( + "Deno.fsync()", + new Error().stack, + "Use `file.sync()` instead.", + ); await op_fs_fsync_async(rid); } @@ -739,6 +749,14 @@ class FsFile { return this.#writable; } + async sync() { + await op_fs_fsync_async(this.rid); + } + + syncSync() { + op_fs_fsync_sync(this.rid); + } + [SymbolDispose]() { core.tryClose(this.rid); } diff --git a/ext/node/polyfills/_fs/_fs_fsync.ts b/ext/node/polyfills/_fs/_fs_fsync.ts index 489929227f..942aecf6a0 100644 --- a/ext/node/polyfills/_fs/_fs_fsync.ts +++ b/ext/node/polyfills/_fs/_fs_fsync.ts @@ -4,14 +4,15 @@ // deno-lint-ignore-file prefer-primordials import { CallbackWithError } from "ext:deno_node/_fs/_fs_common.ts"; +import { FsFile } from "ext:deno_fs/30_fs.js"; export function fsync( fd: number, callback: CallbackWithError, ) { - Deno.fsync(fd).then(() => callback(null), callback); + new FsFile(fd).sync().then(() => callback(null), callback); } export function fsyncSync(fd: number) { - Deno.fsyncSync(fd); + new FsFile(fd).syncSync(); }