GCC Code Coverage Report
Directory: ../ Exec Total Coverage
File: /home/iojs/build/workspace/node-test-commit-linux-coverage-daily/nodes/benchmark/out/../src/node_zlib.cc Lines: 592 641 92.4 %
Date: 2019-03-02 22:23:06 Branches: 459 774 59.3 %

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 "node.h"
23
#include "node_buffer.h"
24
25
#include "async_wrap-inl.h"
26
#include "env-inl.h"
27
#include "util-inl.h"
28
29
#include "v8.h"
30
31
#include "brotli/encode.h"
32
#include "brotli/decode.h"
33
#include "zlib.h"
34
35
#include <cerrno>
36
#include <cstdlib>
37
#include <cstring>
38
#include <sys/types.h>
39
#include <atomic>
40
41
namespace node {
42
43
using v8::Array;
44
using v8::ArrayBuffer;
45
using v8::Context;
46
using v8::Function;
47
using v8::FunctionCallbackInfo;
48
using v8::FunctionTemplate;
49
using v8::HandleScope;
50
using v8::Int32;
51
using v8::Integer;
52
using v8::Local;
53
using v8::Object;
54
using v8::String;
55
using v8::Uint32;
56
using v8::Uint32Array;
57
using v8::Value;
58
59
namespace {
60
61
// Fewer than 64 bytes per chunk is not recommended.
62
// Technically it could work with as few as 8, but even 64 bytes
63
// is low.  Usually a MB or more is best.
64
#define Z_MIN_CHUNK 64
65
#define Z_MAX_CHUNK std::numeric_limits<double>::infinity()
66
#define Z_DEFAULT_CHUNK (16 * 1024)
67
#define Z_MIN_MEMLEVEL 1
68
#define Z_MAX_MEMLEVEL 9
69
#define Z_DEFAULT_MEMLEVEL 8
70
#define Z_MIN_LEVEL -1
71
#define Z_MAX_LEVEL 9
72
#define Z_DEFAULT_LEVEL Z_DEFAULT_COMPRESSION
73
74
#define ZLIB_ERROR_CODES(V)      \
75
  V(Z_OK)                        \
76
  V(Z_STREAM_END)                \
77
  V(Z_NEED_DICT)                 \
78
  V(Z_ERRNO)                     \
79
  V(Z_STREAM_ERROR)              \
80
  V(Z_DATA_ERROR)                \
81
  V(Z_MEM_ERROR)                 \
82
  V(Z_BUF_ERROR)                 \
83
  V(Z_VERSION_ERROR)             \
84
85
25
inline const char* ZlibStrerror(int err) {
86
#define V(code) if (err == code) return #code;
87




25
  ZLIB_ERROR_CODES(V)
88
#undef V
89
  return "Z_UNKNOWN_ERROR";
90
}
91
92
enum node_zlib_mode {
93
  NONE,
94
  DEFLATE,
95
  INFLATE,
96
  GZIP,
97
  GUNZIP,
98
  DEFLATERAW,
99
  INFLATERAW,
100
  UNZIP,
101
  BROTLI_DECODE,
102
  BROTLI_ENCODE
103
};
104
105
#define GZIP_HEADER_ID1 0x1f
106
#define GZIP_HEADER_ID2 0x8b
107
108
struct CompressionError {
109
27
  CompressionError(const char* message, const char* code, int err)
110
27
    : message(message), code(code), err(err) {}
111
11077
  CompressionError() = default;
112
113
  const char* message = nullptr;
114
  const char* code = nullptr;
115
  int err = 0;
116
117
12638
  inline bool IsError() const { return code != nullptr; }
118
};
119
120
1451
class ZlibContext : public MemoryRetainer {
121
 public:
122
1554
  ZlibContext() = default;
123
124
  // Streaming-related, should be available for all compression libraries:
125
  void Close();
126
  void DoThreadPoolWork();
127
  void SetBuffers(char* in, uint32_t in_len, char* out, uint32_t out_len);
128
  void SetFlush(int flush);
129
  void GetAfterWriteOffsets(uint32_t* avail_in, uint32_t* avail_out) const;
130
  CompressionError GetErrorInfo() const;
131
1554
  inline void SetMode(node_zlib_mode mode) { mode_ = mode; }
132
  CompressionError ResetStream();
133
134
  // Zlib-specific:
135
  CompressionError Init(int level, int window_bits, int mem_level, int strategy,
136
                        std::vector<unsigned char>&& dictionary);
137
  void SetAllocationFunctions(alloc_func alloc, free_func free, void* opaque);
138
  CompressionError SetParams(int level, int strategy);
139
140
2
  SET_MEMORY_INFO_NAME(ZlibContext)
141
2
  SET_SELF_SIZE(ZlibContext)
142
143
2
  void MemoryInfo(MemoryTracker* tracker) const override {
144
2
    tracker->TrackField("dictionary", dictionary_);
145
2
  }
146
147
 private:
148
  CompressionError ErrorForMessage(const char* message) const;
149
  CompressionError SetDictionary();
150
151
  int err_ = 0;
152
  int flush_ = 0;
153
  int level_ = 0;
154
  int mem_level_ = 0;
155
  node_zlib_mode mode_ = NONE;
156
  int strategy_ = 0;
157
  int window_bits_ = 0;
158
  unsigned int gzip_id_bytes_read_ = 0;
159
  std::vector<unsigned char> dictionary_;
160
161
  z_stream strm_;
162
163
  DISALLOW_COPY_AND_ASSIGN(ZlibContext);
164
};
165
166
// Brotli has different data types for compression and decompression streams,
167
// so some of the specifics are implemented in more specific subclasses
168
197
class BrotliContext : public MemoryRetainer {
169
 public:
170
197
  BrotliContext() = default;
171
172
  void SetBuffers(char* in, uint32_t in_len, char* out, uint32_t out_len);
173
  void SetFlush(int flush);
174
  void GetAfterWriteOffsets(uint32_t* avail_in, uint32_t* avail_out) const;
175
197
  inline void SetMode(node_zlib_mode mode) { mode_ = mode; }
176
177
 protected:
178
  node_zlib_mode mode_ = NONE;
179
  uint8_t* next_in_ = nullptr;
180
  uint8_t* next_out_ = nullptr;
181
  size_t avail_in_ = 0;
182
  size_t avail_out_ = 0;
183
  BrotliEncoderOperation flush_ = BROTLI_OPERATION_PROCESS;
184
  // TODO(addaleax): These should not need to be stored here.
185
  // This is currently only done this way to make implementing ResetStream()
186
  // easier.
187
  brotli_alloc_func alloc_ = nullptr;
188
  brotli_free_func free_ = nullptr;
189
  void* alloc_opaque_ = nullptr;
190
191
 private:
192
  DISALLOW_COPY_AND_ASSIGN(BrotliContext);
193
};
194
195
206
class BrotliEncoderContext final : public BrotliContext {
196
 public:
197
  void Close();
198
  void DoThreadPoolWork();
199
  CompressionError Init(brotli_alloc_func alloc,
200
                        brotli_free_func free,
201
                        void* opaque);
202
  CompressionError ResetStream();
203
  CompressionError SetParams(int key, uint32_t value);
204
  CompressionError GetErrorInfo() const;
205
206
  SET_MEMORY_INFO_NAME(BrotliEncoderContext)
207
  SET_SELF_SIZE(BrotliEncoderContext)
208
  SET_NO_MEMORY_INFO()  // state_ is covered through allocation tracking.
209
210
 private:
211
  bool last_result_ = false;
212
  DeleteFnPtr<BrotliEncoderState, BrotliEncoderDestroyInstance> state_;
213
};
214
215
188
class BrotliDecoderContext final : public BrotliContext {
216
 public:
217
  void Close();
218
  void DoThreadPoolWork();
219
  CompressionError Init(brotli_alloc_func alloc,
220
                        brotli_free_func free,
221
                        void* opaque);
222
  CompressionError ResetStream();
223
  CompressionError SetParams(int key, uint32_t value);
224
  CompressionError GetErrorInfo() const;
225
226
  SET_MEMORY_INFO_NAME(BrotliDecoderContext)
227
  SET_SELF_SIZE(BrotliDecoderContext)
228
  SET_NO_MEMORY_INFO()  // state_ is covered through allocation tracking.
229
230
 private:
231
  BrotliDecoderResult last_result_ = BROTLI_DECODER_RESULT_SUCCESS;
232
  BrotliDecoderErrorCode error_ = BROTLI_DECODER_NO_ERROR;
233
  std::string error_string_;
234
  DeleteFnPtr<BrotliDecoderState, BrotliDecoderDestroyInstance> state_;
235
};
236
237
template <typename CompressionContext>
238
class CompressionStream : public AsyncWrap, public ThreadPoolWork {
239
 public:
240
1751
  CompressionStream(Environment* env, Local<Object> wrap)
241
      : AsyncWrap(env, wrap, AsyncWrap::PROVIDER_ZLIB),
242
        ThreadPoolWork(env),
243
3502
        write_result_(nullptr) {
244
1751
    MakeWeak();
245
1751
  }
246
247
1648
  ~CompressionStream() override {
248

1648
    CHECK_EQ(false, write_in_progress_ && "write in progress");
249
1648
    Close();
250

1648
    CHECK_EQ(zlib_memory_, 0);
251

1648
    CHECK_EQ(unreported_allocations_, 0);
252

4944
  }
253
254
3239
  void Close() {
255

3239
    if (write_in_progress_) {
256
7
      pending_close_ = true;
257
3246
      return;
258
    }
259
260
3232
    pending_close_ = false;
261
3232
    closed_ = true;
262

3232
    CHECK(init_done_ && "close before init");
263
264
3232
    AllocScope alloc_scope(this);
265
3232
    ctx_.Close();
266
  }
267
268
269
1584
  static void Close(const FunctionCallbackInfo<Value>& args) {
270
    CompressionStream* ctx;
271

3168
    ASSIGN_OR_RETURN_UNWRAP(&ctx, args.Holder());
272
1584
    ctx->Close();
273
  }
274
275
276
  // write(flush, in, in_off, in_len, out, out_off, out_len)
277
  template <bool async>
278
9307
  static void Write(const FunctionCallbackInfo<Value>& args) {
279
9307
    Environment* env = Environment::GetCurrent(args);
280
9307
    Local<Context> context = env->context();
281



9307
    CHECK_EQ(args.Length(), 7);
282
283
    uint32_t in_off, in_len, out_off, out_len, flush;
284
    char* in;
285
    char* out;
286
287









37228
    CHECK_EQ(false, args[0]->IsUndefined() && "must provide flush value");
288



27921
    if (!args[0]->Uint32Value(context).To(&flush)) return;
289
290


















9307
    if (flush != Z_NO_FLUSH &&
291
        flush != Z_PARTIAL_FLUSH &&
292
        flush != Z_SYNC_FLUSH &&
293
        flush != Z_FULL_FLUSH &&
294
        flush != Z_FINISH &&
295
        flush != Z_BLOCK) {
296
      CHECK(0 && "Invalid flush value");
297
    }
298
299



27921
    if (args[1]->IsNull()) {
300
      // just a flush
301
      in = nullptr;
302
      in_len = 0;
303
      in_off = 0;
304
    } else {
305



9307
      CHECK(Buffer::HasInstance(args[1]));
306
18614
      Local<Object> in_buf = args[1].As<Object>();
307



27921
      if (!args[2]->Uint32Value(context).To(&in_off)) return;
308



27921
      if (!args[3]->Uint32Value(context).To(&in_len)) return;
309
310



9307
      CHECK(Buffer::IsWithinBounds(in_off, in_len, Buffer::Length(in_buf)));
311
9307
      in = Buffer::Data(in_buf) + in_off;
312
    }
313
314



9307
    CHECK(Buffer::HasInstance(args[4]));
315
18614
    Local<Object> out_buf = args[4].As<Object>();
316



27921
    if (!args[5]->Uint32Value(context).To(&out_off)) return;
317



27921
    if (!args[6]->Uint32Value(context).To(&out_len)) return;
318



9307
    CHECK(Buffer::IsWithinBounds(out_off, out_len, Buffer::Length(out_buf)));
319
9307
    out = Buffer::Data(out_buf) + out_off;
320
321
    CompressionStream* ctx;
322



9307
    ASSIGN_OR_RETURN_UNWRAP(&ctx, args.Holder());
323
324
9307
    ctx->Write<async>(flush, in, in_len, out, out_len);
325
  }
326
327
  template <bool async>
328
9307
  void Write(uint32_t flush,
329
             char* in, uint32_t in_len,
330
             char* out, uint32_t out_len) {
331
9307
    AllocScope alloc_scope(this);
332
333



9307
    CHECK(init_done_ && "write before init");
334



9307
    CHECK(!closed_ && "already finalized");
335
336



9307
    CHECK_EQ(false, write_in_progress_);
337



9307
    CHECK_EQ(false, pending_close_);
338
9307
    write_in_progress_ = true;
339
9307
    Ref();
340
341
9307
    ctx_.SetBuffers(in, in_len, out, out_len);
342
9307
    ctx_.SetFlush(flush);
343
344
    if (!async) {
345
      // sync version
346
830
      env()->PrintSyncTrace();
347
830
      DoThreadPoolWork();
348

830
      if (CheckError()) {
349
824
        UpdateWriteResult();
350
824
        write_in_progress_ = false;
351
      }
352
830
      Unref();
353

10137
      return;
354
    }
355
356
    // async version
357

8477
    ScheduleWork();
358
  }
359
360
9281
  void UpdateWriteResult() {
361
9281
    ctx_.GetAfterWriteOffsets(&write_result_[1], &write_result_[0]);
362
9281
  }
363
364
  // thread pool!
365
  // This function may be called multiple times on the uv_work pool
366
  // for a single write() call, until all of the input bytes have
367
  // been consumed.
368
9306
  void DoThreadPoolWork() override {
369
9306
    ctx_.DoThreadPoolWork();
370
9307
  }
371
372
373
9307
  bool CheckError() {
374
9307
    const CompressionError err = ctx_.GetErrorInfo();
375

9307
    if (!err.IsError()) return true;
376
26
    EmitError(err);
377
26
    return false;
378
  }
379
380
381
  // v8 land!
382
8477
  void AfterThreadPoolWork(int status) override {
383
8477
    AllocScope alloc_scope(this);
384

25411
    OnScopeLeave on_scope_leave([&]() { Unref(); });
385
386
8477
    write_in_progress_ = false;
387
388

8477
    if (status == UV_ECANCELED) {
389
      Close();
390
      return;
391
    }
392
393

8477
    CHECK_EQ(status, 0);
394
395

16934
    HandleScope handle_scope(env()->isolate());
396

16934
    Context::Scope context_scope(env()->context());
397
398

8477
    if (!CheckError())
399
20
      return;
400
401
8457
    UpdateWriteResult();
402
403
    // call the write() cb
404
    Local<Function> cb = PersistentToLocal::Default(env()->isolate(),
405
8457
                                                    write_js_callback_);
406
8457
    MakeCallback(cb, 0, nullptr);
407
408

8457
    if (pending_close_)
409
8458
      Close();
410
  }
411
412
  // TODO(addaleax): Switch to modern error system (node_errors.h).
413
27
  void EmitError(const CompressionError& err) {
414
    // If you hit this assertion, you forgot to enter the v8::Context first.
415

54
    CHECK_EQ(env()->context(), env()->isolate()->GetCurrentContext());
416
417
27
    HandleScope scope(env()->isolate());
418
    Local<Value> args[3] = {
419
      OneByteString(env()->isolate(), err.message),
420
      Integer::New(env()->isolate(), err.err),
421
      OneByteString(env()->isolate(), err.code)
422
108
    };
423
27
    MakeCallback(env()->onerror_string(), arraysize(args), args);
424
425
    // no hope of rescue.
426
27
    write_in_progress_ = false;
427

27
    if (pending_close_)
428
6
      Close();
429
27
  }
430
431
12
  static void Reset(const FunctionCallbackInfo<Value> &args) {
432
    CompressionStream* wrap;
433

24
    ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder());
434
435
12
    AllocScope alloc_scope(wrap);
436
12
    const CompressionError err = wrap->context()->ResetStream();
437

12
    if (err.IsError())
438
      wrap->EmitError(err);
439
  }
440
441
2
  void MemoryInfo(MemoryTracker* tracker) const override {
442
2
    tracker->TrackField("compression context", ctx_);
443
2
    tracker->TrackFieldWithSize("zlib_memory",
444
2
                                zlib_memory_ + unreported_allocations_);
445
2
  }
446
447
 protected:
448
5082
  CompressionContext* context() { return &ctx_; }
449
450
1751
  void InitStream(uint32_t* write_result, Local<Function> write_js_callback) {
451
1751
    write_result_ = write_result;
452
1751
    write_js_callback_.Reset(env()->isolate(), write_js_callback);
453
1751
    init_done_ = true;
454
1751
  }
455
456
  // Allocation functions provided to zlib itself. We store the real size of
457
  // the allocated memory chunk just before the "payload" memory we return
458
  // to zlib.
459
  // Because we use zlib off the thread pool, we can not report memory directly
460
  // to V8; rather, we first store it as "unreported" memory in a separate
461
  // field and later report it back from the main thread.
462
5743
  static void* AllocForZlib(void* data, uInt items, uInt size) {
463
    size_t real_size =
464
        MultiplyWithOverflowCheck(static_cast<size_t>(items),
465
5743
                                  static_cast<size_t>(size));
466
5743
    return AllocForBrotli(data, real_size);
467
  }
468
469
10764
  static void* AllocForBrotli(void* data, size_t size) {
470
10764
    size += sizeof(size_t);
471
10764
    CompressionStream* ctx = static_cast<CompressionStream*>(data);
472
10764
    char* memory = UncheckedMalloc(size);
473

10765
    if (UNLIKELY(memory == nullptr)) return nullptr;
474
10765
    *reinterpret_cast<size_t*>(memory) = size;
475
10765
    ctx->unreported_allocations_.fetch_add(size,
476
                                           std::memory_order_relaxed);
477
10765
    return memory + sizeof(size_t);
478
  }
479
480
13005
  static void FreeForZlib(void* data, void* pointer) {
481

26010
    if (UNLIKELY(pointer == nullptr)) return;
482
10764
    CompressionStream* ctx = static_cast<CompressionStream*>(data);
483
10764
    char* real_pointer = static_cast<char*>(pointer) - sizeof(size_t);
484
10764
    size_t real_size = *reinterpret_cast<size_t*>(real_pointer);
485
10764
    ctx->unreported_allocations_.fetch_sub(real_size,
486
                                           std::memory_order_relaxed);
487
10764
    free(real_pointer);
488
  }
489
490
  // This is called on the main thread after zlib may have allocated something
491
  // in order to report it back to V8.
492
22780
  void AdjustAmountOfExternalAllocatedMemory() {
493
    ssize_t report =
494
45560
        unreported_allocations_.exchange(0, std::memory_order_relaxed);
495

45560
    if (report == 0) return;
496




3922
    CHECK_IMPLIES(report < 0, zlib_memory_ >= static_cast<size_t>(-report));
497
3922
    zlib_memory_ += report;
498
3922
    env()->isolate()->AdjustAmountOfExternalAllocatedMemory(report);
499
  }
500
501
  struct AllocScope {
502
22780
    explicit AllocScope(CompressionStream* stream) : stream(stream) {}
503
22780
    ~AllocScope() { stream->AdjustAmountOfExternalAllocatedMemory(); }
504
    CompressionStream* stream;
505
  };
506
507
 private:
508
9307
  void Ref() {
509

9307
    if (++refs_ == 1) {
510
1929
      ClearWeak();
511
    }
512
9307
  }
513
514
9307
  void Unref() {
515

9307
    CHECK_GT(refs_, 0);
516

9307
    if (--refs_ == 0) {
517
1929
      MakeWeak();
518
    }
519
9307
  }
520
521
  bool init_done_ = false;
522
  bool write_in_progress_ = false;
523
  bool pending_close_ = false;
524
  bool closed_ = false;
525
  unsigned int refs_ = 0;
526
  uint32_t* write_result_ = nullptr;
527
  Persistent<Function> write_js_callback_;
528
  std::atomic<ssize_t> unreported_allocations_{0};
529
  size_t zlib_memory_ = 0;
530
531
  CompressionContext ctx_;
532
};
533
534
2902
class ZlibStream : public CompressionStream<ZlibContext> {
535
 public:
536
1554
  ZlibStream(Environment* env, Local<Object> wrap, node_zlib_mode mode)
537
1554
    : CompressionStream(env, wrap) {
538
1554
    context()->SetMode(mode);
539
1554
  }
540
541
1554
  static void New(const FunctionCallbackInfo<Value>& args) {
542
1554
    Environment* env = Environment::GetCurrent(args);
543
3108
    CHECK(args[0]->IsInt32());
544
    node_zlib_mode mode =
545
4662
        static_cast<node_zlib_mode>(args[0].As<Int32>()->Value());
546
1554
    new ZlibStream(env, args.This(), mode);
547
1554
  }
548
549
  // just pull the ints out of the args and call the other Init
550
1554
  static void Init(const FunctionCallbackInfo<Value>& args) {
551
    // Refs: https://github.com/nodejs/node/issues/16649
552
    // Refs: https://github.com/nodejs/node/issues/14161
553
1554
    if (args.Length() == 5) {
554
      fprintf(stderr,
555
          "WARNING: You are likely using a version of node-tar or npm that "
556
          "is incompatible with this version of Node.js.\nPlease use "
557
          "either the version of npm that is bundled with Node.js, or "
558
          "a version of npm (> 5.5.1 or < 5.4.0) or node-tar (> 4.0.1) "
559
          "that is compatible with Node.js 9 and above.\n");
560
    }
561

1554
    CHECK(args.Length() == 7 &&
562
      "init(windowBits, level, memLevel, strategy, writeResult, writeCallback,"
563
      " dictionary)");
564
565
    ZlibStream* wrap;
566
1554
    ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder());
567
568
1554
    Local<Context> context = args.GetIsolate()->GetCurrentContext();
569
570
    // windowBits is special. On the compression side, 0 is an invalid value.
571
    // But on the decompression side, a value of 0 for windowBits tells zlib
572
    // to use the window size in the zlib header of the compressed stream.
573
    uint32_t window_bits;
574
4662
    if (!args[0]->Uint32Value(context).To(&window_bits)) return;
575
576
    int32_t level;
577
4662
    if (!args[1]->Int32Value(context).To(&level)) return;
578
579
    uint32_t mem_level;
580
4662
    if (!args[2]->Uint32Value(context).To(&mem_level)) return;
581
582
    uint32_t strategy;
583
4662
    if (!args[3]->Uint32Value(context).To(&strategy)) return;
584
585
3108
    CHECK(args[4]->IsUint32Array());
586
3108
    Local<Uint32Array> array = args[4].As<Uint32Array>();
587
1554
    Local<ArrayBuffer> ab = array->Buffer();
588
1554
    uint32_t* write_result = static_cast<uint32_t*>(ab->GetContents().Data());
589
590
3108
    CHECK(args[5]->IsFunction());
591
3108
    Local<Function> write_js_callback = args[5].As<Function>();
592
593
1554
    std::vector<unsigned char> dictionary;
594
1554
    if (Buffer::HasInstance(args[6])) {
595
      unsigned char* data =
596
51
          reinterpret_cast<unsigned char*>(Buffer::Data(args[6]));
597
153
      dictionary = std::vector<unsigned char>(
598
          data,
599
102
          data + Buffer::Length(args[6]));
600
    }
601
602
1554
    wrap->InitStream(write_result, write_js_callback);
603
604
3108
    AllocScope alloc_scope(wrap);
605
    wrap->context()->SetAllocationFunctions(
606
1554
        AllocForZlib, FreeForZlib, static_cast<CompressionStream*>(wrap));
607
    const CompressionError err =
608
        wrap->context()->Init(level, window_bits, mem_level, strategy,
609
1554
                              std::move(dictionary));
610
1554
    if (err.IsError())
611
      wrap->EmitError(err);
612
613
6216
    return args.GetReturnValue().Set(!err.IsError());
614
  }
615
616
1
  static void Params(const FunctionCallbackInfo<Value>& args) {
617

1
    CHECK(args.Length() == 2 && "params(level, strategy)");
618
    ZlibStream* wrap;
619
1
    ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder());
620
1
    Local<Context> context = args.GetIsolate()->GetCurrentContext();
621
    int level;
622
3
    if (!args[0]->Int32Value(context).To(&level)) return;
623
    int strategy;
624
3
    if (!args[1]->Int32Value(context).To(&strategy)) return;
625
626
1
    AllocScope alloc_scope(wrap);
627
1
    const CompressionError err = wrap->context()->SetParams(level, strategy);
628
1
    if (err.IsError())
629
      wrap->EmitError(err);
630
  }
