Node.js  v8.x
Node.js is a JavaScript runtime built on Chrome's V8 JavaScript engine
node_zlib.cc
Go to the documentation of this file.
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 "node.h"
23 #include "node_buffer.h"
24 
25 #include "async-wrap.h"
26 #include "async-wrap-inl.h"
27 #include "env.h"
28 #include "env-inl.h"
29 #include "util.h"
30 #include "util-inl.h"
31 
32 #include "v8.h"
33 #include "zlib.h"
34 
35 #include <errno.h>
36 #include <stdlib.h>
37 #include <string.h>
38 #include <sys/types.h>
39 
40 namespace node {
41 
42 using v8::Array;
43 using v8::Context;
44 using v8::FunctionCallbackInfo;
45 using v8::FunctionTemplate;
46 using v8::HandleScope;
47 using v8::Integer;
48 using v8::Local;
49 using v8::Number;
50 using v8::Object;
51 using v8::String;
52 using v8::Value;
53 
54 namespace {
55 
57  NONE,
58  DEFLATE,
59  INFLATE,
60  GZIP,
61  GUNZIP,
62  DEFLATERAW,
63  INFLATERAW,
64  UNZIP
65 };
66 
67 #define GZIP_HEADER_ID1 0x1f
68 #define GZIP_HEADER_ID2 0x8b
69 
73 class ZCtx : public AsyncWrap {
74  public:
75  ZCtx(Environment* env, Local<Object> wrap, node_zlib_mode mode)
76  : AsyncWrap(env, wrap, AsyncWrap::PROVIDER_ZLIB),
77  dictionary_(nullptr),
78  dictionary_len_(0),
79  err_(0),
80  flush_(0),
81  init_done_(false),
82  level_(0),
83  memLevel_(0),
84  mode_(mode),
85  strategy_(0),
86  windowBits_(0),
87  write_in_progress_(false),
88  pending_close_(false),
89  refs_(0),
90  gzip_id_bytes_read_(0) {
91  MakeWeak<ZCtx>(this);
92  Wrap(wrap, this);
93  }
94 
95 
96  ~ZCtx() override {
97  CHECK_EQ(false, write_in_progress_ && "write in progress");
98  Close();
99  }
100 
101  void Close() {
102  if (write_in_progress_) {
103  pending_close_ = true;
104  return;
105  }
106 
107  pending_close_ = false;
108  CHECK(init_done_ && "close before init");
109  CHECK_LE(mode_, UNZIP);
110 
111  if (mode_ == DEFLATE || mode_ == GZIP || mode_ == DEFLATERAW) {
112  (void)deflateEnd(&strm_);
113  int64_t change_in_bytes = -static_cast<int64_t>(kDeflateContextSize);
114  env()->isolate()->AdjustAmountOfExternalAllocatedMemory(change_in_bytes);
115  } else if (mode_ == INFLATE || mode_ == GUNZIP || mode_ == INFLATERAW ||
116  mode_ == UNZIP) {
117  (void)inflateEnd(&strm_);
118  int64_t change_in_bytes = -static_cast<int64_t>(kInflateContextSize);
119  env()->isolate()->AdjustAmountOfExternalAllocatedMemory(change_in_bytes);
120  }
121  mode_ = NONE;
122 
123  if (dictionary_ != nullptr) {
124  delete[] dictionary_;
125  dictionary_ = nullptr;
126  }
127  }
128 
129 
130  static void Close(const FunctionCallbackInfo<Value>& args) {
131  ZCtx* ctx;
132  ASSIGN_OR_RETURN_UNWRAP(&ctx, args.Holder());
133  ctx->Close();
134  }
135 
136 
137  // write(flush, in, in_off, in_len, out, out_off, out_len)
138  template <bool async>
139  static void Write(const FunctionCallbackInfo<Value>& args) {
140  CHECK_EQ(args.Length(), 7);
141 
142  ZCtx* ctx;
143  ASSIGN_OR_RETURN_UNWRAP(&ctx, args.Holder());
144  CHECK(ctx->init_done_ && "write before init");
145  CHECK(ctx->mode_ != NONE && "already finalized");
146 
147  CHECK_EQ(false, ctx->write_in_progress_ && "write already in progress");
148  CHECK_EQ(false, ctx->pending_close_ && "close is pending");
149  ctx->write_in_progress_ = true;
150  ctx->Ref();
151 
152  CHECK_EQ(false, args[0]->IsUndefined() && "must provide flush value");
153 
154  unsigned int flush = args[0]->Uint32Value();
155 
156  if (flush != Z_NO_FLUSH &&
157  flush != Z_PARTIAL_FLUSH &&
158  flush != Z_SYNC_FLUSH &&
159  flush != Z_FULL_FLUSH &&
160  flush != Z_FINISH &&
161  flush != Z_BLOCK) {
162  CHECK(0 && "Invalid flush value");
163  }
164 
165  Bytef *in;
166  Bytef *out;
167  size_t in_off, in_len, out_off, out_len;
168  Environment* env = ctx->env();
169 
170  if (args[1]->IsNull()) {
171  // just a flush
172  in = nullptr;
173  in_len = 0;
174  in_off = 0;
175  } else {
176  CHECK(Buffer::HasInstance(args[1]));
177  Local<Object> in_buf;
178  in_buf = args[1]->ToObject(env->isolate());
179  in_off = args[2]->Uint32Value();
180  in_len = args[3]->Uint32Value();
181 
182  CHECK(Buffer::IsWithinBounds(in_off, in_len, Buffer::Length(in_buf)));
183  in = reinterpret_cast<Bytef *>(Buffer::Data(in_buf) + in_off);
184  }
185 
186  CHECK(Buffer::HasInstance(args[4]));
187  Local<Object> out_buf = args[4]->ToObject(env->isolate());
188  out_off = args[5]->Uint32Value();
189  out_len = args[6]->Uint32Value();
190  CHECK(Buffer::IsWithinBounds(out_off, out_len, Buffer::Length(out_buf)));
191  out = reinterpret_cast<Bytef *>(Buffer::Data(out_buf) + out_off);
192 
193  // build up the work request
194  uv_work_t* work_req = &(ctx->work_req_);
195 
196  ctx->strm_.avail_in = in_len;
197  ctx->strm_.next_in = in;
198  ctx->strm_.avail_out = out_len;
199  ctx->strm_.next_out = out;
200  ctx->flush_ = flush;
201 
202  if (!async) {
203  // sync version
204  ctx->env()->PrintSyncTrace();
205  Process(work_req);
206  if (CheckError(ctx))
207  AfterSync(ctx, args);
208  return;
209  }
210 
211  // async version
212  uv_queue_work(ctx->env()->event_loop(),
213  work_req,
214  ZCtx::Process,
215  ZCtx::After);
216 
217  args.GetReturnValue().Set(ctx->object());
218  }
219 
220 
221  static void AfterSync(ZCtx* ctx, const FunctionCallbackInfo<Value>& args) {
222  Environment* env = ctx->env();
223  Local<Integer> avail_out = Integer::New(env->isolate(),
224  ctx->strm_.avail_out);
225  Local<Integer> avail_in = Integer::New(env->isolate(),
226  ctx->strm_.avail_in);
227 
228  ctx->write_in_progress_ = false;
229 
230  Local<Array> result = Array::New(env->isolate(), 2);
231  result->Set(0, avail_in);
232  result->Set(1, avail_out);
233  args.GetReturnValue().Set(result);
234 
235  ctx->Unref();
236  }
237 
238 
239  // thread pool!
240  // This function may be called multiple times on the uv_work pool
241  // for a single write() call, until all of the input bytes have
242  // been consumed.
243  static void Process(uv_work_t* work_req) {
244  ZCtx *ctx = ContainerOf(&ZCtx::work_req_, work_req);
245 
246  const Bytef* next_expected_header_byte = nullptr;
247 
248  // If the avail_out is left at 0, then it means that it ran out
249  // of room. If there was avail_out left over, then it means
250  // that all of the input was consumed.
251  switch (ctx->mode_) {
252  case DEFLATE:
253  case GZIP:
254  case DEFLATERAW:
255  ctx->err_ = deflate(&ctx->strm_, ctx->flush_);
256  break;
257  case UNZIP:
258  if (ctx->strm_.avail_in > 0) {
259  next_expected_header_byte = ctx->strm_.next_in;
260  }
261 
262  switch (ctx->gzip_id_bytes_read_) {
263  case 0:
264  if (next_expected_header_byte == nullptr) {
265  break;
266  }
267 
268  if (*next_expected_header_byte == GZIP_HEADER_ID1) {
269  ctx->gzip_id_bytes_read_ = 1;
270  next_expected_header_byte++;
271 
272  if (ctx->strm_.avail_in == 1) {
273  // The only available byte was already read.
274  break;
275  }
276  } else {
277  ctx->mode_ = INFLATE;
278  break;
279  }
280 
281  // fallthrough
282  case 1:
283  if (next_expected_header_byte == nullptr) {
284  break;
285  }
286 
287  if (*next_expected_header_byte == GZIP_HEADER_ID2) {
288  ctx->gzip_id_bytes_read_ = 2;
289  ctx->mode_ = GUNZIP;
290  } else {
291  // There is no actual difference between INFLATE and INFLATERAW
292  // (after initialization).
293  ctx->mode_ = INFLATE;
294  }
295 
296  break;
297  default:
298  CHECK(0 && "invalid number of gzip magic number bytes read");
299  }
300 
301  // fallthrough
302  case INFLATE:
303  case GUNZIP:
304  case INFLATERAW:
305  ctx->err_ = inflate(&ctx->strm_, ctx->flush_);
306 
307  // If data was encoded with dictionary (INFLATERAW will have it set in
308  // SetDictionary, don't repeat that here)
309  if (ctx->mode_ != INFLATERAW &&
310  ctx->err_ == Z_NEED_DICT &&
311  ctx->dictionary_ != nullptr) {
312  // Load it
313  ctx->err_ = inflateSetDictionary(&ctx->strm_,
314  ctx->dictionary_,
315  ctx->dictionary_len_);
316  if (ctx->err_ == Z_OK) {
317  // And try to decode again
318  ctx->err_ = inflate(&ctx->strm_, ctx->flush_);
319  } else if (ctx->err_ == Z_DATA_ERROR) {
320  // Both inflateSetDictionary() and inflate() return Z_DATA_ERROR.
321  // Make it possible for After() to tell a bad dictionary from bad
322  // input.
323  ctx->err_ = Z_NEED_DICT;
324  }
325  }
326 
327  while (ctx->strm_.avail_in > 0 &&
328  ctx->mode_ == GUNZIP &&
329  ctx->err_ == Z_STREAM_END &&
330  ctx->strm_.next_in[0] != 0x00) {
331  // Bytes remain in input buffer. Perhaps this is another compressed
332  // member in the same archive, or just trailing garbage.
333  // Trailing zero bytes are okay, though, since they are frequently
334  // used for padding.
335 
336  Reset(ctx);
337  ctx->err_ = inflate(&ctx->strm_, ctx->flush_);
338  }
339  break;
340  default:
341  CHECK(0 && "wtf?");
342  }
343 
344  // pass any errors back to the main thread to deal with.
345 
346  // now After will emit the output, and
347  // either schedule another call to Process,
348  // or shift the queue and call Process.
349  }
350 
351 
352  static bool CheckError(ZCtx* ctx) {
353  // Acceptable error states depend on the type of zlib stream.
354  switch (ctx->err_) {
355  case Z_OK:
356  case Z_BUF_ERROR:
357  if (ctx->strm_.avail_out != 0 && ctx->flush_ == Z_FINISH) {
358  ZCtx::Error(ctx, "unexpected end of file");
359  return false;
360  }
361  case Z_STREAM_END:
362  // normal statuses, not fatal
363  break;
364  case Z_NEED_DICT:
365  if (ctx->dictionary_ == nullptr)
366  ZCtx::Error(ctx, "Missing dictionary");
367  else
368  ZCtx::Error(ctx, "Bad dictionary");
369  return false;
370  default:
371  // something else.
372  ZCtx::Error(ctx, "Zlib error");
373  return false;
374  }
375 
376  return true;
377  }
378 
379 
380  // v8 land!
381  static void After(uv_work_t* work_req, int status) {
382  CHECK_EQ(status, 0);
383 
384  ZCtx* ctx = ContainerOf(&ZCtx::work_req_, work_req);
385  Environment* env = ctx->env();
386 
387  HandleScope handle_scope(env->isolate());
388  Context::Scope context_scope(env->context());
389 
390  if (!CheckError(ctx))
391  return;
392 
393  Local<Integer> avail_out = Integer::New(env->isolate(),
394  ctx->strm_.avail_out);
395  Local<Integer> avail_in = Integer::New(env->isolate(),
396  ctx->strm_.avail_in);
397 
398  ctx->write_in_progress_ = false;
399 
400  // call the write() cb
401  Local<Value> args[2] = { avail_in, avail_out };
402  ctx->MakeCallback(env->callback_string(), arraysize(args), args);
403 
404  ctx->Unref();
405  if (ctx->pending_close_)
406  ctx->Close();
407  }
408 
409  static void Error(ZCtx* ctx, const char* message) {
410  Environment* env = ctx->env();
411 
412  // If you hit this assertion, you forgot to enter the v8::Context first.
413  CHECK_EQ(env->context(), env->isolate()->GetCurrentContext());
414 
415  if (ctx->strm_.msg != nullptr) {
416  message = ctx->strm_.msg;
417  }
418 
419  HandleScope scope(env->isolate());
420  Local<Value> args[2] = {
421  OneByteString(env->isolate(), message),
422  Number::New(env->isolate(), ctx->err_)
423  };
424  ctx->MakeCallback(env->onerror_string(), arraysize(args), args);
425 
426  // no hope of rescue.
427  if (ctx->write_in_progress_)
428  ctx->Unref();
429  ctx->write_in_progress_ = false;
430  if (ctx->pending_close_)
431  ctx->Close();
432  }
433 
434  static void New(const FunctionCallbackInfo<Value>& args) {
435  Environment* env = Environment::GetCurrent(args);
436 
437  if (args.Length() < 1 || !args[0]->IsInt32()) {
438  return env->ThrowTypeError("Bad argument");
439  }
440  node_zlib_mode mode = static_cast<node_zlib_mode>(args[0]->Int32Value());
441 
442  if (mode < DEFLATE || mode > UNZIP) {
443  return env->ThrowTypeError("Bad argument");
444  }
445 
446  new ZCtx(env, args.This(), mode);
447  }
448 
449  // just pull the ints out of the args and call the other Init
450  static void Init(const FunctionCallbackInfo<Value>& args) {
451  CHECK((args.Length() == 4 || args.Length() == 5) &&
452  "init(windowBits, level, memLevel, strategy, [dictionary])");
453 
454  ZCtx* ctx;
455  ASSIGN_OR_RETURN_UNWRAP(&ctx, args.Holder());
456 
457  int windowBits = args[0]->Uint32Value();
458  CHECK((windowBits >= 8 && windowBits <= 15) && "invalid windowBits");
459 
460  int level = args[1]->Int32Value();
461  CHECK((level >= -1 && level <= 9) && "invalid compression level");
462 
463  int memLevel = args[2]->Uint32Value();
464  CHECK((memLevel >= 1 && memLevel <= 9) && "invalid memlevel");
465 
466  int strategy = args[3]->Uint32Value();
467  CHECK((strategy == Z_FILTERED ||
468  strategy == Z_HUFFMAN_ONLY ||
469  strategy == Z_RLE ||
470  strategy == Z_FIXED ||
471  strategy == Z_DEFAULT_STRATEGY) && "invalid strategy");
472 
473  char* dictionary = nullptr;
474  size_t dictionary_len = 0;
475  if (args.Length() >= 5 && Buffer::HasInstance(args[4])) {
476  Local<Object> dictionary_ = args[4]->ToObject(args.GetIsolate());
477 
478  dictionary_len = Buffer::Length(dictionary_);
479  dictionary = new char[dictionary_len];
480 
481  memcpy(dictionary, Buffer::Data(dictionary_), dictionary_len);
482  }
483 
484  Init(ctx, level, windowBits, memLevel, strategy,
485  dictionary, dictionary_len);
486  SetDictionary(ctx);
487  }
488 
489  static void Params(const FunctionCallbackInfo<Value>& args) {
490  CHECK(args.Length() == 2 && "params(level, strategy)");
491  ZCtx* ctx;
492  ASSIGN_OR_RETURN_UNWRAP(&ctx, args.Holder());
493  Params(ctx, args[0]->Int32Value(), args[1]->Int32Value());
494  }
495 
496  static void Reset(const FunctionCallbackInfo<Value> &args) {
497  ZCtx* ctx;
498  ASSIGN_OR_RETURN_UNWRAP(&ctx, args.Holder());
499  Reset(ctx);
500  SetDictionary(ctx);
501  }
502 
503  static void Init(ZCtx *ctx, int level, int windowBits, int memLevel,
504  int strategy, char* dictionary, size_t dictionary_len) {
505  ctx->level_ = level;
506  ctx->windowBits_ = windowBits;
507  ctx->memLevel_ = memLevel;
508  ctx->strategy_ = strategy;
509 
510  ctx->strm_.zalloc = Z_NULL;
511  ctx->strm_.zfree = Z_NULL;
512  ctx->strm_.opaque = Z_NULL;
513 
514  ctx->flush_ = Z_NO_FLUSH;
515 
516  ctx->err_ = Z_OK;
517 
518  if (ctx->mode_ == GZIP || ctx->mode_ == GUNZIP) {
519  ctx->windowBits_ += 16;
520  }
521 
522  if (ctx->mode_ == UNZIP) {
523  ctx->windowBits_ += 32;
524  }
525 
526  if (ctx->mode_ == DEFLATERAW || ctx->mode_ == INFLATERAW) {
527  ctx->windowBits_ *= -1;
528  }
529 
530  switch (ctx->mode_) {
531  case DEFLATE:
532  case GZIP:
533  case DEFLATERAW:
534  ctx->err_ = deflateInit2(&ctx->strm_,
535  ctx->level_,
536  Z_DEFLATED,
537  ctx->windowBits_,
538  ctx->memLevel_,
539  ctx->strategy_);
540  ctx->env()->isolate()
541  ->AdjustAmountOfExternalAllocatedMemory(kDeflateContextSize);
542  break;
543  case INFLATE:
544  case GUNZIP:
545  case INFLATERAW:
546  case UNZIP:
547  ctx->err_ = inflateInit2(&ctx->strm_, ctx->windowBits_);
548  ctx->env()->isolate()
549  ->AdjustAmountOfExternalAllocatedMemory(kInflateContextSize);
550  break;
551  default:
552  CHECK(0 && "wtf?");
553  }
554 
555  ctx->dictionary_ = reinterpret_cast<Bytef *>(dictionary);
556  ctx->dictionary_len_ = dictionary_len;
557 
558  ctx->write_in_progress_ = false;
559  ctx->init_done_ = true;
560 
561  if (ctx->err_ != Z_OK) {
562  if (dictionary != nullptr) {
563  delete[] dictionary;
564  ctx->dictionary_ = nullptr;
565  }
566  ctx->mode_ = NONE;
567  ctx->env()->ThrowError("Init error");
568  }
569  }
570 
571  static void SetDictionary(ZCtx* ctx) {
572  if (ctx->dictionary_ == nullptr)
573  return;
574 
575  ctx->err_ = Z_OK;
576 
577  switch (ctx->mode_) {
578  case DEFLATE:
579  case DEFLATERAW:
580  ctx->err_ = deflateSetDictionary(&ctx->strm_,
581  ctx->dictionary_,
582  ctx->dictionary_len_);
583  break;
584  case INFLATERAW:
585  // The other inflate cases will have the dictionary set when inflate()
586  // returns Z_NEED_DICT in Process()
587  ctx->err_ = inflateSetDictionary(&ctx->strm_,
588  ctx->dictionary_,
589  ctx->dictionary_len_);
590  break;
591  default:
592  break;
593  }
594 
595  if (ctx->err_ != Z_OK) {
596  ZCtx::Error(ctx, "Failed to set dictionary");
597  }
598  }
599 
600  static void Params(ZCtx* ctx, int level, int strategy) {
601  ctx->err_ = Z_OK;
602 
603  switch (ctx->mode_) {
604  case DEFLATE:
605  case DEFLATERAW:
606  ctx->err_ = deflateParams(&ctx->strm_, level, strategy);
607  break;
608  default:
609  break;
610  }
611 
612  if (ctx->err_ != Z_OK && ctx->err_ != Z_BUF_ERROR) {
613  ZCtx::Error(ctx, "Failed to set parameters");
614  }
615  }
616 
617  static void Reset(ZCtx* ctx) {
618  ctx->err_ = Z_OK;
619 
620  switch (ctx->mode_) {
621  case DEFLATE:
622  case DEFLATERAW:
623  case GZIP:
624  ctx->err_ = deflateReset(&ctx->strm_);
625  break;
626  case INFLATE:
627  case INFLATERAW:
628  case GUNZIP:
629  ctx->err_ = inflateReset(&ctx->strm_);
630  break;
631  default:
632  break;
633  }
634 
635  if (ctx->err_ != Z_OK) {
636  ZCtx::Error(ctx, "Failed to reset stream");
637  }
638  }
639 
640  size_t self_size() const override { return sizeof(*this); }
641 
642  private:
643  void Ref() {
644  if (++refs_ == 1) {
645  ClearWeak();
646  }
647  }
648 
649  void Unref() {
650  CHECK_GT(refs_, 0);
651  if (--refs_ == 0) {
652  MakeWeak<ZCtx>(this);
653  }
654  }
655 
656  static const int kDeflateContextSize = 16384; // approximate
657  static const int kInflateContextSize = 10240; // approximate
658 
659  Bytef* dictionary_;
660  size_t dictionary_len_;
661  int err_;
662  int flush_;
663  bool init_done_;
664  int level_;
665  int memLevel_;
666  node_zlib_mode mode_;
667  int strategy_;
668  z_stream strm_;
669  int windowBits_;
670  uv_work_t work_req_;
671  bool write_in_progress_;
672  bool pending_close_;
673  unsigned int refs_;
674  unsigned int gzip_id_bytes_read_;
675 };
676 
677 
678 void InitZlib(Local<Object> target,
679  Local<Value> unused,
680  Local<Context> context,
681  void* priv) {
682  Environment* env = Environment::GetCurrent(context);
683  Local<FunctionTemplate> z = env->NewFunctionTemplate(ZCtx::New);
684 
685  z->InstanceTemplate()->SetInternalFieldCount(1);
686 
687  AsyncWrap::AddWrapMethods(env, z);
688  env->SetProtoMethod(z, "write", ZCtx::Write<true>);
689  env->SetProtoMethod(z, "writeSync", ZCtx::Write<false>);
690  env->SetProtoMethod(z, "init", ZCtx::Init);
691  env->SetProtoMethod(z, "close", ZCtx::Close);
692  env->SetProtoMethod(z, "params", ZCtx::Params);
693  env->SetProtoMethod(z, "reset", ZCtx::Reset);
694 
695  Local<String> zlibString = FIXED_ONE_BYTE_STRING(env->isolate(), "Zlib");
696  z->SetClassName(zlibString);
697  target->Set(zlibString, z->GetFunction());
698 
699  target->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "ZLIB_VERSION"),
700  FIXED_ONE_BYTE_STRING(env->isolate(), ZLIB_VERSION));
701 }
702 
703 } // anonymous namespace
704 } // namespace node
705 
706 NODE_MODULE_CONTEXT_AWARE_BUILTIN(zlib, node::InitZlib)
bool HasInstance(Local< Value > val)
Definition: node_buffer.cc:201
NODE_MODULE_CONTEXT_AWARE_BUILTIN(inspector, node::inspector::Agent::InitInspector)
QueryWrap * wrap
Definition: cares_wrap.cc:478
int status
Definition: cares_wrap.cc:479
#define GZIP_HEADER_ID1
Definition: node_zlib.cc:67
size_t Length(Local< Value > val)
Definition: node_buffer.cc:227
char * Data(Local< Value > val)
Definition: node_buffer.cc:211
MaybeLocal< Object > New(Isolate *isolate, Local< String > string, enum encoding enc)
Definition: node_buffer.cc:241
#define GZIP_HEADER_ID2
Definition: node_zlib.cc:68
this ctx
Definition: v8ustack.d:369
void Init(int *argc, const char **argv, int *exec_argc, const char ***exec_argv)
Definition: node.cc:4351