GCC Code Coverage Report
Directory: ../ Exec Total Coverage
File: /home/iojs/build/workspace/node-test-commit-linux-coverage-daily/nodes/benchmark/out/../src/node_file-inl.h Lines: 145 152 95.4 %
Date: 2020-02-27 22:14:15 Branches: 77 122 63.1 %

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
4472
FSContinuationData::FSContinuationData(uv_fs_t* req, int mode, uv_fs_cb done_cb)
13
4472
  : done_cb_(done_cb), req_(req), mode_(mode) {
14
4472
}
15
16
62
void FSContinuationData::PushPath(std::string&& path) {
17
62
  paths_.emplace_back(std::move(path));
18
62
}
19
20
4458
void FSContinuationData::PushPath(const std::string& path) {
21
4458
  paths_.push_back(path);
22
4458
}
23
24
150
void FSContinuationData::MaybeSetFirstPath(const std::string& path) {
25
150
  if (first_path_.empty()) {
26
127
    first_path_ = path;
27
  }
28
150
}
29
30
4520
std::string FSContinuationData::PopPath() {
31
4520
  CHECK_GT(paths_.size(), 0);
32
4520
  std::string path = std::move(paths_.back());
33
4520
  paths_.pop_back();
34
4520
  return path;
35
}
36
37
14
void FSContinuationData::Done(int result) {
38
14
  req_->result = result;
39
14
  done_cb_(req_);
40
14
}
41
42
49680
FSReqBase::FSReqBase(Environment* env,
43
          v8::Local<v8::Object> req,
44
          AsyncWrap::ProviderType type,
45
49680
          bool use_bigint)
46
49680
  : ReqWrap(env, req, type), use_bigint_(use_bigint) {
47
49680
}
48
49
49548
void FSReqBase::Init(const char* syscall,
50
                     const char* data,
51
                     size_t len,
52
                     enum encoding encoding) {
53
49548
  syscall_ = syscall;
54
49548
  encoding_ = encoding;
55
56
49548
  if (data != nullptr) {
57
248
    CHECK(!has_data_);
58
248
    buffer_.AllocateSufficientStorage(len + 1);
59
248
    buffer_.SetLengthAndZeroTerminate(len);
60
248
    memcpy(*buffer_, data, len);
61
248
    has_data_ = true;
62
  }
63
49548
}
64
65
FSReqBase::FSReqBuffer&
66
109
FSReqBase::Init(const char* syscall, size_t len, enum encoding encoding) {
67
109
  syscall_ = syscall;
68
109
  encoding_ = encoding;
69
70
109
  buffer_.AllocateSufficientStorage(len + 1);
71
109
  has_data_ = false;  // so that the data does not show up in error messages
72
109
  return buffer_;
73
}
74
75
48441
FSReqCallback::FSReqCallback(Environment* env,
76
48441
                             v8::Local<v8::Object> req, bool use_bigint)
77
48441
  : FSReqBase(env, req, AsyncWrap::PROVIDER_FSREQCALLBACK, use_bigint) {}
