Node.js  v8.x
Node.js is a JavaScript runtime built on Chrome's V8 JavaScript engine
js_stream.cc
Go to the documentation of this file.
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::FunctionCallbackInfo;
16 using v8::FunctionTemplate;
17 using v8::HandleScope;
18 using v8::Local;
19 using v8::MaybeLocal;
20 using v8::Object;
21 using v8::String;
22 using v8::Value;
23 
24 
25 JSStream::JSStream(Environment* env, Local<Object> obj)
26  : AsyncWrap(env, obj, AsyncWrap::PROVIDER_JSSTREAM),
27  StreamBase(env) {
28  node::Wrap(obj, this);
29  MakeWeak<JSStream>(this);
30 }
31 
32 
33 JSStream::~JSStream() {
34 }
35 
36 
37 void* JSStream::Cast() {
38  return static_cast<void*>(this);
39 }
40 
41 
42 AsyncWrap* JSStream::GetAsyncWrap() {
43  return static_cast<AsyncWrap*>(this);
44 }
45 
46 
47 bool JSStream::IsAlive() {
48  v8::Local<v8::Value> fn = object()->Get(env()->isalive_string());
49  if (!fn->IsFunction())
50  return false;
51  return MakeCallback(fn.As<v8::Function>(), 0, nullptr)
52  .ToLocalChecked()->IsTrue();
53 }
54 
55 
56 bool JSStream::IsClosing() {
57  return MakeCallback(env()->isclosing_string(), 0, nullptr)
58  .ToLocalChecked()->IsTrue();
59 }
60 
61 
62 int JSStream::ReadStart() {
63  return MakeCallback(env()->onreadstart_string(), 0, nullptr)
64  .ToLocalChecked()->Int32Value();
65 }
66 
67 
68 int JSStream::ReadStop() {
69  return MakeCallback(env()->onreadstop_string(), 0, nullptr)
70  .ToLocalChecked()->Int32Value();
71 }
72 
73 
74 int JSStream::DoShutdown(ShutdownWrap* req_wrap) {
75  HandleScope scope(env()->isolate());
76 
77  Local<Value> argv[] = {
78  req_wrap->object()
79  };
80 
81  req_wrap->Dispatched();
82  MaybeLocal<Value> res =
83  MakeCallback(env()->onshutdown_string(), arraysize(argv), argv);
84 
85  return res.ToLocalChecked()->Int32Value();
86 }
87 
88 
89 int JSStream::DoWrite(WriteWrap* w,
90  uv_buf_t* bufs,
91  size_t count,
92  uv_stream_t* send_handle) {
93  CHECK_EQ(send_handle, nullptr);
94 
95  HandleScope scope(env()->isolate());
96 
97  Local<Array> bufs_arr = Array::New(env()->isolate(), count);
98  Local<Object> buf;
99  for (size_t i = 0; i < count; i++) {
100  buf = Buffer::Copy(env(), bufs[i].base, bufs[i].len).ToLocalChecked();
101  bufs_arr->Set(i, buf);
102  }
103 
104  Local<Value> argv[] = {
105  w->object(),
106  bufs_arr
107  };
108 
109  w->Dispatched();
110  MaybeLocal<Value> res =
111  MakeCallback(env()->onwrite_string(), arraysize(argv), argv);
112 
113  return res.ToLocalChecked()->Int32Value();
114 }
115 
116 
117 void JSStream::New(const FunctionCallbackInfo<Value>& args) {
118  // This constructor should not be exposed to public javascript.
119  // Therefore we assert that we are not trying to call this as a
120  // normal function.
121  CHECK(args.IsConstructCall());
122  Environment* env = Environment::GetCurrent(args);
123  new JSStream(env, args.This());
124 }
125 
126 
127 static void FreeCallback(char* data, void* hint) {
128  // Intentional no-op
129 }
130 
131 
132 void JSStream::DoAlloc(const FunctionCallbackInfo<Value>& args) {
133  JSStream* wrap;
134  ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder());
135 
136  uv_buf_t buf;
137  wrap->OnAlloc(args[0]->Int32Value(), &buf);
138  Local<Object> vbuf = Buffer::New(
139  wrap->env(),
140  buf.base,
141  buf.len,
142  FreeCallback,
143  nullptr).ToLocalChecked();
144  return args.GetReturnValue().Set(vbuf);
145 }
146 
147 
148 void JSStream::DoRead(const FunctionCallbackInfo<Value>& args) {
149  JSStream* wrap;
150  ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder());
151 
152  CHECK(Buffer::HasInstance(args[1]));
153  uv_buf_t buf = uv_buf_init(Buffer::Data(args[1]), Buffer::Length(args[1]));
154  wrap->OnRead(args[0]->Int32Value(), &buf);
155 }
156 
157 
158 void JSStream::DoAfterWrite(const FunctionCallbackInfo<Value>& args) {
159  JSStream* wrap;
160  CHECK(args[0]->IsObject());
161  WriteWrap* w;
162  ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder());
163  ASSIGN_OR_RETURN_UNWRAP(&w, args[0].As<Object>());
164 
165  wrap->OnAfterWrite(w);
166 }
167 
168 
169 template <class Wrap>
170 void JSStream::Finish(const FunctionCallbackInfo<Value>& args) {
171  Wrap* w;
172  CHECK(args[0]->IsObject());
173  ASSIGN_OR_RETURN_UNWRAP(&w, args[0].As<Object>());
174 
175  w->Done(args[1]->Int32Value());
176 }
177 
178 
179 void JSStream::ReadBuffer(const FunctionCallbackInfo<Value>& args) {
180  JSStream* wrap;
181  ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder());
182 
183  CHECK(Buffer::HasInstance(args[0]));
184  char* data = Buffer::Data(args[0]);
185  int len = Buffer::Length(args[0]);
186 
187  do {
188  uv_buf_t buf;
189  ssize_t avail = len;
190  wrap->OnAlloc(len, &buf);
191  if (static_cast<ssize_t>(buf.len) < avail)
192  avail = buf.len;
193 
194  memcpy(buf.base, data, avail);
195  data += avail;
196  len -= avail;
197  wrap->OnRead(avail, &buf);
198  } while (len != 0);
199 }
200 
201 
202 void JSStream::EmitEOF(const FunctionCallbackInfo<Value>& args) {
203  JSStream* wrap;
204  ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder());
205 
206  wrap->OnRead(UV_EOF, nullptr);
207 }
208 
209 
210 void JSStream::Initialize(Local<Object> target,
211  Local<Value> unused,
212  Local<Context> context) {
213  Environment* env = Environment::GetCurrent(context);
214 
215  Local<FunctionTemplate> t = env->NewFunctionTemplate(New);
216  Local<String> jsStreamString =
217  FIXED_ONE_BYTE_STRING(env->isolate(), "JSStream");
218  t->SetClassName(jsStreamString);
219  t->InstanceTemplate()->SetInternalFieldCount(1);
220 
221  AsyncWrap::AddWrapMethods(env, t);
222 
223  env->SetProtoMethod(t, "doAlloc", DoAlloc);
224  env->SetProtoMethod(t, "doRead", DoRead);
225  env->SetProtoMethod(t, "doAfterWrite", DoAfterWrite);
226  env->SetProtoMethod(t, "finishWrite", Finish<WriteWrap>);
227  env->SetProtoMethod(t, "finishShutdown", Finish<ShutdownWrap>);
228  env->SetProtoMethod(t, "readBuffer", ReadBuffer);
229  env->SetProtoMethod(t, "emitEOF", EmitEOF);
230 
231  StreamBase::AddMethods<JSStream>(env, t, StreamBase::kFlagHasWritev);
232  target->Set(jsStreamString, t->GetFunction());
233 }
234 
235 } // namespace node
236 
bool HasInstance(Local< Value > val)
Definition: node_buffer.cc:201
unsigned char * buf
Definition: cares_wrap.cc:483
NODE_MODULE_CONTEXT_AWARE_BUILTIN(inspector, node::inspector::Agent::InitInspector)
int len
Definition: cares_wrap.cc:485
QueryWrap * wrap
Definition: cares_wrap.cc:478
union node::cares_wrap::@8::CaresAsyncData::@0 data
size_t Length(Local< Value > val)
Definition: node_buffer.cc:227
void Initialize(Local< Object > target, Local< Value > unused, Local< Context > context, void *priv)
Definition: node_http2.cc:1172
char * Data(Local< Value > val)
Definition: node_buffer.cc:211
dtrace t
Definition: v8ustack.d:582
MaybeLocal< Object > New(Isolate *isolate, Local< String > string, enum encoding enc)
Definition: node_buffer.cc:241
MaybeLocal< Value > MakeCallback(Isolate *isolate, Local< Object > recv, Local< Function > callback, int argc, Local< Value > *argv, async_id asyncId, async_id triggerAsyncId)
Definition: async-wrap.cc:802
void(* FreeCallback)(char *data, void *hint)
Definition: node_buffer.h:37
MaybeLocal< Object > Copy(Isolate *isolate, const char *data, size_t length)
Definition: node_buffer.cc:320