Skip to content

Commit 2ced07c

Browse files
committed
zlib: support all ArrayBufferView types
PR-URL: #12223 Reviewed-By: Matteo Collina <[email protected]> Reviewed-By: James M Snell <[email protected]> Reviewed-By: Anna Henningsen <[email protected]>
1 parent a8f460f commit 2ced07c

6 files changed

+89
-43
lines changed

doc/api/zlib.md

+56-13
Original file line numberDiff line numberDiff line change
@@ -300,7 +300,7 @@ ignored by the decompression classes.
300300
* `level` {integer} (compression only)
301301
* `memLevel` {integer} (compression only)
302302
* `strategy` {integer} (compression only)
303-
* `dictionary` {Buffer|Uint8Array} (deflate/inflate only, empty dictionary by
303+
* `dictionary` {Buffer|TypedArray|DataView} (deflate/inflate only, empty dictionary by
304304
default)
305305

306306
See the description of `deflateInit2` and `inflateInit2` at
@@ -477,9 +477,9 @@ Returns a new [Unzip][] object with an [options][].
477477

478478
<!--type=misc-->
479479

480-
All of these take a [Buffer][], [Uint8Array][], or string as the first
481-
argument, an optional second argument to supply options to the `zlib` classes
482-
and will call the supplied callback with `callback(error, result)`.
480+
All of these take a [`Buffer`][], [`TypedArray`][], [`DataView`][], or string as
481+
the first argument, an optional second argument to supply options to the `zlib`
482+
classes and will call the supplied callback with `callback(error, result)`.
483483

484484
Every method has a `*Sync` counterpart, which accept the same arguments, but
485485
without a callback.
@@ -488,6 +488,9 @@ without a callback.
488488
<!-- YAML
489489
added: v0.6.0
490490
changes:
491+
- version: REPLACEME
492+
pr-url: REPLACEME
493+
description: The `buffer` parameter can be any TypedArray or DataView now.
491494
- version: REPLACEME
492495
pr-url: https://github.com/nodejs/node/pull/12001
493496
description: The `buffer` parameter can be an Uint8Array now.
@@ -496,19 +499,25 @@ changes:
496499
<!-- YAML
497500
added: v0.11.12
498501
changes:
502+
- version: REPLACEME
503+
pr-url: REPLACEME
504+
description: The `buffer` parameter can be any TypedArray or DataView now.
499505
- version: REPLACEME
500506
pr-url: https://github.com/nodejs/node/pull/12001
501507
description: The `buffer` parameter can be an Uint8Array now.
502508
-->
503509

504-
- `buffer` {Buffer|Uint8Array|string}
510+
- `buffer` {Buffer|TypedArray|DataView|string}
505511

506512
Compress a chunk of data with [Deflate][].
507513

508514
### zlib.deflateRaw(buffer[, options], callback)
509515
<!-- YAML
510516
added: v0.6.0
511517
changes:
518+
- version: REPLACEME
519+
pr-url: REPLACEME
520+
description: The `buffer` parameter can be any TypedArray or DataView now.
512521
- version: REPLACEME
513522
pr-url: https://github.com/nodejs/node/pull/12001
514523
description: The `buffer` parameter can be an Uint8Array now.
@@ -517,19 +526,25 @@ changes:
517526
<!-- YAML
518527
added: v0.11.12
519528
changes:
529+
- version: REPLACEME
530+
pr-url: REPLACEME
531+
description: The `buffer` parameter can be any TypedArray or DataView now.
520532
- version: REPLACEME
521533
pr-url: https://github.com/nodejs/node/pull/12001
522534
description: The `buffer` parameter can be an Uint8Array now.
523535
-->
524536

525-
- `buffer` {Buffer|Uint8Array|string}
537+
- `buffer` {Buffer|TypedArray|DataView|string}
526538

527539
Compress a chunk of data with [DeflateRaw][].
528540

529541
### zlib.gunzip(buffer[, options], callback)
530542
<!-- YAML
531543
added: v0.6.0
532544
changes:
545+
- version: REPLACEME
546+
pr-url: REPLACEME
547+
description: The `buffer` parameter can be any TypedArray or DataView now.
533548
- version: REPLACEME
534549
pr-url: https://github.com/nodejs/node/pull/12001
535550
description: The `buffer` parameter can be an Uint8Array now.
@@ -538,19 +553,25 @@ changes:
538553
<!-- YAML
539554
added: v0.11.12
540555
changes:
556+
- version: REPLACEME
557+
pr-url: REPLACEME
558+
description: The `buffer` parameter can be any TypedArray or DataView now.
541559
- version: REPLACEME
542560
pr-url: https://github.com/nodejs/node/pull/12001
543561
description: The `buffer` parameter can be an Uint8Array now.
544562
-->
545563

546-
- `buffer` {Buffer|Uint8Array|string}
564+
- `buffer` {Buffer|TypedArray|DataView|string}
547565

548566
Decompress a chunk of data with [Gunzip][].
549567

550568
### zlib.gzip(buffer[, options], callback)
551569
<!-- YAML
552570
added: v0.6.0
553571
changes:
572+
- version: REPLACEME
573+
pr-url: REPLACEME
574+
description: The `buffer` parameter can be any TypedArray or DataView now.
554575
- version: REPLACEME
555576
pr-url: https://github.com/nodejs/node/pull/12001
556577
description: The `buffer` parameter can be an Uint8Array now.
@@ -559,19 +580,25 @@ changes:
559580
<!-- YAML
560581
added: v0.11.12
561582
changes:
583+
- version: REPLACEME
584+
pr-url: REPLACEME
585+
description: The `buffer` parameter can be any TypedArray or DataView now.
562586
- version: REPLACEME
563587
pr-url: https://github.com/nodejs/node/pull/12001
564588
description: The `buffer` parameter can be an Uint8Array now.
565589
-->
566590

567-
- `buffer` {Buffer|Uint8Array|string}
591+
- `buffer` {Buffer|TypedArray|DataView|string}
568592

569593
Compress a chunk of data with [Gzip][].
570594

571595
### zlib.inflate(buffer[, options], callback)
572596
<!-- YAML
573597
added: v0.6.0
574598
changes:
599+
- version: REPLACEME
600+
pr-url: REPLACEME
601+
description: The `buffer` parameter can be any TypedArray or DataView now.
575602
- version: REPLACEME
576603
pr-url: https://github.com/nodejs/node/pull/12001
577604
description: The `buffer` parameter can be an Uint8Array now.
@@ -580,19 +607,25 @@ changes:
580607
<!-- YAML
581608
added: v0.11.12
582609
changes:
610+
- version: REPLACEME
611+
pr-url: REPLACEME
612+
description: The `buffer` parameter can be any TypedArray or DataView now.
583613
- version: REPLACEME
584614
pr-url: https://github.com/nodejs/node/pull/12001
585615
description: The `buffer` parameter can be an Uint8Array now.
586616
-->
587617

588-
- `buffer` {Buffer|Uint8Array|string}
618+
- `buffer` {Buffer|TypedArray|DataView|string}
589619

590620
Decompress a chunk of data with [Inflate][].
591621

592622
### zlib.inflateRaw(buffer[, options], callback)
593623
<!-- YAML
594624
added: v0.6.0
595625
changes:
626+
- version: REPLACEME
627+
pr-url: REPLACEME
628+
description: The `buffer` parameter can be any TypedArray or DataView now.
596629
- version: REPLACEME
597630
pr-url: https://github.com/nodejs/node/pull/12001
598631
description: The `buffer` parameter can be an Uint8Array now.
@@ -601,19 +634,25 @@ changes:
601634
<!-- YAML
602635
added: v0.11.12
603636
changes:
637+
- version: REPLACEME
638+
pr-url: REPLACEME
639+
description: The `buffer` parameter can be any TypedArray or DataView now.
604640
- version: REPLACEME
605641
pr-url: https://github.com/nodejs/node/pull/12001
606642
description: The `buffer` parameter can be an Uint8Array now.
607643
-->
608644

609-
- `buffer` {Buffer|Uint8Array|string}
645+
- `buffer` {Buffer|TypedArray|DataView|string}
610646

611647
Decompress a chunk of data with [InflateRaw][].
612648

613649
### zlib.unzip(buffer[, options], callback)
614650
<!-- YAML
615651
added: v0.6.0
616652
changes:
653+
- version: REPLACEME
654+
pr-url: REPLACEME
655+
description: The `buffer` parameter can be any TypedArray or DataView now.
617656
- version: REPLACEME
618657
pr-url: https://github.com/nodejs/node/pull/12001
619658
description: The `buffer` parameter can be an Uint8Array now.
@@ -622,12 +661,15 @@ changes:
622661
<!-- YAML
623662
added: v0.11.12
624663
changes:
664+
- version: REPLACEME
665+
pr-url: REPLACEME
666+
description: The `buffer` parameter can be any TypedArray or DataView now.
625667
- version: REPLACEME
626668
pr-url: https://github.com/nodejs/node/pull/12001
627669
description: The `buffer` parameter can be an Uint8Array now.
628670
-->
629671

630-
- `buffer` {Buffer|Uint8Array|string}
672+
- `buffer` {Buffer|TypedArray|DataView|string}
631673

632674
Decompress a chunk of data with [Unzip][].
633675

@@ -644,5 +686,6 @@ Decompress a chunk of data with [Unzip][].
644686
[InflateRaw]: #zlib_class_zlib_inflateraw
645687
[Unzip]: #zlib_class_zlib_unzip
646688
[`.flush()`]: #zlib_zlib_flush_kind_callback
647-
[Buffer]: buffer.html
648-
[Uint8Array]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint8Array
689+
[`Buffer`]: buffer.html#buffer_class_buffer
690+
[`DataView`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DataView
691+
[`TypedArray`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray

lib/zlib.js

+13-14
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@
2424
const Buffer = require('buffer').Buffer;
2525
const internalUtil = require('internal/util');
2626
const Transform = require('_stream_transform');
27-
const { isUint8Array } = process.binding('util');
2827
const binding = process.binding('zlib');
2928
const assert = require('assert').ok;
3029
const kMaxLength = require('buffer').kMaxLength;
@@ -79,9 +78,9 @@ function isInvalidStrategy(strategy) {
7978
}
8079

8180
function zlibBuffer(engine, buffer, callback) {
82-
// Streams do not support non-Buffer Uint8Arrays yet. Convert it to a
81+
// Streams do not support non-Buffer ArrayBufferViews yet. Convert it to a
8382
// Buffer without copying.
84-
if (isUint8Array(buffer) &&
83+
if (ArrayBuffer.isView(buffer) &&
8584
Object.getPrototypeOf(buffer) !== Buffer.prototype) {
8685
buffer = Buffer.from(buffer.buffer, buffer.byteOffset, buffer.byteLength);
8786
}
@@ -99,7 +98,7 @@ function zlibBuffer(engine, buffer, callback) {
9998
var chunk;
10099
while (null !== (chunk = engine.read())) {
101100
buffers.push(chunk);
102-
nread += chunk.length;
101+
nread += chunk.byteLength;
103102
}
104103
engine.once('readable', flow);
105104
}
@@ -129,9 +128,9 @@ function zlibBuffer(engine, buffer, callback) {
129128
function zlibBufferSync(engine, buffer) {
130129
if (typeof buffer === 'string')
131130
buffer = Buffer.from(buffer);
132-
else if (!isUint8Array(buffer))
133-
throw new TypeError('"buffer" argument must be a string, Buffer, or ' +
134-
'Uint8Array');
131+
else if (!ArrayBuffer.isView(buffer))
132+
throw new TypeError('"buffer" argument must be a string, Buffer, ' +
133+
'TypedArray, or DataView');
135134

136135
var flushFlag = engine._finishFlushFlag;
137136

@@ -214,9 +213,9 @@ class Zlib extends Transform {
214213
throw new TypeError('Invalid strategy: ' + opts.strategy);
215214

216215
if (opts.dictionary) {
217-
if (!isUint8Array(opts.dictionary)) {
216+
if (!ArrayBuffer.isView(opts.dictionary)) {
218217
throw new TypeError(
219-
'Invalid dictionary: it should be a Buffer or an Uint8Array');
218+
'Invalid dictionary: it should be a Buffer, TypedArray, or DataView');
220219
}
221220
}
222221

@@ -309,9 +308,9 @@ class Zlib extends Transform {
309308
var flushFlag;
310309
var ws = this._writableState;
311310
var ending = ws.ending || ws.ended;
312-
var last = ending && (!chunk || ws.length === chunk.length);
311+
var last = ending && (!chunk || ws.length === chunk.byteLength);
313312

314-
if (chunk !== null && !isUint8Array(chunk))
313+
if (chunk !== null && !ArrayBuffer.isView(chunk))
315314
return cb(new TypeError('invalid input'));
316315

317316
if (!this._handle)
@@ -328,7 +327,7 @@ class Zlib extends Transform {
328327
flushFlag = this._flushFlag;
329328
// once we've flushed the last of the queue, stop flushing and
330329
// go back to the normal behavior.
331-
if (chunk.length >= ws.length) {
330+
if (chunk.byteLength >= ws.length) {
332331
this._flushFlag = this._opts.flush || constants.Z_NO_FLUSH;
333332
}
334333
}
@@ -337,7 +336,7 @@ class Zlib extends Transform {
337336
}
338337

339338
_processChunk(chunk, flushFlag, cb) {
340-
var availInBefore = chunk && chunk.length;
339+
var availInBefore = chunk && chunk.byteLength;
341340
var availOutBefore = this._chunkSize - this._offset;
342341
var inOff = 0;
343342

@@ -417,7 +416,7 @@ class Zlib extends Transform {
417416
self.push(out);
418417
} else {
419418
buffers.push(out);
420-
nread += out.length;
419+
nread += out.byteLength;
421420
}
422421
}
423422

test/parallel/test-zlib-convenience-methods.js

+15-11
Original file line numberDiff line numberDiff line change
@@ -26,24 +26,28 @@ const common = require('../common');
2626
const assert = require('assert');
2727
const zlib = require('zlib');
2828

29-
const expectStr = 'blahblahblahblahblahblah';
29+
// Must be a multiple of 4 characters in total to test all ArrayBufferView
30+
// types.
31+
const expectStr = 'blah'.repeat(8);
3032
const expectBuf = Buffer.from(expectStr);
31-
const expectUint8Array = new Uint8Array(expectBuf);
33+
3234
const opts = {
3335
level: 9,
3436
chunkSize: 1024,
3537
};
3638

37-
for (const method of [
38-
['gzip', 'gunzip'],
39-
['gzip', 'unzip'],
40-
['deflate', 'inflate'],
41-
['deflateRaw', 'inflateRaw'],
39+
for (const [type, expect] of [
40+
['string', expectStr],
41+
['Buffer', expectBuf],
42+
...common.getArrayBufferViews(expectBuf).map((obj) =>
43+
[obj[Symbol.toStringTag], obj]
44+
)
4245
]) {
43-
for (const [type, expect] of [
44-
['string', expectStr],
45-
['Buffer', expectBuf],
46-
['Uint8Array', expectUint8Array]
46+
for (const method of [
47+
['gzip', 'gunzip'],
48+
['gzip', 'unzip'],
49+
['deflate', 'inflate'],
50+
['deflateRaw', 'inflateRaw'],
4751
]) {
4852
zlib[method[0]](expect, opts, common.mustCall((err, result) => {
4953
zlib[method[1]](result, opts, common.mustCall((err, result) => {

test/parallel/test-zlib-deflate-constructors.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -107,5 +107,6 @@ assert.throws(
107107
// Throws if opts.dictionary is not a Buffer
108108
assert.throws(
109109
() => { new zlib.Deflate({dictionary: 'not a buffer'}); },
110-
/^TypeError: Invalid dictionary: it should be a Buffer or an Uint8Array$/
110+
new RegExp('^TypeError: Invalid dictionary: it should be a Buffer, ' +
111+
'TypedArray, or DataView$')
111112
);

test/parallel/test-zlib-dictionary.js

+1-2
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,6 @@ const spdyDict = Buffer.from([
4141
'ation/xhtmltext/plainpublicmax-agecharset=iso-8859-1utf-8gzipdeflateHTTP/1',
4242
'.1statusversionurl\0'
4343
].join(''));
44-
const spdyDictUint8Array = new Uint8Array(spdyDict);
4544

4645
const input = [
4746
'HTTP/1.1 200 Ok',
@@ -168,7 +167,7 @@ function deflateRawResetDictionaryTest(spdyDict) {
168167
});
169168
}
170169

171-
for (const dict of [spdyDict, spdyDictUint8Array]) {
170+
for (const dict of [spdyDict, ...common.getArrayBufferViews(spdyDict)]) {
172171
basicDictionaryTest(dict);
173172
deflateResetDictionaryTest(dict);
174173
rawDictionaryTest(dict);

test/parallel/test-zlib-not-string-or-buffer.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@ require('../common');
77
const assert = require('assert');
88
const zlib = require('zlib');
99

10-
const expected =
11-
/^TypeError: "buffer" argument must be a string, Buffer, or Uint8Array$/;
10+
const expected = new RegExp('^TypeError: "buffer" argument must be a string, ' +
11+
'Buffer, TypedArray, or DataView$');
1212

1313
assert.throws(() => { zlib.deflateSync(undefined); }, expected);
1414
assert.throws(() => { zlib.deflateSync(null); }, expected);

0 commit comments

Comments
 (0)