GCC Code Coverage Report
Directory: ../ Exec Total Coverage
File: /home/iojs/build/workspace/node-test-commit-linux-coverage/nodes/benchmark/out/../src/node_zlib.cc Lines: 592 641 92.4 %
Date: 2019-01-07 12:15:22 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
#include "node_internals.h"
25
26
#include "async_wrap-inl.h"
27
#include "env-inl.h"
28
#include "util-inl.h"
29
30
#include "v8.h"
31
32
#include "brotli/encode.h"
33
#include "brotli/decode.h"
34
#include "zlib.h"
35
36
#include <errno.h>
37
#include <stdlib.h>
38
#include <string.h>
39
#include <sys/types.h>
40
#include <atomic>
41
42
namespace node {
43
44
using v8::Array;
45
using v8::ArrayBuffer;
46
using v8::Context;
47
using v8::Function;
48
using v8::FunctionCallbackInfo;
49
using v8::FunctionTemplate;
50
using v8::HandleScope;
51
using v8::Int32;
52
using v8::Integer;
53
using v8::Local;
54
using v8::Object;
55
using v8::String;
56
using v8::Uint32;
57
using v8::Uint32Array;
58
using v8::Value;
59
60
namespace {
61
62
#define ZLIB_ERROR_CODES(V)      \
63
  V(Z_OK)                        \
64
  V(Z_STREAM_END)                \
65
  V(Z_NEED_DICT)                 \
66
  V(Z_ERRNO)                     \
67
  V(Z_STREAM_ERROR)              \
68
  V(Z_DATA_ERROR)                \
69
  V(Z_MEM_ERROR)                 \
70
  V(Z_BUF_ERROR)                 \
71
  V(Z_VERSION_ERROR)             \
72
73
25
inline const char* ZlibStrerror(int err) {
74
#define V(code) if (err == code) return #code;
75




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

1178
    CHECK_EQ(false, write_in_progress_ && "write in progress");
237
1178
    Close();
238

1178
    CHECK_EQ(zlib_memory_, 0);
239

1178
    CHECK_EQ(unreported_allocations_, 0);
240

3534
  }
241
242
2302
  void Close() {
243

2302
    if (write_in_progress_) {
244
7
      pending_close_ = true;
245
2309
      return;
246
    }
247
248
2295
    pending_close_ = false;
249
2295
    closed_ = true;
250

2295
    CHECK(init_done_ && "close before init");
251
252
2295
    AllocScope alloc_scope(this);
253
2295
    ctx_.Close();
254
  }
255
256
257
1117
  static void Close(const FunctionCallbackInfo<Value>& args) {
258
    CompressionStream* ctx;
259

2234
    ASSIGN_OR_RETURN_UNWRAP(&ctx, args.Holder());
260
1117
    ctx->Close();
261
  }
262
263
264
  // write(flush, in, in_off, in_len, out, out_off, out_len)
265
  template <bool async>
266
8368
  static void Write(const FunctionCallbackInfo<Value>& args) {
267
8368
    Environment* env = Environment::GetCurrent(args);
268
8368
    Local<Context> context = env->context();
269



8368
    CHECK_EQ(args.Length(), 7);
270
271
    uint32_t in_off, in_len, out_off, out_len, flush;
272
    char* in;
273
    char* out;
274
275









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



25104
    if (!args[0]->Uint32Value(context).To(&flush)) return;
277
278


















8368
    if (flush != Z_NO_FLUSH &&
279
        flush != Z_PARTIAL_FLUSH &&
280
        flush != Z_SYNC_FLUSH &&
281
        flush != Z_FULL_FLUSH &&
282
        flush != Z_FINISH &&
283
        flush != Z_BLOCK) {
284
      CHECK(0 && "Invalid flush value");
285
    }
286
287



25104
    if (args[1]->IsNull()) {
288
      // just a flush
289
      in = nullptr;
290
      in_len = 0;
291
      in_off = 0;
292
    } else {
293



8368
      CHECK(Buffer::HasInstance(args[1]));
294
16736
      Local<Object> in_buf = args[1].As<Object>();
295



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



25104
      if (!args[3]->Uint32Value(context).To(&in_len)) return;
297
298



8368
      CHECK(Buffer::IsWithinBounds(in_off, in_len, Buffer::Length(in_buf)));
299
8368
      in = Buffer::Data(in_buf) + in_off;
300
    }
301
302



8368
    CHECK(Buffer::HasInstance(args[4]));
303
16736
    Local<Object> out_buf = args[4].As<Object>();
304



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



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



8368
    CHECK(Buffer::IsWithinBounds(out_off, out_len, Buffer::Length(out_buf)));
307
8368
    out = Buffer::Data(out_buf) + out_off;
308
309
    CompressionStream* ctx;
310



8368
    ASSIGN_OR_RETURN_UNWRAP(&ctx, args.Holder());
311
312
8368
    ctx->Write<async>(flush, in, in_len, out, out_len);
313
  }
314
315
  template <bool async>
316
8368
  void Write(uint32_t flush,
317
             char* in, uint32_t in_len,
318
             char* out, uint32_t out_len) {
319
8368
    AllocScope alloc_scope(this);
320
321



8368
    CHECK(init_done_ && "write before init");
322



8368
    CHECK(!closed_ && "already finalized");
323
324



8368
    CHECK_EQ(false, write_in_progress_);
325



8368
    CHECK_EQ(false, pending_close_);
326
8368
    write_in_progress_ = true;
327
8368
    Ref();
328
329
8368
    ctx_.SetBuffers(in, in_len, out, out_len);
330
8368
    ctx_.SetFlush(flush);
331
332
    if (!async) {
333
      // sync version
334
825
      env()->PrintSyncTrace();
335
825
      DoThreadPoolWork();
336

825
      if (CheckError()) {
337
819
        UpdateWriteResult();
338
819
        write_in_progress_ = false;
339
      }
340
825
      Unref();
341

9193
      return;
342
    }
343
344
    // async version
345

7543
    ScheduleWork();
346
  }
347
348
8342
  void UpdateWriteResult() {
349
8342
    ctx_.GetAfterWriteOffsets(&write_result_[1], &write_result_[0]);
350
8342
  }
351
352
  // thread pool!
353
  // This function may be called multiple times on the uv_work pool
354
  // for a single write() call, until all of the input bytes have
355
  // been consumed.
356
8368
  void DoThreadPoolWork() override {
357
8368
    ctx_.DoThreadPoolWork();
358
8368
  }
359
360
361
8368
  bool CheckError() {
362
8368
    const CompressionError err = ctx_.GetErrorInfo();
363

8368
    if (!err.IsError()) return true;
364
26
    EmitError(err);
365
26
    return false;
366
  }
367
368
369
  // v8 land!
370
7543
  void AfterThreadPoolWork(int status) override {
371
7543
    AllocScope alloc_scope(this);
372

22609
    OnScopeLeave on_scope_leave([&]() { Unref(); });
373
374
7543
    write_in_progress_ = false;
375
376

7543
    if (status == UV_ECANCELED) {
377
      Close();
378
      return;
379
    }
380
381

7543
    CHECK_EQ(status, 0);
382
383

15066
    HandleScope handle_scope(env()->isolate());
384

15066
    Context::Scope context_scope(env()->context());
385
386

7543
    if (!CheckError())
387
20
      return;
388
389
7523
    UpdateWriteResult();
390
391
    // call the write() cb
392
    Local<Function> cb = PersistentToLocal::Default(env()->isolate(),
393
7523
                                                    write_js_callback_);
394
7523
    MakeCallback(cb, 0, nullptr);
395
396

7523
    if (pending_close_)
397
7524
      Close();
398
  }
399
400
  // TODO(addaleax): Switch to modern error system (node_errors.h).
401
27
  void EmitError(const CompressionError& err) {
402
    // If you hit this assertion, you forgot to enter the v8::Context first.
403

54
    CHECK_EQ(env()->context(), env()->isolate()->GetCurrentContext());
404
405
27
    HandleScope scope(env()->isolate());
406
    Local<Value> args[3] = {
407
      OneByteString(env()->isolate(), err.message),
408
      Integer::New(env()->isolate(), err.err),
409
      OneByteString(env()->isolate(), err.code)
410
108
    };
411
27
    MakeCallback(env()->onerror_string(), arraysize(args), args);
412
413
    // no hope of rescue.
414
27
    write_in_progress_ = false;
415

27
    if (pending_close_)
416
6
      Close();
417
27
  }
418
419
12
  static void Reset(const FunctionCallbackInfo<Value> &args) {
420
    CompressionStream* wrap;
421

24
    ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder());
422
423
12
    AllocScope alloc_scope(wrap);
424
12
    const CompressionError err = wrap->context()->ResetStream();
425

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

8418
    if (UNLIKELY(memory == nullptr)) return nullptr;
462
8418
    *reinterpret_cast<size_t*>(memory) = size;
463
8418
    ctx->unreported_allocations_.fetch_add(size,
464
                                           std::memory_order_relaxed);
465
8418
    return memory + sizeof(size_t);
466
  }
467
468
10639
  static void FreeForZlib(void* data, void* pointer) {
469

21278
    if (UNLIKELY(pointer == nullptr)) return;
470
8417
    CompressionStream* ctx = static_cast<CompressionStream*>(data);
471
8417
    char* real_pointer = static_cast<char*>(pointer) - sizeof(size_t);
472
8417
    size_t real_size = *reinterpret_cast<size_t*>(real_pointer);
473
8417
    ctx->unreported_allocations_.fetch_sub(real_size,
474
                                           std::memory_order_relaxed);
475
8417
    free(real_pointer);
476
  }
477
478
  // This is called on the main thread after zlib may have allocated something
479
  // in order to report it back to V8.
480
19500
  void AdjustAmountOfExternalAllocatedMemory() {
481
    ssize_t report =
482
39000
        unreported_allocations_.exchange(0, std::memory_order_relaxed);
483

39000
    if (report == 0) return;
484




2960
    CHECK_IMPLIES(report < 0, zlib_memory_ >= static_cast<size_t>(-report));
485
2960
    zlib_memory_ += report;
486
2960
    env()->isolate()->AdjustAmountOfExternalAllocatedMemory(report);
487
  }
488
489
  struct AllocScope {
490
19500
    explicit AllocScope(CompressionStream* stream) : stream(stream) {}
491
19500
    ~AllocScope() { stream->AdjustAmountOfExternalAllocatedMemory(); }
492
    CompressionStream* stream;
493
  };
494
495
 private:
496
8368
  void Ref() {
497

8368
    if (++refs_ == 1) {
498
1457
      ClearWeak();
499
    }
500
8368
  }
501
502
8368
  void Unref() {
503

8368
    CHECK_GT(refs_, 0);
504

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

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

1
    CHECK(args.Length() == 2 && "params(level, strategy)");
606
    ZlibStream* wrap;
607
1
    ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder());
608
1
    Local<Context> context = args.GetIsolate()->GetCurrentContext();
609
    int level;
610
3
    if (!args[0]->Int32Value(context).To(&level)) return;
611
    int strategy;
612
3
    if (!args[1]->Int32Value(context).To(&strategy)) return;
613
614
1
    AllocScope alloc_scope(wrap);
615
1
    const CompressionError err = wrap->context()->SetParams(level, strategy);
616
1
    if (err.IsError())
617
      wrap->EmitError(err);
618
  }