78
79
template <typename NativeT, typename V8T>
80
157400
void FillStatsArray(AliasedBufferBase<NativeT, V8T>* fields,
81
                    const uv_stat_t* s,
82
                    const size_t offset) {
83
#define SET_FIELD_WITH_STAT(stat_offset, stat)                               \
84
  fields->SetValue(offset + static_cast<size_t>(FsStatsOffset::stat_offset), \
85
                   static_cast<NativeT>(stat))
86
87
#define SET_FIELD_WITH_TIME_STAT(stat_offset, stat)                          \
88
  /* NOLINTNEXTLINE(runtime/int) */                                          \
89
  SET_FIELD_WITH_STAT(stat_offset, static_cast<unsigned long>(stat))
90
91
157400
  SET_FIELD_WITH_STAT(kDev, s->st_dev);
92
157402
  SET_FIELD_WITH_STAT(kMode, s->st_mode);
93
157402
  SET_FIELD_WITH_STAT(kNlink, s->st_nlink);
94
157402
  SET_FIELD_WITH_STAT(kUid, s->st_uid);
95
157401
  SET_FIELD_WITH_STAT(kGid, s->st_gid);
96
157400
  SET_FIELD_WITH_STAT(kRdev, s->st_rdev);
97
157402
  SET_FIELD_WITH_STAT(kBlkSize, s->st_blksize);
98
157402
  SET_FIELD_WITH_STAT(kIno, s->st_ino);
99
157401
  SET_FIELD_WITH_STAT(kSize, s->st_size);
100
157402
  SET_FIELD_WITH_STAT(kBlocks, s->st_blocks);
101
102
157402
  SET_FIELD_WITH_TIME_STAT(kATimeSec, s->st_atim.tv_sec);
103
157402
  SET_FIELD_WITH_TIME_STAT(kATimeNsec, s->st_atim.tv_nsec);
104
157401
  SET_FIELD_WITH_TIME_STAT(kMTimeSec, s->st_mtim.tv_sec);
105
157402
  SET_FIELD_WITH_TIME_STAT(kMTimeNsec, s->st_mtim.tv_nsec);
106
157402
  SET_FIELD_WITH_TIME_STAT(kCTimeSec, s->st_ctim.tv_sec);
107
157401
  SET_FIELD_WITH_TIME_STAT(kCTimeNsec, s->st_ctim.tv_nsec);
108
157400
  SET_FIELD_WITH_TIME_STAT(kBirthTimeSec, s->st_birthtim.tv_sec);
109
157402
  SET_FIELD_WITH_TIME_STAT(kBirthTimeNsec, s->st_birthtim.tv_nsec);
110
111
#undef SET_FIELD_WITH_TIME_STAT
112
#undef SET_FIELD_WITH_STAT
113
157402
}
114
115
157075
v8::Local<v8::Value> FillGlobalStatsArray(Environment* env,
116
                                          const bool use_bigint,
117
                                          const uv_stat_t* s,
118
                                          const bool second) {
119
  const ptrdiff_t offset =
120
157075
      second ? static_cast<ptrdiff_t>(FsStatsOffset::kFsStatsFieldsNumber) : 0;
121
157075
  if (use_bigint) {
122
10
    auto* const arr = env->fs_stats_field_bigint_array();
123
10
    FillStatsArray(arr, s, offset);
124
20
    return arr->GetJSArray();
125
  } else {
126
157065
    auto* const arr = env->fs_stats_field_array();
127
157063
    FillStatsArray(arr, s, offset);
128
314128
    return arr->GetJSArray();
129
  }
130
}
131
132
template <typename AliasedBufferT>
133
FSReqPromise<AliasedBufferT>*
134
1239
FSReqPromise<AliasedBufferT>::New(Environment* env, bool use_bigint) {
135
  v8::Local<v8::Object> obj;
136

3717
  if (!env->fsreqpromise_constructor_template()
137
3717
           ->NewInstance(env->context())
138
1239
           .ToLocal(&obj)) {
139
    return nullptr;
140
  }
141
  v8::Local<v8::Promise::Resolver> resolver;
142



4956
  if (!v8::Promise::Resolver::New(env->context()).ToLocal(&resolver) ||
143
6195
      obj->Set(env->context(), env->promise_string(), resolver).IsNothing()) {
144
    return nullptr;
145
  }
146
1239
  return new FSReqPromise(env, obj, use_bigint);
147
}
148
149
template <typename AliasedBufferT>
150
2478
FSReqPromise<AliasedBufferT>::~FSReqPromise() {
151
  // Validate that the promise was explicitly resolved or rejected.
152

1239
  CHECK(finished_);
153
3717
}
154
155
template <typename AliasedBufferT>
156
1239
FSReqPromise<AliasedBufferT>::FSReqPromise(
157
    Environment* env,
158
    v8::Local<v8::Object> obj,
159
    bool use_bigint)
160
  : FSReqBase(env, obj, AsyncWrap::PROVIDER_FSREQPROMISE, use_bigint),
161
    stats_field_array_(
162
        env->isolate(),
163
1239
        static_cast<size_t>(FsStatsOffset::kFsStatsFieldsNumber)) {}
