From 2f00b0add476bb151bc3a713da165296906cfc2a Mon Sep 17 00:00:00 2001 From: Divy Srivastava Date: Fri, 11 Aug 2023 17:12:35 +0530 Subject: [PATCH] fix(ext/node): support dictionary option in zlib init (#20035) Fixes https://github.com/denoland/deno/issues/19540 --- cli/tests/unit_node/zlib_test.ts | 18 ++++++++++++++++++ ext/node/ops/zlib/mod.rs | 8 ++++++-- ext/node/polyfills/_zlib.mjs | 15 +++++++++++---- ext/node/polyfills/_zlib_binding.mjs | 2 +- 4 files changed, 36 insertions(+), 7 deletions(-) diff --git a/cli/tests/unit_node/zlib_test.ts b/cli/tests/unit_node/zlib_test.ts index 96d392d1db2ce7..6b09c50b0853e5 100644 --- a/cli/tests/unit_node/zlib_test.ts +++ b/cli/tests/unit_node/zlib_test.ts @@ -11,6 +11,7 @@ import { brotliDecompressSync, createBrotliCompress, createBrotliDecompress, + createDeflate, } from "node:zlib"; import { Buffer } from "node:buffer"; import { createReadStream, createWriteStream } from "node:fs"; @@ -60,3 +61,20 @@ Deno.test("brotli compression", async () => { // pass } }); + +Deno.test( + "zlib create deflate with dictionary", + { sanitizeResources: false }, + async () => { + const promise = deferred(); + const handle = createDeflate({ + dictionary: Buffer.alloc(0), + }); + + handle.on("close", () => promise.resolve()); + handle.end(); + handle.destroy(); + + await promise; + }, +); diff --git a/ext/node/ops/zlib/mod.rs b/ext/node/ops/zlib/mod.rs index 3d58d16f9476c1..2ddf6f2cd43b03 100644 --- a/ext/node/ops/zlib/mod.rs +++ b/ext/node/ops/zlib/mod.rs @@ -344,7 +344,7 @@ pub fn op_zlib_init( window_bits: i32, mem_level: i32, strategy: i32, - dictionary: Option<&[u8]>, + dictionary: &[u8], ) -> Result { let resource = zlib(state, handle)?; let mut zlib = resource.inner.borrow_mut(); @@ -373,7 +373,11 @@ pub fn op_zlib_init( zlib.init_stream()?; - zlib.dictionary = dictionary.map(|buf| buf.to_vec()); + zlib.dictionary = if !dictionary.is_empty() { + Some(dictionary.to_vec()) + } else { + None + }; Ok(zlib.err) } diff --git a/ext/node/polyfills/_zlib.mjs b/ext/node/polyfills/_zlib.mjs index f7336580007a62..a66ab6d0460da7 100644 --- a/ext/node/polyfills/_zlib.mjs +++ b/ext/node/polyfills/_zlib.mjs @@ -11,6 +11,10 @@ import util from "node:util"; import { ok as assert } from "node:assert"; import { zlib as zlibConstants } from "ext:deno_node/internal_binding/constants.ts"; import { nextTick } from "ext:deno_node/_next_tick.ts"; +import { + isAnyArrayBuffer, + isArrayBufferView, +} from "ext:deno_node/internal/util/types.ts"; var kRangeErrorMessage = "Cannot create final Buffer. It would be larger " + "than 0x" + kMaxLength.toString(16) + " bytes"; @@ -321,9 +325,12 @@ function Zlib(opts, mode) { } } - if (opts.dictionary) { - if (!Buffer.isBuffer(opts.dictionary)) { - throw new Error("Invalid dictionary: it should be a Buffer instance"); + let dictionary = opts.dictionary; + if (dictionary !== undefined && !isArrayBufferView(dictionary)) { + if (isAnyArrayBuffer(dictionary)) { + dictionary = Buffer.from(dictionary); + } else { + throw new TypeError("Invalid dictionary"); } } @@ -354,7 +361,7 @@ function Zlib(opts, mode) { level, opts.memLevel || zlibConstants.Z_DEFAULT_MEMLEVEL, strategy, - opts.dictionary, + dictionary, ); this._buffer = Buffer.allocUnsafe(this._chunkSize); diff --git a/ext/node/polyfills/_zlib_binding.mjs b/ext/node/polyfills/_zlib_binding.mjs index a04e7fed75d057..0b155cfd51657a 100644 --- a/ext/node/polyfills/_zlib_binding.mjs +++ b/ext/node/polyfills/_zlib_binding.mjs @@ -149,7 +149,7 @@ class Zlib { windowBits, memLevel, strategy, - dictionary, + dictionary ?? new Uint8Array(0), ); if (err != Z_OK) {