Skip to content

fix(node/ext): make zlib write callback async to match node behavior#32130

Merged
fraidev merged 1 commit intodenoland:mainfrom
fraidev:fix/node-compat-zlib-async-callback
Feb 12, 2026
Merged

fix(node/ext): make zlib write callback async to match node behavior#32130
fraidev merged 1 commit intodenoland:mainfrom
fraidev:fix/node-compat-zlib-async-callback

Conversation

@fraidev
Copy link
Copy Markdown
Contributor

@fraidev fraidev commented Feb 11, 2026

Deno's zlib Zlib::write was calling processCallback synchronously, while Node.js runs compression on the libuv threadpool and calls it asynchronously. This caused several issues:

  • destroy() couldn't propagate before subsequent write callbacks fired
  • stream buffering didn't work correctly (needDrain was never set)
  • flush operations didn't produce separate compressed chunks

This change removes the synchronous callback from Rust's Zlib::write and schedules processCallback via process.nextTick from JavaScript. A _callbackPending flag ensures backward compatibility with Brotli/Zstd handles which still call the callback synchronously.

Enables 3 node_compat tests:

  • test-zlib-destroy-pipe
  • test-zlib-flush-drain
  • test-zlib-flush-write-sync-interleaved

@fraidev fraidev changed the title fix(node/zlib): make Zlib write callback async to match Node.js behavior fix(node/ext): make Zlib write callback async to match Node.js behavior Feb 11, 2026
Deno's zlib `Zlib::write` was calling `processCallback` synchronously,
while Node.js runs compression on the libuv threadpool and calls it
asynchronously. This caused several issues:

- destroy() couldn't propagate before subsequent write callbacks fired
- stream buffering didn't work correctly (needDrain was never set)
- flush operations didn't produce separate compressed chunks

This change removes the synchronous callback from Rust's `Zlib::write`
and schedules `processCallback` via `process.nextTick` from JavaScript.
A `_callbackPending` flag ensures backward compatibility with Brotli/Zstd
handles which still call the callback synchronously.

Enables 3 node_compat tests:
- test-zlib-destroy-pipe
- test-zlib-flush-drain
- test-zlib-flush-write-sync-interleaved
@fraidev fraidev force-pushed the fix/node-compat-zlib-async-callback branch from 687af3b to 2ef2ca7 Compare February 11, 2026 19:31
@fraidev fraidev changed the title fix(node/ext): make Zlib write callback async to match Node.js behavior fix(node/ext): make zlib write callback async to match node behavior Feb 11, 2026
Copy link
Copy Markdown
Member

@bartlomieju bartlomieju left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice

@fraidev fraidev merged commit 82b506d into denoland:main Feb 12, 2026
24 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants