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: 596 655 91.0 %
Date: 2020-02-27 22:14:15 Branches: 443 732 60.5 %

Line Branch Exec Source
1
// Copyright Joyent, Inc. and other Node contributors.
2
//
3
// Permission is hereby granted, free of charge, to any person obtaining a
4
// copy of this software and associated documentation files (the
5
// "Software"), to deal in the Software without restriction, including
6
// without limitation the rights to use, copy, modify, merge, publish,
7
// distribute, sublicense, and/or sell copies of the Software, and to permit
8
// persons to whom the Software is furnished to do so, subject to the
9
// following conditions:
10
//
11
// The above copyright notice and this permission notice shall be included
12
// in all copies or substantial portions of the Software.
13
//
14
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
17
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
18
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
19
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
20
// USE OR OTHER DEALINGS IN THE SOFTWARE.
21
22
#include "memory_tracker-inl.h"
23
#include "node.h"
24
#include "node_buffer.h"
25
26
#include "async_wrap-inl.h"
27
#include "env-inl.h"
28
#include "threadpoolwork-inl.h"
29
#include "util-inl.h"
30
31
#include "v8.h"
32
33
#include "brotli/encode.h"
34
#include "brotli/decode.h"
35
#include "zlib.h"
36
37
#include <sys/types.h>
38
39
#include <cerrno>
40
#include <cstdlib>
41
#include <cstring>
42
#include <atomic>
43
44
namespace node {
45
46
using v8::Array;
47
using v8::ArrayBuffer;
48
using v8::Context;
49
using v8::Function;
50
using v8::FunctionCallbackInfo;
51
using v8::FunctionTemplate;
52
using v8::Global;
53
using v8::HandleScope;
54
using v8::Int32;
55
using v8::Integer;
56
using v8::Local;
57
using v8::Object;
58
using v8::String;
59
using v8::Uint32;
60
using v8::Uint32Array;
61
using v8::Value;
62
63
namespace {
64
65
// Fewer than 64 bytes per chunk is not recommended.
66
// Technically it could work with as few as 8, but even 64 bytes
67
// is low.  Usually a MB or more is best.
68
#define Z_MIN_CHUNK 64
69
#define Z_MAX_CHUNK std::numeric_limits<double>::infinity()
70
#define Z_DEFAULT_CHUNK (16 * 1024)
71
#define Z_MIN_MEMLEVEL 1
72
#define Z_MAX_MEMLEVEL 9
73
#define Z_DEFAULT_MEMLEVEL 8
74
#define Z_MIN_LEVEL -1
75
#define Z_MAX_LEVEL 9
76
#define Z_DEFAULT_LEVEL Z_DEFAULT_COMPRESSION
77
78
#define ZLIB_ERROR_CODES(V)      \
79
  V(Z_OK)                        \
80
  V(Z_STREAM_END)                \
81
  V(Z_NEED_DICT)                 \
82
  V(Z_ERRNO)                     \
83
  V(Z_STREAM_ERROR)              \
84
  V(Z_DATA_ERROR)                \
85
  V(Z_MEM_ERROR)                 \
86
  V(Z_BUF_ERROR)                 \
87
  V(Z_VERSION_ERROR)             \
88
89
21
inline const char* ZlibStrerror(int err) {
90
#define V(code) if (err == code) return #code;
91




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

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

1194
    CHECK_EQ(zlib_memory_, 0);
256

1194
    CHECK_EQ(unreported_allocations_, 0);
257
3582
  }
258
259
2260
  void Close() {
260

2260
    if (write_in_progress_) {
261
31
      pending_close_ = true;
262
31
      return;
263
    }
264
265
2229
    pending_close_ = false;
266
2229
    closed_ = true;
267

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

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



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






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



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






12771
    if (flush != Z_NO_FLUSH &&
296



7775
        flush != Z_PARTIAL_FLUSH &&
297



7085
        flush != Z_SYNC_FLUSH &&
298



4444
        flush != Z_FULL_FLUSH &&
299



1009
        flush != Z_FINISH &&
300
        flush != Z_BLOCK) {
301
      CHECK(0 && "Invalid flush value");
302
    }
303
304



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



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



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



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



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



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



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



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



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



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



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



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



8646
    CHECK_EQ(false, write_in_progress_);
342



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

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

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

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

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

22631
    auto on_scope_leave = OnScopeLeave([&]() { Unref(); });
390
391
7549
    write_in_progress_ = false;
392
393

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

7549
    CHECK_EQ(status, 0);
399
400
7549
    Environment* env = AsyncWrap::env();
401

15082
    HandleScope handle_scope(env->isolate());
402

15082
    Context::Scope context_scope(env->context());
403
404

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

7533
    if (pending_close_)
415
25
      Close();
416
  }
417
418
  // TODO(addaleax): Switch to modern error system (node_errors.h).
419
23
  void EmitError(const CompressionError& err) {
420
23
    Environment* env = AsyncWrap::env();
421
    // If you hit this assertion, you forgot to enter the v8::Context first.
422

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

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

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

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

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

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

19805
    if (report == 0) return;
503



2970
    CHECK_IMPLIES(report < 0, zlib_memory_ >= static_cast<size_t>(-report));
504
2970
    zlib_memory_ += report;
505
2970
    AsyncWrap::env()->isolate()->AdjustAmountOfExternalAllocatedMemory(report);
506
  }
507
508
  struct AllocScope {
509
19805
    explicit AllocScope(CompressionStream* stream) : stream(stream) {}
510
19805
    ~AllocScope() { stream->AdjustAmountOfExternalAllocatedMemory(); }
511
    CompressionStream* stream;
512
  };
513
514
 private:
515
8646
  void Ref() {
516

8646
    if (++refs_ == 1) {
517
1735
      ClearWeak();
518
    }
519
8646
  }
520
521
8646
  void Unref() {
522

8646
    CHECK_GT(refs_, 0);
523

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

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

1
    CHECK(args.Length() == 2 && "params(level, strategy)");
626
    ZlibStream* wrap;
627
1
    ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder());
628
1
    Local<Context> context = args.GetIsolate()->GetCurrentContext();
629
    int level;
630
3
    if (!args[0]->Int32Value(context).To(&level)) return;
631
    int strategy;
632
3
    if (!args[1]->Int32Value(context).To(&strategy)) return;
633
634
2
    AllocScope alloc_scope(wrap);
635
1
    const CompressionError err = wrap->context()->SetParams(level, strategy);
636
1
    if (err.IsError())
637
      wrap->EmitError(err);
638
  }
639
640
  SET_MEMORY_INFO_NAME(ZlibStream)
641
  SET_SELF_SIZE(ZlibStream)
642
};
643
644
template <typename CompressionContext>
645
402
class BrotliCompressionStream : public CompressionStream<CompressionContext> {
646
 public:
647
201
  BrotliCompressionStream(Environment* env,
648
                          Local<Object> wrap,
649
                          node_zlib_mode mode)
650
201
    : CompressionStream<CompressionContext>(env, wrap) {
651
201
    context()->SetMode(mode);
652
201
  }
653
654
415
  inline CompressionContext* context() {
655
415
    return this->CompressionStream<CompressionContext>::context();
656
  }
657
  typedef typename CompressionStream<CompressionContext>::AllocScope AllocScope;
658
659
201
  static void New(const FunctionCallbackInfo<Value>& args) {
660
201
    Environment* env = Environment::GetCurrent(args);
661

402
    CHECK(args[0]->IsInt32());
662
    node_zlib_mode mode =
663
603
        static_cast<node_zlib_mode>(args[0].As<Int32>()->Value());
664
201
    new BrotliCompressionStream(env, args.This(), mode);
665
201
  }
666
667
201
  static void Init(const FunctionCallbackInfo<Value>& args) {
668
    BrotliCompressionStream* wrap;
669

202
    ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder());
670


201
    CHECK(args.Length() == 3 && "init(params, writeResult, writeCallback)");
671
672

402
    CHECK(args[1]->IsUint32Array());
673
201
    uint32_t* write_result = reinterpret_cast<uint32_t*>(Buffer::Data(args[1]));
674
675

402
    CHECK(args[2]->IsFunction());
676
402
    Local<Function> write_js_callback = args[2].As<Function>();
677
201
    wrap->InitStream(write_result, write_js_callback);
678
679
401
    AllocScope alloc_scope(wrap);
680
    CompressionError err =
681
        wrap->context()->Init(
682
          CompressionStream<CompressionContext>::AllocForBrotli,
683
          CompressionStream<CompressionContext>::FreeForZlib,
684
201
          static_cast<CompressionStream<CompressionContext>*>(wrap));
685

201
    if (err.IsError()) {
686
      wrap->EmitError(err);
687
      args.GetReturnValue().Set(false);
688
      return;
689
    }
690
691

402
    CHECK(args[0]->IsUint32Array());
692
201
    const uint32_t* data = reinterpret_cast<uint32_t*>(Buffer::Data(args[0]));
693
603
    size_t len = args[0].As<Uint32Array>()->Length();
694
695

2005
    for (int i = 0; static_cast<size_t>(i) < len; i++) {
696

1805
      if (data[i] == static_cast<uint32_t>(-1))
697
1792
        continue;
698
13
      err = wrap->context()->SetParams(i, data[i]);
699

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

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

1829
  if (mode_ == DEFLATE || mode_ == GZIP || mode_ == DEFLATERAW) {
728
543
    status = deflateEnd(&strm_);
729


2121
  } else if (mode_ == INFLATE || mode_ == GUNZIP || mode_ == INFLATERAW ||
730
835
             mode_ == UNZIP) {
731
452
    status = inflateEnd(&strm_);
732
  }
733
734

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

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

15997
      if (mode_ != INFLATERAW &&
806

5890
          err_ == Z_NEED_DICT &&
807
14
          !dictionary_.empty()) {
808
        // Load it
809
26
        err_ = inflateSetDictionary(&strm_,
810
13
                                    dictionary_.data(),
811
13
                                    dictionary_.size());
812
13
        if (err_ == Z_OK) {
813
          // And try to decode again
814
12
          err_ = inflate(&strm_, flush_);
815
1
        } else if (err_ == Z_DATA_ERROR) {
816
          // Both inflateSetDictionary() and inflate() return Z_DATA_ERROR.
817
          // Make it possible for After() to tell a bad dictionary from bad
818
          // input.
819
1
          err_ = Z_NEED_DICT;
820
        }
821
      }
822
823
6280
      while (strm_.avail_in > 0 &&
824
692
             mode_ == GUNZIP &&
825

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

7318
  switch (err_) {
874
  case Z_OK:
875
  case Z_BUF_ERROR:
876

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

1578
  if (!((window_bits == 0) &&
934
738
        (mode_ == INFLATE ||
935
573
         mode_ == GUNZIP ||
936
246
         mode_ == UNZIP))) {
937

756
    CHECK(
938
        (window_bits >= Z_MIN_WINDOWBITS && window_bits <= Z_MAX_WINDOWBITS) &&
939
        "invalid windowBits");
940
  }
941
942

1167
  CHECK((level >= Z_MIN_LEVEL && level <= Z_MAX_LEVEL) &&
943
    "invalid compression level");
944
945

1167
  CHECK((mem_level >= Z_MIN_MEMLEVEL && mem_level <= Z_MAX_MEMLEVEL) &&
946
        "invalid memlevel");
947
948




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

1167
  if (mode_ == GZIP || mode_ == GUNZIP) {
963
430
    window_bits_ += 16;
964
  }
965
966
1167
  if (mode_ == UNZIP) {
967
270
    window_bits_ += 32;
968
  }
969
970

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

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

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