GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: node_file-inl.h Lines: 150 157 95.5 %
Date: 2022-06-20 04:16:14 Branches: 26 36 72.2 %

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
7091
FSContinuationData::FSContinuationData(uv_fs_t* req, int mode, uv_fs_cb done_cb)
13
7091
  : done_cb_(done_cb), req_(req), mode_(mode) {
14
7091
}
15
16
766
void FSContinuationData::PushPath(std::string&& path) {
17
766
  paths_.emplace_back(std::move(path));
18
766
}
19
20
6731
void FSContinuationData::PushPath(const std::string& path) {
21
6731
  paths_.push_back(path);
22
6731
}
23
24
613
void FSContinuationData::MaybeSetFirstPath(const std::string& path) {
25
613
  if (first_path_.empty()) {
26
526
    first_path_ = path;
27
  }
28
613
}
29
30
7497
std::string FSContinuationData::PopPath() {
31
7497
  CHECK(!paths_.empty());
32
7497
  std::string path = std::move(paths_.back());
33
7497
  paths_.pop_back();
34
7497
  return path;
35
}
36
37
360
void FSContinuationData::Done(int result) {
38
360
  req_->result = result;
39
360
  done_cb_(req_);
40
360
}
41
42
57673
FSReqBase::FSReqBase(BindingData* binding_data,
43
                     v8::Local<v8::Object> req,
44
                     AsyncWrap::ProviderType type,
45
57673
                     bool use_bigint)
46
  : ReqWrap(binding_data->env(), req, type),
47
    use_bigint_(use_bigint),
48
57673
    binding_data_(binding_data) {
49
57673
}
50
51
57594
void FSReqBase::Init(const char* syscall,
52
                     const char* data,
53
                     size_t len,
54
                     enum encoding encoding) {
55
57594
  syscall_ = syscall;
56
57594
  encoding_ = encoding;
57
58
57594
  if (data != nullptr) {
59
133
    CHECK(!has_data_);
60
133
    buffer_.AllocateSufficientStorage(len + 1);
61
133
    buffer_.SetLengthAndZeroTerminate(len);
62
133
    memcpy(*buffer_, data, len);
63
133
    has_data_ = true;
64
  }
65
57594
}
66
67
FSReqBase::FSReqBuffer&
68
79
FSReqBase::Init(const char* syscall, size_t len, enum encoding encoding) {
69
79
  syscall_ = syscall;
70
79
  encoding_ = encoding;
71
72
79
  buffer_.AllocateSufficientStorage(len + 1);
73
79
  has_data_ = false;  // so that the data does not show up in error messages
74
79
  return buffer_;
75
}
76
77
51522
FSReqCallback::FSReqCallback(BindingData* binding_data,
78
                             v8::Local<v8::Object> req,
79
51522
                             bool use_bigint)
80
  : FSReqBase(binding_data,
81
              req,
82
              AsyncWrap::PROVIDER_FSREQCALLBACK,
83
51522
              use_bigint) {}
84
85
template <typename NativeT, typename V8T>
86
380428
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
190214
  SET_FIELD_WITH_STAT(kDev, s->st_dev);
98
190214
  SET_FIELD_WITH_STAT(kMode, s->st_mode);
99
190214
  SET_FIELD_WITH_STAT(kNlink, s->st_nlink);
100
190214
  SET_FIELD_WITH_STAT(kUid, s->st_uid);
101
190214
  SET_FIELD_WITH_STAT(kGid, s->st_gid);
102
190214
  SET_FIELD_WITH_STAT(kRdev, s->st_rdev);
103
190214
  SET_FIELD_WITH_STAT(kBlkSize, s->st_blksize);
104
190214
  SET_FIELD_WITH_STAT(kIno, s->st_ino);
105
190214
  SET_FIELD_WITH_STAT(kSize, s->st_size);
106
190214
  SET_FIELD_WITH_STAT(kBlocks, s->st_blocks);
107
108
190214
  SET_FIELD_WITH_TIME_STAT(kATimeSec, s->st_atim.tv_sec);
109
190214
  SET_FIELD_WITH_TIME_STAT(kATimeNsec, s->st_atim.tv_nsec);
110
190214
  SET_FIELD_WITH_TIME_STAT(kMTimeSec, s->st_mtim.tv_sec);
111
190214
  SET_FIELD_WITH_TIME_STAT(kMTimeNsec, s->st_mtim.tv_nsec);
112
190214
  SET_FIELD_WITH_TIME_STAT(kCTimeSec, s->st_ctim.tv_sec);
113
190214
  SET_FIELD_WITH_TIME_STAT(kCTimeNsec, s->st_ctim.tv_nsec);
