From 10cb7e5a020a55e926b726c24d55d8d07dbfa212 Mon Sep 17 00:00:00 2001 From: Yagiz Nizipli Date: Sun, 10 Sep 2023 15:17:37 -0400 Subject: [PATCH] fs: reimplement `accessSync` --- benchmark/fs/bench-accessSync.js | 29 +++++++++++++++++++++++++++++ lib/fs.js | 7 +------ lib/internal/fs/sync.js | 14 +++++++++++++- src/node_file_sync.cc | 28 ++++++++++++++++++++++++++++ src/node_file_sync.h | 1 + 5 files changed, 72 insertions(+), 7 deletions(-) create mode 100644 benchmark/fs/bench-accessSync.js diff --git a/benchmark/fs/bench-accessSync.js b/benchmark/fs/bench-accessSync.js new file mode 100644 index 00000000000000..1f1970c0ce68e0 --- /dev/null +++ b/benchmark/fs/bench-accessSync.js @@ -0,0 +1,29 @@ +'use strict'; + +const common = require('../common'); +const fs = require('fs'); +const tmpdir = require('../../test/common/tmpdir'); +tmpdir.refresh(); + +const paths = [ + __filename, + tmpdir.resolve(`.non-existing-file-${process.pid}`), +]; + +const bench = common.createBenchmark(main, { + n: [1e5], +}); + +function main({ n }) { + bench.start(); + for (let i = 0; i < n; i++) { + for (let j = 0; j < paths.length; j++) { + try { + fs.accessSync(paths[j]); + } catch { + // do nothing + } + } + } + bench.end(n); +} diff --git a/lib/fs.js b/lib/fs.js index d583b74eec8fdc..347f49287a1495 100644 --- a/lib/fs.js +++ b/lib/fs.js @@ -243,12 +243,7 @@ function access(path, mode, callback) { * @returns {void} */ function accessSync(path, mode) { - path = getValidatedPath(path); - mode = getValidMode(mode, 'access'); - - const ctx = { path }; - binding.access(pathModule.toNamespacedPath(path), mode, undefined, ctx); - handleErrorFromBinding(ctx); + syncFs.access(path, mode); } /** diff --git a/lib/internal/fs/sync.js b/lib/internal/fs/sync.js index bc389885414b37..6db208dcc7ab49 100644 --- a/lib/internal/fs/sync.js +++ b/lib/internal/fs/sync.js @@ -1,7 +1,7 @@ 'use strict'; const pathModule = require('path'); -const { handleErrorFromBinding, getValidatedPath, stringToFlags } = require('internal/fs/utils'); +const { handleErrorFromBinding, getValidatedPath, stringToFlags, getValidMode } = require('internal/fs/utils'); const syncBinding = internalBinding('fs_sync'); @@ -32,7 +32,19 @@ function exists(path) { return syncBinding.exists(pathModule.toNamespacedPath(path)); } +function access(path, mode) { + path = getValidatedPath(path); + mode = getValidMode(mode, 'access'); + + const errno = syncBinding.access(pathModule.toNamespacedPath(path), mode); + + if (errno !== undefined) { + handleErrorFromBinding({ errno, syscall: 'access', path }); + } +} + module.exports = { readFileUtf8, exists, + access, }; diff --git a/src/node_file_sync.cc b/src/node_file_sync.cc index c0053d5ff29156..bf51c082273fdd 100644 --- a/src/node_file_sync.cc +++ b/src/node_file_sync.cc @@ -122,6 +122,32 @@ void BindingData::Deserialize(v8::Local context, CHECK_NOT_NULL(binding); } +void BindingData::Access(const FunctionCallbackInfo& args) { + Environment* env = Environment::GetCurrent(args); + Isolate* isolate = env->isolate(); + + const int argc = args.Length(); + CHECK_GE(argc, 2); + + CHECK(args[1]->IsInt32()); + int mode = args[1].As()->Value(); + + BufferValue path(isolate, args[0]); + CHECK_NOT_NULL(*path); + THROW_IF_INSUFFICIENT_PERMISSIONS( + env, permission::PermissionScope::kFileSystemRead, path.ToStringView()); + + uv_fs_t req; + auto make = OnScopeLeave([&req]() { uv_fs_req_cleanup(&req); }); + FS_SYNC_TRACE_BEGIN(access); + uv_fs_access(nullptr, &req, *path, mode, nullptr); + FS_SYNC_TRACE_END(access); + + if (req.result < 0) { + return args.GetReturnValue().Set(int(req.result)); + } +} + bool BindingData::ExistsInternal(const std::string_view path) { uv_fs_t req; auto make = OnScopeLeave([&req]() { uv_fs_req_cleanup(&req); }); @@ -237,6 +263,7 @@ void BindingData::ReadFileUtf8(const FunctionCallbackInfo& args) { void BindingData::CreatePerIsolateProperties(IsolateData* isolate_data, Local target) { Isolate* isolate = isolate_data->isolate(); + SetMethodNoSideEffect(isolate, target, "access", Access); SetFastMethodNoSideEffect(isolate, target, "exists", Exists, &fast_exists_); SetMethodNoSideEffect(isolate, target, "readFileUtf8", ReadFileUtf8); } @@ -251,6 +278,7 @@ void BindingData::CreatePerContextProperties(Local target, void BindingData::RegisterExternalReferences( ExternalReferenceRegistry* registry) { + registry->Register(Access); registry->Register(Exists); registry->Register(FastExists); registry->Register(fast_exists_.GetTypeInfo()); diff --git a/src/node_file_sync.h b/src/node_file_sync.h index 89f0c059ad2d1f..0a4917790d4baf 100644 --- a/src/node_file_sync.h +++ b/src/node_file_sync.h @@ -34,6 +34,7 @@ class BindingData : public SnapshotableObject { static void Exists(const v8::FunctionCallbackInfo& args); static bool FastExists(v8::Local receiver, const v8::FastOneByteString& path); + static void Access(const v8::FunctionCallbackInfo& args); static void ReadFileUtf8(const v8::FunctionCallbackInfo& args); static void CreatePerIsolateProperties(IsolateData* isolate_data,