631
632
2
  SET_MEMORY_INFO_NAME(ZlibStream)
633
2
  SET_SELF_SIZE(ZlibStream)
634
};
635
636
template <typename CompressionContext>
637

394
class BrotliCompressionStream : public CompressionStream<CompressionContext> {
638
 public:
639
197
  BrotliCompressionStream(Environment* env,
640
                          Local<Object> wrap,
641
                          node_zlib_mode mode)
642
197
    : CompressionStream<CompressionContext>(env, wrap) {
643
197
    context()->SetMode(mode);
644
197
  }
645
646
407
  inline CompressionContext* context() {
647
407
    return this->CompressionStream<CompressionContext>::context();
648
  }
649
  typedef typename CompressionStream<CompressionContext>::AllocScope AllocScope;
650
651
197
  static void New(const FunctionCallbackInfo<Value>& args) {
652
197
    Environment* env = Environment::GetCurrent(args);
653

394
    CHECK(args[0]->IsInt32());
654
    node_zlib_mode mode =
655
591
        static_cast<node_zlib_mode>(args[0].As<Int32>()->Value());
656
197
    new BrotliCompressionStream(env, args.This(), mode);
657
197
  }
658
659
197
  static void Init(const FunctionCallbackInfo<Value>& args) {
660
    BrotliCompressionStream* wrap;
661

198
    ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder());
662


197
    CHECK(args.Length() == 3 && "init(params, writeResult, writeCallback)");
663
664

394
    CHECK(args[1]->IsUint32Array());
665
197
    uint32_t* write_result = reinterpret_cast<uint32_t*>(Buffer::Data(args[1]));
666
667

394
    CHECK(args[2]->IsFunction());
668
394
    Local<Function> write_js_callback = args[2].As<Function>();
669
197
    wrap->InitStream(write_result, write_js_callback);
670
671
197
    AllocScope alloc_scope(wrap);
672
    CompressionError err =
673
        wrap->context()->Init(
674
          CompressionStream<CompressionContext>::AllocForBrotli,
675
          CompressionStream<CompressionContext>::FreeForZlib,
676
197
          static_cast<CompressionStream<CompressionContext>*>(wrap));
677

197
    if (err.IsError()) {
678
      wrap->EmitError(err);
679
      args.GetReturnValue().Set(false);
680
      return;
681
    }
682
683

394
    CHECK(args[0]->IsUint32Array());
684
197
    const uint32_t* data = reinterpret_cast<uint32_t*>(Buffer::Data(args[0]));
685
591
    size_t len = args[0].As<Uint32Array>()->Length();
686
687

1965
    for (int i = 0; static_cast<size_t>(i) < len; i++) {
688

1769
      if (data[i] == static_cast<uint32_t>(-1))
689
1756
        continue;
690
13
      err = wrap->context()->SetParams(i, data[i]);
691

13
      if (err.IsError()) {
692
1
        wrap->EmitError(err);
693
2
        args.GetReturnValue().Set(false);
694
1
        return;
695
      }
696
    }
697
698

392
    args.GetReturnValue().Set(true);
699
  }
