GCC Code Coverage Report
Directory: ../ Exec Total Coverage
File: /home/iojs/build/workspace/node-test-commit-linux-coverage/nodes/benchmark/out/../src/fs_event_wrap.cc Lines: 65 73 89.0 %
Date: 2017-11-19 Branches: 25 42 59.5 %

Line Branch Exec Source
1
// Copyright Joyent, Inc. and other Node contributors.
2
//
3
// Permission is hereby granted, free of charge, to any person obtaining a
4
// copy of this software and associated documentation files (the
5
// "Software"), to deal in the Software without restriction, including
6
// without limitation the rights to use, copy, modify, merge, publish,
7
// distribute, sublicense, and/or sell copies of the Software, and to permit
8
// persons to whom the Software is furnished to do so, subject to the
9
// following conditions:
10
//
11
// The above copyright notice and this permission notice shall be included
12
// in all copies or substantial portions of the Software.
13
//
14
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
17
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
18
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
19
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
20
// USE OR OTHER DEALINGS IN THE SOFTWARE.
21
22
#include "async_wrap-inl.h"
23
#include "env-inl.h"
24
#include "util-inl.h"
25
#include "node.h"
26
#include "handle_wrap.h"
27
#include "string_bytes.h"
28
29
#include <stdlib.h>
30
31
namespace node {
32
33
using v8::Context;
34
using v8::FunctionCallbackInfo;
35
using v8::FunctionTemplate;
36
using v8::HandleScope;
37
using v8::Integer;
38
using v8::Local;
39
using v8::MaybeLocal;
40
using v8::Object;
41
using v8::String;
42
using v8::Value;
43
44
namespace {
45
46
class FSEventWrap: public HandleWrap {
47
 public:
48
  static void Initialize(Local<Object> target,
49
                         Local<Value> unused,
50
                         Local<Context> context);
51
  static void New(const FunctionCallbackInfo<Value>& args);
52
  static void Start(const FunctionCallbackInfo<Value>& args);
53
  static void Close(const FunctionCallbackInfo<Value>& args);
54
55
  size_t self_size() const override { return sizeof(*this); }
56
57
 private:
58
  static const encoding kDefaultEncoding = UTF8;
59
60
  FSEventWrap(Environment* env, Local<Object> object);
61
  ~FSEventWrap() override;
62
63
  static void OnEvent(uv_fs_event_t* handle, const char* filename, int events,
64
    int status);
65
66
  uv_fs_event_t handle_;
67
  bool initialized_ = false;
68
  enum encoding encoding_ = kDefaultEncoding;
69
};
70
71
72
17
FSEventWrap::FSEventWrap(Environment* env, Local<Object> object)
73
    : HandleWrap(env,
74
                 object,
75
                 reinterpret_cast<uv_handle_t*>(&handle_),
76
17
                 AsyncWrap::PROVIDER_FSEVENTWRAP) {}
77
78
79
45
FSEventWrap::~FSEventWrap() {
80
15
  CHECK_EQ(initialized_, false);
81
30
}
82
83
84
3287
void FSEventWrap::Initialize(Local<Object> target,
85
                             Local<Value> unused,
86
                             Local<Context> context) {
87
3287
  Environment* env = Environment::GetCurrent(context);
88
89
3287
  auto fsevent_string = FIXED_ONE_BYTE_STRING(env->isolate(), "FSEvent");
90
3287
  Local<FunctionTemplate> t = env->NewFunctionTemplate(New);
91
6574
  t->InstanceTemplate()->SetInternalFieldCount(1);
92
3287
  t->SetClassName(fsevent_string);
93
94
3287
  AsyncWrap::AddWrapMethods(env, t);
95
3287
  env->SetProtoMethod(t, "start", Start);
96
3287
  env->SetProtoMethod(t, "close", Close);
97
98
6574
  target->Set(fsevent_string, t->GetFunction());
99
3287
}
100
101
102
17
void FSEventWrap::New(const FunctionCallbackInfo<Value>& args) {
103
17
  CHECK(args.IsConstructCall());
104
17
  Environment* env = Environment::GetCurrent(args);
105
17
  new FSEventWrap(env, args.This());
106
17
}
107
108
109
16
void FSEventWrap::Start(const FunctionCallbackInfo<Value>& args) {
110
16
  Environment* env = Environment::GetCurrent(args);
111
112
  FSEventWrap* wrap;
113
16
  ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder());
114
16
  CHECK_EQ(wrap->initialized_, false);
115
116
  static const char kErrMsg[] = "filename must be a string or Buffer";
117
16
  if (args.Length() < 1)
118
    return env->ThrowTypeError(kErrMsg);
119
120
16
  BufferValue path(env->isolate(), args[0]);
121
16
  if (*path == nullptr)
122
    return env->ThrowTypeError(kErrMsg);
123
124
16
  unsigned int flags = 0;
125
32
  if (args[2]->IsTrue())
126
    flags |= UV_FS_EVENT_RECURSIVE;
127
128
32
  wrap->encoding_ = ParseEncoding(env->isolate(), args[3], kDefaultEncoding);
129
130
16
  int err = uv_fs_event_init(wrap->env()->event_loop(), &wrap->handle_);
131
16
  if (err == 0) {
132
16
    wrap->initialized_ = true;
133
134
16
    err = uv_fs_event_start(&wrap->handle_, OnEvent, *path, flags);
135
136
16
    if (err == 0) {
137
      // Check for persistent argument
138
30
      if (!args[1]->IsTrue()) {
139
1
        uv_unref(reinterpret_cast<uv_handle_t*>(&wrap->handle_));
140
      }
141
    } else {
142
1
      FSEventWrap::Close(args);
143
    }
144
  }
145
146
32
  args.GetReturnValue().Set(err);
147
}
148
149
150
9
void FSEventWrap::OnEvent(uv_fs_event_t* handle, const char* filename,
151
    int events, int status) {
152
9
  FSEventWrap* wrap = static_cast<FSEventWrap*>(handle->data);
153
9
  Environment* env = wrap->env();
154
155
9
  HandleScope handle_scope(env->isolate());
156
9
  Context::Scope context_scope(env->context());
157
158
18
  CHECK_EQ(wrap->persistent().IsEmpty(), false);
159
160
  // We're in a bind here. libuv can set both UV_RENAME and UV_CHANGE but
161
  // the Node API only lets us pass a single event to JS land.
162
  //
163
  // The obvious solution is to run the callback twice, once for each event.
164
  // However, since the second event is not allowed to fire if the handle is
165
  // closed after the first event, and since there is no good way to detect
166
  // closed handles, that option is out.
167
  //
168
  // For now, ignore the UV_CHANGE event if UV_RENAME is also set. Make the
169
  // assumption that a rename implicitly means an attribute change. Not too
170
  // unreasonable, right? Still, we should revisit this before v1.0.
171
  Local<String> event_string;
172
9
  if (status) {
173
    event_string = String::Empty(env->isolate());
174
9
  } else if (events & UV_RENAME) {
175
5
    event_string = env->rename_string();
176
4
  } else if (events & UV_CHANGE) {
177
4
    event_string = env->change_string();
178
  } else {
179
    CHECK(0 && "bad fs events flag");
180
  }
181
182
  Local<Value> argv[] = {
183
    Integer::New(env->isolate(), status),
184
    event_string,
185
    Null(env->isolate())
186
36
  };
187
188
9
  if (filename != nullptr) {
189
    Local<Value> error;
190
    MaybeLocal<Value> fn = StringBytes::Encode(env->isolate(),
191
                                               filename,
192
                                               wrap->encoding_,
193
9
                                               &error);
194
9
    if (fn.IsEmpty()) {
195
      argv[0] = Integer::New(env->isolate(), UV_EINVAL);
196
      argv[2] = StringBytes::Encode(env->isolate(),
197
                                    filename,
198
                                    strlen(filename),
199
                                    BUFFER,
200
                                    &error).ToLocalChecked();
201
    } else {
202
9
      argv[2] = fn.ToLocalChecked();
203
    }
204
  }
205
206
18
  wrap->MakeCallback(env->onchange_string(), arraysize(argv), argv);
207
9
}
208
209
210
16
void FSEventWrap::Close(const FunctionCallbackInfo<Value>& args) {
211
  FSEventWrap* wrap;
212
17
  ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder());
213
214

16
  if (wrap == nullptr || wrap->initialized_ == false)
215
1
    return;
216
15
  wrap->initialized_ = false;
217
218
15
  HandleWrap::Close(args);
219
}
220
221
}  // anonymous namespace
222
}  // namespace node
223
224
3332
NODE_BUILTIN_MODULE_CONTEXT_AWARE(fs_event_wrap, node::FSEventWrap::Initialize)