What's Changed in v2.25.0
Bug fixes
- Concurrent
ZipWriter#close()calls now share the same finalization and all resolve to the zip file. Previously the second call rejected with a locked-streamTypeErrorfromgetWriter()while the first one succeeded. A call that threw, e.g. on an invalid comment, can still be retried ZipDirectoryEntry#exportFileSystemHandle()now aborts and unlocks the destination file stream when reading an entry fails before its data is written, e.g. on a wrong password or a corrupted entry. Previously the stream opened for that entry was left open and lockedZipDirectoryEntry#addFileSystemEntry()now rejects when reading a nested directory fails, e.g. on a permission error. Previously the error surfaced as an unhandled rejection and the returned promise never settledZipFileEntry#getData()now accepts a bareWritableStream, as declared, instead of throwing "Cannot read properties of undefined (reading 'getWriter')"; an object exposing awritableproperty keeps working
Type declarations
Reader#readUint8Array(),Writer#writeUint8Array(),Writer#getData()and theinit()methods now declare that they may return synchronously, which is whatUint8ArrayReader,Uint8ArrayWriterandData64URIWriterdo. A custom reader or writer implemented synchronously now type-checks, and calling.then()on these methods is no longer accepted by TypeScript since it fails at runtime on the synchronous classes: useawaitinstead. The classes implemented asynchronously, e.g.TextWriterandBlobWriter, keep their promise-only declarationsZipWriterStream#transform()andZipWriterStream#writable()are now typed onUint8Arraychunks on both sides and no longer take a type parameter: the readable side oftransform()is the zipped stream, never the type of the input chunks
Documentation
- New README section "Reading untrusted zip files", with remarks on
FileEntry#getData()andUint8ArrayWriter: the declared sizes are not verified before an entry is read, so checkentry.uncompressedSizeagainst your limit before extracting an entry from an untrusted source.Uint8ArrayWriterallocates its buffer from the declared size, capped at 1032 timescompressedSize msDosCompatible: Info-ZIPunzipbuilds without Unicode support, e.g. the one shipped with macOS, fail to extract entries with non-ASCII names when the MS-DOS platform is declared, whatever the language encoding flag says- The
ZipWriterStreamexamples now encode their strings with aTextEncoderStream: the streams piped into the instance must carryUint8Arraychunks - A lazily-read
Blobfromfs.openAsBlob()orBun.file()must be wrapped in aBlobReader; the two passages saying it could be passed directly toZipReaderwere wrong passThrough: "compressed": two encrypted entries holding the same content read identical only when the content was compressed identically; different compressed data does not prove different contentuseUnicodeFileNames: false:ZipReaderdecodes the resulting UTF-8 names correctly since it detects valid UTF-8 when the flag is clear; the readers that trust the flag, e.g. Pythonzipfileand Info-ZIPunzip, do notZipDirectoryEntry#exportWritable()resolves to theWritableStreaminstance, not to aUint8Arrayas its description said- The default appended data size of the
"balanced"strictness is 65535 bytes, the opening examples of the API documentation import the npm package@zip.js/zip.jsrather than the JSR name, and smaller wording fixes
Build and CI
- The Chrome 76, Chrome 87 and Firefox 102 test jobs run on
windows-2022, because those browsers no longer start on the currentwindows-latest(Windows Server 2025) image
Full Changelog: v2.24.0...v2.25.0
Co-Authored-By: Claude Fable 5.1 noreply@anthropic.com