700
701
  static void Params(const FunctionCallbackInfo<Value>& args) {
702
    // Currently a no-op, and not accessed from JS land.
703
    // At some point Brotli may support changing parameters on the fly,
704
    // in which case we can implement this and a JS equivalent similar to
705
    // the zlib Params() function.
706
  }
707
708
  SET_MEMORY_INFO_NAME(BrotliCompressionStream)
709
  SET_SELF_SIZE(BrotliCompressionStream)
710
};
711
712
using BrotliEncoderStream = BrotliCompressionStream<BrotliEncoderContext>;
713
using BrotliDecoderStream = BrotliCompressionStream<BrotliDecoderContext>;
714
715
2842
void ZlibContext::Close() {
716
2842
  CHECK_LE(mode_, UNZIP);
717
718
2842
  int status = Z_OK;
719

2842
  if (mode_ == DEFLATE || mode_ == GZIP || mode_ == DEFLATERAW) {
720
1013
    status = deflateEnd(&strm_);
721


3118
  } else if (mode_ == INFLATE || mode_ == GUNZIP || mode_ == INFLATERAW ||
722
1289
             mode_ == UNZIP) {
723
541
    status = inflateEnd(&strm_);
724
  }
725
726

2842
  CHECK(status == Z_OK || status == Z_DATA_ERROR);
727
2842
  mode_ = NONE;
728
729
2842
  dictionary_.clear();
730
2842
}
731
732
733
7981
void ZlibContext::DoThreadPoolWork() {
734
7981
  const Bytef* next_expected_header_byte = nullptr;
735
736
  // If the avail_out is left at 0, then it means that it ran out
737
  // of room.  If there was avail_out left over, then it means
738
  // that all of the input was consumed.
739

7981
  switch (mode_) {
740
    case DEFLATE:
741
    case GZIP:
742
    case DEFLATERAW:
743
2378
      err_ = deflate(&strm_, flush_);
744
2378
      break;
745
    case UNZIP:
746
201
      if (strm_.avail_in > 0) {
747
200
        next_expected_header_byte = strm_.next_in;
748
      }
749
750
201
      switch (gzip_id_bytes_read_) {
751
        case 0:
752
198
          if (next_expected_header_byte == nullptr) {
753
            break;
754
          }
755
756
198
          if (*next_expected_header_byte == GZIP_HEADER_ID1) {
757
192
            gzip_id_bytes_read_ = 1;
758
192
            next_expected_header_byte++;
759
760
192
            if (strm_.avail_in == 1) {
761
              // The only available byte was already read.
762
2
              break;
763
            }
764
          } else {
765
6
            mode_ = INFLATE;
766
6
            break;
767
          }
768
769
          // fallthrough
770
        case 1:
771
193
          if (next_expected_header_byte == nullptr) {
772
1
            break;
773
          }
774
775
192
          if (*next_expected_header_byte == GZIP_HEADER_ID2) {
776
192
            gzip_id_bytes_read_ = 2;
777
192
            mode_ = GUNZIP;
778
          } else {
779
            // There is no actual difference between INFLATE and INFLATERAW
780
            // (after initialization).
781
            mode_ = INFLATE;
782
          }
783
784
192
          break;
785
        default:
786
          CHECK(0 && "invalid number of gzip magic number bytes read");
787
      }
788
789
      // fallthrough
790
    case INFLATE:
791
    case GUNZIP:
792
    case INFLATERAW:
793
5603
      err_ = inflate(&strm_, flush_);
794
795
      // If data was encoded with dictionary (INFLATERAW will have it set in
796
      // SetDictionary, don't repeat that here)
797

15186
      if (mode_ != INFLATERAW &&
798

5618
          err_ == Z_NEED_DICT &&
799
14
          !dictionary_.empty()) {
800
        // Load it
801
        err_ = inflateSetDictionary(&strm_,
802
13
                                    dictionary_.data(),
803
26
                                    dictionary_.size());
804
13
        if (err_ == Z_OK) {
805
          // And try to decode again
806
12
          err_ = inflate(&strm_, flush_);
807
1
        } else if (err_ == Z_DATA_ERROR) {
808
          // Both inflateSetDictionary() and inflate() return Z_DATA_ERROR.
809
          // Make it possible for After() to tell a bad dictionary from bad
810
          // input.
811
1
          err_ = Z_NEED_DICT;
812
        }
813
      }
814
815

11471
      while (strm_.avail_in > 0 &&
816
452
             mode_ == GUNZIP &&
817
231
             err_ == Z_STREAM_END &&
818
22
             strm_.next_in[0] != 0x00) {
819
        // Bytes remain in input buffer. Perhaps this is another compressed
820
        // member in the same archive, or just trailing garbage.
821
        // Trailing zero bytes are okay, though, since they are frequently
822
        // used for padding.
823
824
20
        ResetStream();
825
20
        err_ = inflate(&strm_, flush_);
826
      }
827
5604
      break;
828
    default:
829
      UNREACHABLE();
830
  }
831
7982
}
832
833
834
7982
void ZlibContext::SetBuffers(char* in, uint32_t in_len,
835
                             char* out, uint32_t out_len) {
836
7982
  strm_.avail_in = in_len;
837
7982
  strm_.next_in = reinterpret_cast<Bytef*>(in);
838
7982
  strm_.avail_out = out_len;
839
7982
  strm_.next_out = reinterpret_cast<Bytef*>(out);
840
7982
}
841
842
843
7982
void ZlibContext::SetFlush(int flush) {
844
7982
  flush_ = flush;
845
7982
}
846
847
848
7957
void ZlibContext::GetAfterWriteOffsets(uint32_t* avail_in,
849
                                       uint32_t* avail_out) const {
850
7957
  *avail_in = strm_.avail_in;
851
7957
  *avail_out = strm_.avail_out;
852
7957
}
853
854
855
25
CompressionError ZlibContext::ErrorForMessage(const char* message) const {
856
25
  if (strm_.msg != nullptr)
857
11
    message = strm_.msg;
858
859
25
  return CompressionError { message, ZlibStrerror(err_), err_ };
860
}
861
862
863
7982
CompressionError ZlibContext::GetErrorInfo() const {
864
  // Acceptable error states depend on the type of zlib stream.
865

7982
  switch (err_) {
866
  case Z_OK:
867
  case Z_BUF_ERROR:
868

6245
    if (strm_.avail_out != 0 && flush_ == Z_FINISH) {
869
12
      return ErrorForMessage("unexpected end of file");
870
    }
871
  case Z_STREAM_END:
872
    // normal statuses, not fatal
873
7957
    break;
874
  case Z_NEED_DICT:
875
2
    if (dictionary_.empty())
876
1
      return ErrorForMessage("Missing dictionary");
877
    else
878
1
      return ErrorForMessage("Bad dictionary");
879
  default:
880
    // something else.
881
11
    return ErrorForMessage("Zlib error");
882
  }
883
884
7957
  return CompressionError {};
885
}
886
887
888
32
CompressionError ZlibContext::ResetStream() {
889
32
  err_ = Z_OK;
890
891
32
  switch (mode_) {
892
    case DEFLATE:
893
    case DEFLATERAW:
894
    case GZIP:
895
12
      err_ = deflateReset(&strm_);
896
12
      break;
897
    case INFLATE:
898
    case INFLATERAW:
899
    case GUNZIP:
900
20
      err_ = inflateReset(&strm_);
901
20
      break;
902
    default:
903
      break;
904
  }
905
906
32
  if (err_ != Z_OK)
907
    return ErrorForMessage("Failed to reset stream");
908
909
32
  return SetDictionary();
910
}
911
912
913
1554
void ZlibContext::SetAllocationFunctions(alloc_func alloc,
914
                                         free_func free,
915
                                         void* opaque) {
916
1554
  strm_.zalloc = alloc;
917
1554
  strm_.zfree = free;
918
1554
  strm_.opaque = opaque;
919
1554
}
920
921
922
1554
CompressionError ZlibContext::Init(
923
    int level, int window_bits, int mem_level, int strategy,
924
    std::vector<unsigned char>&& dictionary) {
925
1554
  if (!((window_bits == 0) &&
926
400
        (mode_ == INFLATE ||
927
232
         mode_ == GUNZIP ||
928
316
         mode_ == UNZIP))) {
929

1312
    CHECK(
930
        (window_bits >= Z_MIN_WINDOWBITS && window_bits <= Z_MAX_WINDOWBITS) &&
931
        "invalid windowBits");
932
  }
933
934

1554
  CHECK((level >= Z_MIN_LEVEL && level <= Z_MAX_LEVEL) &&
935
    "invalid compression level");
936
937

1554
  CHECK((mem_level >= Z_MIN_MEMLEVEL && mem_level <= Z_MAX_MEMLEVEL) &&
938
        "invalid memlevel");
939
940



1554
  CHECK((strategy == Z_FILTERED || strategy == Z_HUFFMAN_ONLY ||
941
         strategy == Z_RLE || strategy == Z_FIXED ||
942
         strategy == Z_DEFAULT_STRATEGY) &&
943
        "invalid strategy");
944
945
1554
  level_ = level;
946
1554
  window_bits_ = window_bits;
947
1554
  mem_level_ = mem_level;
948
1554
  strategy_ = strategy;
949
950
1554
  flush_ = Z_NO_FLUSH;
951
952
1554
  err_ = Z_OK;
953
954

1554
  if (mode_ == GZIP || mode_ == GUNZIP) {
955
435
    window_bits_ += 16;
956
  }
957
958
1554
  if (mode_ == UNZIP) {
959
199
    window_bits_ += 32;
960
  }
961
962

1554
  if (mode_ == DEFLATERAW || mode_ == INFLATERAW) {
963
211
    window_bits_ *= -1;
964
  }
965
966
1554
  switch (mode_) {
967
    case DEFLATE:
968
    case GZIP:
969
    case DEFLATERAW:
970
1013
      err_ = deflateInit2(&strm_,
971
                          level_,
972
                          Z_DEFLATED,
973
                          window_bits_,
974
                          mem_level_,
975
1013
                          strategy_);
976
1013
      break;
977
    case INFLATE:
978
    case GUNZIP:
979
    case INFLATERAW:
980
    case UNZIP:
981
541
      err_ = inflateInit2(&strm_, window_bits_);
982
541
      break;
983
    default:
984
      UNREACHABLE();
985
  }
986
987
1554
  dictionary_ = std::move(dictionary);
988
989
1554
  if (err_ != Z_OK) {
990
    dictionary_.clear();
991
    mode_ = NONE;
992
    return ErrorForMessage(nullptr);
993
  }
994
995
1554
  return SetDictionary();
996
}
997
998
999
1586
CompressionError ZlibContext::SetDictionary() {
1000
1586
  if (dictionary_.empty())
1001
1524
    return CompressionError {};
1002
1003
62
  err_ = Z_OK;
1004
1005
62
  switch (mode_) {
1006
    case DEFLATE:
1007
    case DEFLATERAW:
1008
      err_ = deflateSetDictionary(&strm_,
1009
36
                                  dictionary_.data(),
1010
72
                                  dictionary_.size());
1011
36
      break;
1012
    case INFLATERAW:
1013
      // The other inflate cases will have the dictionary set when inflate()
1014
      // returns Z_NEED_DICT in Process()
1015
      err_ = inflateSetDictionary(&strm_,
1016
13
                                  dictionary_.data(),
1017
26
                                  dictionary_.size());
1018
13
      break;
1019
    default:
1020
13
      break;
1021
  }
1022
1023
62
  if (err_ != Z_OK) {
1024
    return ErrorForMessage("Failed to set dictionary");
1025
  }
1026
1027
62
  return CompressionError {};
1028
}
1029
1030
1031
1
CompressionError ZlibContext::SetParams(int level, int strategy) {
1032
1
  err_ = Z_OK;
1033
1034
1
  switch (mode_) {
1035
    case DEFLATE:
1036
    case DEFLATERAW:
1037
1
      err_ = deflateParams(&strm_, level, strategy);
1038
1
      break;
1039
    default:
1040
      break;
1041
  }
1042
1043

1
  if (err_ != Z_OK && err_ != Z_BUF_ERROR) {
1044
    return ErrorForMessage("Failed to set parameters");
1045
  }
1046
1047
1
  return CompressionError {};
1048
}
1049
1050
1051
1325
void BrotliContext::SetBuffers(char* in, uint32_t in_len,
1052
                               char* out, uint32_t out_len) {
1053
1325
  next_in_ = reinterpret_cast<uint8_t*>(in);
1054
1325
  next_out_ = reinterpret_cast<uint8_t*>(out);
1055
1325
  avail_in_ = in_len;
1056
1325
  avail_out_ = out_len;
1057
1325
}
1058
1059
1060
1325
void BrotliContext::SetFlush(int flush) {
1061
1325
  flush_ = static_cast<BrotliEncoderOperation>(flush);
1062
1325
}
1063
1064
1065
1324
void BrotliContext::GetAfterWriteOffsets(uint32_t* avail_in,
1066
                                         uint32_t* avail_out) const {
1067
1324
  *avail_in = avail_in_;
1068
1324
  *avail_out = avail_out_;
1069
1324
}
1070
1071
1072
331
void BrotliEncoderContext::DoThreadPoolWork() {
1073
331
  CHECK_EQ(mode_, BROTLI_ENCODE);
1074
331
  CHECK(state_);
1075
331
  const uint8_t* next_in = next_in_;
1076
  last_result_ = BrotliEncoderCompressStream(state_.get(),
1077
                                             flush_,
1078
                                             &avail_in_,
1079
                                             &next_in,
1080
                                             &avail_out_,
1081
                                             &next_out_,
1082
331
                                             nullptr);
1083
331
  next_in_ += next_in - next_in_;
1084
331
}
1085
1086
1087
203
void BrotliEncoderContext::Close() {
1088
203
  state_.reset();
1089
203
  mode_ = NONE;
1090
203
}
1091
1092
103
CompressionError BrotliEncoderContext::Init(brotli_alloc_func alloc,
1093
                                            brotli_free_func free,
1094
                                            void* opaque) {
1095
103
  alloc_ = alloc;
1096
103
  free_ = free;
1097
103
  alloc_opaque_ = opaque;
1098
103
  state_.reset(BrotliEncoderCreateInstance(alloc, free, opaque));
1099
103
  if (!state_) {
1100
    return CompressionError("Could not initialize Brotli instance",
1101
                            "ERR_ZLIB_INITIALIZATION_FAILED",
1102
                            -1);
1103
  } else {
1104
103
    return CompressionError {};
1105
  }
1106
}
1107
1108
CompressionError BrotliEncoderContext::ResetStream() {
1109
  return Init(alloc_, free_, alloc_opaque_);
1110
}
1111
1112
13
CompressionError BrotliEncoderContext::SetParams(int key, uint32_t value) {
1113
13
  if (!BrotliEncoderSetParameter(state_.get(),
1114
                                 static_cast<BrotliEncoderParameter>(key),
1115
13
                                 value)) {
1116
    return CompressionError("Setting parameter failed",
1117
                            "ERR_BROTLI_PARAM_SET_FAILED",
1118
1
                            -1);
1119
  } else {
1120
12
    return CompressionError {};
1121
  }
1122
}
1123
1124
331
CompressionError BrotliEncoderContext::GetErrorInfo() const {
1125
331
  if (!last_result_) {
1126
    return CompressionError("Compression failed",
1127
                            "ERR_BROTLI_COMPRESSION_FAILED",
1128
                            -1);
1129
  } else {
1130
331
    return CompressionError {};
1131
  }
1132
}
1133
1134
1135
187
void BrotliDecoderContext::Close() {
1136
187
  state_.reset();
1137
187
  mode_ = NONE;
1138
187
}
1139
1140
994
void BrotliDecoderContext::DoThreadPoolWork() {
1141
994
  CHECK_EQ(mode_, BROTLI_DECODE);
1142
994
  CHECK(state_);
1143
994
  const uint8_t* next_in = next_in_;
1144
  last_result_ = BrotliDecoderDecompressStream(state_.get(),
1145
                                               &avail_in_,
1146
                                               &next_in,
1147
                                               &avail_out_,
1148
                                               &next_out_,
1149
994
                                               nullptr);
1150
994
  next_in_ += next_in - next_in_;
1151
994
  if (last_result_ == BROTLI_DECODER_RESULT_ERROR) {
1152
1
    error_ = BrotliDecoderGetErrorCode(state_.get());
1153
1
    error_string_ = std::string("ERR_") + BrotliDecoderErrorString(error_);
1154
  }
1155
994
}
1156
1157
94
CompressionError BrotliDecoderContext::Init(brotli_alloc_func alloc,
1158
                                            brotli_free_func free,
1159
                                            void* opaque) {
1160
94
  alloc_ = alloc;
1161
94
  free_ = free;
1162
94
  alloc_opaque_ = opaque;
1163
94
  state_.reset(BrotliDecoderCreateInstance(alloc, free, opaque));
1164
94
  if (!state_) {
1165
    return CompressionError("Could not initialize Brotli instance",
1166
                            "ERR_ZLIB_INITIALIZATION_FAILED",
1167
                            -1);
1168
  } else {
1169
94
    return CompressionError {};
1170
  }
1171
}
1172
1173
CompressionError BrotliDecoderContext::ResetStream() {
1174
  return Init(alloc_, free_, alloc_opaque_);
1175
}
1176
1177
CompressionError BrotliDecoderContext::SetParams(int key, uint32_t value) {
1178
  if (!BrotliDecoderSetParameter(state_.get(),
1179
                                 static_cast<BrotliDecoderParameter>(key),
1180
                                 value)) {
1181
    return CompressionError("Setting parameter failed",
1182
                            "ERR_BROTLI_PARAM_SET_FAILED",
1183
                            -1);
1184
  } else {
1185
    return CompressionError {};
1186
  }
1187
}
1188
1189
994
CompressionError BrotliDecoderContext::GetErrorInfo() const {
1190
994
  if (error_ != BROTLI_DECODER_NO_ERROR) {
1191
    return CompressionError("Decompression failed",
1192
                            error_string_.c_str(),
1193
1
                            static_cast<int>(error_));
1194

1085
  } else if (flush_ == BROTLI_OPERATION_FINISH &&
1195
92
             last_result_ == BROTLI_DECODER_RESULT_NEEDS_MORE_INPUT) {
1196
    // Match zlib's behaviour, as brotli doesn't have its own code for this.
1197
    return CompressionError("unexpected end of file",
1198
                            "Z_BUF_ERROR",
1199
                            Z_BUF_ERROR);
1200
  } else {
1201
993
    return CompressionError {};
1202
  }
1203
}
1204
1205
1206
template <typename Stream>
1207
struct MakeClass {
1208
186
  static void Make(Environment* env, Local<Object> target, const char* name) {
1209
186
    Local<FunctionTemplate> z = env->NewFunctionTemplate(Stream::New);
1210
1211
372
    z->InstanceTemplate()->SetInternalFieldCount(1);
1212
372
    z->Inherit(AsyncWrap::GetConstructorTemplate(env));
1213
1214
186
    env->SetProtoMethod(z, "write", Stream::template Write<true>);
1215
186
    env->SetProtoMethod(z, "writeSync", Stream::template Write<false>);
1216
186
    env->SetProtoMethod(z, "close", Stream::Close);
1217
1218
186
    env->SetProtoMethod(z, "init", Stream::Init);
1219
186
    env->SetProtoMethod(z, "params", Stream::Params);
1220
186
    env->SetProtoMethod(z, "reset", Stream::Reset);
1221
1222
186
    Local<String> zlibString = OneByteString(env->isolate(), name);
1223
186
    z->SetClassName(zlibString);
1224
    target->Set(env->context(),
1225
                zlibString,
1226
930
                z->GetFunction(env->context()).ToLocalChecked()).FromJust();
1227
186
  }
1228
};
1229
1230
62
void Initialize(Local<Object> target,
1231
                Local<Value> unused,
1232
                Local<Context> context,
1233
                void* priv) {
1234
62
  Environment* env = Environment::GetCurrent(context);
1235
1236
62
  MakeClass<ZlibStream>::Make(env, target, "Zlib");
1237
62
  MakeClass<BrotliEncoderStream>::Make(env, target, "BrotliEncoder");
1238
62
  MakeClass<BrotliDecoderStream>::Make(env, target, "BrotliDecoder");
1239
1240
  target->Set(env->context(),
1241
              FIXED_ONE_BYTE_STRING(env->isolate(), "ZLIB_VERSION"),
1242
310
              FIXED_ONE_BYTE_STRING(env->isolate(), ZLIB_VERSION)).FromJust();
1243
62
}
1244
1245
}  // anonymous namespace
1246
1247
4410
void DefineZlibConstants(Local<Object> target) {
1248
17640
  NODE_DEFINE_CONSTANT(target, Z_NO_FLUSH);
1249
17640
  NODE_DEFINE_CONSTANT(target, Z_PARTIAL_FLUSH);
1250
17640
  NODE_DEFINE_CONSTANT(target, Z_SYNC_FLUSH);
1251
17640
  NODE_DEFINE_CONSTANT(target, Z_FULL_FLUSH);
1252
17640
  NODE_DEFINE_CONSTANT(target, Z_FINISH);
1253
17640
  NODE_DEFINE_CONSTANT(target, Z_BLOCK);
1254
1255
  // return/error codes
1256
17640
  NODE_DEFINE_CONSTANT(target, Z_OK);
1257
17640
  NODE_DEFINE_CONSTANT(target, Z_STREAM_END);
1258
17640
  NODE_DEFINE_CONSTANT(target, Z_NEED_DICT);
1259
17640
  NODE_DEFINE_CONSTANT(target, Z_ERRNO);
1260
17640
  NODE_DEFINE_CONSTANT(target, Z_STREAM_ERROR);
1261
17640
  NODE_DEFINE_CONSTANT(target, Z_DATA_ERROR);
1262
17640
  NODE_DEFINE_CONSTANT(target, Z_MEM_ERROR);
1263
17640
  NODE_DEFINE_CONSTANT(target, Z_BUF_ERROR);
1264
17640
  NODE_DEFINE_CONSTANT(target, Z_VERSION_ERROR);
1265
1266
17640
  NODE_DEFINE_CONSTANT(target, Z_NO_COMPRESSION);
1267
17640
  NODE_DEFINE_CONSTANT(target, Z_BEST_SPEED);
1268
17640
  NODE_DEFINE_CONSTANT(target, Z_BEST_COMPRESSION);
1269
17640
  NODE_DEFINE_CONSTANT(target, Z_DEFAULT_COMPRESSION);
1270
17640
  NODE_DEFINE_CONSTANT(target, Z_FILTERED);
1271
17640
  NODE_DEFINE_CONSTANT(target, Z_HUFFMAN_ONLY);
1272
17640
  NODE_DEFINE_CONSTANT(target, Z_RLE);
1273
17640
  NODE_DEFINE_CONSTANT(target, Z_FIXED);
1274
17640
  NODE_DEFINE_CONSTANT(target, Z_DEFAULT_STRATEGY);
1275
17640
  NODE_DEFINE_CONSTANT(target, ZLIB_VERNUM);
1276
1277
17640
  NODE_DEFINE_CONSTANT(target, DEFLATE);
1278
17640
  NODE_DEFINE_CONSTANT(target, INFLATE);
1279
17640
  NODE_DEFINE_CONSTANT(target, GZIP);
1280
17640
  NODE_DEFINE_CONSTANT(target, GUNZIP);
1281
17640
  NODE_DEFINE_CONSTANT(target, DEFLATERAW);
1282
17640
  NODE_DEFINE_CONSTANT(target, INFLATERAW);
1283
17640
  NODE_DEFINE_CONSTANT(target, UNZIP);
1284
17640
  NODE_DEFINE_CONSTANT(target, BROTLI_DECODE);
1285
17640
  NODE_DEFINE_CONSTANT(target, BROTLI_ENCODE);
1286
1287
17640
  NODE_DEFINE_CONSTANT(target, Z_MIN_WINDOWBITS);
1288
17640
  NODE_DEFINE_CONSTANT(target, Z_MAX_WINDOWBITS);
1289
17640
  NODE_DEFINE_CONSTANT(target, Z_DEFAULT_WINDOWBITS);
1290
17640
  NODE_DEFINE_CONSTANT(target, Z_MIN_CHUNK);
1291
17640
  NODE_DEFINE_CONSTANT(target, Z_MAX_CHUNK);
1292
17640
  NODE_DEFINE_CONSTANT(target, Z_DEFAULT_CHUNK);
1293
17640
  NODE_DEFINE_CONSTANT(target, Z_MIN_MEMLEVEL);
1294
17640
  NODE_DEFINE_CONSTANT(target, Z_MAX_MEMLEVEL);
1295
17640
  NODE_DEFINE_CONSTANT(target, Z_DEFAULT_MEMLEVEL);
1296
17640
  NODE_DEFINE_CONSTANT(target, Z_MIN_LEVEL);
1297
17640
  NODE_DEFINE_CONSTANT(target, Z_MAX_LEVEL);
1298
17640
  NODE_DEFINE_CONSTANT(target, Z_DEFAULT_LEVEL);
1299
1300
  // Brotli constants
1301
17640
  NODE_DEFINE_CONSTANT(target, BROTLI_OPERATION_PROCESS);
1302
17640
  NODE_DEFINE_CONSTANT(target, BROTLI_OPERATION_FLUSH);
1303
17640
  NODE_DEFINE_CONSTANT(target, BROTLI_OPERATION_FINISH);
1304
17640
  NODE_DEFINE_CONSTANT(target, BROTLI_OPERATION_EMIT_METADATA);
1305
17640
  NODE_DEFINE_CONSTANT(target, BROTLI_PARAM_MODE);
1306
17640
  NODE_DEFINE_CONSTANT(target, BROTLI_MODE_GENERIC);
1307
17640
  NODE_DEFINE_CONSTANT(target, BROTLI_MODE_TEXT);
1308
17640
  NODE_DEFINE_CONSTANT(target, BROTLI_MODE_FONT);
1309
17640
  NODE_DEFINE_CONSTANT(target, BROTLI_DEFAULT_MODE);
1310
17640
  NODE_DEFINE_CONSTANT(target, BROTLI_PARAM_QUALITY);
1311
17640
  NODE_DEFINE_CONSTANT(target, BROTLI_MIN_QUALITY);
1312
17640
  NODE_DEFINE_CONSTANT(target, BROTLI_MAX_QUALITY);
1313
17640
  NODE_DEFINE_CONSTANT(target, BROTLI_DEFAULT_QUALITY);
1314
17640
  NODE_DEFINE_CONSTANT(target, BROTLI_PARAM_LGWIN);
1315
17640
  NODE_DEFINE_CONSTANT(target, BROTLI_MIN_WINDOW_BITS);
1316
17640
  NODE_DEFINE_CONSTANT(target, BROTLI_MAX_WINDOW_BITS);
1317
17640
  NODE_DEFINE_CONSTANT(target, BROTLI_LARGE_MAX_WINDOW_BITS);
1318
17640
  NODE_DEFINE_CONSTANT(target, BROTLI_DEFAULT_WINDOW);
1319
17640
  NODE_DEFINE_CONSTANT(target, BROTLI_PARAM_LGBLOCK);
1320
17640
  NODE_DEFINE_CONSTANT(target, BROTLI_MIN_INPUT_BLOCK_BITS);
1321
17640
  NODE_DEFINE_CONSTANT(target, BROTLI_MAX_INPUT_BLOCK_BITS);
1322
17640
  NODE_DEFINE_CONSTANT(target, BROTLI_PARAM_DISABLE_LITERAL_CONTEXT_MODELING);
1323
17640
  NODE_DEFINE_CONSTANT(target, BROTLI_PARAM_SIZE_HINT);
1324
17640
  NODE_DEFINE_CONSTANT(target, BROTLI_PARAM_LARGE_WINDOW);
1325
17640
  NODE_DEFINE_CONSTANT(target, BROTLI_PARAM_NPOSTFIX);
1326
17640
  NODE_DEFINE_CONSTANT(target, BROTLI_PARAM_NDIRECT);
1327
17640
  NODE_DEFINE_CONSTANT(target, BROTLI_DECODER_RESULT_ERROR);
1328
17640
  NODE_DEFINE_CONSTANT(target, BROTLI_DECODER_RESULT_SUCCESS);
1329
17640
  NODE_DEFINE_CONSTANT(target, BROTLI_DECODER_RESULT_NEEDS_MORE_INPUT);
1330
17640
  NODE_DEFINE_CONSTANT(target, BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT);
1331
17640
  NODE_DEFINE_CONSTANT(target,
1332
      BROTLI_DECODER_PARAM_DISABLE_RING_BUFFER_REALLOCATION);
1333
17640
  NODE_DEFINE_CONSTANT(target, BROTLI_DECODER_PARAM_LARGE_WINDOW);
1334
17640
  NODE_DEFINE_CONSTANT(target, BROTLI_DECODER_NO_ERROR);
1335
17640
  NODE_DEFINE_CONSTANT(target, BROTLI_DECODER_SUCCESS);
1336
17640
  NODE_DEFINE_CONSTANT(target, BROTLI_DECODER_NEEDS_MORE_INPUT);
1337
17640
  NODE_DEFINE_CONSTANT(target, BROTLI_DECODER_NEEDS_MORE_OUTPUT);
1338
17640
  NODE_DEFINE_CONSTANT(target, BROTLI_DECODER_ERROR_FORMAT_EXUBERANT_NIBBLE);
1339
17640
  NODE_DEFINE_CONSTANT(target, BROTLI_DECODER_ERROR_FORMAT_RESERVED);
1340
17640
  NODE_DEFINE_CONSTANT(target,
1341
      BROTLI_DECODER_ERROR_FORMAT_EXUBERANT_META_NIBBLE);
1342
17640
  NODE_DEFINE_CONSTANT(target,
1343
      BROTLI_DECODER_ERROR_FORMAT_SIMPLE_HUFFMAN_ALPHABET);
1344
17640
  NODE_DEFINE_CONSTANT(target, BROTLI_DECODER_ERROR_FORMAT_SIMPLE_HUFFMAN_SAME);
1345
17640
  NODE_DEFINE_CONSTANT(target, BROTLI_DECODER_ERROR_FORMAT_CL_SPACE);
1346
17640
  NODE_DEFINE_CONSTANT(target, BROTLI_DECODER_ERROR_FORMAT_HUFFMAN_SPACE);
1347
17640
  NODE_DEFINE_CONSTANT(target, BROTLI_DECODER_ERROR_FORMAT_CONTEXT_MAP_REPEAT);
1348
17640
  NODE_DEFINE_CONSTANT(target, BROTLI_DECODER_ERROR_FORMAT_BLOCK_LENGTH_1);
1349
17640
  NODE_DEFINE_CONSTANT(target, BROTLI_DECODER_ERROR_FORMAT_BLOCK_LENGTH_2);
1350
17640
  NODE_DEFINE_CONSTANT(target, BROTLI_DECODER_ERROR_FORMAT_TRANSFORM);
1351
17640
  NODE_DEFINE_CONSTANT(target, BROTLI_DECODER_ERROR_FORMAT_DICTIONARY);
1352
17640
  NODE_DEFINE_CONSTANT(target, BROTLI_DECODER_ERROR_FORMAT_WINDOW_BITS);
1353
17640
  NODE_DEFINE_CONSTANT(target, BROTLI_DECODER_ERROR_FORMAT_PADDING_1);
1354
17640
  NODE_DEFINE_CONSTANT(target, BROTLI_DECODER_ERROR_FORMAT_PADDING_2);
1355
17640
  NODE_DEFINE_CONSTANT(target, BROTLI_DECODER_ERROR_FORMAT_DISTANCE);
1356
17640
  NODE_DEFINE_CONSTANT(target, BROTLI_DECODER_ERROR_DICTIONARY_NOT_SET);
1357
17640
  NODE_DEFINE_CONSTANT(target, BROTLI_DECODER_ERROR_INVALID_ARGUMENTS);
1358
17640
  NODE_DEFINE_CONSTANT(target, BROTLI_DECODER_ERROR_ALLOC_CONTEXT_MODES);
1359
17640
  NODE_DEFINE_CONSTANT(target, BROTLI_DECODER_ERROR_ALLOC_TREE_GROUPS);
1360
17640
  NODE_DEFINE_CONSTANT(target, BROTLI_DECODER_ERROR_ALLOC_CONTEXT_MAP);
1361
17640
  NODE_DEFINE_CONSTANT(target, BROTLI_DECODER_ERROR_ALLOC_RING_BUFFER_1);
1362
17640
  NODE_DEFINE_CONSTANT(target, BROTLI_DECODER_ERROR_ALLOC_RING_BUFFER_2);
1363
17640
  NODE_DEFINE_CONSTANT(target, BROTLI_DECODER_ERROR_ALLOC_BLOCK_TYPE_TREES);
1364
17640
  NODE_DEFINE_CONSTANT(target, BROTLI_DECODER_ERROR_UNREACHABLE);
1365
4410
}
1366
1367
}  // namespace node
1368
1369
4292
NODE_MODULE_CONTEXT_AWARE_INTERNAL(zlib, node::Initialize)