114
190214
  SET_FIELD_WITH_TIME_STAT(kBirthTimeSec, s->st_birthtim.tv_sec);
115
190214
  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
190214
}
120
121
188670
v8::Local<v8::Value> FillGlobalStatsArray(BindingData* binding_data,
122
                                          const bool use_bigint,
123
                                          const uv_stat_t* s,
124
                                          const bool second) {
125
188670
  const ptrdiff_t offset =
126
188670
      second ? static_cast<ptrdiff_t>(FsStatsOffset::kFsStatsFieldsNumber) : 0;
127
188670
  if (use_bigint) {
128
113834
    auto* const arr = &binding_data->stats_field_bigint_array;
129
113834
    FillStatsArray(arr, s, offset);
130
227668
    return arr->GetJSArray();
131
  } else {
132
74836
    auto* const arr = &binding_data->stats_field_array;
133
74836
    FillStatsArray(arr, s, offset);
134
149672
    return arr->GetJSArray();
135
  }
136
}
137
138
template <typename AliasedBufferT>
139
FSReqPromise<AliasedBufferT>*
140
12302
FSReqPromise<AliasedBufferT>::New(BindingData* binding_data,
141
                                  bool use_bigint) {
142
12302
  Environment* env = binding_data->env();
143
  v8::Local<v8::Object> obj;
144
12302
  if (!env->fsreqpromise_constructor_template()
145
12302
           ->NewInstance(env->context())
146
12302
           .ToLocal(&obj)) {
147
    return nullptr;
148
  }
149
  v8::Local<v8::Promise::Resolver> resolver;
150
36906
  if (!v8::Promise::Resolver::New(env->context()).ToLocal(&resolver) ||
151

49208
      obj->Set(env->context(), env->promise_string(), resolver).IsNothing()) {
152
    return nullptr;
153
  }
154
12302
  return new FSReqPromise(binding_data, obj, use_bigint);
155
}
156
157
template <typename AliasedBufferT>
158
24588
FSReqPromise<AliasedBufferT>::~FSReqPromise() {
159
  // Validate that the promise was explicitly resolved or rejected but only if
160
  // the Isolate is not terminating because in this case the promise might have
161
  // not finished.
162

12294
  if (!env()->is_stopping()) CHECK(finished_);
163
36882
}
164
165
template <typename AliasedBufferT>
166
12302
FSReqPromise<AliasedBufferT>::FSReqPromise(
167
    BindingData* binding_data,
168
    v8::Local<v8::Object> obj,
169
    bool use_bigint)
170
  : FSReqBase(binding_data,
171
              obj,
172
              AsyncWrap::PROVIDER_FSREQPROMISE,
173
              use_bigint),
174
    stats_field_array_(
175
        env()->isolate(),
176
12302
        static_cast<size_t>(FsStatsOffset::kFsStatsFieldsNumber)) {}