619
620
2
  SET_MEMORY_INFO_NAME(ZlibStream)
621
2
  SET_SELF_SIZE(ZlibStream)
622
};
623
624
template <typename CompressionContext>
625

388
class BrotliCompressionStream : public CompressionStream<CompressionContext> {
626
 public:
627
194
  BrotliCompressionStream(Environment* env,
628
                          Local<Object> wrap,
629
                          node_zlib_mode mode)
630
194
    : CompressionStream<CompressionContext>(env, wrap) {
631
194
    context()->SetMode(mode);
632
194
  }
633
634
401
  inline CompressionContext* context() {
635
401
    return this->CompressionStream<CompressionContext>::context();
636
  }
637
  typedef typename CompressionStream<CompressionContext>::AllocScope AllocScope;
638
639
194
  static void New(const FunctionCallbackInfo<Value>& args) {
640
194
    Environment* env = Environment::GetCurrent(args);
641

388
    CHECK(args[0]->IsInt32());
642
    node_zlib_mode mode =
643
582
        static_cast<node_zlib_mode>(args[0].As<Int32>()->Value());
644
194
    new BrotliCompressionStream(env, args.This(), mode);
645
194
  }
646
647
194
  static void Init(const FunctionCallbackInfo<Value>& args) {
648
    BrotliCompressionStream* wrap;
649

195
    ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder());
650


194
    CHECK(args.Length() == 3 && "init(params, writeResult, writeCallback)");
651
652

388
    CHECK(args[1]->IsUint32Array());
653
194
    uint32_t* write_result = reinterpret_cast<uint32_t*>(Buffer::Data(args[1]));
654
655

388
    CHECK(args[2]->IsFunction());
656
388
    Local<Function> write_js_callback = args[2].As<Function>();
657
194
    wrap->InitStream(write_result, write_js_callback);
658
659
194
    AllocScope alloc_scope(wrap);
660
    CompressionError err =
661
        wrap->context()->Init(
662
          CompressionStream<CompressionContext>::AllocForBrotli,
663
          CompressionStream<CompressionContext>::FreeForZlib,
664
194
          static_cast<CompressionStream<CompressionContext>*>(wrap));
665

194
    if (err.IsError()) {
666
      wrap->EmitError(err);
667
      args.GetReturnValue().Set(false);
668
      return;
669
    }
670
671

388
    CHECK(args[0]->IsUint32Array());
672
194
    const uint32_t* data = reinterpret_cast<uint32_t*>(Buffer::Data(args[0]));
673
582
    size_t len = args[0].As<Uint32Array>()->Length();
674
675

1935
    for (int i = 0; static_cast<size_t>(i) < len; i++) {
676

1742
      if (data[i] == static_cast<uint32_t>(-1))
677
1729
        continue;
678
13
      err = wrap->context()->SetParams(i, data[i]);
679

13
      if (err.IsError()) {
680
1
        wrap->EmitError(err);
681
2
        args.GetReturnValue().Set(false);
682
1
        return;
683
      }
684
    }
685
686

386
    args.GetReturnValue().Set(true);
687
  }
