From b026c0e4c07502b5a88677bc903c0c73314106ac Mon Sep 17 00:00:00 2001 From: Dan Fabulich Date: Mon, 27 Jun 2016 22:29:11 -0700 Subject: [PATCH 1/3] fs: make existsSync faster by not throwing The existing implementation throws ignored exceptions, which is slow. The new implementation returns a simple boolean without throwing. --- lib/fs.js | 8 +++----- src/node_file.cc | 26 ++++++++++++++++++++++++++ 2 files changed, 29 insertions(+), 5 deletions(-) diff --git a/lib/fs.js b/lib/fs.js index 2fc22b1bddecc0..c6dc8f7759c509 100644 --- a/lib/fs.js +++ b/lib/fs.js @@ -259,13 +259,11 @@ fs.exists = function(path, callback) { }; fs.existsSync = function(path) { - try { - nullCheck(path); - binding.stat(pathModule._makeLong(path)); - return true; - } catch (e) { + if (String(path).indexOf('\u0000') !== -1) { return false; } + + return binding.accessibleSync(pathModule._makeLong(path), fs.F_OK); }; fs.readFile = function(path, options, callback_) { diff --git a/src/node_file.cc b/src/node_file.cc index 77d11756a2dbe5..3002b1a03ed9ae 100644 --- a/src/node_file.cc +++ b/src/node_file.cc @@ -27,6 +27,7 @@ namespace node { using v8::Array; +using v8::Boolean; using v8::Context; using v8::EscapableHandleScope; using v8::Function; @@ -399,6 +400,30 @@ static void Access(const FunctionCallbackInfo& args) { } } +static void AccessibleSync(const FunctionCallbackInfo& args) { + Environment* env = Environment::GetCurrent(args.GetIsolate()); + HandleScope scope(env->isolate()); + + if (args.Length() < 2) + return TYPE_ERROR("path and mode are required"); + if (!args[1]->IsInt32()) + return TYPE_ERROR("mode must be an integer"); + + BufferValue path(env->isolate(), args[0]); + ASSERT_PATH(path) + + int mode = static_cast(args[1]->Int32Value()); + + fs_req_wrap req_wrap; + env->PrintSyncTrace(); + int err = uv_fs_access( + env->event_loop(), &req_wrap.req, *path, mode, nullptr); + + bool failed = err < 0; + + args.GetReturnValue().Set(Boolean::New(env->isolate(), !failed)); +} + static void Close(const FunctionCallbackInfo& args) { Environment* env = Environment::GetCurrent(args); @@ -1448,6 +1473,7 @@ void InitFs(Local target, env->NewFunctionTemplate(FSInitialize)->GetFunction()); env->SetMethod(target, "access", Access); + env->SetMethod(target, "accessibleSync", AccessibleSync); env->SetMethod(target, "close", Close); env->SetMethod(target, "open", Open); env->SetMethod(target, "read", Read); From 19689e4369ef2a1faf388ed3add59d8fb1a98e85 Mon Sep 17 00:00:00 2001 From: Dan Fabulich Date: Mon, 27 Jun 2016 22:30:37 -0700 Subject: [PATCH 2/3] fs: make exists faster by using access access is faster than stat, because we don't have to return the actual stat results. --- lib/fs.js | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/lib/fs.js b/lib/fs.js index c6dc8f7759c509..0c75f4d6b1de1b 100644 --- a/lib/fs.js +++ b/lib/fs.js @@ -250,10 +250,8 @@ fs.accessSync = function(path, mode) { fs.exists = function(path, callback) { if (!nullCheck(path, cb)) return; - var req = new FSReqWrap(); - req.oncomplete = cb; - binding.stat(pathModule._makeLong(path), req); - function cb(err, stats) { + fs.access(path, fs.F_OK, cb); + function cb(err) { if (callback) callback(err ? false : true); } }; From d255e0fe6960dc6ae8401de13dc9898f9167c080 Mon Sep 17 00:00:00 2001 From: Dan Fabulich Date: Mon, 27 Jun 2016 22:31:20 -0700 Subject: [PATCH 3/3] fs: undeprecate existsSync There's no alternative method to use that doesn't throw an exception when the file doesn't exist. --- doc/api/fs.md | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/doc/api/fs.md b/doc/api/fs.md index 40b8a990631271..3cac285dec7903 100644 --- a/doc/api/fs.md +++ b/doc/api/fs.md @@ -597,8 +597,9 @@ deprecated: v1.0.0 * `path` {String | Buffer} * `callback` {Function} -Test whether or not the given path exists by checking with the file system. -Then call the `callback` argument with either true or false. Example: +Test whether or not the given path exists and is accessible by checking +with the file system. Then call the `callback` argument with either +true or false. Example: ```js fs.exists('/etc/passwd', (exists) => { @@ -615,16 +616,12 @@ non-existent. ## fs.existsSync(path) -> Stability: 0 - Deprecated: Use [`fs.statSync()`][] or [`fs.accessSync()`][] -> instead. - * `path` {String | Buffer} Synchronous version of [`fs.exists()`][]. -Returns `true` if the file exists, `false` otherwise. +Returns `true` if the file exists and is accessible, `false` otherwise. ## fs.fchmod(fd, mode, callback)