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-09-25 22:36:03 Branches: 461 774 59.6 %

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




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

1745
    CHECK_EQ(false, write_in_progress_ && "write in progress");
254
1745
    Close();
255

1745
    CHECK_EQ(zlib_memory_, 0);
256

1745
    CHECK_EQ(unreported_allocations_, 0);
257

5235
  }
258
259
3358
  void Close() {
260

3358
    if (write_in_progress_) {
261
29
      pending_close_ = true;
262
3387
      return;
263
    }
264
265
3329
    pending_close_ = false;
266
3329
    closed_ = true;
267

3329
    CHECK(init_done_ && "close before init");
268
269
3329
    AllocScope alloc_scope(this);
270
3329
    ctx_.Close();
271
  }
272
273
274
1584
  static void Close(const FunctionCallbackInfo<Value>& args) {
275
    CompressionStream* ctx;
276

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



9700
    CHECK_EQ(args.Length(), 7);
287
288
    uint32_t in_off, in_len, out_off, out_len, flush;
289
    char* in;
290
    char* out;
291
292









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



29100
    if (!args[0]->Uint32Value(context).To(&flush)) return;
294
295


















9700
    if (flush != Z_NO_FLUSH &&
296
        flush != Z_PARTIAL_FLUSH &&
297
        flush != Z_SYNC_FLUSH &&
298
        flush != Z_FULL_FLUSH &&
299
        flush != Z_FINISH &&
300
        flush != Z_BLOCK) {
301
      CHECK(0 && "Invalid flush value");
302
    }
303
304



29100
    if (args[1]->IsNull()) {
305
      // just a flush
306
      in = nullptr;
307
      in_len = 0;
308
      in_off = 0;
309
    } else {
310



9700
      CHECK(Buffer::HasInstance(args[1]));
311
19400
      Local<Object> in_buf = args[1].As<Object>();
312



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



29100
      if (!args[3]->Uint32Value(context).To(&in_len)) return;
314
315



9700
      CHECK(Buffer::IsWithinBounds(in_off, in_len, Buffer::Length(in_buf)));
316
9700
      in = Buffer::Data(in_buf) + in_off;
317
    }
318
319



9700
    CHECK(Buffer::HasInstance(args[4]));
320
19400
    Local<Object> out_buf = args[4].As<Object>();
321



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



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



9700
    CHECK(Buffer::IsWithinBounds(out_off, out_len, Buffer::Length(out_buf)));
324
9700
    out = Buffer::Data(out_buf) + out_off;
325
326
    CompressionStream* ctx;
327



9700
    ASSIGN_OR_RETURN_UNWRAP(&ctx, args.Holder());
328
329
9700
    ctx->Write<async>(flush, in, in_len, out, out_len);
330
  }
331
332
  template <bool async>
333
9700
  void Write(uint32_t flush,
334
             char* in, uint32_t in_len,
335
             char* out, uint32_t out_len) {
336
9700
    AllocScope alloc_scope(this);
337
338



9700
    CHECK(init_done_ && "write before init");
339



9700
    CHECK(!closed_ && "already finalized");
340
341



9700
    CHECK_EQ(false, write_in_progress_);
342



9700
    CHECK_EQ(false, pending_close_);
343
9700
    write_in_progress_ = true;
344
9700
    Ref();
345
346
9700
    ctx_.SetBuffers(in, in_len, out, out_len);
347
9700
    ctx_.SetFlush(flush);
348
349
    if (!async) {
350
      // sync version
351
1468
      env()->PrintSyncTrace();
352
1468
      DoThreadPoolWork();
353

1468
      if (CheckError()) {
354
1462
        UpdateWriteResult();
355
1462
        write_in_progress_ = false;
356
      }
357
1468
      Unref();
358

11168
      return;
359
    }
360
361
    // async version
362

8232
    ScheduleWork();
363
  }
364
365
9678
  void UpdateWriteResult() {
366
9678
    ctx_.GetAfterWriteOffsets(&write_result_[1], &write_result_[0]);
367
9678
  }
368
369
  // thread pool!
370
  // This function may be called multiple times on the uv_work pool
371
  // for a single write() call, until all of the input bytes have
372
  // been consumed.
373
9700
  void DoThreadPoolWork() override {
374
9700
    ctx_.DoThreadPoolWork();
375
9699
  }
376
377
378
9700
  bool CheckError() {
379
9700
    const CompressionError err = ctx_.GetErrorInfo();
380

9700
    if (!err.IsError()) return true;
381
22
    EmitError(err);
382
22
    return false;
383
  }
