GCC Code Coverage Report
Directory: ../src/ Exec Total Coverage
File: /home/node-core-coverage/node-core-coverage/workdir/node/src/pipe_wrap.cc Lines: 100 102 98.0 %
Date: 2016-07-26 Branches: 20 36 55.6 %

Line Exec Source
1
#include "pipe_wrap.h"
2
3
#include "async-wrap.h"
4
#include "connection_wrap.h"
5
#include "env.h"
6
#include "env-inl.h"
7
#include "handle_wrap.h"
8
#include "node.h"
9
#include "node_buffer.h"
10
#include "node_wrap.h"
11
#include "req-wrap.h"
12
#include "req-wrap-inl.h"
13
#include "stream_wrap.h"
14
#include "util-inl.h"
15
#include "util.h"
16
17
namespace node {
18
19
using v8::Boolean;
20
using v8::Context;
21
using v8::EscapableHandleScope;
22
using v8::External;
23
using v8::Function;
24
using v8::FunctionCallbackInfo;
25
using v8::FunctionTemplate;
26
using v8::HandleScope;
27
using v8::Integer;
28
using v8::Local;
29
using v8::Object;
30
using v8::String;
31
using v8::Value;
32
33
34
// TODO(bnoordhuis) share with TCPWrap?
35
14
class PipeConnectWrap : public ReqWrap<uv_connect_t> {
36
 public:
37
  PipeConnectWrap(Environment* env, Local<Object> req_wrap_obj);
38
39
  size_t self_size() const override { return sizeof(*this); }
40
};
41
42
43
14
PipeConnectWrap::PipeConnectWrap(Environment* env, Local<Object> req_wrap_obj)
44
14
    : ReqWrap(env, req_wrap_obj, AsyncWrap::PROVIDER_PIPECONNECTWRAP) {
45
14
  Wrap(req_wrap_obj, this);
46
14
}
47
48
49
14
static void NewPipeConnectWrap(const FunctionCallbackInfo<Value>& args) {
50
14
  CHECK(args.IsConstructCall());
51
14
}
52
53
54
11
Local<Object> PipeWrap::Instantiate(Environment* env, AsyncWrap* parent) {
55
22
  EscapableHandleScope handle_scope(env->isolate());
56
22
  CHECK_EQ(false, env->pipe_constructor_template().IsEmpty());
57
11
  Local<Function> constructor = env->pipe_constructor_template()->GetFunction();
58
11
  CHECK_EQ(false, constructor.IsEmpty());
59
22
  Local<Value> ptr = External::New(env->isolate(), parent);
60
  Local<Object> instance =
61
22
      constructor->NewInstance(env->context(), 1, &ptr).ToLocalChecked();
62
22
  return handle_scope.Escape(instance);
63
}
64
65
66
1510
void PipeWrap::Initialize(Local<Object> target,
67
                          Local<Value> unused,
68
                          Local<Context> context) {
69
1510
  Environment* env = Environment::GetCurrent(context);
70
71
3020
  Local<FunctionTemplate> t = env->NewFunctionTemplate(New);
72
1510
  t->SetClassName(FIXED_ONE_BYTE_STRING(env->isolate(), "Pipe"));
73
3020
  t->InstanceTemplate()->SetInternalFieldCount(1);
74
75
1510
  env->SetProtoMethod(t, "close", HandleWrap::Close);
76
1510
  env->SetProtoMethod(t, "unref", HandleWrap::Unref);
77
1510
  env->SetProtoMethod(t, "ref", HandleWrap::Ref);
78
1510
  env->SetProtoMethod(t, "hasRef", HandleWrap::HasRef);
79
80
1510
  StreamWrap::AddMethods(env, t);
81
82
1510
  env->SetProtoMethod(t, "bind", Bind);
83
1510
  env->SetProtoMethod(t, "listen", Listen);
84
1510
  env->SetProtoMethod(t, "connect", Connect);
85
1510
  env->SetProtoMethod(t, "open", Open);
86
87
#ifdef _WIN32
88
  env->SetProtoMethod(t, "setPendingInstances", SetPendingInstances);
89
#endif
90
91
4530
  target->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "Pipe"), t->GetFunction());
92
1510
  env->set_pipe_constructor_template(t);
93
94
  // Create FunctionTemplate for PipeConnectWrap.
95
  Local<FunctionTemplate> cwt =
96
3020
      FunctionTemplate::New(env->isolate(), NewPipeConnectWrap);
97
3020
  cwt->InstanceTemplate()->SetInternalFieldCount(1);
98
1510
  cwt->SetClassName(FIXED_ONE_BYTE_STRING(env->isolate(), "PipeConnectWrap"));
99
6040
  target->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "PipeConnectWrap"),
100
1510
              cwt->GetFunction());
101
1510
}
102
103
104
1778
void PipeWrap::New(const FunctionCallbackInfo<Value>& args) {
105
  // This constructor should not be exposed to public javascript.
106
  // Therefore we assert that we are not trying to call this as a
107
  // normal function.
108
1778
  CHECK(args.IsConstructCall());
109
1778
  Environment* env = Environment::GetCurrent(args);
110
1778
  if (args[0]->IsExternal()) {
111
22
    void* ptr = args[0].As<External>()->Value();
112
11
    new PipeWrap(env, args.This(), false, static_cast<AsyncWrap*>(ptr));
113
  } else {
114
3534
    new PipeWrap(env, args.This(), args[0]->IsTrue(), nullptr);
115
  }
116
1778
}
117
118
119
1778
PipeWrap::PipeWrap(Environment* env,
120
                   Local<Object> object,
121
                   bool ipc,
122
                   AsyncWrap* parent)
