diff --git a/src/bun.js/node/node_fs_binding.zig b/src/bun.js/node/node_fs_binding.zig index c8ee2aced3..2055109c75 100644 --- a/src/bun.js/node/node_fs_binding.zig +++ b/src/bun.js/node/node_fs_binding.zig @@ -197,6 +197,8 @@ pub const NodeJSFS = struct { pub const watch = callSync(.watch); pub const watchFile = callSync(.watchFile); pub const unwatchFile = callSync(.unwatchFile); + // pub const statfs = callAsync(.statfs); + // pub const statfsSync = callSync(.statfs); }; pub fn createBinding(globalObject: *JSC.JSGlobalObject) JSC.JSValue { diff --git a/src/bun.js/node/types.zig b/src/bun.js/node/types.zig index 9ebb42e18e..b2c1e6c01c 100644 --- a/src/bun.js/node/types.zig +++ b/src/bun.js/node/types.zig @@ -1919,23 +1919,23 @@ pub const Dirent = struct { const path = try path_js.toBunString2(global); errdefer path.deref(); - const kind = try type_js.toInt32(global); - switch (kind) { + const kind = type_js.toInt32(); + const kind_enum: Kind = switch (kind) { // these correspond to the libuv constants else => .unknown, 1 => .file, 2 => .directory, 3 => .sym_link, - 4 => .fifo, + 4 => .named_pipe, 5 => .unix_domain_socket, 6 => .character_device, 7 => .block_device, - } + }; return Dirent.new(.{ .name = name, .path = path, - .kind = kind, + .kind = kind_enum, }); } diff --git a/test/js/node/test/parallel/test-fs-readdir-types.js b/test/js/node/test/parallel/test-fs-readdir-types.js new file mode 100644 index 0000000000..d9cc855728 --- /dev/null +++ b/test/js/node/test/parallel/test-fs-readdir-types.js @@ -0,0 +1,138 @@ +// Flags: --expose-internals +'use strict'; + +const common = require('../common'); +const assert = require('assert'); +const fs = require('fs'); + +const tmpdir = require('../common/tmpdir'); + +// const { internalBinding } = require('internal/test/binding'); +// const binding = internalBinding('fs'); + +const readdirDir = tmpdir.path; +const files = ['empty', 'files', 'for', 'just', 'testing']; +const constants = require('fs').constants; +const types = { + isDirectory: constants.UV_DIRENT_DIR, + isFile: constants.UV_DIRENT_FILE, + isBlockDevice: constants.UV_DIRENT_BLOCK, + isCharacterDevice: constants.UV_DIRENT_CHAR, + isSymbolicLink: constants.UV_DIRENT_LINK, + isFIFO: constants.UV_DIRENT_FIFO, + isSocket: constants.UV_DIRENT_SOCKET +}; +const typeMethods = Object.keys(types); + +// Make sure tmp directory is clean +tmpdir.refresh(); + +// Create the necessary files +files.forEach(function(currentFile) { + fs.writeFileSync(`${readdirDir}/${currentFile}`, '', 'utf8'); +}); + +const sortedFiles = files.slice().sort(); + +function assertDirents(dirents) { + // Bun: sort the dirents. node.js doesn't do this, which is interesting because + // they are able to return the dirents in the order that its written, but bun + // returns ["empty", "just", "testing", "for", "files"] + dirents = dirents.slice().sort((a, b) => a.name.localeCompare(b.name)); + + assert.strictEqual(files.length, dirents.length); + for (const [i, dirent] of dirents.entries()) { + assert(dirent instanceof fs.Dirent); + assert.strictEqual(dirent.name, sortedFiles[i]); + assert.strictEqual(dirent.isFile(), true); + assert.strictEqual(dirent.isDirectory(), false); + assert.strictEqual(dirent.isSocket(), false); + assert.strictEqual(dirent.isBlockDevice(), false); + assert.strictEqual(dirent.isCharacterDevice(), false); + assert.strictEqual(dirent.isFIFO(), false); + assert.strictEqual(dirent.isSymbolicLink(), false); + } +} + +// Check the readdir Sync version +assertDirents(fs.readdirSync(readdirDir, { withFileTypes: true })); + +fs.readdir(__filename, { + withFileTypes: true +}, common.mustCall((err) => { + assert.throws( + () => { throw err; }, + { + code: 'ENOTDIR', + name: 'Error', + message: `ENOTDIR: not a directory, scandir '${__filename}'` + } + ); +})); + +// Check the readdir async version +fs.readdir(readdirDir, { + withFileTypes: true +}, common.mustSucceed((dirents) => { + assertDirents(dirents); +})); + +(async () => { + const dirents = await fs.promises.readdir(readdirDir, { + withFileTypes: true + }); + assertDirents(dirents); +})().then(common.mustCall()); + +// Check that mutating options doesn't affect results +(async () => { + const options = { withFileTypes: true }; + const direntsPromise = fs.promises.readdir(readdirDir, options); + options.withFileTypes = false; + assertDirents(await direntsPromise); +})().then(common.mustCall()); + +{ + const options = { recursive: true, withFileTypes: true }; + fs.readdir(readdirDir, options, common.mustSucceed((dirents) => { + assertDirents(dirents); + })); + options.withFileTypes = false; +} + +// Check for correct types when the binding returns unknowns +// const UNKNOWN = constants.UV_DIRENT_UNKNOWN; +// const oldReaddir = binding.readdir; +// process.on('beforeExit', () => { binding.readdir = oldReaddir; }); +// binding.readdir = common.mustCall((path, encoding, types, req, ctx) => { +// if (req) { +// const oldCb = req.oncomplete; +// req.oncomplete = (err, results) => { +// if (err) { +// oldCb(err); +// return; +// } +// results[1] = results[1].map(() => UNKNOWN); +// oldCb(null, results); +// }; +// oldReaddir(path, encoding, types, req); +// } else { +// const results = oldReaddir(path, encoding, types); +// results[1] = results[1].map(() => UNKNOWN); +// return results; +// } +// }, 2); +assertDirents(fs.readdirSync(readdirDir, { withFileTypes: true })); +fs.readdir(readdirDir, { + withFileTypes: true +}, common.mustSucceed((dirents) => { + assertDirents(dirents); +})); + +// Dirent types +for (const method of typeMethods) { + const dirent = new fs.Dirent('foo', types[method]); + for (const testMethod of typeMethods) { + assert.strictEqual(dirent[testMethod](), testMethod === method); + } +}