688
689
  static void Params(const FunctionCallbackInfo<Value>& args) {
690
    // Currently a no-op, and not accessed from JS land.
691
    // At some point Brotli may support changing parameters on the fly,
692
    // in which case we can implement this and a JS equivalent similar to
693
    // the zlib Params() function.
694
  }
695
696
  SET_MEMORY_INFO_NAME(BrotliCompressionStream)
697
  SET_SELF_SIZE(BrotliCompressionStream)
698
};
699
700
using BrotliEncoderStream = BrotliCompressionStream<BrotliEncoderContext>;
701
using BrotliDecoderStream = BrotliCompressionStream<BrotliDecoderContext>;
702
703
1909
void ZlibContext::Close() {
704
1909
  CHECK_LE(mode_, UNZIP);
705
706
1909
  int status = Z_OK;
707

1909
  if (mode_ == DEFLATE || mode_ == GZIP || mode_ == DEFLATERAW) {
708
546
    status = deflateEnd(&strm_);
709


2186
  } else if (mode_ == INFLATE || mode_ == GUNZIP || mode_ == INFLATERAW ||
710
823
             mode_ == UNZIP) {
711
541
    status = inflateEnd(&strm_);
712
  }
713
714

1909
  CHECK(status == Z_OK || status == Z_DATA_ERROR);
715
1909
  mode_ = NONE;
716
717
1909
  dictionary_.clear();
718
1909
}
719
720
721
7045
void ZlibContext::DoThreadPoolWork() {
722
7045
  const Bytef* next_expected_header_byte = nullptr;
723
724
  // If the avail_out is left at 0, then it means that it ran out
725
  // of room.  If there was avail_out left over, then it means
726
  // that all of the input was consumed.
727

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

15171
      if (mode_ != INFLATERAW &&
786

5613
          err_ == Z_NEED_DICT &&
787
14
          !dictionary_.empty()) {
788
        // Load it
789
        err_ = inflateSetDictionary(&strm_,
790
13
                                    dictionary_.data(),
791
26
                                    dictionary_.size());
792
13
        if (err_ == Z_OK) {
793
          // And try to decode again
794
12
          err_ = inflate(&strm_, flush_);
795
1
        } else if (err_ == Z_DATA_ERROR) {
796
          // Both inflateSetDictionary() and inflate() return Z_DATA_ERROR.
797
          // Make it possible for After() to tell a bad dictionary from bad
798
          // input.
799
1
          err_ = Z_NEED_DICT;
800
        }
801
      }
802
803

11460
      while (strm_.avail_in > 0 &&
804
450
             mode_ == GUNZIP &&
805
230
             err_ == Z_STREAM_END &&
806
22
             strm_.next_in[0] != 0x00) {
807
        // Bytes remain in input buffer. Perhaps this is another compressed
808
        // member in the same archive, or just trailing garbage.
809
        // Trailing zero bytes are okay, though, since they are frequently
810
        // used for padding.
811
812
20
        ResetStream();
813
20
        err_ = inflate(&strm_, flush_);
814
      }
815
5599
      break;
816
    default:
817
      UNREACHABLE();
818
  }
