| File: | out/../src/node_dir.cc |
| Warning: | line 345, column 31 Potential leak of memory pointed to by 'handle' |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
| 1 | #include "node_dir.h" | |||
| 2 | #include "node_external_reference.h" | |||
| 3 | #include "node_file-inl.h" | |||
| 4 | #include "node_process-inl.h" | |||
| 5 | #include "memory_tracker-inl.h" | |||
| 6 | #include "util.h" | |||
| 7 | ||||
| 8 | #include "tracing/trace_event.h" | |||
| 9 | ||||
| 10 | #include "string_bytes.h" | |||
| 11 | ||||
| 12 | #include <fcntl.h> | |||
| 13 | #include <sys/types.h> | |||
| 14 | #include <sys/stat.h> | |||
| 15 | #include <cstring> | |||
| 16 | #include <cerrno> | |||
| 17 | #include <climits> | |||
| 18 | ||||
| 19 | #include <memory> | |||
| 20 | ||||
| 21 | namespace node { | |||
| 22 | ||||
| 23 | namespace fs_dir { | |||
| 24 | ||||
| 25 | using fs::FSReqAfterScope; | |||
| 26 | using fs::FSReqBase; | |||
| 27 | using fs::FSReqWrapSync; | |||
| 28 | using fs::GetReqWrap; | |||
| 29 | ||||
| 30 | using v8::Array; | |||
| 31 | using v8::Context; | |||
| 32 | using v8::FunctionCallbackInfo; | |||
| 33 | using v8::FunctionTemplate; | |||
| 34 | using v8::HandleScope; | |||
| 35 | using v8::Integer; | |||
| 36 | using v8::Isolate; | |||
| 37 | using v8::Local; | |||
| 38 | using v8::MaybeLocal; | |||
| 39 | using v8::Null; | |||
| 40 | using v8::Number; | |||
| 41 | using v8::Object; | |||
| 42 | using v8::ObjectTemplate; | |||
| 43 | using v8::Value; | |||
| 44 | ||||
| 45 | #define TRACE_NAME(name)"fs_dir.sync." "name" "fs_dir.sync." #name | |||
| 46 | #define GET_TRACE_ENABLED(*node::tracing::TraceEventHelper::GetCategoryGroupEnabled ("node" "," "node" "." "fs_dir" "," "node" "." "fs_dir" "." "sync") != 0) \ | |||
| 47 | (*TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLEDnode::tracing::TraceEventHelper::GetCategoryGroupEnabled \ | |||
| 48 | (TRACING_CATEGORY_NODE2(fs_dir, sync)"node" "," "node" "." "fs_dir" "," "node" "." "fs_dir" "." "sync") != 0) | |||
| 49 | #define FS_DIR_SYNC_TRACE_BEGIN(syscall, ...)if ((*node::tracing::TraceEventHelper::GetCategoryGroupEnabled ("node" "," "node" "." "fs_dir" "," "node" "." "fs_dir" "." "sync" ) != 0)) do { static std::atomic<intptr_t> trace_event_unique_atomic49 {0}; const uint8_t* trace_event_unique_category_group_enabled49 ; trace_event_unique_category_group_enabled49 = reinterpret_cast <const uint8_t*>((trace_event_unique_atomic49).load()); if (!trace_event_unique_category_group_enabled49) { trace_event_unique_category_group_enabled49 = node::tracing::TraceEventHelper::GetCategoryGroupEnabled("node" "," "node" "." "fs_dir" "," "node" "." "fs_dir" "." "sync"); (trace_event_unique_atomic49).store(reinterpret_cast<intptr_t >( trace_event_unique_category_group_enabled49)); };; if ( *trace_event_unique_category_group_enabled49 & (kEnabledForRecording_CategoryGroupEnabledFlags | kEnabledForEventCallback_CategoryGroupEnabledFlags)) { node ::tracing::AddTraceEvent( ('B'), trace_event_unique_category_group_enabled49 , "fs_dir.sync." "syscall", node::tracing::kGlobalScope, node ::tracing::kNoId, node::tracing::kNoId, (static_cast<unsigned int>(0)), ...); } } while (0); \ | |||
| 50 | if (GET_TRACE_ENABLED(*node::tracing::TraceEventHelper::GetCategoryGroupEnabled ("node" "," "node" "." "fs_dir" "," "node" "." "fs_dir" "." "sync") != 0)) \ | |||
| 51 | TRACE_EVENT_BEGIN(TRACING_CATEGORY_NODE2(fs_dir, sync), TRACE_NAME(syscall), \do { static std::atomic<intptr_t> trace_event_unique_atomic52 {0}; const uint8_t* trace_event_unique_category_group_enabled52 ; trace_event_unique_category_group_enabled52 = reinterpret_cast <const uint8_t*>((trace_event_unique_atomic52).load()); if (!trace_event_unique_category_group_enabled52) { trace_event_unique_category_group_enabled52 = node::tracing::TraceEventHelper::GetCategoryGroupEnabled("node" "," "node" "." "fs_dir" "," "node" "." "fs_dir" "." "sync"); (trace_event_unique_atomic52).store(reinterpret_cast<intptr_t >( trace_event_unique_category_group_enabled52)); };; if ( *trace_event_unique_category_group_enabled52 & (kEnabledForRecording_CategoryGroupEnabledFlags | kEnabledForEventCallback_CategoryGroupEnabledFlags)) { node ::tracing::AddTraceEvent( ('B'), trace_event_unique_category_group_enabled52 , "fs_dir.sync." "syscall", node::tracing::kGlobalScope, node ::tracing::kNoId, node::tracing::kNoId, (static_cast<unsigned int>(0)), ##__VA_ARGS__); } } while (0) | |||
| 52 | ##__VA_ARGS__)do { static std::atomic<intptr_t> trace_event_unique_atomic52 {0}; const uint8_t* trace_event_unique_category_group_enabled52 ; trace_event_unique_category_group_enabled52 = reinterpret_cast <const uint8_t*>((trace_event_unique_atomic52).load()); if (!trace_event_unique_category_group_enabled52) { trace_event_unique_category_group_enabled52 = node::tracing::TraceEventHelper::GetCategoryGroupEnabled("node" "," "node" "." "fs_dir" "," "node" "." "fs_dir" "." "sync"); (trace_event_unique_atomic52).store(reinterpret_cast<intptr_t >( trace_event_unique_category_group_enabled52)); };; if ( *trace_event_unique_category_group_enabled52 & (kEnabledForRecording_CategoryGroupEnabledFlags | kEnabledForEventCallback_CategoryGroupEnabledFlags)) { node ::tracing::AddTraceEvent( ('B'), trace_event_unique_category_group_enabled52 , "fs_dir.sync." "syscall", node::tracing::kGlobalScope, node ::tracing::kNoId, node::tracing::kNoId, (static_cast<unsigned int>(0)), ##__VA_ARGS__); } } while (0); | |||
| 53 | #define FS_DIR_SYNC_TRACE_END(syscall, ...)if ((*node::tracing::TraceEventHelper::GetCategoryGroupEnabled ("node" "," "node" "." "fs_dir" "," "node" "." "fs_dir" "." "sync" ) != 0)) do { static std::atomic<intptr_t> trace_event_unique_atomic53 {0}; const uint8_t* trace_event_unique_category_group_enabled53 ; trace_event_unique_category_group_enabled53 = reinterpret_cast <const uint8_t*>((trace_event_unique_atomic53).load()); if (!trace_event_unique_category_group_enabled53) { trace_event_unique_category_group_enabled53 = node::tracing::TraceEventHelper::GetCategoryGroupEnabled("node" "," "node" "." "fs_dir" "," "node" "." "fs_dir" "." "sync"); (trace_event_unique_atomic53).store(reinterpret_cast<intptr_t >( trace_event_unique_category_group_enabled53)); };; if ( *trace_event_unique_category_group_enabled53 & (kEnabledForRecording_CategoryGroupEnabledFlags | kEnabledForEventCallback_CategoryGroupEnabledFlags)) { node ::tracing::AddTraceEvent( ('E'), trace_event_unique_category_group_enabled53 , "fs_dir.sync." "syscall", node::tracing::kGlobalScope, node ::tracing::kNoId, node::tracing::kNoId, (static_cast<unsigned int>(0)), ...); } } while (0); \ | |||
| 54 | if (GET_TRACE_ENABLED(*node::tracing::TraceEventHelper::GetCategoryGroupEnabled ("node" "," "node" "." "fs_dir" "," "node" "." "fs_dir" "." "sync") != 0)) \ | |||
| 55 | TRACE_EVENT_END(TRACING_CATEGORY_NODE2(fs_dir, sync), TRACE_NAME(syscall), \do { static std::atomic<intptr_t> trace_event_unique_atomic56 {0}; const uint8_t* trace_event_unique_category_group_enabled56 ; trace_event_unique_category_group_enabled56 = reinterpret_cast <const uint8_t*>((trace_event_unique_atomic56).load()); if (!trace_event_unique_category_group_enabled56) { trace_event_unique_category_group_enabled56 = node::tracing::TraceEventHelper::GetCategoryGroupEnabled("node" "," "node" "." "fs_dir" "," "node" "." "fs_dir" "." "sync"); (trace_event_unique_atomic56).store(reinterpret_cast<intptr_t >( trace_event_unique_category_group_enabled56)); };; if ( *trace_event_unique_category_group_enabled56 & (kEnabledForRecording_CategoryGroupEnabledFlags | kEnabledForEventCallback_CategoryGroupEnabledFlags)) { node ::tracing::AddTraceEvent( ('E'), trace_event_unique_category_group_enabled56 , "fs_dir.sync." "syscall", node::tracing::kGlobalScope, node ::tracing::kNoId, node::tracing::kNoId, (static_cast<unsigned int>(0)), ##__VA_ARGS__); } } while (0) | |||
| 56 | ##__VA_ARGS__)do { static std::atomic<intptr_t> trace_event_unique_atomic56 {0}; const uint8_t* trace_event_unique_category_group_enabled56 ; trace_event_unique_category_group_enabled56 = reinterpret_cast <const uint8_t*>((trace_event_unique_atomic56).load()); if (!trace_event_unique_category_group_enabled56) { trace_event_unique_category_group_enabled56 = node::tracing::TraceEventHelper::GetCategoryGroupEnabled("node" "," "node" "." "fs_dir" "," "node" "." "fs_dir" "." "sync"); (trace_event_unique_atomic56).store(reinterpret_cast<intptr_t >( trace_event_unique_category_group_enabled56)); };; if ( *trace_event_unique_category_group_enabled56 & (kEnabledForRecording_CategoryGroupEnabledFlags | kEnabledForEventCallback_CategoryGroupEnabledFlags)) { node ::tracing::AddTraceEvent( ('E'), trace_event_unique_category_group_enabled56 , "fs_dir.sync." "syscall", node::tracing::kGlobalScope, node ::tracing::kNoId, node::tracing::kNoId, (static_cast<unsigned int>(0)), ##__VA_ARGS__); } } while (0); | |||
| 57 | ||||
| 58 | DirHandle::DirHandle(Environment* env, Local<Object> obj, uv_dir_t* dir) | |||
| 59 | : AsyncWrap(env, obj, AsyncWrap::PROVIDER_DIRHANDLE), | |||
| 60 | dir_(dir) { | |||
| 61 | MakeWeak(); | |||
| 62 | ||||
| 63 | dir_->nentries = 0; | |||
| 64 | dir_->dirents = nullptr; | |||
| 65 | } | |||
| 66 | ||||
| 67 | DirHandle* DirHandle::New(Environment* env, uv_dir_t* dir) { | |||
| 68 | Local<Object> obj; | |||
| 69 | if (!env->dir_instance_template() | |||
| 70 | ->NewInstance(env->context()) | |||
| 71 | .ToLocal(&obj)) { | |||
| 72 | return nullptr; | |||
| 73 | } | |||
| 74 | ||||
| 75 | return new DirHandle(env, obj, dir); | |||
| 76 | } | |||
| 77 | ||||
| 78 | void DirHandle::New(const FunctionCallbackInfo<Value>& args) { | |||
| 79 | CHECK(args.IsConstructCall())do { if (__builtin_expect(!!(!(args.IsConstructCall())), 0)) { do { static const node::AssertionInfo args = { "../src/node_dir.cc" ":" "79", "args.IsConstructCall()", __PRETTY_FUNCTION__ }; node ::Assert(args); } while (0); } } while (0); | |||
| 80 | } | |||
| 81 | ||||
| 82 | DirHandle::~DirHandle() { | |||
| 83 | CHECK(!closing_)do { if (__builtin_expect(!!(!(!closing_)), 0)) { do { static const node::AssertionInfo args = { "../src/node_dir.cc" ":" "83" , "!closing_", __PRETTY_FUNCTION__ }; node::Assert(args); } while (0); } } while (0); // We should not be deleting while explicitly closing! | |||
| 84 | GCClose(); // Close synchronously and emit warning | |||
| 85 | CHECK(closed_)do { if (__builtin_expect(!!(!(closed_)), 0)) { do { static const node::AssertionInfo args = { "../src/node_dir.cc" ":" "85", "closed_" , __PRETTY_FUNCTION__ }; node::Assert(args); } while (0); } } while (0); // We have to be closed at the point | |||
| 86 | } | |||
| 87 | ||||
| 88 | void DirHandle::MemoryInfo(MemoryTracker* tracker) const { | |||
| 89 | tracker->TrackFieldWithSize("dir", sizeof(*dir_)); | |||
| 90 | } | |||
| 91 | ||||
| 92 | // Close the directory handle if it hasn't already been closed. A process | |||
| 93 | // warning will be emitted using a SetImmediate to avoid calling back to | |||
| 94 | // JS during GC. If closing the fd fails at this point, a fatal exception | |||
| 95 | // will crash the process immediately. | |||
| 96 | inline void DirHandle::GCClose() { | |||
| 97 | if (closed_) return; | |||
| 98 | uv_fs_t req; | |||
| 99 | int ret = uv_fs_closedir(nullptr, &req, dir_, nullptr); | |||
| 100 | uv_fs_req_cleanup(&req); | |||
| 101 | closing_ = false; | |||
| 102 | closed_ = true; | |||
| 103 | ||||
| 104 | struct err_detail { int ret; }; | |||
| 105 | ||||
| 106 | err_detail detail { ret }; | |||
| 107 | ||||
| 108 | if (ret < 0) { | |||
| 109 | // Do not unref this | |||
| 110 | env()->SetImmediate([detail](Environment* env) { | |||
| 111 | const char* msg = "Closing directory handle on garbage collection failed"; | |||
| 112 | // This exception will end up being fatal for the process because | |||
| 113 | // it is being thrown from within the SetImmediate handler and | |||
| 114 | // there is no JS stack to bubble it to. In other words, tearing | |||
| 115 | // down the process is the only reasonable thing we can do here. | |||
| 116 | HandleScope handle_scope(env->isolate()); | |||
| 117 | env->ThrowUVException(detail.ret, "close", msg); | |||
| 118 | }); | |||
| 119 | return; | |||
| 120 | } | |||
| 121 | ||||
| 122 | // If the close was successful, we still want to emit a process warning | |||
| 123 | // to notify that the file descriptor was gc'd. We want to be noisy about | |||
| 124 | // this because not explicitly closing the DirHandle is a bug. | |||
| 125 | ||||
| 126 | env()->SetImmediate([](Environment* env) { | |||
| 127 | ProcessEmitWarning(env, | |||
| 128 | "Closing directory handle on garbage collection"); | |||
| 129 | }, CallbackFlags::kUnrefed); | |||
| 130 | } | |||
| 131 | ||||
| 132 | void AfterClose(uv_fs_t* req) { | |||
| 133 | FSReqBase* req_wrap = FSReqBase::from_req(req); | |||
| 134 | FSReqAfterScope after(req_wrap, req); | |||
| 135 | ||||
| 136 | if (after.Proceed()) | |||
| 137 | req_wrap->Resolve(Undefined(req_wrap->env()->isolate())); | |||
| 138 | } | |||
| 139 | ||||
| 140 | void DirHandle::Close(const FunctionCallbackInfo<Value>& args) { | |||
| 141 | Environment* env = Environment::GetCurrent(args); | |||
| 142 | ||||
| 143 | const int argc = args.Length(); | |||
| 144 | CHECK_GE(argc, 1)do { if (__builtin_expect(!!(!((argc) >= (1))), 0)) { do { static const node::AssertionInfo args = { "../src/node_dir.cc" ":" "144", "(argc) >= (1)", __PRETTY_FUNCTION__ }; node:: Assert(args); } while (0); } } while (0); | |||
| 145 | ||||
| 146 | DirHandle* dir; | |||
| 147 | ASSIGN_OR_RETURN_UNWRAP(&dir, args.Holder())do { *&dir = static_cast<typename std::remove_reference <decltype(*&dir)>::type>( BaseObject::FromJSObject (args.Holder())); if (*&dir == nullptr) return ; } while ( 0); | |||
| 148 | ||||
| 149 | dir->closing_ = false; | |||
| 150 | dir->closed_ = true; | |||
| 151 | ||||
| 152 | FSReqBase* req_wrap_async = GetReqWrap(args, 0); | |||
| 153 | if (req_wrap_async != nullptr) { // close(req) | |||
| 154 | AsyncCall(env, req_wrap_async, args, "closedir", UTF8, AfterClose, | |||
| 155 | uv_fs_closedir, dir->dir()); | |||
| 156 | } else { // close(undefined, ctx) | |||
| 157 | CHECK_EQ(argc, 2)do { if (__builtin_expect(!!(!((argc) == (2))), 0)) { do { static const node::AssertionInfo args = { "../src/node_dir.cc" ":" "157" , "(argc) == (2)", __PRETTY_FUNCTION__ }; node::Assert(args); } while (0); } } while (0); | |||
| 158 | FSReqWrapSync req_wrap_sync; | |||
| 159 | FS_DIR_SYNC_TRACE_BEGIN(closedir)if ((*node::tracing::TraceEventHelper::GetCategoryGroupEnabled ("node" "," "node" "." "fs_dir" "," "node" "." "fs_dir" "." "sync" ) != 0)) do { static std::atomic<intptr_t> trace_event_unique_atomic159 {0}; const uint8_t* trace_event_unique_category_group_enabled159 ; trace_event_unique_category_group_enabled159 = reinterpret_cast <const uint8_t*>((trace_event_unique_atomic159).load()) ; if (!trace_event_unique_category_group_enabled159) { trace_event_unique_category_group_enabled159 = node::tracing::TraceEventHelper::GetCategoryGroupEnabled("node" "," "node" "." "fs_dir" "," "node" "." "fs_dir" "." "sync"); (trace_event_unique_atomic159).store(reinterpret_cast<intptr_t >( trace_event_unique_category_group_enabled159)); };; if ( *trace_event_unique_category_group_enabled159 & (kEnabledForRecording_CategoryGroupEnabledFlags | kEnabledForEventCallback_CategoryGroupEnabledFlags)) { node ::tracing::AddTraceEvent( ('B'), trace_event_unique_category_group_enabled159 , "fs_dir.sync." "closedir", node::tracing::kGlobalScope, node ::tracing::kNoId, node::tracing::kNoId, (static_cast<unsigned int>(0))); } } while (0);; | |||
| 160 | SyncCall(env, args[1], &req_wrap_sync, "closedir", uv_fs_closedir, | |||
| 161 | dir->dir()); | |||
| 162 | FS_DIR_SYNC_TRACE_END(closedir)if ((*node::tracing::TraceEventHelper::GetCategoryGroupEnabled ("node" "," "node" "." "fs_dir" "," "node" "." "fs_dir" "." "sync" ) != 0)) do { static std::atomic<intptr_t> trace_event_unique_atomic162 {0}; const uint8_t* trace_event_unique_category_group_enabled162 ; trace_event_unique_category_group_enabled162 = reinterpret_cast <const uint8_t*>((trace_event_unique_atomic162).load()) ; if (!trace_event_unique_category_group_enabled162) { trace_event_unique_category_group_enabled162 = node::tracing::TraceEventHelper::GetCategoryGroupEnabled("node" "," "node" "." "fs_dir" "," "node" "." "fs_dir" "." "sync"); (trace_event_unique_atomic162).store(reinterpret_cast<intptr_t >( trace_event_unique_category_group_enabled162)); };; if ( *trace_event_unique_category_group_enabled162 & (kEnabledForRecording_CategoryGroupEnabledFlags | kEnabledForEventCallback_CategoryGroupEnabledFlags)) { node ::tracing::AddTraceEvent( ('E'), trace_event_unique_category_group_enabled162 , "fs_dir.sync." "closedir", node::tracing::kGlobalScope, node ::tracing::kNoId, node::tracing::kNoId, (static_cast<unsigned int>(0))); } } while (0);; | |||
| 163 | } | |||
| 164 | } | |||
| 165 | ||||
| 166 | static MaybeLocal<Array> DirentListToArray( | |||
| 167 | Environment* env, | |||
| 168 | uv_dirent_t* ents, | |||
| 169 | int num, | |||
| 170 | enum encoding encoding, | |||
| 171 | Local<Value>* err_out) { | |||
| 172 | MaybeStackBuffer<Local<Value>, 64> entries(num * 2); | |||
| 173 | ||||
| 174 | // Return an array of all read filenames. | |||
| 175 | int j = 0; | |||
| 176 | for (int i = 0; i < num; i++) { | |||
| 177 | Local<Value> filename; | |||
| 178 | Local<Value> error; | |||
| 179 | const size_t namelen = strlen(ents[i].name); | |||
| 180 | if (!StringBytes::Encode(env->isolate(), | |||
| 181 | ents[i].name, | |||
| 182 | namelen, | |||
| 183 | encoding, | |||
| 184 | &error).ToLocal(&filename)) { | |||
| 185 | *err_out = error; | |||
| 186 | return MaybeLocal<Array>(); | |||
| 187 | } | |||
| 188 | ||||
| 189 | entries[j++] = filename; | |||
| 190 | entries[j++] = Integer::New(env->isolate(), ents[i].type); | |||
| 191 | } | |||
| 192 | ||||
| 193 | return Array::New(env->isolate(), entries.out(), j); | |||
| 194 | } | |||
| 195 | ||||
| 196 | static void AfterDirRead(uv_fs_t* req) { | |||
| 197 | BaseObjectPtr<FSReqBase> req_wrap { FSReqBase::from_req(req) }; | |||
| 198 | FSReqAfterScope after(req_wrap.get(), req); | |||
| 199 | ||||
| 200 | if (!after.Proceed()) { | |||
| 201 | return; | |||
| 202 | } | |||
| 203 | ||||
| 204 | Environment* env = req_wrap->env(); | |||
| 205 | Isolate* isolate = env->isolate(); | |||
| 206 | ||||
| 207 | if (req->result == 0) { | |||
| 208 | // Done | |||
| 209 | Local<Value> done = Null(isolate); | |||
| 210 | after.Clear(); | |||
| 211 | req_wrap->Resolve(done); | |||
| 212 | return; | |||
| 213 | } | |||
| 214 | ||||
| 215 | uv_dir_t* dir = static_cast<uv_dir_t*>(req->ptr); | |||
| 216 | ||||
| 217 | Local<Value> error; | |||
| 218 | Local<Array> js_array; | |||
| 219 | if (!DirentListToArray(env, | |||
| 220 | dir->dirents, | |||
| 221 | static_cast<int>(req->result), | |||
| 222 | req_wrap->encoding(), | |||
| 223 | &error) | |||
| 224 | .ToLocal(&js_array)) { | |||
| 225 | // Clear libuv resources *before* delivering results to JS land because | |||
| 226 | // that can schedule another operation on the same uv_dir_t. Ditto below. | |||
| 227 | after.Clear(); | |||
| 228 | return req_wrap->Reject(error); | |||
| 229 | } | |||
| 230 | ||||
| 231 | after.Clear(); | |||
| 232 | req_wrap->Resolve(js_array); | |||
| 233 | } | |||
| 234 | ||||
| 235 | ||||
| 236 | void DirHandle::Read(const FunctionCallbackInfo<Value>& args) { | |||
| 237 | Environment* env = Environment::GetCurrent(args); | |||
| 238 | Isolate* isolate = env->isolate(); | |||
| 239 | ||||
| 240 | const int argc = args.Length(); | |||
| 241 | CHECK_GE(argc, 3)do { if (__builtin_expect(!!(!((argc) >= (3))), 0)) { do { static const node::AssertionInfo args = { "../src/node_dir.cc" ":" "241", "(argc) >= (3)", __PRETTY_FUNCTION__ }; node:: Assert(args); } while (0); } } while (0); | |||
| 242 | ||||
| 243 | const enum encoding encoding = ParseEncoding(isolate, args[0], UTF8); | |||
| 244 | ||||
| 245 | DirHandle* dir; | |||
| 246 | ASSIGN_OR_RETURN_UNWRAP(&dir, args.Holder())do { *&dir = static_cast<typename std::remove_reference <decltype(*&dir)>::type>( BaseObject::FromJSObject (args.Holder())); if (*&dir == nullptr) return ; } while ( 0); | |||
| 247 | ||||
| 248 | CHECK(args[1]->IsNumber())do { if (__builtin_expect(!!(!(args[1]->IsNumber())), 0)) { do { static const node::AssertionInfo args = { "../src/node_dir.cc" ":" "248", "args[1]->IsNumber()", __PRETTY_FUNCTION__ }; node ::Assert(args); } while (0); } } while (0); | |||
| 249 | uint64_t buffer_size = static_cast<uint64_t>(args[1].As<Number>()->Value()); | |||
| 250 | ||||
| 251 | if (buffer_size != dir->dirents_.size()) { | |||
| 252 | dir->dirents_.resize(buffer_size); | |||
| 253 | dir->dir_->nentries = buffer_size; | |||
| 254 | dir->dir_->dirents = dir->dirents_.data(); | |||
| 255 | } | |||
| 256 | ||||
| 257 | FSReqBase* req_wrap_async = GetReqWrap(args, 2); | |||
| 258 | if (req_wrap_async != nullptr) { // dir.read(encoding, bufferSize, req) | |||
| 259 | AsyncCall(env, req_wrap_async, args, "readdir", encoding, | |||
| 260 | AfterDirRead, uv_fs_readdir, dir->dir()); | |||
| 261 | } else { // dir.read(encoding, bufferSize, undefined, ctx) | |||
| 262 | CHECK_EQ(argc, 4)do { if (__builtin_expect(!!(!((argc) == (4))), 0)) { do { static const node::AssertionInfo args = { "../src/node_dir.cc" ":" "262" , "(argc) == (4)", __PRETTY_FUNCTION__ }; node::Assert(args); } while (0); } } while (0); | |||
| 263 | FSReqWrapSync req_wrap_sync; | |||
| 264 | FS_DIR_SYNC_TRACE_BEGIN(readdir)if ((*node::tracing::TraceEventHelper::GetCategoryGroupEnabled ("node" "," "node" "." "fs_dir" "," "node" "." "fs_dir" "." "sync" ) != 0)) do { static std::atomic<intptr_t> trace_event_unique_atomic264 {0}; const uint8_t* trace_event_unique_category_group_enabled264 ; trace_event_unique_category_group_enabled264 = reinterpret_cast <const uint8_t*>((trace_event_unique_atomic264).load()) ; if (!trace_event_unique_category_group_enabled264) { trace_event_unique_category_group_enabled264 = node::tracing::TraceEventHelper::GetCategoryGroupEnabled("node" "," "node" "." "fs_dir" "," "node" "." "fs_dir" "." "sync"); (trace_event_unique_atomic264).store(reinterpret_cast<intptr_t >( trace_event_unique_category_group_enabled264)); };; if ( *trace_event_unique_category_group_enabled264 & (kEnabledForRecording_CategoryGroupEnabledFlags | kEnabledForEventCallback_CategoryGroupEnabledFlags)) { node ::tracing::AddTraceEvent( ('B'), trace_event_unique_category_group_enabled264 , "fs_dir.sync." "readdir", node::tracing::kGlobalScope, node ::tracing::kNoId, node::tracing::kNoId, (static_cast<unsigned int>(0))); } } while (0);; | |||
| 265 | int err = SyncCall(env, args[3], &req_wrap_sync, "readdir", uv_fs_readdir, | |||
| 266 | dir->dir()); | |||
| 267 | FS_DIR_SYNC_TRACE_END(readdir)if ((*node::tracing::TraceEventHelper::GetCategoryGroupEnabled ("node" "," "node" "." "fs_dir" "," "node" "." "fs_dir" "." "sync" ) != 0)) do { static std::atomic<intptr_t> trace_event_unique_atomic267 {0}; const uint8_t* trace_event_unique_category_group_enabled267 ; trace_event_unique_category_group_enabled267 = reinterpret_cast <const uint8_t*>((trace_event_unique_atomic267).load()) ; if (!trace_event_unique_category_group_enabled267) { trace_event_unique_category_group_enabled267 = node::tracing::TraceEventHelper::GetCategoryGroupEnabled("node" "," "node" "." "fs_dir" "," "node" "." "fs_dir" "." "sync"); (trace_event_unique_atomic267).store(reinterpret_cast<intptr_t >( trace_event_unique_category_group_enabled267)); };; if ( *trace_event_unique_category_group_enabled267 & (kEnabledForRecording_CategoryGroupEnabledFlags | kEnabledForEventCallback_CategoryGroupEnabledFlags)) { node ::tracing::AddTraceEvent( ('E'), trace_event_unique_category_group_enabled267 , "fs_dir.sync." "readdir", node::tracing::kGlobalScope, node ::tracing::kNoId, node::tracing::kNoId, (static_cast<unsigned int>(0))); } } while (0);; | |||
| 268 | if (err < 0) { | |||
| 269 | return; // syscall failed, no need to continue, error info is in ctx | |||
| 270 | } | |||
| 271 | ||||
| 272 | if (req_wrap_sync.req.result == 0) { | |||
| 273 | // Done | |||
| 274 | Local<Value> done = Null(isolate); | |||
| 275 | args.GetReturnValue().Set(done); | |||
| 276 | return; | |||
| 277 | } | |||
| 278 | ||||
| 279 | CHECK_GE(req_wrap_sync.req.result, 0)do { if (__builtin_expect(!!(!((req_wrap_sync.req.result) >= (0))), 0)) { do { static const node::AssertionInfo args = { "../src/node_dir.cc" ":" "279", "(req_wrap_sync.req.result) >= (0)", __PRETTY_FUNCTION__ }; node::Assert(args); } while (0); } } while (0); | |||
| 280 | ||||
| 281 | Local<Value> error; | |||
| 282 | Local<Array> js_array; | |||
| 283 | if (!DirentListToArray(env, | |||
| 284 | dir->dir()->dirents, | |||
| 285 | static_cast<int>(req_wrap_sync.req.result), | |||
| 286 | encoding, | |||
| 287 | &error) | |||
| 288 | .ToLocal(&js_array)) { | |||
| 289 | Local<Object> ctx = args[2].As<Object>(); | |||
| 290 | USE(ctx->Set(env->context(), env->error_string(), error)); | |||
| 291 | return; | |||
| 292 | } | |||
| 293 | ||||
| 294 | args.GetReturnValue().Set(js_array); | |||
| 295 | } | |||
| 296 | } | |||
| 297 | ||||
| 298 | void AfterOpenDir(uv_fs_t* req) { | |||
| 299 | FSReqBase* req_wrap = FSReqBase::from_req(req); | |||
| 300 | FSReqAfterScope after(req_wrap, req); | |||
| 301 | ||||
| 302 | if (!after.Proceed()) { | |||
| 303 | return; | |||
| 304 | } | |||
| 305 | ||||
| 306 | Environment* env = req_wrap->env(); | |||
| 307 | ||||
| 308 | uv_dir_t* dir = static_cast<uv_dir_t*>(req->ptr); | |||
| 309 | DirHandle* handle = DirHandle::New(env, dir); | |||
| 310 | ||||
| 311 | req_wrap->Resolve(handle->object().As<Value>()); | |||
| 312 | } | |||
| 313 | ||||
| 314 | static void OpenDir(const FunctionCallbackInfo<Value>& args) { | |||
| 315 | Environment* env = Environment::GetCurrent(args); | |||
| 316 | Isolate* isolate = env->isolate(); | |||
| 317 | ||||
| 318 | const int argc = args.Length(); | |||
| 319 | CHECK_GE(argc, 3)do { if (__builtin_expect(!!(!((argc) >= (3))), 0)) { do { static const node::AssertionInfo args = { "../src/node_dir.cc" ":" "319", "(argc) >= (3)", __PRETTY_FUNCTION__ }; node:: Assert(args); } while (0); } } while (0); | |||
| ||||
| 320 | ||||
| 321 | BufferValue path(isolate, args[0]); | |||
| 322 | CHECK_NOT_NULL(*path)do { if (__builtin_expect(!!(!((*path) != nullptr)), 0)) { do { static const node::AssertionInfo args = { "../src/node_dir.cc" ":" "322", "(*path) != nullptr", __PRETTY_FUNCTION__ }; node ::Assert(args); } while (0); } } while (0); | |||
| 323 | ||||
| 324 | const enum encoding encoding = ParseEncoding(isolate, args[1], UTF8); | |||
| 325 | ||||
| 326 | FSReqBase* req_wrap_async = GetReqWrap(args, 2); | |||
| 327 | if (req_wrap_async != nullptr) { // openDir(path, encoding, req) | |||
| 328 | AsyncCall(env, req_wrap_async, args, "opendir", encoding, AfterOpenDir, | |||
| 329 | uv_fs_opendir, *path); | |||
| 330 | } else { // openDir(path, encoding, undefined, ctx) | |||
| 331 | CHECK_EQ(argc, 4)do { if (__builtin_expect(!!(!((argc) == (4))), 0)) { do { static const node::AssertionInfo args = { "../src/node_dir.cc" ":" "331" , "(argc) == (4)", __PRETTY_FUNCTION__ }; node::Assert(args); } while (0); } } while (0); | |||
| 332 | FSReqWrapSync req_wrap_sync; | |||
| 333 | FS_DIR_SYNC_TRACE_BEGIN(opendir)if ((*node::tracing::TraceEventHelper::GetCategoryGroupEnabled ("node" "," "node" "." "fs_dir" "," "node" "." "fs_dir" "." "sync" ) != 0)) do { static std::atomic<intptr_t> trace_event_unique_atomic333 {0}; const uint8_t* trace_event_unique_category_group_enabled333 ; trace_event_unique_category_group_enabled333 = reinterpret_cast <const uint8_t*>((trace_event_unique_atomic333).load()) ; if (!trace_event_unique_category_group_enabled333) { trace_event_unique_category_group_enabled333 = node::tracing::TraceEventHelper::GetCategoryGroupEnabled("node" "," "node" "." "fs_dir" "," "node" "." "fs_dir" "." "sync"); (trace_event_unique_atomic333).store(reinterpret_cast<intptr_t >( trace_event_unique_category_group_enabled333)); };; if ( *trace_event_unique_category_group_enabled333 & (kEnabledForRecording_CategoryGroupEnabledFlags | kEnabledForEventCallback_CategoryGroupEnabledFlags)) { node ::tracing::AddTraceEvent( ('B'), trace_event_unique_category_group_enabled333 , "fs_dir.sync." "opendir", node::tracing::kGlobalScope, node ::tracing::kNoId, node::tracing::kNoId, (static_cast<unsigned int>(0))); } } while (0);; | |||
| 334 | int result = SyncCall(env, args[3], &req_wrap_sync, "opendir", | |||
| 335 | uv_fs_opendir, *path); | |||
| 336 | FS_DIR_SYNC_TRACE_END(opendir)if ((*node::tracing::TraceEventHelper::GetCategoryGroupEnabled ("node" "," "node" "." "fs_dir" "," "node" "." "fs_dir" "." "sync" ) != 0)) do { static std::atomic<intptr_t> trace_event_unique_atomic336 {0}; const uint8_t* trace_event_unique_category_group_enabled336 ; trace_event_unique_category_group_enabled336 = reinterpret_cast <const uint8_t*>((trace_event_unique_atomic336).load()) ; if (!trace_event_unique_category_group_enabled336) { trace_event_unique_category_group_enabled336 = node::tracing::TraceEventHelper::GetCategoryGroupEnabled("node" "," "node" "." "fs_dir" "," "node" "." "fs_dir" "." "sync"); (trace_event_unique_atomic336).store(reinterpret_cast<intptr_t >( trace_event_unique_category_group_enabled336)); };; if ( *trace_event_unique_category_group_enabled336 & (kEnabledForRecording_CategoryGroupEnabledFlags | kEnabledForEventCallback_CategoryGroupEnabledFlags)) { node ::tracing::AddTraceEvent( ('E'), trace_event_unique_category_group_enabled336 , "fs_dir.sync." "opendir", node::tracing::kGlobalScope, node ::tracing::kNoId, node::tracing::kNoId, (static_cast<unsigned int>(0))); } } while (0);; | |||
| 337 | if (result
| |||
| 338 | return; // syscall failed, no need to continue, error info is in ctx | |||
| 339 | } | |||
| 340 | ||||
| 341 | uv_fs_t* req = &req_wrap_sync.req; | |||
| 342 | uv_dir_t* dir = static_cast<uv_dir_t*>(req->ptr); | |||
| 343 | DirHandle* handle = DirHandle::New(env, dir); | |||
| 344 | ||||
| 345 | args.GetReturnValue().Set(handle->object().As<Value>()); | |||
| ||||
| 346 | } | |||
| 347 | } | |||
| 348 | ||||
| 349 | void Initialize(Local<Object> target, | |||
| 350 | Local<Value> unused, | |||
| 351 | Local<Context> context, | |||
| 352 | void* priv) { | |||
| 353 | Environment* env = Environment::GetCurrent(context); | |||
| 354 | ||||
| 355 | env->SetMethod(target, "opendir", OpenDir); | |||
| 356 | ||||
| 357 | // Create FunctionTemplate for DirHandle | |||
| 358 | Local<FunctionTemplate> dir = env->NewFunctionTemplate(DirHandle::New); | |||
| 359 | dir->Inherit(AsyncWrap::GetConstructorTemplate(env)); | |||
| 360 | env->SetProtoMethod(dir, "read", DirHandle::Read); | |||
| 361 | env->SetProtoMethod(dir, "close", DirHandle::Close); | |||
| 362 | Local<ObjectTemplate> dirt = dir->InstanceTemplate(); | |||
| 363 | dirt->SetInternalFieldCount(DirHandle::kInternalFieldCount); | |||
| 364 | env->SetConstructorFunction(target, "DirHandle", dir); | |||
| 365 | env->set_dir_instance_template(dirt); | |||
| 366 | } | |||
| 367 | ||||
| 368 | void RegisterExternalReferences(ExternalReferenceRegistry* registry) { | |||
| 369 | registry->Register(OpenDir); | |||
| 370 | registry->Register(DirHandle::New); | |||
| 371 | registry->Register(DirHandle::Read); | |||
| 372 | registry->Register(DirHandle::Close); | |||
| 373 | } | |||
| 374 | ||||
| 375 | } // namespace fs_dir | |||
| 376 | ||||
| 377 | } // end namespace node | |||
| 378 | ||||
| 379 | NODE_MODULE_CONTEXT_AWARE_INTERNAL(fs_dir, node::fs_dir::Initialize)static node::node_module _module = { 108, NM_F_INTERNAL, nullptr , "../src/node_dir.cc", nullptr, (node::addon_context_register_func )(node::fs_dir::Initialize), "fs_dir", nullptr, nullptr}; void _register_fs_dir() { node_module_register(&_module); } | |||
| 380 | NODE_MODULE_EXTERNAL_REFERENCE(fs_dir, node::fs_dir::RegisterExternalReferences)void _register_external_reference_fs_dir( node::ExternalReferenceRegistry * registry) { node::fs_dir::RegisterExternalReferences(registry ); } |