Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions doc/api/zlib.md
Original file line number Diff line number Diff line change
Expand Up @@ -1099,6 +1099,10 @@ added:
- v23.8.0
- v22.15.0
changes:
- version: REPLACEME
pr-url: https://github.com/nodejs/node/pull/64599
description: The `dictionary` option can be a `TypedArray`, `DataView`, or
`ArrayBuffer`.
- version: v26.5.0
pr-url: https://github.com/nodejs/node/pull/64023
description: The `rejectGarbageAfterEnd` option was added.
Expand All @@ -1115,8 +1119,8 @@ Each Zstd-based class takes an `options` object. All options are optional.
* `maxOutputLength` {integer} Limits output size when using
[convenience methods][]. **Default:** [`buffer.kMaxLength`][]
* `info` {boolean} If `true`, returns an object with `buffer` and `engine`. **Default:** `false`
* `dictionary` {Buffer} Optional dictionary used to
improve compression efficiency when compressing or decompressing data that
* `dictionary` {Buffer|TypedArray|DataView|ArrayBuffer} Optional dictionary used
to improve compression efficiency when compressing or decompressing data that
shares common patterns with the dictionary.
* `rejectGarbageAfterEnd` {boolean} If `true`, decompression fails when
input remains after the first complete compressed stream. **Default:** `false`
Expand Down
12 changes: 11 additions & 1 deletion lib/zlib.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ const {
ObjectSetPrototypeOf,
Symbol,
Uint32Array,
Uint8Array,
} = primordials;

const {
Expand Down Expand Up @@ -926,6 +927,15 @@ class Zstd extends ZlibBase {
});
}

let dictionary = opts?.dictionary;
if (dictionary !== undefined && !isArrayBufferView(dictionary)) {
if (isAnyArrayBuffer(dictionary)) {
dictionary = new Uint8Array(dictionary);
} else {
dictionary = undefined;
}
}

const handle = mode === ZSTD_COMPRESS ?
new binding.ZstdCompress() : new binding.ZstdDecompress();

Expand All @@ -938,7 +948,7 @@ class Zstd extends ZlibBase {
pledgedSrcSize,
writeState,
processCallback,
opts?.dictionary && isArrayBufferView(opts.dictionary) ? opts.dictionary : undefined,
dictionary,
);

super(opts, mode, handle, zstdDefaultOpts);
Expand Down
16 changes: 16 additions & 0 deletions test/parallel/test-zlib-zstd-dictionary.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,19 @@ zlib.zstdCompress(input, { dictionary }, common.mustSucceed((compressed) => {
assert.strictEqual(decompressed.toString(), input.toString());
}));
}));

const baseline = zlib.zstdCompressSync(input, { dictionary }).length;

const arrayBuffer = dictionary.buffer.slice(
dictionary.byteOffset, dictionary.byteOffset + dictionary.byteLength);
const uint8 = new Uint8Array(arrayBuffer);
const dataView = new DataView(arrayBuffer);

for (const dict of [arrayBuffer, uint8, dataView]) {
assert.strictEqual(zlib.zstdCompressSync(input, { dictionary: dict }).length,
baseline);

const compressed = zlib.zstdCompressSync(input, { dictionary: dict });
const decompressed = zlib.zstdDecompressSync(compressed, { dictionary: dict });
assert.strictEqual(decompressed.toString(), input.toString());
}
Loading