From 2f47ec6c3a583c8323a06c386feeaee4fbf75edc Mon Sep 17 00:00:00 2001 From: Asher Gomez Date: Wed, 24 Jan 2024 10:31:52 +1100 Subject: [PATCH] feat: `Deno.FsFile.dataSync()` and `Deno.FsFile.dataSyncSync()` (#22019) This change: 1. Implements `Deno.FsFile.dataSync()` and `Deno.FsFile.dataSyncSync()`. 2. Deprecates `Deno.fdatasync()` and `Deno.fdatasyncSync()` for removal in Deno v2, in favour of the above corresponding methods. 3. Replaces use of `Deno.fdatasync()` and `Deno.fdatasyncSync()` with the above instance methods. Related #21995 --- cli/js/40_testing.js | 2 +- cli/tests/unit/files_test.ts | 36 +++++++++++++++++++++++ cli/tests/unit/utime_test.ts | 4 +-- cli/tsc/dts/lib.deno.ns.d.ts | 38 +++++++++++++++++++++++++ ext/fs/30_fs.js | 20 ++++++++++++- ext/node/polyfills/_fs/_fs_fdatasync.ts | 5 ++-- 6 files changed, 99 insertions(+), 6 deletions(-) diff --git a/cli/js/40_testing.js b/cli/js/40_testing.js index 91d7f105fe..eb75a4d436 100644 --- a/cli/js/40_testing.js +++ b/cli/js/40_testing.js @@ -94,7 +94,7 @@ const OP_DETAILS = { "op_net_send_udp": ["send a datagram message via UDP", "awaiting the result of `Deno.DatagramConn#send` call"], "op_net_send_unixpacket": ["send a datagram message via Unixpacket", "awaiting the result of `Deno.DatagramConn#send` call"], "op_dns_resolve": ["resolve a DNS name", "awaiting the result of a `Deno.resolveDns` call"], - "op_fdatasync_async": ["flush pending data operations for a file to disk", "awaiting the result of a `Deno.fdatasync` call"], + "op_fdatasync_async": ["flush pending data operations for a file to disk", "awaiting the result of a `file.fdatasync` call"], "op_fetch_send": ["send a HTTP request", "awaiting the result of a `fetch` call"], "op_ffi_call_nonblocking": ["do a non blocking ffi call", "awaiting the returned promise"], "op_ffi_call_ptr_nonblocking": ["do a non blocking ffi call", "awaiting the returned promise"], diff --git a/cli/tests/unit/files_test.ts b/cli/tests/unit/files_test.ts index 977d6463db..d02471b077 100644 --- a/cli/tests/unit/files_test.ts +++ b/cli/tests/unit/files_test.ts @@ -824,3 +824,39 @@ Deno.test( // calling [Symbol.dispose] after manual close is a no-op }, ); + +Deno.test( + { permissions: { read: true, write: true } }, + function fsFileDatasyncSyncSuccess() { + const filename = Deno.makeTempDirSync() + "/test_fdatasyncSync.txt"; + const file = Deno.openSync(filename, { + read: true, + write: true, + create: true, + }); + const data = new Uint8Array(64); + file.writeSync(data); + file.dataSyncSync(); + assertEquals(Deno.readFileSync(filename), data); + file.close(); + Deno.removeSync(filename); + }, +); + +Deno.test( + { permissions: { read: true, write: true } }, + async function fsFileDatasyncSuccess() { + const filename = (await Deno.makeTempDir()) + "/test_fdatasync.txt"; + const file = await Deno.open(filename, { + read: true, + write: true, + create: true, + }); + const data = new Uint8Array(64); + await file.write(data); + await file.dataSync(); + assertEquals(await Deno.readFile(filename), data); + file.close(); + await Deno.remove(filename); + }, +); diff --git a/cli/tests/unit/utime_test.ts b/cli/tests/unit/utime_test.ts index 02566bad6e..48f4f405ab 100644 --- a/cli/tests/unit/utime_test.ts +++ b/cli/tests/unit/utime_test.ts @@ -19,7 +19,7 @@ Deno.test( const atime = 1000; const mtime = 50000; await Deno.futime(file.rid, atime, mtime); - await Deno.fdatasync(file.rid); + await file.dataSync(); const fileInfo = Deno.statSync(filename); assertEquals(fileInfo.atime, new Date(atime * 1000)); @@ -40,7 +40,7 @@ Deno.test( const atime = 1000; const mtime = 50000; Deno.futimeSync(file.rid, atime, mtime); - Deno.fdatasyncSync(file.rid); + file.dataSyncSync(); const fileInfo = Deno.statSync(filename); assertEquals(fileInfo.atime, new Date(atime * 1000)); diff --git a/cli/tsc/dts/lib.deno.ns.d.ts b/cli/tsc/dts/lib.deno.ns.d.ts index 83292f2dd8..e32b90b414 100644 --- a/cli/tsc/dts/lib.deno.ns.d.ts +++ b/cli/tsc/dts/lib.deno.ns.d.ts @@ -2203,6 +2203,9 @@ declare namespace Deno { * console.log(await Deno.readTextFile("my_file.txt")); // Hello World * ``` * + * @deprecated Use {@linkcode Deno.FsFile.dataSync} instead. + * {@linkcode Deno.fdatasync} will be removed in v2.0.0. + * * @category I/O */ export function fdatasync(rid: number): Promise; @@ -2221,6 +2224,9 @@ declare namespace Deno { * console.log(Deno.readTextFileSync("my_file.txt")); // Hello World * ``` * + * @deprecated Use {@linkcode Deno.FsFile.dataSyncSync} instead. + * {@linkcode Deno.fdatasyncSync} will be removed in v2.0.0. + * * @category I/O */ export function fdatasyncSync(rid: number): void; @@ -2524,6 +2530,38 @@ declare namespace Deno { * ``` */ statSync(): FileInfo; + /** + * Flushes any pending data operations of the given file stream to disk. + * ```ts + * using file = await Deno.open( + * "my_file.txt", + * { read: true, write: true, create: true }, + * ); + * await file.write(new TextEncoder().encode("Hello World")); + * await file.dataSync(); + * console.log(await Deno.readTextFile("my_file.txt")); // Hello World + * ``` + * + * @category I/O + */ + dataSync(): Promise; + /** + * Synchronously flushes any pending data operations of the given file stream + * to disk. + * + * ```ts + * using file = Deno.openSync( + * "my_file.txt", + * { read: true, write: true, create: true }, + * ); + * file.writeSync(new TextEncoder().encode("Hello World")); + * file.dataSyncSync(); + * console.log(Deno.readTextFileSync("my_file.txt")); // Hello World + * ``` + * + * @category I/O + */ + dataSyncSync(): void; /** Close the file. Closing a file when you are finished with it is * important to avoid leaking resources. * diff --git a/ext/fs/30_fs.js b/ext/fs/30_fs.js index 277a1c73ca..3c888f1f12 100644 --- a/ext/fs/30_fs.js +++ b/ext/fs/30_fs.js @@ -1,6 +1,6 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. -import { core, primordials } from "ext:core/mod.js"; +import { core, internals, primordials } from "ext:core/mod.js"; const { isDate, } = core; @@ -558,10 +558,20 @@ async function symlink( } function fdatasyncSync(rid) { + internals.warnOnDeprecatedApi( + "Deno.fdatasyncSync()", + new Error().stack, + "Use `file.dataSyncSync()` instead.", + ); op_fs_fdatasync_sync(rid); } async function fdatasync(rid) { + internals.warnOnDeprecatedApi( + "Deno.fdatasync()", + new Error().stack, + "Use `await file.dataSync()` instead.", + ); await op_fs_fdatasync_async(rid); } @@ -703,6 +713,14 @@ class FsFile { return fstatSync(this.rid); } + async dataSync() { + await op_fs_fdatasync_async(this.rid); + } + + dataSyncSync() { + op_fs_fdatasync_sync(this.rid); + } + close() { core.close(this.rid); } diff --git a/ext/node/polyfills/_fs/_fs_fdatasync.ts b/ext/node/polyfills/_fs/_fs_fdatasync.ts index f6ed4a39b1..482b4378c3 100644 --- a/ext/node/polyfills/_fs/_fs_fdatasync.ts +++ b/ext/node/polyfills/_fs/_fs_fdatasync.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 fdatasync( fd: number, callback: CallbackWithError, ) { - Deno.fdatasync(fd).then(() => callback(null), callback); + new FsFile(fd).dataSync().then(() => callback(null), callback); } export function fdatasyncSync(fd: number) { - Deno.fdatasyncSync(fd); + new FsFile(fd).dataSyncSync(); }