GCC Code Coverage Report
Directory: ../src/ Exec Total Coverage
File: /home/node-core-coverage/node-core-coverage/workdir/node/out/../src/js_stream.cc Lines: 80 106 75.5 %
Date: 2016-11-30 Branches: 19 44 43.2 %

Line Branch Exec Source
1
#include "js_stream.h"
2
3
#include "async-wrap.h"
4
#include "env.h"
5
#include "env-inl.h"
6
#include "node_buffer.h"
7
#include "stream_base.h"
8
#include "stream_base-inl.h"
9
#include "v8.h"
10
11
namespace node {
12
13
using v8::Array;
14
using v8::Context;
15
using v8::External;
16
using v8::FunctionCallbackInfo;
17
using v8::FunctionTemplate;
18
using v8::HandleScope;
19
using v8::Local;
20
using v8::Object;
21
using v8::Value;
22
23
24
8
JSStream::JSStream(Environment* env, Local<Object> obj, AsyncWrap* parent)
25
    : AsyncWrap(env, obj, AsyncWrap::PROVIDER_JSSTREAM, parent),
26
16
      StreamBase(env) {
27
8
  node::Wrap(obj, this);
28
8
  MakeWeak<JSStream>(this);
29
8
}
30
31
32
2
JSStream::~JSStream() {
33
1
}
34
35
36
void* JSStream::Cast() {
37
  return static_cast<void*>(this);
38
}
39
40
41
1
AsyncWrap* JSStream::GetAsyncWrap() {
42
1
  return static_cast<AsyncWrap*>(this);
43
}
44
45
46
13
bool JSStream::IsAlive() {
47
52
  v8::Local<v8::Value> fn = object()->Get(env()->isalive_string());
48
13
  if (!fn->IsFunction())
49
    return false;
50
24
  return MakeCallback(fn.As<v8::Function>(), 0, nullptr)->IsTrue();
51
}
52
53
54
bool JSStream::IsClosing() {
55
  return MakeCallback(env()->isclosing_string(), 0, nullptr)->IsTrue();
56
}
57
58
59
7
int JSStream::ReadStart() {
60
21
  return MakeCallback(env()->onreadstart_string(), 0, nullptr)->Int32Value();
61
}
62
63
64
int JSStream::ReadStop() {
65
  return MakeCallback(env()->onreadstop_string(), 0, nullptr)->Int32Value();
66
}
67
68
69
2
int JSStream::DoShutdown(ShutdownWrap* req_wrap) {
70
4
  HandleScope scope(env()->isolate());
71
72
  Local<Value> argv[] = {
73
    req_wrap->object()
74
6
  };
75
76
4
  req_wrap->Dispatched();
77
  Local<Value> res =
78
4
      MakeCallback(env()->onshutdown_string(), arraysize(argv), argv);
79
80
4
  return res->Int32Value();
81
}
82
83
84
11
int JSStream::DoWrite(WriteWrap* w,
85
                      uv_buf_t* bufs,
86
                      size_t count,
87
                      uv_stream_t* send_handle) {
88
11
  CHECK_EQ(send_handle, nullptr);
89
90
22
  HandleScope scope(env()->isolate());
91
92
11
  Local<Array> bufs_arr = Array::New(env()->isolate(), count);
93
11
  Local<Object> buf;
94
23
  for (size_t i = 0; i < count; i++) {
95
24
    buf = Buffer::Copy(env(), bufs[i].base, bufs[i].len).ToLocalChecked();
96
24
    bufs_arr->Set(i, buf);
97
  }
98
99
  Local<Value> argv[] = {
100
    w->object(),
101
    bufs_arr
102
44
  };
103
104
22
  w->Dispatched();
105
  Local<Value> res =
106
22
      MakeCallback(env()->onwrite_string(), arraysize(argv), argv);
107
108
22
  return res->Int32Value();
109
}
110
111
112
8
void JSStream::New(const FunctionCallbackInfo<Value>& args) {
113
  // This constructor should not be exposed to public javascript.
114
  // Therefore we assert that we are not trying to call this as a
115
  // normal function.
116
8
  CHECK(args.IsConstructCall());
117
8
  Environment* env = Environment::GetCurrent(args);
118
  JSStream* wrap;
119
120
8
  if (args.Length() == 0) {
121
8
    wrap = new JSStream(env, args.This(), nullptr);
122
  } else if (args[0]->IsExternal()) {
123
    void* ptr = args[0].As<External>()->Value();
124
    wrap = new JSStream(env, args.This(), static_cast<AsyncWrap*>(ptr));
125
  } else {
126
    UNREACHABLE();
127
  }
128
8
  CHECK(wrap);
129
8
}
130
131
132
static void FreeCallback(char* data, void* hint) {
133
  // Intentional no-op
134
}
135
136
137
void JSStream::DoAlloc(const FunctionCallbackInfo<Value>& args) {
138
  JSStream* wrap;
139
  ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder());
140
141
  uv_buf_t buf;
142
  wrap->OnAlloc(args[0]->Int32Value(), &buf);
143
  Local<Object> vbuf = Buffer::New(
144
      wrap->env(),
145
      buf.base,
146
      buf.len,
147
      FreeCallback,
148
      nullptr).ToLocalChecked();
149
  return args.GetReturnValue().Set(vbuf);
150
}
151
152
153
void JSStream::DoRead(const FunctionCallbackInfo<Value>& args) {
154
  JSStream* wrap;
155
  ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder());
