GCC Code Coverage Report | |||||||||||||||||||||
|
|||||||||||||||||||||
Line | Branch | Exec | Source |
1 |
#ifndef SRC_NODE_FILE_INL_H_ |
||
2 |
#define SRC_NODE_FILE_INL_H_ |
||
3 |
|||
4 |
#if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS |
||
5 |
|||
6 |
#include "node_file.h" |
||
7 |
#include "req_wrap-inl.h" |
||
8 |
|||
9 |
namespace node { |
||
10 |
namespace fs { |
||
11 |
|||
12 |
5876 |
FSContinuationData::FSContinuationData(uv_fs_t* req, int mode, uv_fs_cb done_cb) |
|
13 |
5876 |
: done_cb_(done_cb), req_(req), mode_(mode) { |
|
14 |
5876 |
} |
|
15 |
|||
16 |
925 |
void FSContinuationData::PushPath(std::string&& path) { |
|
17 |
925 |
paths_.emplace_back(std::move(path)); |
|
18 |
925 |
} |
|
19 |
|||
20 |
5263 |
void FSContinuationData::PushPath(const std::string& path) { |
|
21 |
5263 |
paths_.push_back(path); |
|
22 |
5263 |
} |
|
23 |
|||
24 |
569 |
void FSContinuationData::MaybeSetFirstPath(const std::string& path) { |
|
25 |
✓✓ | 569 |
if (first_path_.empty()) { |
26 |
507 |
first_path_ = path; |
|
27 |
} |
||
28 |
569 |
} |
|
29 |
|||
30 |
6188 |
std::string FSContinuationData::PopPath() { |
|
31 |
✗✓ | 6188 |
CHECK(!paths_.empty()); |
32 |
6188 |
std::string path = std::move(paths_.back()); |
|
33 |
6188 |
paths_.pop_back(); |
|
34 |
6188 |
return path; |
|
35 |
} |
||
36 |
|||
37 |
613 |
void FSContinuationData::Done(int result) { |
|
38 |
613 |
req_->result = result; |
|
39 |
613 |
done_cb_(req_); |
|
40 |
613 |
} |
|
41 |
|||
42 |
53549 |
FSReqBase::FSReqBase(BindingData* binding_data, |
|
43 |
v8::Local<v8::Object> req, |
||
44 |
AsyncWrap::ProviderType type, |
||
45 |
53549 |
bool use_bigint) |
|
46 |
: ReqWrap(binding_data->env(), req, type), |
||
47 |
use_bigint_(use_bigint), |
||
48 |
53549 |
binding_data_(binding_data) { |
|
49 |
53549 |
} |
|
50 |
|||
51 |
53482 |
void FSReqBase::Init(const char* syscall, |
|
52 |
const char* data, |
||
53 |
size_t len, |
||
54 |
enum encoding encoding) { |
||
55 |
53482 |
syscall_ = syscall; |
|
56 |
53482 |
encoding_ = encoding; |
|
57 |
|||
58 |
✓✓ | 53482 |
if (data != nullptr) { |
59 |
✗✓ | 108 |
CHECK(!has_data_); |
60 |
108 |
buffer_.AllocateSufficientStorage(len + 1); |
|
61 |
108 |
buffer_.SetLengthAndZeroTerminate(len); |
|
62 |
108 |
memcpy(*buffer_, data, len); |
|
63 |
108 |
has_data_ = true; |
|
64 |
} |
||
65 |
53482 |
} |
|
66 |
|||
67 |
FSReqBase::FSReqBuffer& |
||
68 |
67 |
FSReqBase::Init(const char* syscall, size_t len, enum encoding encoding) { |
|
69 |
67 |
syscall_ = syscall; |
|
70 |
67 |
encoding_ = encoding; |
|
71 |
|||
72 |
67 |
buffer_.AllocateSufficientStorage(len + 1); |
|
73 |
67 |
has_data_ = false; // so that the data does not show up in error messages |
|
74 |
67 |
return buffer_; |
|
75 |
} |
||
76 |
|||
77 |
50732 |
FSReqCallback::FSReqCallback(BindingData* binding_data, |
|
78 |
v8::Local<v8::Object> req, |
||
79 |
50732 |
bool use_bigint) |
|
80 |
: FSReqBase(binding_data, |
||
81 |
req, |
||
82 |
AsyncWrap::PROVIDER_FSREQCALLBACK, |
||
83 |
50732 |
use_bigint) {} |
|
84 |
|||
85 |
template <typename NativeT, typename V8T> |
||
86 |
161502 |
void FillStatsArray(AliasedBufferBase<NativeT, V8T>* fields, |
|
87 |
const uv_stat_t* s, |
||
88 |
const size_t offset) { |
||
89 |
#define SET_FIELD_WITH_STAT(stat_offset, stat) \ |
||
90 |
fields->SetValue(offset + static_cast<size_t>(FsStatsOffset::stat_offset), \ |
||
91 |
static_cast<NativeT>(stat)) |
||
92 |
|||
93 |
#define SET_FIELD_WITH_TIME_STAT(stat_offset, stat) \ |
||
94 |
/* NOLINTNEXTLINE(runtime/int) */ \ |
||
95 |
SET_FIELD_WITH_STAT(stat_offset, static_cast<unsigned long>(stat)) |
||
96 |
|||
97 |
161502 |
SET_FIELD_WITH_STAT(kDev, s->st_dev); |
|
98 |
161502 |
SET_FIELD_WITH_STAT(kMode, s->st_mode); |
|
99 |
161502 |
SET_FIELD_WITH_STAT(kNlink, s->st_nlink); |
|
100 |
161502 |
SET_FIELD_WITH_STAT(kUid, s->st_uid); |
|
101 |
161502 |
SET_FIELD_WITH_STAT(kGid, s->st_gid); |
|
102 |
161502 |
SET_FIELD_WITH_STAT(kRdev, s->st_rdev); |
|
103 |
161502 |
SET_FIELD_WITH_STAT(kBlkSize, s->st_blksize); |
|
104 |
161502 |
SET_FIELD_WITH_STAT(kIno, s->st_ino); |
|
105 |
161502 |
SET_FIELD_WITH_STAT(kSize, s->st_size); |
|
106 |
161502 |
SET_FIELD_WITH_STAT(kBlocks, s->st_blocks); |
|
107 |
|||
108 |
161502 |
SET_FIELD_WITH_TIME_STAT(kATimeSec, s->st_atim.tv_sec); |
|
109 |
161502 |
SET_FIELD_WITH_TIME_STAT(kATimeNsec, s->st_atim.tv_nsec); |
|
110 |
161502 |
SET_FIELD_WITH_TIME_STAT(kMTimeSec, s->st_mtim.tv_sec); |
|
111 |
161502 |
SET_FIELD_WITH_TIME_STAT(kMTimeNsec, s->st_mtim.tv_nsec); |
|
112 |
161502 |
SET_FIELD_WITH_TIME_STAT(kCTimeSec, s->st_ctim.tv_sec); |
|
113 |
161502 |
SET_FIELD_WITH_TIME_STAT(kCTimeNsec, s->st_ctim.tv_nsec); |
|
114 |
161502 |
SET_FIELD_WITH_TIME_STAT(kBirthTimeSec, s->st_birthtim.tv_sec); |
|
115 |
161502 |
SET_FIELD_WITH_TIME_STAT(kBirthTimeNsec, s->st_birthtim.tv_nsec); |
|
116 |
|||
117 |
#undef SET_FIELD_WITH_TIME_STAT |
||
118 |
#undef SET_FIELD_WITH_STAT |
||
119 |
161502 |
} |
|
120 |
|||
121 |
160823 |
v8::Local<v8::Value> FillGlobalStatsArray(BindingData* binding_data, |
|
122 |
const bool use_bigint, |
||
123 |
const uv_stat_t* s, |
||
124 |
const bool second) { |
||
125 |
const ptrdiff_t offset = |
||
126 |
✓✓ | 160823 |
second ? static_cast<ptrdiff_t>(FsStatsOffset::kFsStatsFieldsNumber) : 0; |
127 |
✓✓ | 160823 |
if (use_bigint) { |
128 |
102200 |
auto* const arr = &binding_data->stats_field_bigint_array; |
|
129 |
102200 |
FillStatsArray(arr, s, offset); |
|
130 |
204400 |
return arr->GetJSArray(); |
|
131 |
} else { |
||
132 |
58623 |
auto* const arr = &binding_data->stats_field_array; |
|
133 |
58623 |
FillStatsArray(arr, s, offset); |
|
134 |
117246 |
return arr->GetJSArray(); |
|
135 |
} |
||
136 |
} |
||
137 |
|||
138 |
template <typename AliasedBufferT> |
||
139 |
FSReqPromise<AliasedBufferT>* |
||
140 |
2817 |
FSReqPromise<AliasedBufferT>::New(BindingData* binding_data, |
|
141 |
bool use_bigint) { |
||
142 |
2817 |
Environment* env = binding_data->env(); |
|
143 |
v8::Local<v8::Object> obj; |
||
144 |
✗✓✗✓ |
8451 |
if (!env->fsreqpromise_constructor_template() |
145 |
8451 |
->NewInstance(env->context()) |
|
146 |
2817 |
.ToLocal(&obj)) { |
|
147 |
return nullptr; |
||
148 |
} |
||
149 |
v8::Local<v8::Promise::Resolver> resolver; |
||
150 |
✓✗✗✓ ✗✓✓✗ ✗✓✗✓ |
11268 |
if (!v8::Promise::Resolver::New(env->context()).ToLocal(&resolver) || |
151 |
14085 |
obj->Set(env->context(), env->promise_string(), resolver).IsNothing()) { |
|
152 |
return nullptr; |
||
153 |
} |
||
154 |
2817 |
return new FSReqPromise(binding_data, obj, use_bigint); |
|
155 |
} |
||
156 |
|||
157 |
template <typename AliasedBufferT> |
||
158 |
5630 |
FSReqPromise<AliasedBufferT>::~FSReqPromise() { |
|
159 |
// Validate that the promise was explicitly resolved or rejected. |
||
160 |
✗✓✗✓ |
2815 |
CHECK(finished_); |
161 |
8445 |
} |
|
162 |
|||
163 |
template <typename AliasedBufferT> |
||
164 |
2817 |
FSReqPromise<AliasedBufferT>::FSReqPromise( |
|
165 |
BindingData* binding_data, |
||
166 |
v8::Local<v8::Object> obj, |
||
167 |
bool use_bigint) |
||
168 |
: FSReqBase(binding_data, |
||
169 |
obj, |
||
170 |
AsyncWrap::PROVIDER_FSREQPROMISE, |
||
171 |
use_bigint), |
||
172 |
stats_field_array_( |
||
173 |
env()->isolate(), |
||
174 |
2817 |
static_cast<size_t>(FsStatsOffset::kFsStatsFieldsNumber)) {} |
|
175 |
|||
176 |
template <typename AliasedBufferT> |
||
177 |
211 |
void FSReqPromise<AliasedBufferT>::Reject(v8::Local<v8::Value> reject) { |
|
178 |
211 |
finished_ = true; |
|
179 |
422 |
v8::HandleScope scope(env()->isolate()); |
|
180 |
422 |
InternalCallbackScope callback_scope(this); |
|
181 |
v8::Local<v8::Value> value = |
||
182 |
422 |
object()->Get(env()->context(), |
|
183 |
1055 |
env()->promise_string()).ToLocalChecked(); |
|
184 |
211 |
v8::Local<v8::Promise::Resolver> resolver = value.As<v8::Promise::Resolver>(); |
|
185 |
633 |
USE(resolver->Reject(env()->context(), reject).FromJust()); |
|
186 |
211 |
} |
|
187 |
|||
188 |
template <typename AliasedBufferT> |
||
189 |
2604 |
void FSReqPromise<AliasedBufferT>::Resolve(v8::Local<v8::Value> value) { |
|
190 |
2604 |
finished_ = true; |
|
191 |
5208 |
v8::HandleScope scope(env()->isolate()); |
|
192 |
5208 |
InternalCallbackScope callback_scope(this); |
|
193 |
v8::Local<v8::Value> val = |
||
194 |
5208 |
object()->Get(env()->context(), |
|
195 |
13020 |
env()->promise_string()).ToLocalChecked(); |
|
196 |
2604 |
v8::Local<v8::Promise::Resolver> resolver = val.As<v8::Promise::Resolver>(); |
|
197 |
7812 |
USE(resolver->Resolve(env()->context(), value).FromJust()); |
|
198 |
2604 |
} |
|
199 |
|||
200 |
template <typename AliasedBufferT> |
||
201 |
679 |
void FSReqPromise<AliasedBufferT>::ResolveStat(const uv_stat_t* stat) { |
|
202 |
679 |
FillStatsArray(&stats_field_array_, stat); |
|
203 |
1358 |
Resolve(stats_field_array_.GetJSArray()); |
|
204 |
679 |
} |
|
205 |
|||
206 |
template <typename AliasedBufferT> |
||
207 |
2817 |
void FSReqPromise<AliasedBufferT>::SetReturnValue( |
|
208 |
const v8::FunctionCallbackInfo<v8::Value>& args) { |
||
209 |
v8::Local<v8::Value> val = |
||
210 |
5634 |
object()->Get(env()->context(), |
|
211 |
14085 |
env()->promise_string()).ToLocalChecked(); |
|
212 |
2817 |
v8::Local<v8::Promise::Resolver> resolver = val.As<v8::Promise::Resolver>(); |
|
213 |
8451 |
args.GetReturnValue().Set(resolver->GetPromise()); |
|
214 |
2817 |
} |
|
215 |
|||
216 |
template <typename AliasedBufferT> |
||
217 |
1 |
void FSReqPromise<AliasedBufferT>::MemoryInfo(MemoryTracker* tracker) const { |
|
218 |
1 |
FSReqBase::MemoryInfo(tracker); |
|
219 |
1 |
tracker->TrackField("stats_field_array", stats_field_array_); |
|
220 |
1 |
} |
|
221 |
|||
222 |
484403 |
FSReqBase* GetReqWrap(const v8::FunctionCallbackInfo<v8::Value>& args, |
|
223 |
int index, |
||
224 |
bool use_bigint) { |
||
225 |
484403 |
v8::Local<v8::Value> value = args[index]; |
|
226 |
✓✓ | 484403 |
if (value->IsObject()) { |
227 |
50732 |
return Unwrap<FSReqBase>(value.As<v8::Object>()); |
|
228 |
} |
||
229 |
|||
230 |
433671 |
BindingData* binding_data = Environment::GetBindingData<BindingData>(args); |
|
231 |
433669 |
Environment* env = binding_data->env(); |
|
232 |
✓✓ | 867338 |
if (value->StrictEquals(env->fs_use_promises_symbol())) { |
233 |
✓✓ | 2817 |
if (use_bigint) { |
234 |
3 |
return FSReqPromise<AliasedBigUint64Array>::New(binding_data, use_bigint); |
|
235 |
} else { |
||
236 |
2814 |
return FSReqPromise<AliasedFloat64Array>::New(binding_data, use_bigint); |
|
237 |
} |
||
238 |
} |
||
239 |
430852 |
return nullptr; |
|
240 |
} |
||
241 |
|||
242 |
// Returns nullptr if the operation fails from the start. |
||
243 |
template <typename Func, typename... Args> |
||
244 |
53482 |
FSReqBase* AsyncDestCall(Environment* env, FSReqBase* req_wrap, |
|
245 |
const v8::FunctionCallbackInfo<v8::Value>& args, |
||
246 |
const char* syscall, const char* dest, |
||
247 |
size_t len, enum encoding enc, uv_fs_cb after, |
||
248 |
Func fn, Args... fn_args) { |
||
249 |
✗✓✗✓ ✗✓✗✓ ✗✓✗✓ ✗✓✗✓ ✗✓✗✗ ✗✓✗✓ ✗✓✗✓ |
53482 |
CHECK_NOT_NULL(req_wrap); |
250 |
53482 |
req_wrap->Init(syscall, dest, len, enc); |
|
251 |
53482 |
int err = req_wrap->Dispatch(fn, fn_args..., after); |
|
252 |
✗✓✗✓ ✗✓✗✓ ✗✓✗✓ ✗✓✗✓ ✗✓✗✗ ✗✓✗✓ ✗✓✗✓ |
53482 |
if (err < 0) { |
253 |
uv_fs_t* uv_req = req_wrap->req(); |
||
254 |
uv_req->result = err; |
||
255 |
uv_req->path = nullptr; |
||
256 |
after(uv_req); // after may delete req_wrap if there is an error |
||
257 |
req_wrap = nullptr; |
||
258 |
} else { |
||
259 |
53482 |
req_wrap->SetReturnValue(args); |
|
260 |
} |
||
261 |
|||
262 |
53482 |
return req_wrap; |
|
263 |
} |
||
264 |
|||
265 |
// Returns nullptr if the operation fails from the start. |
||
266 |
template <typename Func, typename... Args> |
||
267 |
53374 |
FSReqBase* AsyncCall(Environment* env, |
|
268 |
FSReqBase* req_wrap, |
||
269 |
const v8::FunctionCallbackInfo<v8::Value>& args, |
||
270 |
const char* syscall, enum encoding enc, |
||
271 |
uv_fs_cb after, Func fn, Args... fn_args) { |
||
272 |
return AsyncDestCall(env, req_wrap, args, |
||
273 |
syscall, nullptr, 0, enc, |
||
274 |
53374 |
after, fn, fn_args...); |
|
275 |
} |
||
276 |
|||
277 |
// Template counterpart of SYNC_CALL, except that it only puts |
||
278 |
// the error number and the syscall in the context instead of |
||
279 |
// creating an error in the C++ land. |
||
280 |
// ctx must be checked using value->IsObject() before being passed. |
||
281 |
template <typename Func, typename... Args> |
||
282 |
430621 |
int SyncCall(Environment* env, v8::Local<v8::Value> ctx, |
|
283 |
FSReqWrapSync* req_wrap, const char* syscall, |
||
284 |
Func fn, Args... args) { |
||
285 |
430621 |
env->PrintSyncTrace(); |
|
286 |
430621 |
int err = fn(env->event_loop(), &(req_wrap->req), args..., nullptr); |
|
287 |
✓✓✓✓ ✓✓✓✓ ✓✓✗✓ ✓✓✓✓ ✓✓✓✓ ✓✓✗✗ ✓✓✓✓ |
430621 |
if (err < 0) { |
288 |
1660 |
v8::Local<v8::Context> context = env->context(); |
|
289 |
1660 |
v8::Local<v8::Object> ctx_obj = ctx.As<v8::Object>(); |
|
290 |
1660 |
v8::Isolate* isolate = env->isolate(); |
|
291 |
6640 |
ctx_obj->Set(context, |
|
292 |
env->errno_string(), |
||
293 |
v8::Integer::New(isolate, err)).Check(); |
||
294 |
6640 |
ctx_obj->Set(context, |
|
295 |
env->syscall_string(), |
||
296 |
OneByteString(isolate, syscall)).Check(); |
||
297 |
} |
||
298 |
430621 |
return err; |
|
299 |
} |
||
300 |
|||
301 |
} // namespace fs |
||
302 |
} // namespace node |
||
303 |
|||
304 |
#endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS |
||
305 |
|||
306 |
#endif // SRC_NODE_FILE_INL_H_ |
Generated by: GCOVR (Version 3.4) |