diff options
author | Jeremiah Senkpiel <fishrock123@rocketmail.com> | 2019-08-28 03:14:27 +0300 |
---|---|---|
committer | Jeremiah Senkpiel <fishrock123@rocketmail.com> | 2019-10-08 20:34:48 +0300 |
commit | cbd8d715b2286e5726e6988921f5c870cbf74127 (patch) | |
tree | 20c878fd9d7882f2a5b43718a0b3daad4a9a0255 /src/node_file.cc | |
parent | 064e111515185529b6f943dc66929440557fd609 (diff) |
fs: introduce `opendir()` and `fs.Dir`
This adds long-requested methods for asynchronously interacting and
iterating through directory entries by using `uv_fs_opendir`,
`uv_fs_readdir`, and `uv_fs_closedir`.
`fs.opendir()` and friends return an `fs.Dir`, which contains methods
for doing reads and cleanup. `fs.Dir` also has the async iterator
symbol exposed.
The `read()` method and friends only return `fs.Dirent`s for this API.
Having a entry type or doing a `stat` call is deemed to be necessary in
the majority of cases, so just returning dirents seems like the logical
choice for a new api.
Reading when there are no more entries returns `null` instead of a
dirent. However the async iterator hides that (and does automatic
cleanup).
The code lives in separate files from the rest of fs, this is done
partially to prevent over-pollution of those (already very large)
files, but also in the case of js allows loading into `fsPromises`.
Due to async_hooks, this introduces a new handle type of `DIRHANDLE`.
This PR does not attempt to make complete optimization of
this feature. Notable future improvements include:
- Moving promise work into C++ land like FileHandle.
- Possibly adding `readv()` to do multi-entry directory reads.
- Aliasing `fs.readdir` to `fs.scandir` and doing a deprecation.
Refs: https://github.com/nodejs/node-v0.x-archive/issues/388
Refs: https://github.com/nodejs/node/issues/583
Refs: https://github.com/libuv/libuv/pull/2057
PR-URL: https://github.com/nodejs/node/pull/29349
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: David Carlier <devnexen@gmail.com>
Diffstat (limited to 'src/node_file.cc')
-rw-r--r-- | src/node_file.cc | 90 |
1 files changed, 0 insertions, 90 deletions
diff --git a/src/node_file.cc b/src/node_file.cc index 195757f43f3..8b6a90989f8 100644 --- a/src/node_file.cc +++ b/src/node_file.cc @@ -52,11 +52,9 @@ namespace node { namespace fs { using v8::Array; -using v8::BigUint64Array; using v8::Context; using v8::DontDelete; using v8::EscapableHandleScope; -using v8::Float64Array; using v8::Function; using v8::FunctionCallbackInfo; using v8::FunctionTemplate; @@ -678,94 +676,6 @@ void AfterScanDirWithTypes(uv_fs_t* req) { req_wrap->Resolve(result); } - -// This class is only used on sync fs calls. -// For async calls FSReqCallback is used. -class FSReqWrapSync { - public: - FSReqWrapSync() = default; - ~FSReqWrapSync() { uv_fs_req_cleanup(&req); } - uv_fs_t req; - - FSReqWrapSync(const FSReqWrapSync&) = delete; - FSReqWrapSync& operator=(const FSReqWrapSync&) = delete; -}; - -// Returns nullptr if the operation fails from the start. -template <typename Func, typename... Args> -inline FSReqBase* AsyncDestCall(Environment* env, - FSReqBase* req_wrap, - const FunctionCallbackInfo<Value>& args, - const char* syscall, const char* dest, size_t len, - enum encoding enc, uv_fs_cb after, Func fn, Args... fn_args) { - CHECK_NOT_NULL(req_wrap); - req_wrap->Init(syscall, dest, len, enc); - int err = req_wrap->Dispatch(fn, fn_args..., after); - if (err < 0) { - uv_fs_t* uv_req = req_wrap->req(); - uv_req->result = err; - uv_req->path = nullptr; - after(uv_req); // after may delete req_wrap if there is an error - req_wrap = nullptr; - } else { - req_wrap->SetReturnValue(args); - } - - return req_wrap; -} - -// Returns nullptr if the operation fails from the start. -template <typename Func, typename... Args> -inline FSReqBase* AsyncCall(Environment* env, - FSReqBase* req_wrap, - const FunctionCallbackInfo<Value>& args, - const char* syscall, enum encoding enc, - uv_fs_cb after, Func fn, Args... fn_args) { - return AsyncDestCall(env, req_wrap, args, - syscall, nullptr, 0, enc, - after, fn, fn_args...); -} - -// Template counterpart of SYNC_CALL, except that it only puts -// the error number and the syscall in the context instead of -// creating an error in the C++ land. -// ctx must be checked using value->IsObject() before being passed. -template <typename Func, typename... Args> -inline int SyncCall(Environment* env, Local<Value> ctx, FSReqWrapSync* req_wrap, - const char* syscall, Func fn, Args... args) { - env->PrintSyncTrace(); - int err = fn(env->event_loop(), &(req_wrap->req), args..., nullptr); - if (err < 0) { - Local<Context> context = env->context(); - Local<Object> ctx_obj = ctx.As<Object>(); - Isolate* isolate = env->isolate(); - ctx_obj->Set(context, - env->errno_string(), - Integer::New(isolate, err)).Check(); - ctx_obj->Set(context, - env->syscall_string(), - OneByteString(isolate, syscall)).Check(); - } - return err; -} - -// TODO(addaleax): Currently, callers check the return value and assume -// that nullptr indicates a synchronous call, rather than a failure. -// Failure conditions should be disambiguated and handled appropriately. -inline FSReqBase* GetReqWrap(Environment* env, Local<Value> value, - bool use_bigint = false) { - if (value->IsObject()) { - return Unwrap<FSReqBase>(value.As<Object>()); - } else if (value->StrictEquals(env->fs_use_promises_symbol())) { - if (use_bigint) { - return FSReqPromise<AliasedBigUint64Array>::New(env, use_bigint); - } else { - return FSReqPromise<AliasedFloat64Array>::New(env, use_bigint); - } - } - return nullptr; -} - void Access(const FunctionCallbackInfo<Value>& args) { Environment* env = Environment::GetCurrent(args); Isolate* isolate = env->isolate(); |