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: 599 658 91.0 %
Date: 2020-06-24 22:13:30 Branches: 444 734 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::ArrayBuffer;
47
using v8::Context;
48
using v8::Function;
49
using v8::FunctionCallbackInfo;
50
using v8::FunctionTemplate;
51
using v8::Global;
52
using v8::HandleScope;
53
using v8::Int32;
54
using v8::Integer;
55
using v8::Local;
56
using v8::Object;
57
using v8::String;
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
22
inline const char* ZlibStrerror(int err) {
88
#define V(code) if (err == code) return #code;
89




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

1199
    CHECK_EQ(false, write_in_progress_ && "write in progress");
257
1199
    Close();
258

1199
    CHECK_EQ(zlib_memory_, 0);
259

1199
    CHECK_EQ(unreported_allocations_, 0);
260
3597
  }
261
262
2262
  void Close() {
263

2262
    if (write_in_progress_) {
264
30
      pending_close_ = true;
265
30
      return;
266
    }
267
268
2232
    pending_close_ = false;
269
2232
    closed_ = true;
270

2232
    CHECK(init_done_ && "close before init");
271
272
4464
    AllocScope alloc_scope(this);
273
2232
    ctx_.Close();
274
  }
275
276
277
1033
  static void Close(const FunctionCallbackInfo<Value>& args) {
278
    CompressionStream* ctx;
279

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



8667
    CHECK_EQ(args.Length(), 7);
290
291
    uint32_t in_off, in_len, out_off, out_len, flush;
292
    char* in;
293
    char* out;
294
295






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



26001
    if (!args[0]->Uint32Value(context).To(&flush)) return;
297
298






12806
    if (flush != Z_NO_FLUSH &&
299



7800
        flush != Z_PARTIAL_FLUSH &&
300



7104
        flush != Z_SYNC_FLUSH &&
301



4453
        flush != Z_FULL_FLUSH &&
302



1010
        flush != Z_FINISH &&
303
        flush != Z_BLOCK) {
304
      CHECK(0 && "Invalid flush value");
305
    }
306
307



26001
    if (args[1]->IsNull()) {
308
      // just a flush
309
      in = nullptr;
310
      in_len = 0;
311
      in_off = 0;
312
    } else {
313



8667
      CHECK(Buffer::HasInstance(args[1]));
314
17334
      Local<Object> in_buf = args[1].As<Object>();
315



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



26001
      if (!args[3]->Uint32Value(context).To(&in_len)) return;
317
318



8667
      CHECK(Buffer::IsWithinBounds(in_off, in_len, Buffer::Length(in_buf)));
319
8667
      in = Buffer::Data(in_buf) + in_off;
320
    }
321
322



8667
    CHECK(Buffer::HasInstance(args[4]));
323
17334
    Local<Object> out_buf = args[4].As<Object>();
324



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



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



8667
    CHECK(Buffer::IsWithinBounds(out_off, out_len, Buffer::Length(out_buf)));
327
8667
    out = Buffer::Data(out_buf) + out_off;
328
329
    CompressionStream* ctx;
330



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



8667
    CHECK(init_done_ && "write before init");
342



8667
    CHECK(!closed_ && "already finalized");
343
344



8667
    CHECK_EQ(false, write_in_progress_);
345



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

1091
      if (CheckError()) {
357
1085
        UpdateWriteResult();
358
1085
        write_in_progress_ = false;
359
      }
360
1091
      Unref();
361

1091
      return;
362
    }
363
364
    // async version
365

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

8667
    if (!err.IsError()) return true;
384
23
    EmitError(err);
385
23
    return false;
386
  }
387
388
389
  // v8 land!
390
7576
  void AfterThreadPoolWork(int status) override {
391
15135
    AllocScope alloc_scope(this);
392

22711
    auto on_scope_leave = OnScopeLeave([&]() { Unref(); });
393
394
7576
    write_in_progress_ = false;
395
396

7576
    if (status == UV_ECANCELED) {
397
      Close();
398
      return;
399
    }
400
401

7576
    CHECK_EQ(status, 0);
402
403
7576
    Environment* env = AsyncWrap::env();
404

15135
    HandleScope handle_scope(env->isolate());
405

15135
    Context::Scope context_scope(env->context());
406
407

7576
    if (!CheckError())
408
17
      return;
409
410
7559
    UpdateWriteResult();
411
412
    // call the write() cb
413
7559
    Local<Function> cb = PersistentToLocal::Default(env->isolate(),
414
7559
                                                    write_js_callback_);
415
7559
    MakeCallback(cb, 0, nullptr);
416
417

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

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

24
    if (pending_close_)
438
7
      Close();
439
24
  }
440
441
12
  static void Reset(const FunctionCallbackInfo<Value> &args) {
442
    CompressionStream* wrap;
443

12
    ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder());
444
445
24
    AllocScope alloc_scope(wrap);
