Skip to content

Commit 8a748c4

Browse files
committed
fs: reimplement accessSync
1 parent 80c845b commit 8a748c4

File tree

5 files changed

+87
-21
lines changed

5 files changed

+87
-21
lines changed

benchmark/fs/bench-accessSync.js

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
'use strict';
2+
3+
const common = require('../common');
4+
const fs = require('fs');
5+
const tmpdir = require('../../test/common/tmpdir');
6+
tmpdir.refresh();
7+
8+
const paths = [
9+
__filename,
10+
tmpdir.resolve(`.non-existing-file-${process.pid}`),
11+
];
12+
13+
const bench = common.createBenchmark(main, {
14+
n: [1e5],
15+
});
16+
17+
function main({ n }) {
18+
bench.start();
19+
for (let i = 0; i < n; i++) {
20+
for (let j = 0; j < paths.length; j++) {
21+
try {
22+
fs.accessSync(paths[j]);
23+
} catch {
24+
// do nothing
25+
}
26+
}
27+
}
28+
bench.end(n);
29+
}

lib/fs.js

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -243,12 +243,7 @@ function access(path, mode, callback) {
243243
* @returns {void}
244244
*/
245245
function accessSync(path, mode) {
246-
path = getValidatedPath(path);
247-
mode = getValidMode(mode, 'access');
248-
249-
const ctx = { path };
250-
binding.access(pathModule.toNamespacedPath(path), mode, undefined, ctx);
251-
handleErrorFromBinding(ctx);
246+
syncFs.access(path, mode);
252247
}
253248

254249
/**

lib/internal/fs/sync.js

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
'use strict';
22

33
const pathModule = require('path');
4-
const { handleErrorFromBinding, getValidatedPath, stringToFlags } = require('internal/fs/utils');
4+
const { handleErrorFromBinding, getValidatedPath, stringToFlags, getValidMode } = require('internal/fs/utils');
55

66
const syncBinding = internalBinding('fs_sync');
77

@@ -32,7 +32,19 @@ function exists(path) {
3232
return syncBinding.exists(pathModule.toNamespacedPath(path));
3333
}
3434

35+
function access(path, mode) {
36+
path = getValidatedPath(path);
37+
mode = getValidMode(mode, 'access');
38+
39+
const errno = syncBinding.access(pathModule.toNamespacedPath(path), mode);
40+
41+
if (errno !== undefined) {
42+
handleErrorFromBinding({ errno, syscall: 'access', path });
43+
}
44+
}
45+
3546
module.exports = {
3647
readFileUtf8,
3748
exists,
49+
access,
3850
};

src/node_file_sync.cc

Lines changed: 41 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
#include "node_constants.h"
21
#include "node_file_sync.h"
32
#include "memory_tracker-inl.h"
43
#include "node_buffer.h"
4+
#include "node_constants.h"
55
#include "node_errors.h"
66
#include "node_external_reference.h"
77
#include "node_file.h"
@@ -27,12 +27,12 @@ namespace fs_sync {
2727
using v8::Array;
2828
using v8::CFunction;
2929
using v8::Context;
30+
using v8::FastOneByteString;
3031
using v8::FunctionCallbackInfo;
3132
using v8::HandleScope;
3233
using v8::Int32;
3334
using v8::Integer;
3435
using v8::Isolate;
35-
using v8::FastOneByteString;
3636
using v8::JustVoid;
3737
using v8::Local;
3838
using v8::Maybe;
@@ -122,23 +122,49 @@ void BindingData::Deserialize(v8::Local<v8::Context> context,
122122
CHECK_NOT_NULL(binding);
123123
}
124124

125+
void BindingData::Access(const FunctionCallbackInfo<Value>& args) {
126+
Environment* env = Environment::GetCurrent(args);
127+
Isolate* isolate = env->isolate();
128+
129+
const int argc = args.Length();
130+
CHECK_GE(argc, 2);
131+
132+
CHECK(args[1]->IsInt32());
133+
int mode = args[1].As<Int32>()->Value();
134+
135+
BufferValue path(isolate, args[0]);
136+
CHECK_NOT_NULL(*path);
137+
THROW_IF_INSUFFICIENT_PERMISSIONS(
138+
env, permission::PermissionScope::kFileSystemRead, path.ToStringView());
139+
140+
uv_fs_t req;
141+
auto make = OnScopeLeave([&req]() { uv_fs_req_cleanup(&req); });
142+
FS_SYNC_TRACE_BEGIN(access);
143+
uv_fs_access(nullptr, &req, *path, mode, nullptr);
144+
FS_SYNC_TRACE_END(access);
145+
146+
if (req.result < 0) {
147+
return args.GetReturnValue().Set(int(req.result));
148+
}
149+
}
150+
125151
bool BindingData::ExistsInternal(const std::string_view path) {
126152
uv_fs_t req;
127-
auto make = OnScopeLeave([&req]() { uv_fs_req_cleanup(&req); });
153+
auto make = OnScopeLeave([&req]() { uv_fs_req_cleanup(&req); });
128154
FS_SYNC_TRACE_BEGIN(access);
129155
int err = uv_fs_access(nullptr, &req, path.data(), F_OK, nullptr);
130156
FS_SYNC_TRACE_END(access);
131157

132158
#ifdef _WIN32
133-
// In case of an invalid symlink, `binding.access()` on win32
134-
// will **not** return an error and is therefore not enough.
135-
// Double check with `stat()`.
136-
if (err != 0) {
137-
FS_SYNC_TRACE_BEGIN(stat);
138-
err = uv_fs_stat(nullptr, &req, path.data, nullptr);
139-
FS_SYNC_TRACE_END(stat);
140-
}
141-
#endif // _WIN32
159+
// In case of an invalid symlink, `binding.access()` on win32
160+
// will **not** return an error and is therefore not enough.
161+
// Double check with `stat()`.
162+
if (err != 0) {
163+
FS_SYNC_TRACE_BEGIN(stat);
164+
err = uv_fs_stat(nullptr, &req, path.data, nullptr);
165+
FS_SYNC_TRACE_END(stat);
166+
}
167+
#endif // _WIN32
142168

143169
return err == 0;
144170
}
@@ -159,7 +185,7 @@ void BindingData::Exists(const FunctionCallbackInfo<Value>& args) {
159185
}
160186

161187
bool BindingData::FastExists(Local<Value> receiver,
162-
const FastOneByteString& path) {
188+
const FastOneByteString& path) {
163189
// TODO(@anonrig): Add "THROW_IF_INSUFFICIENT_PERMISSIONS"
164190
return ExistsInternal(std::string_view(path.data, path.length));
165191
}
@@ -237,6 +263,7 @@ void BindingData::ReadFileUtf8(const FunctionCallbackInfo<Value>& args) {
237263
void BindingData::CreatePerIsolateProperties(IsolateData* isolate_data,
238264
Local<ObjectTemplate> target) {
239265
Isolate* isolate = isolate_data->isolate();
266+
SetMethodNoSideEffect(isolate, target, "access", Access);
240267
SetFastMethodNoSideEffect(isolate, target, "exists", Exists, &fast_exists_);
241268
SetMethodNoSideEffect(isolate, target, "readFileUtf8", ReadFileUtf8);
242269
}
@@ -251,6 +278,7 @@ void BindingData::CreatePerContextProperties(Local<Object> target,
251278

252279
void BindingData::RegisterExternalReferences(
253280
ExternalReferenceRegistry* registry) {
281+
registry->Register(Access);
254282
registry->Register(Exists);
255283
registry->Register(FastExists);
256284
registry->Register(fast_exists_.GetTypeInfo());

src/node_file_sync.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,10 @@ class BindingData : public SnapshotableObject {
3232
SET_MEMORY_INFO_NAME(BindingData)
3333

3434
static void Exists(const v8::FunctionCallbackInfo<v8::Value>& args);
35-
static bool FastExists(v8::Local<v8::Value> receiver, const v8::FastOneByteString& path);
35+
static bool FastExists(v8::Local<v8::Value> receiver,
36+
const v8::FastOneByteString& path);
3637

38+
static void Access(const v8::FunctionCallbackInfo<v8::Value>& args);
3739
static void ReadFileUtf8(const v8::FunctionCallbackInfo<v8::Value>& args);
3840

3941
static void CreatePerIsolateProperties(IsolateData* isolate_data,

0 commit comments

Comments
 (0)