diff --git a/ext/node/polyfills/_fs/_fs_fdatasync.ts b/ext/node/polyfills/_fs/_fs_fdatasync.ts index 02226e1c96..fce4541099 100644 --- a/ext/node/polyfills/_fs/_fs_fdatasync.ts +++ b/ext/node/polyfills/_fs/_fs_fdatasync.ts @@ -5,6 +5,7 @@ import { CallbackWithError } from "ext:deno_node/_fs/_fs_common.ts"; import { FsFile } from "ext:deno_fs/30_fs.js"; +import { promisify } from "ext:deno_node/internal/util.mjs"; export function fdatasync( fd: number, @@ -19,3 +20,7 @@ export function fdatasync( export function fdatasyncSync(fd: number) { new FsFile(fd, Symbol.for("Deno.internal.FsFile")).syncDataSync(); } + +export const fdatasyncPromise = promisify(fdatasync) as ( + fd: number, +) => Promise; diff --git a/ext/node/polyfills/_fs/_fs_fsync.ts b/ext/node/polyfills/_fs/_fs_fsync.ts index a07f440778..1f31dbd808 100644 --- a/ext/node/polyfills/_fs/_fs_fsync.ts +++ b/ext/node/polyfills/_fs/_fs_fsync.ts @@ -5,6 +5,7 @@ import { CallbackWithError } from "ext:deno_node/_fs/_fs_common.ts"; import { FsFile } from "ext:deno_fs/30_fs.js"; +import { promisify } from "ext:deno_node/internal/util.mjs"; export function fsync( fd: number, @@ -19,3 +20,5 @@ export function fsync( export function fsyncSync(fd: number) { new FsFile(fd, Symbol.for("Deno.internal.FsFile")).syncSync(); } + +export const fsyncPromise = promisify(fsync) as (fd: number) => Promise; diff --git a/ext/node/polyfills/internal/fs/handle.ts b/ext/node/polyfills/internal/fs/handle.ts index e22c3e0ae6..f18f1e5a6c 100644 --- a/ext/node/polyfills/internal/fs/handle.ts +++ b/ext/node/polyfills/internal/fs/handle.ts @@ -16,6 +16,8 @@ import { import { ftruncatePromise } from "ext:deno_node/_fs/_fs_ftruncate.ts"; export type { BigIntStats, Stats } from "ext:deno_node/_fs/_fs_stat.ts"; import { writevPromise, WriteVResult } from "ext:deno_node/_fs/_fs_writev.ts"; +import { fdatasyncPromise } from "ext:deno_node/_fs/_fs_fdatasync.ts"; +import { fsyncPromise } from "ext:deno_node/_fs/_fs_fsync.ts"; interface WriteResult { bytesWritten: number; @@ -158,6 +160,14 @@ export class FileHandle extends EventEmitter { return promises.chmod(this.#path, mode); } + datasync(): Promise { + return fsCall(fdatasyncPromise, this); + } + + sync(): Promise { + return fsCall(fsyncPromise, this); + } + utimes( atime: number | string | Date, mtime: number | string | Date, diff --git a/tests/node_compat/config.jsonc b/tests/node_compat/config.jsonc index c2edc32ef6..4d77a290dd 100644 --- a/tests/node_compat/config.jsonc +++ b/tests/node_compat/config.jsonc @@ -2,6 +2,7 @@ "ignore": { "common": ["index.js", "internet.js"], "fixtures": [ + "baz.js", "child-process-spawn-node.js", "echo.js", "elipses.txt", @@ -480,6 +481,7 @@ "test-fs-opendir.js", "test-fs-promises-exists.js", "test-fs-promises-file-handle-stat.js", + "test-fs-promises-file-handle-sync.js", "test-fs-promises-file-handle-write.js", "test-fs-promises-readfile-empty.js", "test-fs-promises-readfile-with-fd.js", diff --git a/tests/node_compat/runner/TODO.md b/tests/node_compat/runner/TODO.md index c885622d6f..c2e360aef5 100644 --- a/tests/node_compat/runner/TODO.md +++ b/tests/node_compat/runner/TODO.md @@ -1,7 +1,7 @@ # Remaining Node Tests -1152 tests out of 3681 have been ported from Node 20.11.1 (31.30% ported, 69.22% remaining). +1154 tests out of 3681 have been ported from Node 20.11.1 (31.35% ported, 69.19% remaining). NOTE: This file should not be manually edited. Please edit `tests/node_compat/config.json` and run `deno task setup` in `tests/node_compat/runner` dir instead. @@ -673,7 +673,6 @@ NOTE: This file should not be manually edited. Please edit `tests/node_compat/co - [parallel/test-fs-promises-file-handle-read.js](https://github.com/nodejs/node/tree/v20.11.1/test/parallel/test-fs-promises-file-handle-read.js) - [parallel/test-fs-promises-file-handle-readFile.js](https://github.com/nodejs/node/tree/v20.11.1/test/parallel/test-fs-promises-file-handle-readFile.js) - [parallel/test-fs-promises-file-handle-stream.js](https://github.com/nodejs/node/tree/v20.11.1/test/parallel/test-fs-promises-file-handle-stream.js) -- [parallel/test-fs-promises-file-handle-sync.js](https://github.com/nodejs/node/tree/v20.11.1/test/parallel/test-fs-promises-file-handle-sync.js) - [parallel/test-fs-promises-file-handle-truncate.js](https://github.com/nodejs/node/tree/v20.11.1/test/parallel/test-fs-promises-file-handle-truncate.js) - [parallel/test-fs-promises-file-handle-writeFile.js](https://github.com/nodejs/node/tree/v20.11.1/test/parallel/test-fs-promises-file-handle-writeFile.js) - [parallel/test-fs-promises-readfile.js](https://github.com/nodejs/node/tree/v20.11.1/test/parallel/test-fs-promises-readfile.js) diff --git a/tests/node_compat/test/fixtures/baz.js b/tests/node_compat/test/fixtures/baz.js new file mode 100644 index 0000000000..27b52d236c --- /dev/null +++ b/tests/node_compat/test/fixtures/baz.js @@ -0,0 +1,8 @@ +// deno-fmt-ignore-file +// deno-lint-ignore-file + +// Copyright Joyent and Node contributors. All rights reserved. MIT license. +// Taken from Node 20.11.1 +// This file is automatically generated by `tests/node_compat/runner/setup.ts`. Do not modify this file manually. + +module.exports = 'perhaps I work'; diff --git a/tests/node_compat/test/parallel/test-fs-promises-file-handle-sync.js b/tests/node_compat/test/parallel/test-fs-promises-file-handle-sync.js new file mode 100644 index 0000000000..fa7022cb47 --- /dev/null +++ b/tests/node_compat/test/parallel/test-fs-promises-file-handle-sync.js @@ -0,0 +1,42 @@ +// deno-fmt-ignore-file +// deno-lint-ignore-file + +// Copyright Joyent and Node contributors. All rights reserved. MIT license. +// Taken from Node 20.11.1 +// This file is automatically generated by `tests/node_compat/runner/setup.ts`. Do not modify this file manually. + +'use strict'; +require('../common'); +const assert = require('assert'); +const fixtures = require('../common/fixtures'); +const tmpdir = require('../common/tmpdir'); + +const { access, copyFile, open } = require('fs').promises; + +async function validate() { + tmpdir.refresh(); + const dest = tmpdir.resolve('baz.js'); + await assert.rejects( + copyFile(fixtures.path('baz.js'), dest, 'r'), + { + code: 'ERR_INVALID_ARG_TYPE', + } + ); + await copyFile(fixtures.path('baz.js'), dest); + await assert.rejects( + access(dest, 'r'), + { code: 'ERR_INVALID_ARG_TYPE', message: /mode/ } + ); + await access(dest); + const handle = await open(dest, 'r+'); + await handle.datasync(); + await handle.sync(); + const buf = Buffer.from('hello world'); + await handle.write(buf); + const ret = await handle.read(Buffer.alloc(11), 0, 11, 0); + assert.strictEqual(ret.bytesRead, 11); + assert.deepStrictEqual(ret.buffer, buf); + await handle.close(); +} + +validate(); diff --git a/tests/unit_node/_fs/_fs_handle_test.ts b/tests/unit_node/_fs/_fs_handle_test.ts index d7ae32b5ea..6bf37b6e0e 100644 --- a/tests/unit_node/_fs/_fs_handle_test.ts +++ b/tests/unit_node/_fs/_fs_handle_test.ts @@ -300,3 +300,20 @@ Deno.test({ await fileHandle.close(); }, }); + +Deno.test({ + name: + "[node/fs filehandle.sync] Request that all data for the open file descriptor is flushed to the storage device", + async fn() { + const fileHandle = await fs.open(testData, "r+"); + + await fileHandle.datasync(); + await fileHandle.sync(); + const buf = Buffer.from("hello world"); + await fileHandle.write(buf); + const ret = await fileHandle.read(Buffer.alloc(11), 0, 11, 0); + assertEquals(ret.bytesRead, 11); + assertEquals(ret.buffer, buf); + await fileHandle.close(); + }, +});