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




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

1756
    CHECK_EQ(false, write_in_progress_ && "write in progress");
252
1756
    Close();
253

1756
    CHECK_EQ(zlib_memory_, 0);
254

1756
    CHECK_EQ(unreported_allocations_, 0);
255

5268
  }
256
257
3481
  void Close() {
258

3481
    if (write_in_progress_) {
259
29
      pending_close_ = true;
260
3510
      return;
261
    }
262
263
3452
    pending_close_ = false;
264
3452
    closed_ = true;
265

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

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



9967
    CHECK_EQ(args.Length(), 7);
285
286
    uint32_t in_off, in_len, out_off, out_len, flush;
287
    char* in;
288
    char* out;
289
290









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



29901
    if (!args[0]->Uint32Value(context).To(&flush)) return;
292
293


















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



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



9967
      CHECK(Buffer::HasInstance(args[1]));
309
19934
      Local<Object> in_buf = args[1].As<Object>();
310



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



29901
      if (!args[3]->Uint32Value(context).To(&in_len)) return;
312
313



9967
      CHECK(Buffer::IsWithinBounds(in_off, in_len, Buffer::Length(in_buf)));
314
9967
      in = Buffer::Data(in_buf) + in_off;
315
    }
316
317



9967
    CHECK(Buffer::HasInstance(args[4]));
318
19934
    Local<Object> out_buf = args[4].As<Object>();
319



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



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



9967
    CHECK(Buffer::IsWithinBounds(out_off, out_len, Buffer::Length(out_buf)));
322
9967
    out = Buffer::Data(out_buf) + out_off;
323
324
    CompressionStream* ctx;
325



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



9967
    CHECK(init_done_ && "write before init");
337



9967
    CHECK(!closed_ && "already finalized");
338
339



9967
    CHECK_EQ(false, write_in_progress_);
340



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

1549
      if (CheckError()) {
352
1543
        UpdateWriteResult();
353
1543
        write_in_progress_ = false;
354
      }
355
1549
      Unref();
356

11516
      return;
357
    }
358
359
    // async version
360

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

9967
    if (!err.IsError()) return true;
379
26
    EmitError(err);
380
26
    return false;
381
  }
382
383
384
  // v8 land!
385
8418
  void AfterThreadPoolWork(int status) override {
386
8418
    AllocScope alloc_scope(this);
387

25234
    OnScopeLeave on_scope_leave([&]() { Unref(); });
388
389
8418
    write_in_progress_ = false;
390
391

8418
    if (status == UV_ECANCELED) {
392
      Close();
393
      return;
394
    }
395
396

8418
    CHECK_EQ(status, 0);
397
398

16816
    HandleScope handle_scope(env()->isolate());
399

16816
    Context::Scope context_scope(env()->context());
400
401

8418
    if (!CheckError())
402
20
      return;
403
404
8398
    UpdateWriteResult();
405
406
    // call the write() cb
407
    Local<Function> cb = PersistentToLocal::Default(env()->isolate(),
408
8398
                                                    write_js_callback_);
409
8398
    MakeCallback(cb, 0, nullptr);
410
411

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

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

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

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

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

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

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

47426
    if (report == 0) return;
499




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

9967
    if (++refs_ == 1) {
513
2627
      ClearWeak();
514
    }
515
9967
  }
516
517
9967
  void Unref() {
518

9967
    CHECK_GT(refs_, 0);
519

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

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

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

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

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

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


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

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

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

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

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

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

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

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

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

3050
  if (mode_ == DEFLATE || mode_ == GZIP || mode_ == DEFLATERAW) {
723
981
    status = deflateEnd(&strm_);
724


3460
  } else if (mode_ == INFLATE || mode_ == GUNZIP || mode_ == INFLATERAW ||
725
1391
             mode_ == UNZIP) {
726
679
    status = inflateEnd(&strm_);
727
  }
728
729

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

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

17350
      if (mode_ != INFLATERAW &&
801

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

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

8639
  switch (err_) {
869
  case Z_OK:
870
  case Z_BUF_ERROR:
871

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

1417
    CHECK(
933
        (window_bits >= Z_MIN_WINDOWBITS && window_bits <= Z_MAX_WINDOWBITS) &&
934
        "invalid windowBits");
935
  }
936
937

1660
  CHECK((level >= Z_MIN_LEVEL && level <= Z_MAX_LEVEL) &&
938
    "invalid compression level");
939
940

1660
  CHECK((mem_level >= Z_MIN_MEMLEVEL && mem_level <= Z_MAX_MEMLEVEL) &&
941
        "invalid memlevel");
942
943



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

1660
  if (mode_ == GZIP || mode_ == GUNZIP) {
958
437
    window_bits_ += 16;
959
  }
960
961
1660
  if (mode_ == UNZIP) {
962
326
    window_bits_ += 32;
963
  }
964
965

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

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

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