384
385
386
  // v8 land!
387
8232
  void AfterThreadPoolWork(int status) override {
388
8232
    AllocScope alloc_scope(this);
389

24680
    OnScopeLeave on_scope_leave([&]() { Unref(); });
390
391
8232
    write_in_progress_ = false;
392
393

8232
    if (status == UV_ECANCELED) {
394
      Close();
395
      return;
396
    }
397
398

8232
    CHECK_EQ(status, 0);
399
400

16448
    HandleScope handle_scope(env()->isolate());
401

16448
    Context::Scope context_scope(env()->context());
402
403

8232
    if (!CheckError())
404
16
      return;
405
406
8216
    UpdateWriteResult();
407
408
    // call the write() cb
409
    Local<Function> cb = PersistentToLocal::Default(env()->isolate(),
410
8216
                                                    write_js_callback_);
411
8216
    MakeCallback(cb, 0, nullptr);
412
413

8216
    if (pending_close_)
414
8239
      Close();
415
  }
416
417
  // TODO(addaleax): Switch to modern error system (node_errors.h).
418
23
  void EmitError(const CompressionError& err) {
419
    // If you hit this assertion, you forgot to enter the v8::Context first.
420

46
    CHECK_EQ(env()->context(), env()->isolate()->GetCurrentContext());
421
422
23
    HandleScope scope(env()->isolate());
423
    Local<Value> args[3] = {
424
      OneByteString(env()->isolate(), err.message),
425
      Integer::New(env()->isolate(), err.err),
426
      OneByteString(env()->isolate(), err.code)
427
92
    };
428
23
    MakeCallback(env()->onerror_string(), arraysize(args), args);
429
430
    // no hope of rescue.
431
23
    write_in_progress_ = false;
432

23
    if (pending_close_)
433
6
      Close();
434
23
  }
435
436
12
  static void Reset(const FunctionCallbackInfo<Value> &args) {
437
    CompressionStream* wrap;
438

24
    ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder());
439
440
12
    AllocScope alloc_scope(wrap);
441
12
    const CompressionError err = wrap->context()->ResetStream();
442

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

10384
    if (UNLIKELY(memory == nullptr)) return nullptr;
479
10384
    *reinterpret_cast<size_t*>(memory) = size;
480
10384
    ctx->unreported_allocations_.fetch_add(size,
481
                                           std::memory_order_relaxed);
482
10384
    return memory + sizeof(size_t);
483
  }
484
485
12665
  static void FreeForZlib(void* data, void* pointer) {
486

25330
    if (UNLIKELY(pointer == nullptr)) return;
487
10384
    CompressionStream* ctx = static_cast<CompressionStream*>(data);
488
10384
    char* real_pointer = static_cast<char*>(pointer) - sizeof(size_t);
489
10384
    size_t real_size = *reinterpret_cast<size_t*>(real_pointer);
490
10384
    ctx->unreported_allocations_.fetch_sub(real_size,
491
                                           std::memory_order_relaxed);
492
10384
    free(real_pointer);
493
  }
494
495
  // This is called on the main thread after zlib may have allocated something
496
  // in order to report it back to V8.
497
23023
  void AdjustAmountOfExternalAllocatedMemory() {
498
    ssize_t report =
499
46046
        unreported_allocations_.exchange(0, std::memory_order_relaxed);
500

46046
    if (report == 0) return;
501




3889
    CHECK_IMPLIES(report < 0, zlib_memory_ >= static_cast<size_t>(-report));
502
3889
    zlib_memory_ += report;
503
3889
    env()->isolate()->AdjustAmountOfExternalAllocatedMemory(report);
504
  }
505
506
  struct AllocScope {
507
23023
    explicit AllocScope(CompressionStream* stream) : stream(stream) {}
508
23023
    ~AllocScope() { stream->AdjustAmountOfExternalAllocatedMemory(); }
509
    CompressionStream* stream;
510
  };
511
512
 private:
513
9700
  void Ref() {
514

9700
    if (++refs_ == 1) {
515
2452
      ClearWeak();
516
    }
517
9700
  }