446
12
    const CompressionError err = wrap->context()->ResetStream();
447

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

8656
    if (UNLIKELY(memory == nullptr)) return nullptr;
484
8656
    *reinterpret_cast<size_t*>(memory) = size;
485
8656
    ctx->unreported_allocations_.fetch_add(size,
486
                                           std::memory_order_relaxed);
487
8656
    return memory + sizeof(size_t);
488
  }
489
490
10712
  static void FreeForZlib(void* data, void* pointer) {
491

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

19861
    if (report == 0) return;
506



2999
    CHECK_IMPLIES(report < 0, zlib_memory_ >= static_cast<size_t>(-report));
507
2999
    zlib_memory_ += report;
508
2999
    AsyncWrap::env()->isolate()->AdjustAmountOfExternalAllocatedMemory(report);
509
  }
510
511
  struct AllocScope {
512
19861
    explicit AllocScope(CompressionStream* stream) : stream(stream) {}
513
19861
    ~AllocScope() { stream->AdjustAmountOfExternalAllocatedMemory(); }
514
    CompressionStream* stream;
515
  };
516
517
 private:
518
8667
  void Ref() {
519

8667
    if (++refs_ == 1) {
520
1733
      ClearWeak();
521
    }
522
8667
  }
523
524
8667
  void Unref() {
525

8667
    CHECK_GT(refs_, 0);
526

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

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

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

410
    CHECK(args[0]->IsInt32());
665
    node_zlib_mode mode =
666
615
        static_cast<node_zlib_mode>(args[0].As<Int32>()->Value());
667
205
    new BrotliCompressionStream(env, args.This(), mode);
668
205
  }
669
670
205
  static void Init(const FunctionCallbackInfo<Value>& args) {
671
    BrotliCompressionStream* wrap;
672

206
    ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder());
673


205
    CHECK(args.Length() == 3 && "init(params, writeResult, writeCallback)");
674
675

410
    CHECK(args[1]->IsUint32Array());
676
205
    uint32_t* write_result = reinterpret_cast<uint32_t*>(Buffer::Data(args[1]));
677
678

410
    CHECK(args[2]->IsFunction());
679
410
    Local<Function> write_js_callback = args[2].As<Function>();
680
205
    wrap->InitStream(write_result, write_js_callback);
681
682
409
    AllocScope alloc_scope(wrap);
683
    CompressionError err =
684
        wrap->context()->Init(
685
          CompressionStream<CompressionContext>::AllocForBrotli,
686
          CompressionStream<CompressionContext>::FreeForZlib,
687
205
          static_cast<CompressionStream<CompressionContext>*>(wrap));
688

205
    if (err.IsError()) {
689
      wrap->EmitError(err);
690
      args.GetReturnValue().Set(false);
691
      return;
692
    }
693
694

410
    CHECK(args[0]->IsUint32Array());
695
205
    const uint32_t* data = reinterpret_cast<uint32_t*>(Buffer::Data(args[0]));
696
615
    size_t len = args[0].As<Uint32Array>()->Length();
697
698

2045
    for (int i = 0; static_cast<size_t>(i) < len; i++) {
699

1841
      if (data[i] == static_cast<uint32_t>(-1))
700
1828
        continue;
701
13
      err = wrap->context()->SetParams(i, data[i]);
702

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

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

1826
  if (mode_ == DEFLATE || mode_ == GZIP || mode_ == DEFLATERAW) {
731
543
    status = deflateEnd(&strm_);
732


2114
  } else if (mode_ == INFLATE || mode_ == GUNZIP || mode_ == INFLATERAW ||
733
831
             mode_ == UNZIP) {
734
453
    status = inflateEnd(&strm_);
735
  }
736
737

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

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

16015
      if (mode_ != INFLATERAW &&
809

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

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

7328
  switch (err_) {
877
  case Z_OK:
878
  case Z_BUF_ERROR:
879

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

1580
  if (!((window_bits == 0) &&
937
740
        (mode_ == INFLATE ||
938
574
         mode_ == GUNZIP ||
939
246
         mode_ == UNZIP))) {
940

756
    CHECK(
941
        (window_bits >= Z_MIN_WINDOWBITS && window_bits <= Z_MAX_WINDOWBITS) &&
942
        "invalid windowBits");
943
  }
944
945

1168
  CHECK((level >= Z_MIN_LEVEL && level <= Z_MAX_LEVEL) &&
946
    "invalid compression level");
947
948

1168
  CHECK((mem_level >= Z_MIN_MEMLEVEL && mem_level <= Z_MAX_MEMLEVEL) &&
949
        "invalid memlevel");
950
951




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

1168
  if (mode_ == GZIP || mode_ == GUNZIP) {
966
431
    window_bits_ += 16;
967
  }
968
969
1168
  if (mode_ == UNZIP) {
970
270
    window_bits_ += 32;
971
  }
972
973

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

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

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