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 {
2727using v8::Array;
2828using v8::CFunction;
2929using v8::Context;
30+ using v8::FastOneByteString;
3031using v8::FunctionCallbackInfo;
3132using v8::HandleScope;
3233using v8::Int32;
3334using v8::Integer;
3435using v8::Isolate;
35- using v8::FastOneByteString;
3636using v8::JustVoid;
3737using v8::Local;
3838using 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+
125151bool 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
161187bool 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) {
237263void 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
252279void BindingData::RegisterExternalReferences (
253280 ExternalReferenceRegistry* registry) {
281+ registry->Register (Access);
254282 registry->Register (Exists);
255283 registry->Register (FastExists);
256284 registry->Register (fast_exists_.GetTypeInfo ());
0 commit comments