summaryrefslogtreecommitdiff
path: root/src/node_file.cc
diff options
context:
space:
mode:
authorBryan English <bryan@bryanenglish.com>2018-07-27 19:29:32 -0700
committerBryan English <bryan@bryanenglish.com>2018-08-13 19:18:45 -0700
commitc7944a7a7bd92a446ea81d774ccad31e0e7c8a3f (patch)
treec7b86a281f2af282e080b34965debcea28caf2b7 /src/node_file.cc
parent78584b64d88c0567c46e3cf7bae42aa73927df40 (diff)
downloadandroid-node-v8-c7944a7a7bd92a446ea81d774ccad31e0e7c8a3f.tar.gz
android-node-v8-c7944a7a7bd92a446ea81d774ccad31e0e7c8a3f.tar.bz2
android-node-v8-c7944a7a7bd92a446ea81d774ccad31e0e7c8a3f.zip
fs: readdir optionally returning type information
readdir and readdirSync now have a "withFileTypes" option, which, when enabled, provides an array of DirectoryEntry objects, similar to Stats objects, which have the filename and the type information. Refs: https://github.com/nodejs/node/issues/15699 PR-URL: https://github.com/nodejs/node/pull/22020 Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com> Reviewed-By: Roman Reiss <me@silverwind.io> Reviewed-By: John-David Dalton <john.david.dalton@gmail.com>
Diffstat (limited to 'src/node_file.cc')
-rw-r--r--src/node_file.cc217
1 files changed, 174 insertions, 43 deletions
diff --git a/src/node_file.cc b/src/node_file.cc
index 714dec157b..fb976a31a5 100644
--- a/src/node_file.cc
+++ b/src/node_file.cc
@@ -561,51 +561,139 @@ void AfterScanDir(uv_fs_t* req) {
FSReqBase* req_wrap = FSReqBase::from_req(req);
FSReqAfterScope after(req_wrap, req);
- if (after.Proceed()) {
- Environment* env = req_wrap->env();
- Local<Value> error;
- int r;
- Local<Array> names = Array::New(env->isolate(), 0);
- Local<Function> fn = env->push_values_to_array_function();
- Local<Value> name_argv[NODE_PUSH_VAL_TO_ARRAY_MAX];
- size_t name_idx = 0;
+ if (!after.Proceed()) {
+ return;
+ }
+ Environment* env = req_wrap->env();
+ Local<Value> error;
+ int r;
+ Local<Array> names = Array::New(env->isolate(), 0);
+ Local<Function> fn = env->push_values_to_array_function();
+ Local<Value> name_argv[NODE_PUSH_VAL_TO_ARRAY_MAX];
+ size_t name_idx = 0;
- for (int i = 0; ; i++) {
- uv_dirent_t ent;
+ for (int i = 0; ; i++) {
+ uv_dirent_t ent;
- r = uv_fs_scandir_next(req, &ent);
- if (r == UV_EOF)
- break;
- if (r != 0) {
- return req_wrap->Reject(
- UVException(r, nullptr, req_wrap->syscall(),
- static_cast<const char*>(req->path)));
+ r = uv_fs_scandir_next(req, &ent);
+ if (r == UV_EOF)
+ break;
+ if (r != 0) {
+ return req_wrap->Reject(
+ UVException(r, nullptr, req_wrap->syscall(),
+ static_cast<const char*>(req->path)));
+ }
+
+ MaybeLocal<Value> filename =
+ StringBytes::Encode(env->isolate(),
+ ent.name,
+ req_wrap->encoding(),
+ &error);
+ if (filename.IsEmpty())
+ return req_wrap->Reject(error);
+
+ name_argv[name_idx++] = filename.ToLocalChecked();
+
+ if (name_idx >= arraysize(name_argv)) {
+ MaybeLocal<Value> ret = fn->Call(env->context(), names, name_idx,
+ name_argv);
+ if (ret.IsEmpty()) {
+ return;
}
+ name_idx = 0;
+ }
+ }
- MaybeLocal<Value> filename =
- StringBytes::Encode(env->isolate(),
- ent.name,
- req_wrap->encoding(),
- &error);
- if (filename.IsEmpty())
- return req_wrap->Reject(error);
+ if (name_idx > 0) {
+ fn->Call(env->context(), names, name_idx, name_argv)
+ .ToLocalChecked();
+ }
- name_argv[name_idx++] = filename.ToLocalChecked();
+ req_wrap->Resolve(names);
+}
- if (name_idx >= arraysize(name_argv)) {
- fn->Call(env->context(), names, name_idx, name_argv)
- .ToLocalChecked();
- name_idx = 0;
+void AfterScanDirWithTypes(uv_fs_t* req) {
+ FSReqBase* req_wrap = FSReqBase::from_req(req);
+ FSReqAfterScope after(req_wrap, req);
+
+ if (!after.Proceed()) {
+ return;
+ }
+
+ Environment* env = req_wrap->env();
+ Local<Value> error;
+ int r;
+ Local<Array> names = Array::New(env->isolate(), 0);
+ Local<Function> fn = env->push_values_to_array_function();
+ Local<Value> name_argv[NODE_PUSH_VAL_TO_ARRAY_MAX];
+ size_t name_idx = 0;
+ Local<Value> types = Array::New(env->isolate(), 0);
+ Local<Value> type_argv[NODE_PUSH_VAL_TO_ARRAY_MAX];
+ size_t type_idx = 0;
+
+ for (int i = 0; ; i++) {
+ uv_dirent_t ent;
+
+ r = uv_fs_scandir_next(req, &ent);
+ if (r == UV_EOF)
+ break;
+ if (r != 0) {
+ return req_wrap->Reject(
+ UVException(r, nullptr, req_wrap->syscall(),
+ static_cast<const char*>(req->path)));
+ }
+
+ MaybeLocal<Value> filename =
+ StringBytes::Encode(env->isolate(),
+ ent.name,
+ req_wrap->encoding(),
+ &error);
+ if (filename.IsEmpty())
+ return req_wrap->Reject(error);
+
+ name_argv[name_idx++] = filename.ToLocalChecked();
+
+ if (name_idx >= arraysize(name_argv)) {
+ MaybeLocal<Value> ret = fn->Call(env->context(), names, name_idx,
+ name_argv);
+ if (ret.IsEmpty()) {
+ return;
}
+ name_idx = 0;
}
- if (name_idx > 0) {
- fn->Call(env->context(), names, name_idx, name_argv)
- .ToLocalChecked();
+ type_argv[type_idx++] = Integer::New(env->isolate(), ent.type);
+
+ if (type_idx >= arraysize(type_argv)) {
+ MaybeLocal<Value> ret = fn->Call(env->context(), types, type_idx,
+ type_argv);
+ if (ret.IsEmpty()) {
+ return;
+ }
+ type_idx = 0;
}
+ }
- req_wrap->Resolve(names);
+ if (name_idx > 0) {
+ MaybeLocal<Value> ret = fn->Call(env->context(), names, name_idx,
+ name_argv);
+ if (ret.IsEmpty()) {
+ return;
+ }
+ }
+
+ if (type_idx > 0) {
+ MaybeLocal<Value> ret = fn->Call(env->context(), types, type_idx,
+ type_argv);
+ if (ret.IsEmpty()) {
+ return;
+ }
}
+
+ Local<Array> result = Array::New(env->isolate(), 2);
+ result->Set(0, names);
+ result->Set(1, types);
+ req_wrap->Resolve(result);
}
@@ -1372,15 +1460,22 @@ static void ReadDir(const FunctionCallbackInfo<Value>& args) {
const enum encoding encoding = ParseEncoding(env->isolate(), args[1], UTF8);
- FSReqBase* req_wrap_async = GetReqWrap(env, args[2]);
- if (req_wrap_async != nullptr) { // readdir(path, encoding, req)
- AsyncCall(env, req_wrap_async, args, "scandir", encoding, AfterScanDir,
- uv_fs_scandir, *path, 0 /*flags*/);
- } else { // readdir(path, encoding, undefined, ctx)
- CHECK_EQ(argc, 4);
+ bool with_types = args[2]->BooleanValue();
+
+ FSReqBase* req_wrap_async = GetReqWrap(env, args[3]);
+ if (req_wrap_async != nullptr) { // readdir(path, encoding, withTypes, req)
+ if (with_types) {
+ AsyncCall(env, req_wrap_async, args, "scandir", encoding,
+ AfterScanDirWithTypes, uv_fs_scandir, *path, 0 /*flags*/);
+ } else {
+ AsyncCall(env, req_wrap_async, args, "scandir", encoding,
+ AfterScanDir, uv_fs_scandir, *path, 0 /*flags*/);
+ }
+ } else { // readdir(path, encoding, withTypes, undefined, ctx)
+ CHECK_EQ(argc, 5);
FSReqWrapSync req_wrap_sync;
FS_SYNC_TRACE_BEGIN(readdir);
- int err = SyncCall(env, args[3], &req_wrap_sync, "scandir",
+ int err = SyncCall(env, args[4], &req_wrap_sync, "scandir",
uv_fs_scandir, *path, 0 /*flags*/);
FS_SYNC_TRACE_END(readdir);
if (err < 0) {
@@ -1394,6 +1489,14 @@ static void ReadDir(const FunctionCallbackInfo<Value>& args) {
Local<Value> name_v[NODE_PUSH_VAL_TO_ARRAY_MAX];
size_t name_idx = 0;
+ Local<Value> types;
+ Local<Value> type_v[NODE_PUSH_VAL_TO_ARRAY_MAX];
+ size_t type_idx;
+ if (with_types) {
+ types = Array::New(env->isolate(), 0);
+ type_idx = 0;
+ }
+
for (int i = 0; ; i++) {
uv_dirent_t ent;
@@ -1401,7 +1504,7 @@ static void ReadDir(const FunctionCallbackInfo<Value>& args) {
if (r == UV_EOF)
break;
if (r != 0) {
- Local<Object> ctx = args[3].As<Object>();
+ Local<Object> ctx = args[4].As<Object>();
ctx->Set(env->context(), env->errno_string(),
Integer::New(env->isolate(), r)).FromJust();
ctx->Set(env->context(), env->syscall_string(),
@@ -1414,8 +1517,9 @@ static void ReadDir(const FunctionCallbackInfo<Value>& args) {
ent.name,
encoding,
&error);
+
if (filename.IsEmpty()) {
- Local<Object> ctx = args[3].As<Object>();
+ Local<Object> ctx = args[4].As<Object>();
ctx->Set(env->context(), env->error_string(), error).FromJust();
return;
}
@@ -1430,6 +1534,19 @@ static void ReadDir(const FunctionCallbackInfo<Value>& args) {
}
name_idx = 0;
}
+
+ if (with_types) {
+ type_v[type_idx++] = Integer::New(env->isolate(), ent.type);
+
+ if (type_idx >= arraysize(type_v)) {
+ MaybeLocal<Value> ret = fn->Call(env->context(), types, type_idx,
+ type_v);
+ if (ret.IsEmpty()) {
+ return;
+ }
+ type_idx = 0;
+ }
+ }
}
if (name_idx > 0) {
@@ -1439,7 +1556,21 @@ static void ReadDir(const FunctionCallbackInfo<Value>& args) {
}
}
- args.GetReturnValue().Set(names);
+ if (with_types && type_idx > 0) {
+ MaybeLocal<Value> ret = fn->Call(env->context(), types, type_idx, type_v);
+ if (ret.IsEmpty()) {
+ return;
+ }
+ }
+
+ if (with_types) {
+ Local<Array> result = Array::New(env->isolate(), 2);
+ result->Set(0, names);
+ result->Set(1, types);
+ args.GetReturnValue().Set(result);
+ } else {
+ args.GetReturnValue().Set(names);
+ }
}
}