518
519
9700
  void Unref() {
520

9700
    CHECK_GT(refs_, 0);
521

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

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

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

406
class BrotliCompressionStream : public CompressionStream<CompressionContext> {
643
 public:
644
203
  BrotliCompressionStream(Environment* env,
645
                          Local<Object> wrap,
646
                          node_zlib_mode mode)
647
203
    : CompressionStream<CompressionContext>(env, wrap) {
648
203
    context()->SetMode(mode);
649
203
  }
650
651
419
  inline CompressionContext* context() {
652
419
    return this->CompressionStream<CompressionContext>::context();
653
  }
654
  typedef typename CompressionStream<CompressionContext>::AllocScope AllocScope;
655
656
203
  static void New(const FunctionCallbackInfo<Value>& args) {
657
203
    Environment* env = Environment::GetCurrent(args);
658

406
    CHECK(args[0]->IsInt32());
659
    node_zlib_mode mode =
660
609
        static_cast<node_zlib_mode>(args[0].As<Int32>()->Value());
661
203
    new BrotliCompressionStream(env, args.This(), mode);
662
203
  }
663
664
203
  static void Init(const FunctionCallbackInfo<Value>& args) {
665
    BrotliCompressionStream* wrap;
666

204
    ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder());
667


203
    CHECK(args.Length() == 3 && "init(params, writeResult, writeCallback)");
668
669

406
    CHECK(args[1]->IsUint32Array());
670
203
    uint32_t* write_result = reinterpret_cast<uint32_t*>(Buffer::Data(args[1]));
671
672

406
    CHECK(args[2]->IsFunction());
673
406
    Local<Function> write_js_callback = args[2].As<Function>();
674
203
    wrap->InitStream(write_result, write_js_callback);
675
676
203
    AllocScope alloc_scope(wrap);
677
    CompressionError err =
678
        wrap->context()->Init(
679
          CompressionStream<CompressionContext>::AllocForBrotli,
680
          CompressionStream<CompressionContext>::FreeForZlib,
681
203
          static_cast<CompressionStream<CompressionContext>*>(wrap));
682

203
    if (err.IsError()) {
683
      wrap->EmitError(err);
684
      args.GetReturnValue().Set(false);
685
      return;
686
    }
687
688

406
    CHECK(args[0]->IsUint32Array());
689
203
    const uint32_t* data = reinterpret_cast<uint32_t*>(Buffer::Data(args[0]));
690
609
    size_t len = args[0].As<Uint32Array>()->Length();
691
692

2025
    for (int i = 0; static_cast<size_t>(i) < len; i++) {
693

1823
      if (data[i] == static_cast<uint32_t>(-1))
694
1810
        continue;
695
13
      err = wrap->context()->SetParams(i, data[i]);
696

13
      if (err.IsError()) {
697
1
        wrap->EmitError(err);
698
2
        args.GetReturnValue().Set(false);
699
1
        return;
700
      }
701
    }
702
703

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

2927
  if (mode_ == DEFLATE || mode_ == GZIP || mode_ == DEFLATERAW) {
725
886
    status = deflateEnd(&strm_);
726


3423
  } else if (mode_ == INFLATE || mode_ == GUNZIP || mode_ == INFLATERAW ||
727
1382
             mode_ == UNZIP) {
728
660
    status = inflateEnd(&strm_);
729
  }
730
731

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

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

17107
      if (mode_ != INFLATERAW &&
803

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

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

8372
  switch (err_) {
871
  case Z_OK:
872
  case Z_BUF_ERROR:
873

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

1095
    CHECK(
935
        (window_bits >= Z_MIN_WINDOWBITS && window_bits <= Z_MAX_WINDOWBITS) &&
936
        "invalid windowBits");
937
  }
938
939

1546
  CHECK((level >= Z_MIN_LEVEL && level <= Z_MAX_LEVEL) &&
940
    "invalid compression level");
941
942

1546
  CHECK((mem_level >= Z_MIN_MEMLEVEL && mem_level <= Z_MAX_MEMLEVEL) &&
943
        "invalid memlevel");
944
945



1546
  CHECK((strategy == Z_FILTERED || strategy == Z_HUFFMAN_ONLY ||
946
         strategy == Z_RLE || strategy == Z_FIXED ||
947
         strategy == Z_DEFAULT_STRATEGY) &&
948
        "invalid strategy");
949
950
1546
  level_ = level;
951
1546
  window_bits_ = window_bits;
952
1546
  mem_level_ = mem_level;
953
1546
  strategy_ = strategy;
954
955
1546
  flush_ = Z_NO_FLUSH;
956
957
1546
  err_ = Z_OK;
958
959

1546
  if (mode_ == GZIP || mode_ == GUNZIP) {
960
431
    window_bits_ += 16;
961
  }
962
963
1546
  if (mode_ == UNZIP) {
964
306
    window_bits_ += 32;
965
  }
966
967

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

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

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