3131#include " node_stat_watcher.h"
3232#include " permission/permission.h"
3333#include " util-inl.h"
34+ #include " v8-fast-api-calls.h"
3435
3536#include " tracing/trace_event.h"
3637
@@ -57,8 +58,11 @@ namespace fs {
5758
5859using v8::Array;
5960using v8::BigInt;
61+ using v8::CFunction;
6062using v8::Context;
6163using v8::EscapableHandleScope;
64+ using v8::FastApiCallbackOptions;
65+ using v8::FastOneByteString;
6266using v8::Function;
6367using v8::FunctionCallbackInfo;
6468using v8::FunctionTemplate;
@@ -1095,6 +1099,47 @@ static void ExistsSync(const FunctionCallbackInfo<Value>& args) {
10951099 args.GetReturnValue ().Set (err == 0 );
10961100}
10971101
1102+ bool FastExistsSync (v8::Local<v8::Object> recv,
1103+ const FastOneByteString& string,
1104+ // NOLINTNEXTLINE(runtime/references) This is V8 api.
1105+ FastApiCallbackOptions& options) {
1106+ Environment* env = Environment::GetCurrent (recv->GetCreationContextChecked ());
1107+
1108+ MaybeStackBuffer<char > path;
1109+
1110+ path.AllocateSufficientStorage (string.length + 1 );
1111+ memcpy (path.out (), string.data , string.length );
1112+ path.SetLengthAndZeroTerminate (string.length );
1113+
1114+ if (UNLIKELY (!env->permission ()
1115+ ->is_granted (permission::PermissionScope::kFileSystemRead ,
1116+ path.ToStringView ()))) {
1117+ options.fallback = true ;
1118+ return false ;
1119+ }
1120+
1121+ uv_fs_t req;
1122+ auto make = OnScopeLeave ([&req]() { uv_fs_req_cleanup (&req); });
1123+ FS_SYNC_TRACE_BEGIN (access);
1124+ int err = uv_fs_access (nullptr , &req, path.out (), 0 , nullptr );
1125+ FS_SYNC_TRACE_END (access);
1126+
1127+ #ifdef _WIN32
1128+ // In case of an invalid symlink, `uv_fs_access` on win32
1129+ // will **not** return an error and is therefore not enough.
1130+ // Double check with `uv_fs_stat()`.
1131+ if (err == 0 ) {
1132+ FS_SYNC_TRACE_BEGIN (stat);
1133+ err = uv_fs_stat (nullptr , &req, path.out (), nullptr );
1134+ FS_SYNC_TRACE_END (stat);
1135+ }
1136+ #endif // _WIN32
1137+
1138+ return err == 0 ;
1139+ }
1140+
1141+ CFunction fast_exists_sync_ (CFunction::Make(FastExistsSync));
1142+
10981143// Used to speed up module loading. Returns an array [string, boolean]
10991144static void InternalModuleReadJSON (const FunctionCallbackInfo<Value>& args) {
11001145 Environment* env = Environment::GetCurrent (args);
@@ -3364,7 +3409,8 @@ static void CreatePerIsolateProperties(IsolateData* isolate_data,
33643409 SetMethodNoSideEffect (isolate, target, " accessSync" , AccessSync);
33653410 SetMethod (isolate, target, " close" , Close);
33663411 SetMethod (isolate, target, " closeSync" , CloseSync);
3367- SetMethodNoSideEffect (isolate, target, " existsSync" , ExistsSync);
3412+ SetFastMethodNoSideEffect (isolate, target, " existsSync" ,
3413+ ExistsSync, &fast_exists_sync_);
33683414 SetMethod (isolate, target, " open" , Open);
33693415 SetMethod (isolate, target, " openSync" , OpenSync);
33703416 SetMethod (isolate, target, " openFileHandle" , OpenFileHandle);
@@ -3490,6 +3536,8 @@ void RegisterExternalReferences(ExternalReferenceRegistry* registry) {
34903536 registry->Register (Close);
34913537 registry->Register (CloseSync);
34923538 registry->Register (ExistsSync);
3539+ registry->Register (FastExistsSync);
3540+ registry->Register (fast_exists_sync_.GetTypeInfo ());
34933541 registry->Register (Open);
34943542 registry->Register (OpenSync);
34953543 registry->Register (OpenFileHandle);
0 commit comments