156
157
  CHECK(Buffer::HasInstance(args[1]));
158
  uv_buf_t buf = uv_buf_init(Buffer::Data(args[1]), Buffer::Length(args[1]));
159
  wrap->OnRead(args[0]->Int32Value(), &buf);
160
}
161
162
163
11
void JSStream::DoAfterWrite(const FunctionCallbackInfo<Value>& args) {
164
  JSStream* wrap;
165
11
  CHECK(args[0]->IsObject());
166
  WriteWrap* w;
167
11
  ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder());
168
22
  ASSIGN_OR_RETURN_UNWRAP(&w, args[0].As<Object>());
169
170
11
  wrap->OnAfterWrite(w);
171
}
172
173
174
template <class Wrap>
175
13
void JSStream::Finish(const FunctionCallbackInfo<Value>& args) {
176
  Wrap* w;
177

13
  CHECK(args[0]->IsObject());
178

26
  ASSIGN_OR_RETURN_UNWRAP(&w, args[0].As<Object>());
179
180
13
  w->Done(args[1]->Int32Value());
181
}
182
183
184
6
void JSStream::ReadBuffer(const FunctionCallbackInfo<Value>& args) {
185
  JSStream* wrap;
186
6
  ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder());
187
188
6
  CHECK(Buffer::HasInstance(args[0]));
189
6
  char* data = Buffer::Data(args[0]);
190
6
  int len = Buffer::Length(args[0]);
191
192
  do {
193
    uv_buf_t buf;
194
6
    ssize_t avail = len;
195
12
    wrap->OnAlloc(len, &buf);
196
6
    if (static_cast<ssize_t>(buf.len) < avail)
197
      avail = buf.len;
198
199
12
    memcpy(buf.base, data, avail);
200
6
    data += avail;
201
6
    len -= avail;
202
12
    wrap->OnRead(avail, &buf);
203
6
  } while (len != 0);
204
}
205
206
207
void JSStream::EmitEOF(const FunctionCallbackInfo<Value>& args) {
208
  JSStream* wrap;
209
  ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder());
210
211
  wrap->OnRead(UV_EOF, nullptr);
212
}
213
214
215
150
void JSStream::Initialize(Local<Object> target,
216
                          Local<Value> unused,
217
                          Local<Context> context) {
218
150
  Environment* env = Environment::GetCurrent(context);
219
220
300
  Local<FunctionTemplate> t = env->NewFunctionTemplate(New);
221
150
  t->SetClassName(FIXED_ONE_BYTE_STRING(env->isolate(), "JSStream"));
222
300
  t->InstanceTemplate()->SetInternalFieldCount(1);
223
224
150
  env->SetProtoMethod(t, "doAlloc", DoAlloc);
225
150
  env->SetProtoMethod(t, "doRead", DoRead);
226
150
  env->SetProtoMethod(t, "doAfterWrite", DoAfterWrite);
227
150
  env->SetProtoMethod(t, "finishWrite", Finish<WriteWrap>);
228
150
  env->SetProtoMethod(t, "finishShutdown", Finish<ShutdownWrap>);
229
150
  env->SetProtoMethod(t, "readBuffer", ReadBuffer);
230
150
  env->SetProtoMethod(t, "emitEOF", EmitEOF);
231
232
150
  StreamBase::AddMethods<JSStream>(env, t, StreamBase::kFlagHasWritev);
233
750
  target->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "JSStream"),
234
150
              t->GetFunction());
235
150
  env->set_jsstream_constructor_template(t);
236
150
}
237
238
}  // namespace node
239
240
1705
NODE_MODULE_CONTEXT_AWARE_BUILTIN(js_stream, node::JSStream::Initialize)