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 ); } |