164
165
template <typename AliasedBufferT>
166
42
void FSReqPromise<AliasedBufferT>::Reject(v8::Local<v8::Value> reject) {
167
42
  finished_ = true;
168
84
  v8::HandleScope scope(env()->isolate());
169
84
  InternalCallbackScope callback_scope(this);
170
  v8::Local<v8::Value> value =
171
84
      object()->Get(env()->context(),
172
210
                    env()->promise_string()).ToLocalChecked();
173
42
  v8::Local<v8::Promise::Resolver> resolver = value.As<v8::Promise::Resolver>();
174
126
  USE(resolver->Reject(env()->context(), reject).FromJust());
175
42
}
176
177
template <typename AliasedBufferT>
178
1197
void FSReqPromise<AliasedBufferT>::Resolve(v8::Local<v8::Value> value) {
179
1197
  finished_ = true;
180
2394
  v8::HandleScope scope(env()->isolate());
181
2394
  InternalCallbackScope callback_scope(this);
182
  v8::Local<v8::Value> val =
183
2394
      object()->Get(env()->context(),
184
5985
                    env()->promise_string()).ToLocalChecked();
185
1197
  v8::Local<v8::Promise::Resolver> resolver = val.As<v8::Promise::Resolver>();
186
3591
  USE(resolver->Resolve(env()->context(), value).FromJust());
187
1197
}
188
189
template <typename AliasedBufferT>
190
327
void FSReqPromise<AliasedBufferT>::ResolveStat(const uv_stat_t* stat) {
191
327
  FillStatsArray(&stats_field_array_, stat);
192
654
  Resolve(stats_field_array_.GetJSArray());
193
327
}
194
195
template <typename AliasedBufferT>
196
1239
void FSReqPromise<AliasedBufferT>::SetReturnValue(
197
    const v8::FunctionCallbackInfo<v8::Value>& args) {
198
  v8::Local<v8::Value> val =
199
2478
      object()->Get(env()->context(),
200
6195
                    env()->promise_string()).ToLocalChecked();
201
1239
  v8::Local<v8::Promise::Resolver> resolver = val.As<v8::Promise::Resolver>();
202
3717
  args.GetReturnValue().Set(resolver->GetPromise());
203
1239
}
204
205
template <typename AliasedBufferT>
206
1
void FSReqPromise<AliasedBufferT>::MemoryInfo(MemoryTracker* tracker) const {
207
1
  FSReqBase::MemoryInfo(tracker);
208
1
  tracker->TrackField("stats_field_array", stats_field_array_);
209
1
}
210
211
358002
FSReqBase* GetReqWrap(Environment* env, v8::Local<v8::Value> value,
212
                      bool use_bigint) {
213
358002
  if (value->IsObject()) {
214
48418
    return Unwrap<FSReqBase>(value.As<v8::Object>());
215
619167
  } else if (value->StrictEquals(env->fs_use_promises_symbol())) {
216
1239
    if (use_bigint) {
217
3
      return FSReqPromise<AliasedBigUint64Array>::New(env, use_bigint);
218
    } else {
219
1236
      return FSReqPromise<AliasedFloat64Array>::New(env, use_bigint);
220
    }
221
  }
222
308345
  return nullptr;
223
}
224
225
// Returns nullptr if the operation fails from the start.
226
template <typename Func, typename... Args>
227
49548
FSReqBase* AsyncDestCall(Environment* env, FSReqBase* req_wrap,
228
                         const v8::FunctionCallbackInfo<v8::Value>& args,
229
                         const char* syscall, const char* dest,
230
                         size_t len, enum encoding enc, uv_fs_cb after,
231
                         Func fn, Args... fn_args) {
232







49548
  CHECK_NOT_NULL(req_wrap);
233
49548
  req_wrap->Init(syscall, dest, len, enc);
234
49548
  int err = req_wrap->Dispatch(fn, fn_args..., after);
235







49548
  if (err < 0) {
236
    uv_fs_t* uv_req = req_wrap->req();
237
    uv_req->result = err;
238
    uv_req->path = nullptr;
239
    after(uv_req);  // after may delete req_wrap if there is an error
240
    req_wrap = nullptr;
241
  } else {
242
49548
    req_wrap->SetReturnValue(args);
243
  }
244
245
49548
  return req_wrap;
246
}
247
248
// Returns nullptr if the operation fails from the start.
249
template <typename Func, typename... Args>
250
49300
FSReqBase* AsyncCall(Environment* env,
251
                     FSReqBase* req_wrap,
252
                     const v8::FunctionCallbackInfo<v8::Value>& args,
253
                     const char* syscall, enum encoding enc,
254
                     uv_fs_cb after, Func fn, Args... fn_args) {
255
  return AsyncDestCall(env, req_wrap, args,
256
                       syscall, nullptr, 0, enc,
257
49300
                       after, fn, fn_args...);
258
}
259
260
// Template counterpart of SYNC_CALL, except that it only puts
261
// the error number and the syscall in the context instead of
262
// creating an error in the C++ land.
263
// ctx must be checked using value->IsObject() before being passed.
264
template <typename Func, typename... Args>
265
308235
int SyncCall(Environment* env, v8::Local<v8::Value> ctx,
266
             FSReqWrapSync* req_wrap, const char* syscall,
267
             Func fn, Args... args) {
268
308235
  env->PrintSyncTrace();
269
308236
  int err = fn(env->event_loop(), &(req_wrap->req), args..., nullptr);
270







308234
  if (err < 0) {
271
1065
    v8::Local<v8::Context> context = env->context();
272
1065
    v8::Local<v8::Object> ctx_obj = ctx.As<v8::Object>();
273
1065
    v8::Isolate* isolate = env->isolate();
274
4260
    ctx_obj->Set(context,
275
                 env->errno_string(),
276
                 v8::Integer::New(isolate, err)).Check();
277
4260
    ctx_obj->Set(context,
278
                 env->syscall_string(),
279
                 OneByteString(isolate, syscall)).Check();
280
  }
281
308234
  return err;
282
}
283
284
}  // namespace fs
285
}  // namespace node
286
287
#endif  // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
288
289
#endif  // SRC_NODE_FILE_INL_H_