819
7045
}
820
821
822
7045
void ZlibContext::SetBuffers(char* in, uint32_t in_len,
823
                             char* out, uint32_t out_len) {
824
7045
  strm_.avail_in = in_len;
825
7045
  strm_.next_in = reinterpret_cast<Bytef*>(in);
826
7045
  strm_.avail_out = out_len;
827
7045
  strm_.next_out = reinterpret_cast<Bytef*>(out);
828
7045
}
829
830
831
7045
void ZlibContext::SetFlush(int flush) {
832
7045
  flush_ = flush;
833
7045
}
834
835
836
7020
void ZlibContext::GetAfterWriteOffsets(uint32_t* avail_in,
837
                                       uint32_t* avail_out) const {
838
7020
  *avail_in = strm_.avail_in;
839
7020
  *avail_out = strm_.avail_out;
840
7020
}
841
842
843
25
CompressionError ZlibContext::ErrorForMessage(const char* message) const {
844
25
  if (strm_.msg != nullptr)
845
11
    message = strm_.msg;
846
847
25
  return CompressionError { message, ZlibStrerror(err_), err_ };
848
}
849
850
851
7045
CompressionError ZlibContext::GetErrorInfo() const {
852
  // Acceptable error states depend on the type of zlib stream.
853

7045
  switch (err_) {
854
  case Z_OK:
855
  case Z_BUF_ERROR:
856

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

845
    CHECK(
918
        (window_bits >= Z_MIN_WINDOWBITS && window_bits <= Z_MAX_WINDOWBITS) &&
919
        "invalid windowBits");
920
  }
921
922

1087
  CHECK((level >= Z_MIN_LEVEL && level <= Z_MAX_LEVEL) &&
923
    "invalid compression level");
924
925

1087
  CHECK((mem_level >= Z_MIN_MEMLEVEL && mem_level <= Z_MAX_MEMLEVEL) &&
926
        "invalid memlevel");
927
928



1087
  CHECK((strategy == Z_FILTERED || strategy == Z_HUFFMAN_ONLY ||
929
         strategy == Z_RLE || strategy == Z_FIXED ||
930
         strategy == Z_DEFAULT_STRATEGY) &&
931
        "invalid strategy");
932
933
1087
  level_ = level;
934
1087
  window_bits_ = window_bits;
935
1087
  mem_level_ = mem_level;
936
1087
  strategy_ = strategy;
937
938
1087
  flush_ = Z_NO_FLUSH;
939
940
1087
  err_ = Z_OK;
941
942

1087
  if (mode_ == GZIP || mode_ == GUNZIP) {
943
435
    window_bits_ += 16;
944
  }
945
946
1087
  if (mode_ == UNZIP) {
947
199
    window_bits_ += 32;
948
  }
949
950

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

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

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