Skip to content

Commit 06aa4b9

Browse files
anonrigtargos
authored andcommitted
fs: improve error performance of readdirSync
PR-URL: #50131 Reviewed-By: Matteo Collina <[email protected]> Reviewed-By: Geoffrey Booth <[email protected]>
1 parent 0ddb87e commit 06aa4b9

File tree

5 files changed

+28
-35
lines changed

5 files changed

+28
-35
lines changed

lib/fs.js

+11-11
Original file line numberDiff line numberDiff line change
@@ -1408,17 +1408,16 @@ function readdirSyncRecursive(basePath, options) {
14081408
const readdirResults = [];
14091409
const pathsQueue = [basePath];
14101410

1411-
const ctx = { path: basePath };
14121411
function read(path) {
1413-
ctx.path = path;
14141412
const readdirResult = binding.readdir(
14151413
pathModule.toNamespacedPath(path),
14161414
encoding,
14171415
withFileTypes,
1418-
undefined,
1419-
ctx,
14201416
);
1421-
handleErrorFromBinding(ctx);
1417+
1418+
if (readdirResult === undefined) {
1419+
return;
1420+
}
14221421

14231422
if (withFileTypes) {
14241423
// Calling `readdir` with `withFileTypes=true`, the result is an array of arrays.
@@ -1517,12 +1516,13 @@ function readdirSync(path, options) {
15171516
return readdirSyncRecursive(path, options);
15181517
}
15191518

1520-
const ctx = { path };
1521-
const result = binding.readdir(pathModule.toNamespacedPath(path),
1522-
options.encoding, !!options.withFileTypes,
1523-
undefined, ctx);
1524-
handleErrorFromBinding(ctx);
1525-
return options.withFileTypes ? getDirents(path, result) : result;
1519+
const result = binding.readdir(
1520+
pathModule.toNamespacedPath(path),
1521+
options.encoding,
1522+
!!options.withFileTypes,
1523+
);
1524+
1525+
return result !== undefined && options.withFileTypes ? getDirents(path, result) : result;
15261526
}
15271527

15281528
/**

src/node_file.cc

+11-18
Original file line numberDiff line numberDiff line change
@@ -1926,8 +1926,8 @@ static void ReadDir(const FunctionCallbackInfo<Value>& args) {
19261926

19271927
bool with_types = args[2]->IsTrue();
19281928

1929-
FSReqBase* req_wrap_async = GetReqWrap(args, 3);
1930-
if (req_wrap_async != nullptr) { // readdir(path, encoding, withTypes, req)
1929+
if (argc > 3) { // readdir(path, encoding, withTypes, req)
1930+
FSReqBase* req_wrap_async = GetReqWrap(args, 3);
19311931
req_wrap_async->set_with_file_types(with_types);
19321932
FS_ASYNC_TRACE_BEGIN1(
19331933
UV_FS_SCANDIR, req_wrap_async, "path", TRACE_STR_COPY(*path))
@@ -1940,18 +1940,16 @@ static void ReadDir(const FunctionCallbackInfo<Value>& args) {
19401940
uv_fs_scandir,
19411941
*path,
19421942
0 /*flags*/);
1943-
} else { // readdir(path, encoding, withTypes, undefined, ctx)
1944-
CHECK_EQ(argc, 5);
1945-
FSReqWrapSync req_wrap_sync;
1943+
} else { // readdir(path, encoding, withTypes)
1944+
FSReqWrapSync req_wrap_sync("scandir", *path);
19461945
FS_SYNC_TRACE_BEGIN(readdir);
1947-
int err = SyncCall(env, args[4], &req_wrap_sync, "scandir",
1948-
uv_fs_scandir, *path, 0 /*flags*/);
1946+
int err = SyncCallAndThrowOnError(
1947+
env, &req_wrap_sync, uv_fs_scandir, *path, 0 /*flags*/);
19491948
FS_SYNC_TRACE_END(readdir);
1950-
if (err < 0) {
1951-
return; // syscall failed, no need to continue, error info is in ctx
1949+
if (is_uv_error(err)) {
1950+
return;
19521951
}
19531952

1954-
CHECK_GE(req_wrap_sync.req.result, 0);
19551953
int r;
19561954
std::vector<Local<Value>> name_v;
19571955
std::vector<Local<Value>> type_v;
@@ -1962,12 +1960,8 @@ static void ReadDir(const FunctionCallbackInfo<Value>& args) {
19621960
r = uv_fs_scandir_next(&(req_wrap_sync.req), &ent);
19631961
if (r == UV_EOF)
19641962
break;
1965-
if (r != 0) {
1966-
Local<Object> ctx = args[4].As<Object>();
1967-
ctx->Set(env->context(), env->errno_string(),
1968-
Integer::New(isolate, r)).Check();
1969-
ctx->Set(env->context(), env->syscall_string(),
1970-
OneByteString(isolate, "readdir")).Check();
1963+
if (is_uv_error(r)) {
1964+
env->ThrowUVException(r, "scandir", nullptr, *path);
19711965
return;
19721966
}
19731967

@@ -1978,8 +1972,7 @@ static void ReadDir(const FunctionCallbackInfo<Value>& args) {
19781972
&error);
19791973

19801974
if (filename.IsEmpty()) {
1981-
Local<Object> ctx = args[4].As<Object>();
1982-
ctx->Set(env->context(), env->error_string(), error).Check();
1975+
isolate->ThrowException(error);
19831976
return;
19841977
}
19851978

test/parallel/test-fs-readdir-types.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ tmpdir.refresh();
2929

3030
// Create the necessary files
3131
files.forEach(function(currentFile) {
32-
fs.closeSync(fs.openSync(`${readdirDir}/${currentFile}`, 'w'));
32+
fs.writeFileSync(`${readdirDir}/${currentFile}`, '', 'utf8');
3333
});
3434

3535

@@ -95,7 +95,7 @@ binding.readdir = common.mustCall((path, encoding, types, req, ctx) => {
9595
};
9696
oldReaddir(path, encoding, types, req);
9797
} else {
98-
const results = oldReaddir(path, encoding, types, req, ctx);
98+
const results = oldReaddir(path, encoding, types);
9999
results[1] = results[1].map(() => UNKNOWN);
100100
return results;
101101
}

test/parallel/test-repl-underscore.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -180,9 +180,9 @@ function testError() {
180180
/^Uncaught Error: ENOENT: no such file or directory, scandir '.*nonexistent\?'/,
181181
/Object\.readdirSync/,
182182
/^ {2}errno: -(2|4058),$/,
183-
" syscall: 'scandir',",
184183
" code: 'ENOENT',",
185-
" path: '/nonexistent?'",
184+
" syscall: 'scandir',",
185+
/^ {2}path: '*'/,
186186
'}',
187187
"'ENOENT'",
188188
"'scandir'",

typings/internalBinding/fs.d.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -166,8 +166,8 @@ declare namespace InternalFSBinding {
166166
function readdir(path: StringOrBuffer, encoding: unknown, withFileTypes: true, req: FSReqCallback<[string[], number[]]>): void;
167167
function readdir(path: StringOrBuffer, encoding: unknown, withFileTypes: false, req: FSReqCallback<string[]>): void;
168168
function readdir(path: StringOrBuffer, encoding: unknown, withFileTypes: boolean, req: undefined, ctx: FSSyncContext): string[] | [string[], number[]];
169-
function readdir(path: StringOrBuffer, encoding: unknown, withFileTypes: true, req: undefined, ctx: FSSyncContext): [string[], number[]];
170-
function readdir(path: StringOrBuffer, encoding: unknown, withFileTypes: false, req: undefined, ctx: FSSyncContext): string[];
169+
function readdir(path: StringOrBuffer, encoding: unknown, withFileTypes: true): [string[], number[]];
170+
function readdir(path: StringOrBuffer, encoding: unknown, withFileTypes: false): string[];
171171
function readdir(path: StringOrBuffer, encoding: unknown, withFileTypes: boolean, usePromises: typeof kUsePromises): Promise<string[] | [string[], number[]]>;
172172
function readdir(path: StringOrBuffer, encoding: unknown, withFileTypes: true, usePromises: typeof kUsePromises): Promise<[string[], number[]]>;
173173
function readdir(path: StringOrBuffer, encoding: unknown, withFileTypes: false, usePromises: typeof kUsePromises): Promise<string[]>;

0 commit comments

Comments
 (0)