summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTimothy Gu <timothygu99@gmail.com>2017-03-22 19:45:03 -0700
committerAnna Henningsen <anna@addaleax.net>2017-04-03 09:50:09 +0200
commit91383e47fdbb87ae45365396dd0150dcad8ed967 (patch)
treeb68f4883bf29d10bf78aa097fd3c3c8ca736d855
parent2d039ffa29e4c4366a1028555b71cb36b7129fb1 (diff)
downloadandroid-node-v8-91383e47fdbb87ae45365396dd0150dcad8ed967.tar.gz
android-node-v8-91383e47fdbb87ae45365396dd0150dcad8ed967.tar.bz2
android-node-v8-91383e47fdbb87ae45365396dd0150dcad8ed967.zip
zlib: support Uint8Array in convenience methods
Also support Uint8Array as a `dictionary` option. PR-URL: https://github.com/nodejs/node/pull/12001 Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
-rw-r--r--doc/api/zlib.md139
-rw-r--r--lib/zlib.js19
-rw-r--r--test/parallel/test-zlib-convenience-methods.js81
-rw-r--r--test/parallel/test-zlib-deflate-constructors.js2
-rw-r--r--test/parallel/test-zlib-dictionary.js19
-rw-r--r--test/parallel/test-zlib-not-string-or-buffer.js3
6 files changed, 176 insertions, 87 deletions
diff --git a/doc/api/zlib.md b/doc/api/zlib.md
index 5b02a8ed37..928070d577 100644
--- a/doc/api/zlib.md
+++ b/doc/api/zlib.md
@@ -278,6 +278,9 @@ Compression strategy.
<!-- YAML
added: v0.11.1
changes:
+ - version: REPLACEME
+ pr-url: https://github.com/nodejs/node/pull/12001
+ description: The `dictionary` option can be an Uint8Array now.
- version: v5.11.0
pr-url: https://github.com/nodejs/node/pull/6069
description: The `finishFlush` option is supported now.
@@ -290,14 +293,15 @@ Each class takes an `options` object. All options are optional.
Note that some options are only relevant when compressing, and are
ignored by the decompression classes.
-* `flush` (default: `zlib.constants.Z_NO_FLUSH`)
-* `finishFlush` (default: `zlib.constants.Z_FINISH`)
-* `chunkSize` (default: 16*1024)
-* `windowBits`
-* `level` (compression only)
-* `memLevel` (compression only)
-* `strategy` (compression only)
-* `dictionary` (deflate/inflate only, empty dictionary by default)
+* `flush` {integer} (default: `zlib.constants.Z_NO_FLUSH`)
+* `finishFlush` {integer} (default: `zlib.constants.Z_FINISH`)
+* `chunkSize` {integer} (default: 16\*1024)
+* `windowBits` {integer}
+* `level` {integer} (compression only)
+* `memLevel` {integer} (compression only)
+* `strategy` {integer} (compression only)
+* `dictionary` {Buffer|Uint8Array} (deflate/inflate only, empty dictionary by
+ default)
See the description of `deflateInit2` and `inflateInit2` at
<http://zlib.net/manual.html#Advanced> for more information on these.
@@ -473,89 +477,159 @@ Returns a new [Unzip][] object with an [options][].
<!--type=misc-->
-All of these take a [Buffer][] or string as the first argument, an optional
-second argument to supply options to the `zlib` classes and will call the
-supplied callback with `callback(error, result)`.
+All of these take a [Buffer][], [Uint8Array][], or string as the first
+argument, an optional second argument to supply options to the `zlib` classes
+and will call the supplied callback with `callback(error, result)`.
Every method has a `*Sync` counterpart, which accept the same arguments, but
without a callback.
-### zlib.deflate(buf[, options], callback)
+### zlib.deflate(buffer[, options], callback)
<!-- YAML
added: v0.6.0
+changes:
+ - version: REPLACEME
+ pr-url: https://github.com/nodejs/node/pull/12001
+ description: The `buffer` parameter can be an Uint8Array now.
-->
-### zlib.deflateSync(buf[, options])
+### zlib.deflateSync(buffer[, options])
<!-- YAML
added: v0.11.12
+changes:
+ - version: REPLACEME
+ pr-url: https://github.com/nodejs/node/pull/12001
+ description: The `buffer` parameter can be an Uint8Array now.
-->
-Compress a [Buffer][] or string with [Deflate][].
+- `buffer` {Buffer|Uint8Array|string}
+
+Compress a chunk of data with [Deflate][].
-### zlib.deflateRaw(buf[, options], callback)
+### zlib.deflateRaw(buffer[, options], callback)
<!-- YAML
added: v0.6.0
+changes:
+ - version: REPLACEME
+ pr-url: https://github.com/nodejs/node/pull/12001
+ description: The `buffer` parameter can be an Uint8Array now.
-->
-### zlib.deflateRawSync(buf[, options])
+### zlib.deflateRawSync(buffer[, options])
<!-- YAML
added: v0.11.12
+changes:
+ - version: REPLACEME
+ pr-url: https://github.com/nodejs/node/pull/12001
+ description: The `buffer` parameter can be an Uint8Array now.
-->
-Compress a [Buffer][] or string with [DeflateRaw][].
+- `buffer` {Buffer|Uint8Array|string}
+
+Compress a chunk of data with [DeflateRaw][].
-### zlib.gunzip(buf[, options], callback)
+### zlib.gunzip(buffer[, options], callback)
<!-- YAML
added: v0.6.0
+changes:
+ - version: REPLACEME
+ pr-url: https://github.com/nodejs/node/pull/12001
+ description: The `buffer` parameter can be an Uint8Array now.
-->
-### zlib.gunzipSync(buf[, options])
+### zlib.gunzipSync(buffer[, options])
<!-- YAML
added: v0.11.12
+changes:
+ - version: REPLACEME
+ pr-url: https://github.com/nodejs/node/pull/12001
+ description: The `buffer` parameter can be an Uint8Array now.
-->
-Decompress a [Buffer][] or string with [Gunzip][].
+- `buffer` {Buffer|Uint8Array|string}
+
+Decompress a chunk of data with [Gunzip][].
-### zlib.gzip(buf[, options], callback)
+### zlib.gzip(buffer[, options], callback)
<!-- YAML
added: v0.6.0
+changes:
+ - version: REPLACEME
+ pr-url: https://github.com/nodejs/node/pull/12001
+ description: The `buffer` parameter can be an Uint8Array now.
-->
-### zlib.gzipSync(buf[, options])
+### zlib.gzipSync(buffer[, options])
<!-- YAML
added: v0.11.12
+changes:
+ - version: REPLACEME
+ pr-url: https://github.com/nodejs/node/pull/12001
+ description: The `buffer` parameter can be an Uint8Array now.
-->
-Compress a [Buffer][] or string with [Gzip][].
+- `buffer` {Buffer|Uint8Array|string}
-### zlib.inflate(buf[, options], callback)
+Compress a chunk of data with [Gzip][].
+
+### zlib.inflate(buffer[, options], callback)
<!-- YAML
added: v0.6.0
+changes:
+ - version: REPLACEME
+ pr-url: https://github.com/nodejs/node/pull/12001
+ description: The `buffer` parameter can be an Uint8Array now.
-->
-### zlib.inflateSync(buf[, options])
+### zlib.inflateSync(buffer[, options])
<!-- YAML
added: v0.11.12
+changes:
+ - version: REPLACEME
+ pr-url: https://github.com/nodejs/node/pull/12001
+ description: The `buffer` parameter can be an Uint8Array now.
-->
-Decompress a [Buffer][] or string with [Inflate][].
+- `buffer` {Buffer|Uint8Array|string}
-### zlib.inflateRaw(buf[, options], callback)
+Decompress a chunk of data with [Inflate][].
+
+### zlib.inflateRaw(buffer[, options], callback)
<!-- YAML
added: v0.6.0
+changes:
+ - version: REPLACEME
+ pr-url: https://github.com/nodejs/node/pull/12001
+ description: The `buffer` parameter can be an Uint8Array now.
-->
-### zlib.inflateRawSync(buf[, options])
+### zlib.inflateRawSync(buffer[, options])
<!-- YAML
added: v0.11.12
+changes:
+ - version: REPLACEME
+ pr-url: https://github.com/nodejs/node/pull/12001
+ description: The `buffer` parameter can be an Uint8Array now.
-->
-Decompress a [Buffer][] or string with [InflateRaw][].
+- `buffer` {Buffer|Uint8Array|string}
+
+Decompress a chunk of data with [InflateRaw][].
-### zlib.unzip(buf[, options], callback)
+### zlib.unzip(buffer[, options], callback)
<!-- YAML
added: v0.6.0
+changes:
+ - version: REPLACEME
+ pr-url: https://github.com/nodejs/node/pull/12001
+ description: The `buffer` parameter can be an Uint8Array now.
-->
-### zlib.unzipSync(buf[, options])
+### zlib.unzipSync(buffer[, options])
<!-- YAML
added: v0.11.12
+changes:
+ - version: REPLACEME
+ pr-url: https://github.com/nodejs/node/pull/12001
+ description: The `buffer` parameter can be an Uint8Array now.
-->
-Decompress a [Buffer][] or string with [Unzip][].
+- `buffer` {Buffer|Uint8Array|string}
+
+Decompress a chunk of data with [Unzip][].
[`Accept-Encoding`]: https://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.3
[`Content-Encoding`]: https://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.11
@@ -571,3 +645,4 @@ Decompress a [Buffer][] or string with [Unzip][].
[Unzip]: #zlib_class_zlib_unzip
[`.flush()`]: #zlib_zlib_flush_kind_callback
[Buffer]: buffer.html
+[Uint8Array]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint8Array
diff --git a/lib/zlib.js b/lib/zlib.js
index ab06c73689..07040c3ebc 100644
--- a/lib/zlib.js
+++ b/lib/zlib.js
@@ -24,6 +24,7 @@
const Buffer = require('buffer').Buffer;
const internalUtil = require('internal/util');
const Transform = require('_stream_transform');
+const { isUint8Array } = process.binding('util');
const binding = process.binding('zlib');
const assert = require('assert').ok;
const kMaxLength = require('buffer').kMaxLength;
@@ -78,6 +79,13 @@ function isInvalidStrategy(strategy) {
}
function zlibBuffer(engine, buffer, callback) {
+ // Streams do not support non-Buffer Uint8Arrays yet. Convert it to a
+ // Buffer without copying.
+ if (isUint8Array(buffer) &&
+ Object.getPrototypeOf(buffer) !== Buffer.prototype) {
+ buffer = Buffer.from(buffer.buffer, buffer.byteOffset, buffer.byteLength);
+ }
+
var buffers = [];
var nread = 0;
@@ -121,8 +129,9 @@ function zlibBuffer(engine, buffer, callback) {
function zlibBufferSync(engine, buffer) {
if (typeof buffer === 'string')
buffer = Buffer.from(buffer);
- if (!(buffer instanceof Buffer))
- throw new TypeError('Not a string or buffer');
+ else if (!isUint8Array(buffer))
+ throw new TypeError('"buffer" argument must be a string, Buffer, or ' +
+ 'Uint8Array');
var flushFlag = engine._finishFlushFlag;
@@ -205,9 +214,9 @@ class Zlib extends Transform {
throw new TypeError('Invalid strategy: ' + opts.strategy);
if (opts.dictionary) {
- if (!(opts.dictionary instanceof Buffer)) {
+ if (!isUint8Array(opts.dictionary)) {
throw new TypeError(
- 'Invalid dictionary: it should be a Buffer instance');
+ 'Invalid dictionary: it should be a Buffer or an Uint8Array');
}
}
@@ -302,7 +311,7 @@ class Zlib extends Transform {
var ending = ws.ending || ws.ended;
var last = ending && (!chunk || ws.length === chunk.length);
- if (chunk !== null && !(chunk instanceof Buffer))
+ if (chunk !== null && !isUint8Array(chunk))
return cb(new TypeError('invalid input'));
if (!this._handle)
diff --git a/test/parallel/test-zlib-convenience-methods.js b/test/parallel/test-zlib-convenience-methods.js
index 5f1e1ce9e2..df56f21ff4 100644
--- a/test/parallel/test-zlib-convenience-methods.js
+++ b/test/parallel/test-zlib-convenience-methods.js
@@ -22,59 +22,60 @@
'use strict';
// test convenience methods with and without options supplied
-require('../common');
+const common = require('../common');
const assert = require('assert');
const zlib = require('zlib');
-let hadRun = 0;
-
-const expect = 'blahblahblahblahblahblah';
+const expectStr = 'blahblahblahblahblahblah';
+const expectBuf = Buffer.from(expectStr);
+const expectUint8Array = new Uint8Array(expectBuf);
const opts = {
level: 9,
chunkSize: 1024,
};
-[
+for (const method of [
['gzip', 'gunzip'],
['gzip', 'unzip'],
['deflate', 'inflate'],
['deflateRaw', 'inflateRaw'],
-].forEach(function(method) {
-
- zlib[method[0]](expect, opts, function(err, result) {
- zlib[method[1]](result, opts, function(err, result) {
- assert.strictEqual(result.toString(), expect,
- 'Should get original string after ' +
- method[0] + '/' + method[1] + ' with options.');
- hadRun++;
- });
- });
-
- zlib[method[0]](expect, function(err, result) {
- zlib[method[1]](result, function(err, result) {
- assert.strictEqual(result.toString(), expect,
- 'Should get original string after ' +
- method[0] + '/' + method[1] + ' without options.');
- hadRun++;
- });
- });
+]) {
+ for (const [type, expect] of [
+ ['string', expectStr],
+ ['Buffer', expectBuf],
+ ['Uint8Array', expectUint8Array]
+ ]) {
+ zlib[method[0]](expect, opts, common.mustCall((err, result) => {
+ zlib[method[1]](result, opts, common.mustCall((err, result) => {
+ assert.strictEqual(result.toString(), expectStr,
+ `Should get original string after ${method[0]}/` +
+ `${method[1]} ${type} with options.`);
+ }));
+ }));
- let result = zlib[method[0] + 'Sync'](expect, opts);
- result = zlib[method[1] + 'Sync'](result, opts);
- assert.strictEqual(result.toString(), expect,
- 'Should get original string after ' +
- method[0] + '/' + method[1] + ' with options.');
- hadRun++;
+ zlib[method[0]](expect, common.mustCall((err, result) => {
+ zlib[method[1]](result, common.mustCall((err, result) => {
+ assert.strictEqual(result.toString(), expectStr,
+ `Should get original string after ${method[0]}/` +
+ `${method[1]} ${type} without options.`);
+ }));
+ }));
- result = zlib[method[0] + 'Sync'](expect);
- result = zlib[method[1] + 'Sync'](result);
- assert.strictEqual(result.toString(), expect,
- 'Should get original string after ' +
- method[0] + '/' + method[1] + ' without options.');
- hadRun++;
+ {
+ const compressed = zlib[method[0] + 'Sync'](expect, opts);
+ const decompressed = zlib[method[1] + 'Sync'](compressed, opts);
+ assert.strictEqual(decompressed.toString(), expectStr,
+ `Should get original string after ${method[0]}Sync/` +
+ `${method[1]}Sync ${type} with options.`);
+ }
-});
-process.on('exit', function() {
- assert.strictEqual(hadRun, 16, 'expect 16 compressions');
-});
+ {
+ const compressed = zlib[method[0] + 'Sync'](expect);
+ const decompressed = zlib[method[1] + 'Sync'](compressed);
+ assert.strictEqual(decompressed.toString(), expectStr,
+ `Should get original string after ${method[0]}Sync/` +
+ `${method[1]}Sync ${type} without options.`);
+ }
+ }
+}
diff --git a/test/parallel/test-zlib-deflate-constructors.js b/test/parallel/test-zlib-deflate-constructors.js
index ca9c4f801b..c495d2d11d 100644
--- a/test/parallel/test-zlib-deflate-constructors.js
+++ b/test/parallel/test-zlib-deflate-constructors.js
@@ -107,5 +107,5 @@ assert.throws(
// Throws if opts.dictionary is not a Buffer
assert.throws(
() => { new zlib.Deflate({dictionary: 'not a buffer'}); },
- /^TypeError: Invalid dictionary: it should be a Buffer instance$/
+ /^TypeError: Invalid dictionary: it should be a Buffer or an Uint8Array$/
);
diff --git a/test/parallel/test-zlib-dictionary.js b/test/parallel/test-zlib-dictionary.js
index fd70d73556..a3b55bc72d 100644
--- a/test/parallel/test-zlib-dictionary.js
+++ b/test/parallel/test-zlib-dictionary.js
@@ -41,6 +41,7 @@ const spdyDict = Buffer.from([
'ation/xhtmltext/plainpublicmax-agecharset=iso-8859-1utf-8gzipdeflateHTTP/1',
'.1statusversionurl\0'
].join(''));
+const spdyDictUint8Array = new Uint8Array(spdyDict);
const input = [
'HTTP/1.1 200 Ok',
@@ -49,7 +50,7 @@ const input = [
''
].join('\r\n');
-function basicDictionaryTest() {
+function basicDictionaryTest(spdyDict) {
let output = '';
const deflate = zlib.createDeflate({ dictionary: spdyDict });
const inflate = zlib.createInflate({ dictionary: spdyDict });
@@ -75,7 +76,7 @@ function basicDictionaryTest() {
deflate.end();
}
-function deflateResetDictionaryTest() {
+function deflateResetDictionaryTest(spdyDict) {
let doneReset = false;
let output = '';
const deflate = zlib.createDeflate({ dictionary: spdyDict });
@@ -108,7 +109,7 @@ function deflateResetDictionaryTest() {
});
}
-function rawDictionaryTest() {
+function rawDictionaryTest(spdyDict) {
let output = '';
const deflate = zlib.createDeflateRaw({ dictionary: spdyDict });
const inflate = zlib.createInflateRaw({ dictionary: spdyDict });
@@ -134,7 +135,7 @@ function rawDictionaryTest() {
deflate.end();
}
-function deflateRawResetDictionaryTest() {
+function deflateRawResetDictionaryTest(spdyDict) {
let doneReset = false;
let output = '';
const deflate = zlib.createDeflateRaw({ dictionary: spdyDict });
@@ -167,7 +168,9 @@ function deflateRawResetDictionaryTest() {
});
}
-basicDictionaryTest();
-deflateResetDictionaryTest();
-rawDictionaryTest();
-deflateRawResetDictionaryTest();
+for (const dict of [spdyDict, spdyDictUint8Array]) {
+ basicDictionaryTest(dict);
+ deflateResetDictionaryTest(dict);
+ rawDictionaryTest(dict);
+ deflateRawResetDictionaryTest(dict);
+}
diff --git a/test/parallel/test-zlib-not-string-or-buffer.js b/test/parallel/test-zlib-not-string-or-buffer.js
index 3f58583e03..510e111f70 100644
--- a/test/parallel/test-zlib-not-string-or-buffer.js
+++ b/test/parallel/test-zlib-not-string-or-buffer.js
@@ -7,7 +7,8 @@ require('../common');
const assert = require('assert');
const zlib = require('zlib');
-const expected = /^TypeError: Not a string or buffer$/;
+const expected =
+ /^TypeError: "buffer" argument must be a string, Buffer, or Uint8Array$/;
assert.throws(() => { zlib.deflateSync(undefined); }, expected);
assert.throws(() => { zlib.deflateSync(null); }, expected);