Skip to content

Comments

Add ZSTD bindings to the node:zlib package.#6007

Closed
alistairjevans wants to merge 13 commits intocloudflare:mainfrom
alistairjevans:alistairjevans/zstd-support
Closed

Add ZSTD bindings to the node:zlib package.#6007
alistairjevans wants to merge 13 commits intocloudflare:mainfrom
alistairjevans:alistairjevans/zstd-support

Conversation

@alistairjevans
Copy link
Contributor

Based pretty heavily on the brotli support.

Closes #4013

@alistairjevans alistairjevans requested review from a team as code owners February 3, 2026 11:09
@github-actions
Copy link

github-actions bot commented Feb 3, 2026

All contributors have signed the CLA ✍️ ✅
Posted by the CLA Assistant Lite bot.

@alistairjevans
Copy link
Contributor Author

I have read the CLA Document and I hereby sign the CLA

ZstdEncoderContext::~ZstdEncoderContext() {
if (cctx_ != nullptr) {
ZSTD_freeCCtx(cctx_);
cctx_ = nullptr;
Copy link
Collaborator

Choose a reason for hiding this comment

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

It might be worth wrapping this in a custom smart pointer to ensure the cleanup is correct. Non-blocking tho.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Added (brotli implementation does already do this)

@jasnell jasnell requested a review from anonrig February 3, 2026 15:25
@jasnell
Copy link
Collaborator

jasnell commented Feb 3, 2026

@anonrig ... given your familiarity with the zlib impl in workerd, it would be good to have your review on this as well.

@alistairjevans
Copy link
Contributor Author

Thank you for the feedback @anonrig and @jasnell! 🙏 I believe I've addressed all your comments now.

@alistairjevans
Copy link
Contributor Author

Merged latest; @anonrig / @jasnell , any chance of a re-review? 🙏

@anonrig
Copy link
Member

anonrig commented Feb 11, 2026

LGTM. @alistairjevans formatter seems to be failing: https://github.com/cloudflare/workerd/actions/runs/21922721360/job/63307147452?pr=6007

@jasnell can you take a look?

@alistairjevans
Copy link
Contributor Author

alistairjevans commented Feb 11, 2026

Thanks @anonrig, formatting fix pushed, linter passes locally now.

@jasnell
Copy link
Collaborator

jasnell commented Feb 11, 2026

Overall I think this looks good. What I'm considering... (something I wish I had thought to do on the previous node:zlib additions)... is adding this initially behind an experimental compat flag and having the security team do some quick fuzz testing on it. Anything new that is dealing with bytes being passed around makes me just a bit nervous and a little extra testing doesn't hurt. That's not to say I see anything in here concretely questionable, just thinking about taking the extra precaution. @danlapid what do you think?

@alistairjevans
Copy link
Contributor Author

@jasnell, would such a compatibility flag still allow us to opt-in to using the feature in Cloudflare Workers while we wait for the fuzz test to complete?

@jasnell
Copy link
Collaborator

jasnell commented Feb 12, 2026

@alistairjevans ... while the fuzz testing would happening (if we go that route) the compat flag would be marked as "experimental" which means only cloudflare accounts would be able to use it until that annotation is removed. Still need to decide tho if this is the path we'd want to take. Should have a decision soon.

@danlapid
Copy link
Collaborator

danlapid commented Feb 12, 2026

Let's not block - good idea to do as follow up - still want to see this land.
Let's review the code until we're confident this is safe.

Copy link
Collaborator

@jasnell jasnell left a comment

Choose a reason for hiding this comment

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

Overall, LGTM with a couple nits and a question about error handling that might need addressing before this lands. I'll do the sign off once the question is looked at :-) .. great job overall!!

There is a pre-existing issue we need to address with CompressionStream::write's validation of flush values but that's not introduced or made worse with this change (it's relevant for the brotli support also). And, there's missing external memory tracking here that can be done as a follow-up (see, for instance, the CompressionAllocator::AllocForBrotli, CompressionAllocator::FreeForZlib, etc). We'll want to come back to that.

// For decompression, lastResult == 0 means frame is complete
// If we have flush_ == ZSTD_e_end equivalent and there's input left, that's an error
if (flush_ == ZSTD_e_end && input_.pos < input_.size && lastResult == 0) {
// Frame completed but there's still input - could be trailing data
Copy link
Collaborator

Choose a reason for hiding this comment

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

Nit: what is this if block for if it's empty?

Copy link
Contributor Author

@alistairjevans alistairjevans Feb 13, 2026

Choose a reason for hiding this comment

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

This sent me on a bit of a rabbit-hole, initially this code block was added as documentation only, but going back over it made me realise that, unlike the zlib or brotli implementations, you won't get an EOF error if a zstd frame you're decoding got truncated! But you will for brotli and zlib. 😕

Whats even more interesting is that neither will nodejs zstd, which was surprising, a truncated stream will just silently succeed; I'm pretty sure this is a bug in the ZSTD implementation in nodejs, because the tests in https://github.com/nodejs/node/blob/main/test/parallel/test-zlib-truncated.js do not verify zstd behaviour for truncated input as they do with gzip and deflate algorithms, which feels like an oversight.

I've pushed a fairly simple fix for workerd that ensures you do get an EOF error if a payload is truncated. Instinctively I'd go with correctness since this feels like a bug in nodejs, but do say if I should match nodejs behaviour exactly.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Fixing bugs is good. I'm happy with this and I'd encourage you to open a PR fixing it in node.js also :-)

@alistairjevans
Copy link
Contributor Author

Pushed fixes for linter formatting issues.

@codecov-commenter
Copy link

Codecov Report

❌ Patch coverage is 54.09091% with 101 lines in your changes missing coverage. Please review.
✅ Project coverage is 70.35%. Comparing base (6ff050c) to head (40f985d).
⚠️ Report is 58 commits behind head on main.

Files with missing lines Patch % Lines
src/workerd/api/node/zlib-util.c++ 53.48% 78 Missing and 22 partials ⚠️
src/workerd/api/node/zlib-util.h 80.00% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #6007      +/-   ##
==========================================
- Coverage   70.37%   70.35%   -0.02%     
==========================================
  Files         408      408              
  Lines      108811   109036     +225     
  Branches    18000    18035      +35     
==========================================
+ Hits        76574    76713     +139     
- Misses      21430    21495      +65     
- Partials    10807    10828      +21     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@npaun
Copy link
Member

npaun commented Feb 19, 2026

@alistairjevans Merge executed in #6117. I'll ping you again when it's deployed to prod.

@npaun npaun closed this Feb 19, 2026
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.

node:zlib implement zstd

6 participants