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.h Lines: 153 166 92.2 %
Date: 2019-09-13 22:28:55 Branches: 35 62 56.5 %

Line Branch Exec Source
1
#ifndef SRC_NODE_FILE_H_
2
#define SRC_NODE_FILE_H_
3
4
#if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
5
6
#include "node.h"
7
#include "stream_base.h"
8
#include "req_wrap-inl.h"
9
#include <iostream>
10
11
namespace node {
12
13
using v8::Context;
14
using v8::FunctionCallbackInfo;
15
using v8::HandleScope;
16
using v8::Local;
17
using v8::MaybeLocal;
18
using v8::Object;
19
using v8::Promise;
20
using v8::Undefined;
21
using v8::Value;
22
23
namespace fs {
24
25
// structure used to store state during a complex operation, e.g., mkdirp.
26
5011
class FSContinuationData : public MemoryRetainer {
27
 public:
28
5001
  FSContinuationData(uv_fs_t* req, int mode, uv_fs_cb done_cb)
29
5001
      : req(req), mode(mode), done_cb(done_cb) {
30
5001
  }
31
32
  uv_fs_t* req;
33
  int mode;
34
  std::vector<std::string> paths{};
35
36
72
  void PushPath(std::string&& path) {
37
72
    paths.emplace_back(std::move(path));
38
72
  }
39
40
4991
  void PushPath(const std::string& path) {
41
4991
    paths.push_back(path);
42
4991
  }
43
44
5063
  std::string PopPath() {
45
5063
    CHECK_GT(paths.size(), 0);
46
5063
    std::string path = std::move(paths.back());
47
5063
    paths.pop_back();
48
5063
    return path;
49
  }
50
51
10
  void Done(int result) {
52
10
    req->result = result;
53
10
    done_cb(req);
54
10
  }
55
56
  void MemoryInfo(MemoryTracker* tracker) const override {
57
    tracker->TrackField("paths", paths);
58
  }
59
60
  SET_MEMORY_INFO_NAME(FSContinuationData)
61
  SET_SELF_SIZE(FSContinuationData)
62
63
 private:
64
  uv_fs_cb done_cb;
65
};
66
67
59840
class FSReqBase : public ReqWrap<uv_fs_t> {
68
 public:
69
  typedef MaybeStackBuffer<char, 64> FSReqBuffer;
70
  std::unique_ptr<FSContinuationData> continuation_data = nullptr;
71
72
59849
  FSReqBase(Environment* env, Local<Object> req, AsyncWrap::ProviderType type,
73
            bool use_bigint)
74
59849
      : ReqWrap(env, req, type), use_bigint_(use_bigint) {
75
59849
  }
76
77
59689
  void Init(const char* syscall,
78
            const char* data,
79
            size_t len,
80
            enum encoding encoding) {
81
59689
    syscall_ = syscall;
82
59689
    encoding_ = encoding;
83
84
59689
    if (data != nullptr) {
85
358
      CHECK(!has_data_);
86
358
      buffer_.AllocateSufficientStorage(len + 1);
87
358
      buffer_.SetLengthAndZeroTerminate(len);
88
358
      memcpy(*buffer_, data, len);
89
358
      has_data_ = true;
90
    }
91
59689
  }
92
93
141
  FSReqBuffer& Init(const char* syscall, size_t len,
94
                    enum encoding encoding) {
95
141
    syscall_ = syscall;
96
141
    encoding_ = encoding;
97
98
141
    buffer_.AllocateSufficientStorage(len + 1);
99
141
    has_data_ = false;  // so that the data does not show up in error messages
100
141
    return buffer_;
101
  }
102
103
  virtual void Reject(Local<Value> reject) = 0;
104
  virtual void Resolve(Local<Value> value) = 0;
105
  virtual void ResolveStat(const uv_stat_t* stat) = 0;
106
  virtual void SetReturnValue(const FunctionCallbackInfo<Value>& args) = 0;
107
108
4726
  const char* syscall() const { return syscall_; }
109
4726
  const char* data() const { return has_data_ ? *buffer_ : nullptr; }
110
5949
  enum encoding encoding() const { return encoding_; }
111
112
5859
  bool use_bigint() const { return use_bigint_; }
113
114
59878
  static FSReqBase* from_req(uv_fs_t* req) {
115
59878
    return static_cast<FSReqBase*>(ReqWrap::from_req(req));
116
  }
117
118
  FSReqBase(const FSReqBase&) = delete;
119
  FSReqBase& operator=(const FSReqBase&) = delete;
120
121
 private:
122
  enum encoding encoding_ = UTF8;
123
  bool has_data_ = false;
124
  const char* syscall_ = nullptr;
125
  bool use_bigint_ = false;
126
127
  // Typically, the content of buffer_ is something like a file name, so
128
  // something around 64 bytes should be enough.
129
  FSReqBuffer buffer_;
130
};
131
132
118942
class FSReqCallback : public FSReqBase {
133
 public:
134
59480
  FSReqCallback(Environment* env, Local<Object> req, bool use_bigint)
135
59480
      : FSReqBase(env, req, AsyncWrap::PROVIDER_FSREQCALLBACK, use_bigint) { }
136
137
  void Reject(Local<Value> reject) override;
138
  void Resolve(Local<Value> value) override;
139
  void ResolveStat(const uv_stat_t* stat) override;
140
  void SetReturnValue(const FunctionCallbackInfo<Value>& args) override;
141
142
1
  void MemoryInfo(MemoryTracker* tracker) const override {
143
1
    tracker->TrackField("continuation_data", continuation_data);
144
1
  }
145
146
1
  SET_MEMORY_INFO_NAME(FSReqCallback)
147
1
  SET_SELF_SIZE(FSReqCallback)
148
149
  FSReqCallback(const FSReqCallback&) = delete;
150
  FSReqCallback& operator=(const FSReqCallback&) = delete;
151
};
152
153
template <typename NativeT, typename V8T>
154
201843
constexpr void FillStatsArray(AliasedBufferBase<NativeT, V8T>* fields,
155
                              const uv_stat_t* s,
156
                              const size_t offset = 0) {
157
#define SET_FIELD_WITH_STAT(stat_offset, stat)                               \
158
  fields->SetValue(offset + static_cast<size_t>(FsStatsOffset::stat_offset), \
159
                   static_cast<NativeT>(stat))
160
161
#define SET_FIELD_WITH_TIME_STAT(stat_offset, stat)                          \
162
  /* NOLINTNEXTLINE(runtime/int) */                                          \
163
  SET_FIELD_WITH_STAT(stat_offset, static_cast<unsigned long>(stat))
164
165
201843
  SET_FIELD_WITH_STAT(kDev, s->st_dev);
166
201843
  SET_FIELD_WITH_STAT(kMode, s->st_mode);
167
201843
  SET_FIELD_WITH_STAT(kNlink, s->st_nlink);
168
201843
  SET_FIELD_WITH_STAT(kUid, s->st_uid);
169
201843
  SET_FIELD_WITH_STAT(kGid, s->st_gid);
170
201843
  SET_FIELD_WITH_STAT(kRdev, s->st_rdev);
171
201843
  SET_FIELD_WITH_STAT(kBlkSize, s->st_blksize);
172
201843
  SET_FIELD_WITH_STAT(kIno, s->st_ino);
173
201843
  SET_FIELD_WITH_STAT(kSize, s->st_size);
174
201843
  SET_FIELD_WITH_STAT(kBlocks, s->st_blocks);
175
176
201843
  SET_FIELD_WITH_TIME_STAT(kATimeSec, s->st_atim.tv_sec);
177
201843
  SET_FIELD_WITH_TIME_STAT(kATimeNsec, s->st_atim.tv_nsec);
178
201843
  SET_FIELD_WITH_TIME_STAT(kMTimeSec, s->st_mtim.tv_sec);
179
201843
  SET_FIELD_WITH_TIME_STAT(kMTimeNsec, s->st_mtim.tv_nsec);
180
201843
  SET_FIELD_WITH_TIME_STAT(kCTimeSec, s->st_ctim.tv_sec);
181
201843
  SET_FIELD_WITH_TIME_STAT(kCTimeNsec, s->st_ctim.tv_nsec);
182
201843
  SET_FIELD_WITH_TIME_STAT(kBirthTimeSec, s->st_birthtim.tv_sec);
183
201843
  SET_FIELD_WITH_TIME_STAT(kBirthTimeNsec, s->st_birthtim.tv_nsec);
184
185
#undef SET_FIELD_WITH_TIME_STAT
186
#undef SET_FIELD_WITH_STAT
187
201843
}
188
189
201713
inline Local<Value> FillGlobalStatsArray(Environment* env,
190
                                         const bool use_bigint,
191
                                         const uv_stat_t* s,
192
                                         const bool second = false) {
193
  const ptrdiff_t offset =
194
201713
      second ? static_cast<ptrdiff_t>(FsStatsOffset::kFsStatsFieldsNumber) : 0;
195
201713
  if (use_bigint) {
196
10
    auto* const arr = env->fs_stats_field_bigint_array();
197
10
    FillStatsArray(arr, s, offset);
198
20
    return arr->GetJSArray();
199
  } else {
200
201703
    auto* const arr = env->fs_stats_field_array();
201
201703
    FillStatsArray(arr, s, offset);
202
403406
    return arr->GetJSArray();
203
  }
204
}
205
206
template <typename AliasedBufferT>
207
class FSReqPromise : public FSReqBase {
208
 public:
209
369
  static FSReqPromise* New(Environment* env, bool use_bigint) {
210
    v8::Local<Object> obj;
211

738
    if (!env->fsreqpromise_constructor_template()
212
1107
             ->NewInstance(env->context())
213
1107
             .ToLocal(&obj)) {
214
      return nullptr;
215
    }
216
    v8::Local<v8::Promise::Resolver> resolver;
217




1845
    if (!v8::Promise::Resolver::New(env->context()).ToLocal(&resolver) ||
218



1845
        obj->Set(env->context(), env->promise_string(), resolver).IsNothing()) {
219
      return nullptr;
220
    }
221
369
    return new FSReqPromise(env, obj, use_bigint);
222
  }
223
224
738
  ~FSReqPromise() override {
225
    // Validate that the promise was explicitly resolved or rejected.
226

369
    CHECK(finished_);
227

1107
  }
228
229
22
  void Reject(Local<Value> reject) override {
230
22
    finished_ = true;
231
22
    HandleScope scope(env()->isolate());
232
44
    InternalCallbackScope callback_scope(this);
233
    Local<Value> value =
234
22
        object()->Get(env()->context(),
235
110
                      env()->promise_string()).ToLocalChecked();
236
22
    Local<Promise::Resolver> resolver = value.As<Promise::Resolver>();
237
88
    USE(resolver->Reject(env()->context(), reject).FromJust());
238
22
  }
239
240
347
  void Resolve(Local<Value> value) override {
241
347
    finished_ = true;
242
347
    HandleScope scope(env()->isolate());
243
694
    InternalCallbackScope callback_scope(this);
244
    Local<Value> val =
245
347
        object()->Get(env()->context(),
246
1735
                      env()->promise_string()).ToLocalChecked();
247
347
    Local<Promise::Resolver> resolver = val.As<Promise::Resolver>();
248
1388
    USE(resolver->Resolve(env()->context(), value).FromJust());
249
347
  }
250
251
130
  void ResolveStat(const uv_stat_t* stat) override {
252
130
    FillStatsArray(&stats_field_array_, stat);
253
260
    Resolve(stats_field_array_.GetJSArray());
254
130
  }
255
256
369
  void SetReturnValue(const FunctionCallbackInfo<Value>& args) override {
257
    Local<Value> val =
258
369
        object()->Get(env()->context(),
259
1845
                      env()->promise_string()).ToLocalChecked();
260
369
    Local<Promise::Resolver> resolver = val.As<Promise::Resolver>();
261
1107
    args.GetReturnValue().Set(resolver->GetPromise());
262
369
  }
263
264
3
  void MemoryInfo(MemoryTracker* tracker) const override {
265
3
    tracker->TrackField("stats_field_array", stats_field_array_);
266
3
    tracker->TrackField("continuation_data", continuation_data);
267
3
  }
268
269
3
  SET_MEMORY_INFO_NAME(FSReqPromise)
270
3
  SET_SELF_SIZE(FSReqPromise)
271
272
  FSReqPromise(const FSReqPromise&) = delete;
273
  FSReqPromise& operator=(const FSReqPromise&) = delete;
274
  FSReqPromise(const FSReqPromise&&) = delete;
275
  FSReqPromise& operator=(const FSReqPromise&&) = delete;
276
277
 private:
278
369
  FSReqPromise(Environment* env, v8::Local<v8::Object> obj, bool use_bigint)
279
      : FSReqBase(env, obj, AsyncWrap::PROVIDER_FSREQPROMISE, use_bigint),
280
        stats_field_array_(
281
            env->isolate(),
282
369
            static_cast<size_t>(FsStatsOffset::kFsStatsFieldsNumber)) {}
283
284
  bool finished_ = false;
285
  AliasedBufferT stats_field_array_;
286
};
287
288
class FSReqAfterScope {
289
 public:
290
  FSReqAfterScope(FSReqBase* wrap, uv_fs_t* req);
291
  ~FSReqAfterScope();
292
293
  bool Proceed();
294
295
  void Reject(uv_fs_t* req);
296
297
  FSReqAfterScope(const FSReqAfterScope&) = delete;
298
  FSReqAfterScope& operator=(const FSReqAfterScope&) = delete;
299
  FSReqAfterScope(const FSReqAfterScope&&) = delete;
300
  FSReqAfterScope& operator=(const FSReqAfterScope&&) = delete;
301
302
 private:
303
  FSReqBase* wrap_ = nullptr;
304
  uv_fs_t* req_ = nullptr;
305
  HandleScope handle_scope_;
306
  Context::Scope context_scope_;
307
};
308
309
class FileHandle;
310
311
// A request wrap specifically for uv_fs_read()s scheduled for reading
312
// from a FileHandle.
313
30
class FileHandleReadWrap : public ReqWrap<uv_fs_t> {
314
 public:
315
  FileHandleReadWrap(FileHandle* handle, v8::Local<v8::Object> obj);
316
317
221
  static inline FileHandleReadWrap* from_req(uv_fs_t* req) {
318
221
    return static_cast<FileHandleReadWrap*>(ReqWrap::from_req(req));
319
  }
320
321
  void MemoryInfo(MemoryTracker* tracker) const override;
322
2
  SET_MEMORY_INFO_NAME(FileHandleReadWrap)
323
2
  SET_SELF_SIZE(FileHandleReadWrap)
324
325
 private:
326
  FileHandle* file_handle_;
327
  uv_buf_t buffer_;
328
329
  friend class FileHandle;
330
};
331
332
// A wrapper for a file descriptor that will automatically close the fd when
333
// the object is garbage collected
334
class FileHandle : public AsyncWrap, public StreamBase {
335
 public:
336
  static FileHandle* New(Environment* env,
337
                         int fd,
338
                         v8::Local<v8::Object> obj = v8::Local<v8::Object>());
339
  ~FileHandle() override;
340
341
  static void New(const v8::FunctionCallbackInfo<v8::Value>& args);
342
343
  int fd() const { return fd_; }
344
345
  // Will asynchronously close the FD and return a Promise that will
346
  // be resolved once closing is complete.
347
  static void Close(const FunctionCallbackInfo<Value>& args);
348
349
  // Releases ownership of the FD.
350
  static void ReleaseFD(const FunctionCallbackInfo<Value>& args);
351
352
  // StreamBase interface:
353
  int ReadStart() override;
354
  int ReadStop() override;
355
356
227
  bool IsAlive() override { return !closed_; }
357
227
  bool IsClosing() override { return closing_; }
358
126
  AsyncWrap* GetAsyncWrap() override { return this; }
359
360
  // In the case of file streams, shutting down corresponds to closing.
361
  ShutdownWrap* CreateShutdownWrap(v8::Local<v8::Object> object) override;
362
  int DoShutdown(ShutdownWrap* req_wrap) override;
363
364
  int DoWrite(WriteWrap* w,
365
              uv_buf_t* bufs,
366
              size_t count,
367
              uv_stream_t* send_handle) override {
368
    return UV_ENOSYS;  // Not implemented (yet).
369
  }
370
371
2
  void MemoryInfo(MemoryTracker* tracker) const override {
372
2
    tracker->TrackField("current_read", current_read_);
373
2
  }
374
375
2
  SET_MEMORY_INFO_NAME(FileHandle)
376
2
  SET_SELF_SIZE(FileHandle)
377
378
  FileHandle(const FileHandle&) = delete;
379
  FileHandle& operator=(const FileHandle&) = delete;
380
  FileHandle(const FileHandle&&) = delete;
381
  FileHandle& operator=(const FileHandle&&) = delete;
382
383
 private:
384
  FileHandle(Environment* env, v8::Local<v8::Object> obj, int fd);
385
386
  // Synchronous close that emits a warning
387
  void Close();
388
  void AfterClose();
389
390
  class CloseReq : public ReqWrap<uv_fs_t> {
391
   public:
392
69
    CloseReq(Environment* env,
393
             Local<Object> obj,
394
             Local<Promise> promise,
395
             Local<Value> ref)
396
138
        : ReqWrap(env, obj, AsyncWrap::PROVIDER_FILEHANDLECLOSEREQ) {
397
69
      promise_.Reset(env->isolate(), promise);
398
69
      ref_.Reset(env->isolate(), ref);
399
69
    }
400
401
345
    ~CloseReq() override {
402
69
      uv_fs_req_cleanup(req());
403
69
      promise_.Reset();
404
69
      ref_.Reset();
405
138
    }
406
407
    FileHandle* file_handle();
408
409
    void MemoryInfo(MemoryTracker* tracker) const override {
410
      tracker->TrackField("promise", promise_);
411
      tracker->TrackField("ref", ref_);
412
    }
413
414
    SET_MEMORY_INFO_NAME(CloseReq)
415
    SET_SELF_SIZE(CloseReq)
416
417
    void Resolve();
418
419
    void Reject(Local<Value> reason);
420
421
69
    static CloseReq* from_req(uv_fs_t* req) {
422
69
      return static_cast<CloseReq*>(ReqWrap::from_req(req));
423
    }
424
425
    CloseReq(const CloseReq&) = delete;
426
    CloseReq& operator=(const CloseReq&) = delete;
427
    CloseReq(const CloseReq&&) = delete;
428
    CloseReq& operator=(const CloseReq&&) = delete;
429
430
   private:
431
    v8::Global<Promise> promise_{};
432
    v8::Global<Value> ref_{};
433
  };
434
435
  // Asynchronous close
436
  inline MaybeLocal<Promise> ClosePromise();
437
438
  int fd_;
439
  bool closing_ = false;
440
  bool closed_ = false;
441
  int64_t read_offset_ = -1;
442
  int64_t read_length_ = -1;
443
444
  bool reading_ = false;
445
  std::unique_ptr<FileHandleReadWrap> current_read_ = nullptr;
446
};
447
448
int MKDirpSync(uv_loop_t* loop,
449
               uv_fs_t* req,
450
               const std::string& path,
451
               int mode,
452
               uv_fs_cb cb = nullptr);
453
}  // namespace fs
454
455
}  // namespace node
456
457
#endif  // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
458
459
#endif  // SRC_NODE_FILE_H_