123
    : ConnectionWrap(env,
124
                     object,
125
                     AsyncWrap::PROVIDER_PIPEWRAP,
126
1778
                     parent) {
127
3556
  int r = uv_pipe_init(env->event_loop(), &handle_, ipc);
128
1778
  CHECK_EQ(r, 0);  // How do we proxy this error up to javascript?
129
                   // Suggestion: uv_pipe_init() returns void.
130
1778
  UpdateWriteQueueSize();
131
1778
}
132
133
134
16
void PipeWrap::Bind(const FunctionCallbackInfo<Value>& args) {
135
  PipeWrap* wrap;
136
16
  ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder());
137
48
  node::Utf8Value name(args.GetIsolate(), args[0]);
138
16
  int err = uv_pipe_bind(&wrap->handle_, *name);
139
32
  args.GetReturnValue().Set(err);
140
}
141
142
143
#ifdef _WIN32
144
void PipeWrap::SetPendingInstances(const FunctionCallbackInfo<Value>& args) {
145
  PipeWrap* wrap;
146
  ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder());
147
  int instances = args[0]->Int32Value();
148
  uv_pipe_pending_instances(&wrap->handle_, instances);
149
}
150
#endif
151
152
153
15
void PipeWrap::Listen(const FunctionCallbackInfo<Value>& args) {
154
  PipeWrap* wrap;
155
15
  ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder());
156
15
  int backlog = args[0]->Int32Value();
157
15
  int err = uv_listen(reinterpret_cast<uv_stream_t*>(&wrap->handle_),
158
                      backlog,
159
15
                      OnConnection);
160
30
  args.GetReturnValue().Set(err);
161
}
162
163
164
// TODO(bnoordhuis) Maybe share this with TCPWrap?
165
14
void PipeWrap::AfterConnect(uv_connect_t* req, int status) {
166
14
  PipeConnectWrap* req_wrap = static_cast<PipeConnectWrap*>(req->data);
167
14
  PipeWrap* wrap = static_cast<PipeWrap*>(req->handle->data);
168
14
  CHECK_EQ(req_wrap->env(), wrap->env());
169
14
  Environment* env = wrap->env();
170
171
28
  HandleScope handle_scope(env->isolate());
172
42
  Context::Scope context_scope(env->context());
173
174
  // The wrap and request objects should still be there.
175
28
  CHECK_EQ(req_wrap->persistent().IsEmpty(), false);
176
28
  CHECK_EQ(wrap->persistent().IsEmpty(), false);
177
178
  bool readable, writable;
179
180
14
  if (status) {
181
    readable = writable = 0;
182
  } else {
183
10
    readable = uv_is_readable(req->handle) != 0;
184
10
    writable = uv_is_writable(req->handle) != 0;
185
  }
186
187
28
  Local<Object> req_wrap_obj = req_wrap->object();
188
  Local<Value> argv[5] = {
189
    Integer::New(env->isolate(), status),
190
    wrap->object(),
191
    req_wrap_obj,
192
    Boolean::New(env->isolate(), readable),
193
    Boolean::New(env->isolate(), writable)
194
126
  };
195
196
28
  req_wrap->MakeCallback(env->oncomplete_string(), arraysize(argv), argv);
197
198
14
  delete req_wrap;
199
14
}
200
201
202
553
void PipeWrap::Open(const FunctionCallbackInfo<Value>& args) {
203
553
  Environment* env = Environment::GetCurrent(args);
204
205
  PipeWrap* wrap;
206
553
  ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder());
207
208
553
  int fd = args[0]->Int32Value();
209
210
553
  int err = uv_pipe_open(&wrap->handle_, fd);
211
212
553
  if (err != 0)
213
    env->isolate()->ThrowException(UVException(err, "uv_pipe_open"));
214
}
215
216
217
14
void PipeWrap::Connect(const FunctionCallbackInfo<Value>& args) {
218
14
  Environment* env = Environment::GetCurrent(args);
219
220
  PipeWrap* wrap;
221
14
  ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder());
222
223
14
  CHECK(args[0]->IsObject());
224
28
  CHECK(args[1]->IsString());
225
226
28
  Local<Object> req_wrap_obj = args[0].As<Object>();
227
28
  node::Utf8Value name(env->isolate(), args[1]);
228
229
14
  PipeConnectWrap* req_wrap = new PipeConnectWrap(env, req_wrap_obj);
230
14
  uv_pipe_connect(&req_wrap->req_,
231
                  &wrap->handle_,
232
14
                  *name,
233
14
                  AfterConnect);
234
28
  req_wrap->Dispatched();
235
236
28
  args.GetReturnValue().Set(0);  // uv_pipe_connect() doesn't return errors.
237
}
238
239
240
}  // namespace node
241
242
1567
NODE_MODULE_CONTEXT_AWARE_BUILTIN(pipe_wrap, node::PipeWrap::Initialize)