177
178
template <typename AliasedBufferT>
179
1362
void FSReqPromise<AliasedBufferT>::Reject(v8::Local<v8::Value> reject) {
180
1362
  finished_ = true;
181
2724
  v8::HandleScope scope(env()->isolate());
182
1362
  InternalCallbackScope callback_scope(this);
183
  v8::Local<v8::Value> value =
184
4086
      object()->Get(env()->context(),
185
1362
                    env()->promise_string()).ToLocalChecked();
186
1362
  v8::Local<v8::Promise::Resolver> resolver = value.As<v8::Promise::Resolver>();
187
2724
  USE(resolver->Reject(env()->context(), reject).FromJust());
188
1362
}
189
190
template <typename AliasedBufferT>
191
9310
void FSReqPromise<AliasedBufferT>::Resolve(v8::Local<v8::Value> value) {
192
9310
  finished_ = true;
193
18620
  v8::HandleScope scope(env()->isolate());
194
9310
  InternalCallbackScope callback_scope(this);
195
  v8::Local<v8::Value> val =
196
27930
      object()->Get(env()->context(),
197
9310
                    env()->promise_string()).ToLocalChecked();
198
9310
  v8::Local<v8::Promise::Resolver> resolver = val.As<v8::Promise::Resolver>();
199
18620
  USE(resolver->Resolve(env()->context(), value).FromJust());
200
9310
}
201
202
template <typename AliasedBufferT>
203
3088
void FSReqPromise<AliasedBufferT>::ResolveStat(const uv_stat_t* stat) {
204
3088
  FillStatsArray(&stats_field_array_, stat);
205
6176
  Resolve(stats_field_array_.GetJSArray());
206
3088
}
207
208
template <typename AliasedBufferT>
209
12302
void FSReqPromise<AliasedBufferT>::SetReturnValue(
210
    const v8::FunctionCallbackInfo<v8::Value>& args) {
211
  v8::Local<v8::Value> val =
212
36906
      object()->Get(env()->context(),
213
12302
                    env()->promise_string()).ToLocalChecked();
214
12302
  v8::Local<v8::Promise::Resolver> resolver = val.As<v8::Promise::Resolver>();
215
12302
  args.GetReturnValue().Set(resolver->GetPromise());
216
12302
}
217
218
template <typename AliasedBufferT>
219
2
void FSReqPromise<AliasedBufferT>::MemoryInfo(MemoryTracker* tracker) const {
220
2
  FSReqBase::MemoryInfo(tracker);
221
2
  tracker->TrackField("stats_field_array", stats_field_array_);
222
}
223
224
773730
FSReqBase* GetReqWrap(const v8::FunctionCallbackInfo<v8::Value>& args,
225
                      int index,
226
                      bool use_bigint) {
227
773730
  v8::Local<v8::Value> value = args[index];
228
773730
  if (value->IsObject()) {
229
51522
    return Unwrap<FSReqBase>(value.As<v8::Object>());
230
  }
231
232
722208
  BindingData* binding_data = Environment::GetBindingData<BindingData>(args);
233
722208
  Environment* env = binding_data->env();
234
1444416
  if (value->StrictEquals(env->fs_use_promises_symbol())) {
235
6151
    if (use_bigint) {
236
420
      return FSReqPromise<AliasedBigUint64Array>::New(binding_data, use_bigint);
237
    } else {
238
5731
      return FSReqPromise<AliasedFloat64Array>::New(binding_data, use_bigint);
239
    }
240
  }
241
716057
  return nullptr;
242
}
243
244
// Returns nullptr if the operation fails from the start.
245
template <typename Func, typename... Args>
246
115188
FSReqBase* AsyncDestCall(Environment* env, FSReqBase* req_wrap,
247
                         const v8::FunctionCallbackInfo<v8::Value>& args,
248
                         const char* syscall, const char* dest,
249
                         size_t len, enum encoding enc, uv_fs_cb after,
250
                         Func fn, Args... fn_args) {
251
115188
  CHECK_NOT_NULL(req_wrap);
252
115188
  req_wrap->Init(syscall, dest, len, enc);
253
115188
  int err = req_wrap->Dispatch(fn, fn_args..., after);
254
115188
  if (err < 0) {
255
    uv_fs_t* uv_req = req_wrap->req();
256
    uv_req->result = err;
257
    uv_req->path = nullptr;
258
    after(uv_req);  // after may delete req_wrap if there is an error
259
    req_wrap = nullptr;
260
  } else {
261
115188
    req_wrap->SetReturnValue(args);
262
  }
263
264
115188
  return req_wrap;
265
}
266
267
// Returns nullptr if the operation fails from the start.
268
template <typename Func, typename... Args>
269
114922
FSReqBase* AsyncCall(Environment* env,
270
                     FSReqBase* req_wrap,
271
                     const v8::FunctionCallbackInfo<v8::Value>& args,
272
                     const char* syscall, enum encoding enc,
273
                     uv_fs_cb after, Func fn, Args... fn_args) {
274
114922
  return AsyncDestCall(env, req_wrap, args,
275
                       syscall, nullptr, 0, enc,
276
114922
                       after, fn, fn_args...);
277
}
278
279
// Template counterpart of SYNC_CALL, except that it only puts
280
// the error number and the syscall in the context instead of
281
// creating an error in the C++ land.
282
// ctx must be checked using value->IsObject() before being passed.
283
template <typename Func, typename... Args>
284
715774
int SyncCall(Environment* env, v8::Local<v8::Value> ctx,
285
             FSReqWrapSync* req_wrap, const char* syscall,
286
             Func fn, Args... args) {
287
715774
  env->PrintSyncTrace();
288
715774
  int err = fn(env->event_loop(), &(req_wrap->req), args..., nullptr);
289
715774
  if (err < 0) {
290
2689
    v8::Local<v8::Context> context = env->context();
291
2689
    v8::Local<v8::Object> ctx_obj = ctx.As<v8::Object>();
292
2689
    v8::Isolate* isolate = env->isolate();
293
10756
    ctx_obj->Set(context,
294
                 env->errno_string(),
295
                 v8::Integer::New(isolate, err)).Check();
296
10756
    ctx_obj->Set(context,
297
                 env->syscall_string(),
298
                 OneByteString(isolate, syscall)).Check();
299
  }
300
715774
  return err;
301
}
302
303
}  // namespace fs
304
}  // namespace node
305
306
#endif  // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
307
308
#endif  // SRC_NODE_FILE_INL_H_