Update dependency @zip.js/zip.js to v2.12.0 - #544
Open
renovate[bot] wants to merge 1 commit into
Open
Conversation
renovate
Bot
force-pushed
the
renovate/zip.js-zip.js-2.x
branch
3 times, most recently
from
September 4, 2026 15:58
14db1b7 to
b321b90
Compare
renovate
Bot
force-pushed
the
renovate/zip.js-zip.js-2.x
branch
from
September 5, 2026 12:59
b321b90 to
d5057db
Compare
renovate
Bot
force-pushed
the
renovate/zip.js-zip.js-2.x
branch
from
September 5, 2026 17:46
d5057db to
29da05f
Compare
renovate
Bot
force-pushed
the
renovate/zip.js-zip.js-2.x
branch
from
September 6, 2026 12:40
29da05f to
1b02250
Compare
renovate
Bot
force-pushed
the
renovate/zip.js-zip.js-2.x
branch
2 times, most recently
from
September 8, 2026 03:52
872d8fd to
25d3609
Compare
renovate
Bot
force-pushed
the
renovate/zip.js-zip.js-2.x
branch
from
September 8, 2026 15:16
25d3609 to
4e6b8b3
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This PR contains the following updates:
2.8.61→2.12.0Release Notes
gildas-lormeau/zip.js (@zip.js/zip.js)
v2.12.0Compare Source
What's Changed in v2.12.0
Breaking changes
EntryMetaData#filenameUTF8andEntryMetaData#commentUTF8returned byZipWriter#add()now report the flag that was actually written, where they always reportedtrue. They agree with the values read back from the archive, which the previous behaviour contradicted for every entry whose name is printable ASCIIHttpReadernow throws anERR_HTTP_STATUSerror for any status outside 2xx, where it accepted everything below 400. A 304 answered by a caching proxy to a conditional request was read as a successful empty response, and the archive failed later with an unrelated end of central directory errorcheckPasswordOnlyoption combined withpassThroughset totruenow verifies the password. It reported every password as valid, wrong ones included, and streamed the whole entry instead of stopping after the first block: passing the encryption stage through left nothing able to raise the sentinel that means "the password is correct"ZipDirectoryEntryImportOptions#passThroughand thepassThroughoption ofZipDirectoryEntryExportOptions#readerOptionsare typedbooleaninstead ofboolean | "compressed". The filesystem API has always refused"compressed"at runtime, the types now say so and code passing it stops compilingNew features
passThroughvalue,"compressed", which passes the compression stage through and still runs the encryption stage. It is what re-encrypting an entry without recompressing it needs: reading with it decrypts and does not inflate, writing with it encrypts and does not deflate.passThroughis a depth rather than a pair of switches, and encryption is the outer stageentryoption onZipWriter#add(), which takes the entry read from another archive and derives the ten or so values a copy needs from it. Copying an entry by forwarding the obvious subset used to produce silent corruption, an encrypted entry landing markedencrypted=falseover untouched ciphertext. The oracle the option is built on is byte identity: an archive copied entry by entry with{ passThrough: true, entry }is the archive it was read fromcheckLocalFilenameoption, which selects whether the filename of the local header is compared, independently of whether a difference throws. The two axes were conflated:strictness: "strict"compared the filename and rejected, everything else did neither, so a mismatched filename could never be reported as a warning.{ checkLocalFilename: true, checkLocalDirectory: false }now reports it onEntryMetaData#warningsZipDirectoryEntry#exportZip()accepts aZipWriterinstance, the symmetric counterpart ofZipDirectoryEntry#importZip()accepting aZipReader. The entries are added to that writer and the archive is left open, so the caller closes it, can add entries of its own before or after, can export several trees into one archive, and can readZipWriter#warningsZipWriter#warningschannel, reporting the adjustments the writer makes silently: an entry stored because no deflate implementation is reachable, a date clamped to the MS-DOS range with no extra field left to carry the original value. Each reason is deposited once, with the filename of the first entry it applied toZipReaderandZipWriterimplementSymbol.asyncDispose, soawait usingfinalizes the archive on scope exitoutputSizeproperty on the errors thrown by the codecs, holding the number of bytes that reached the writer before the failure. It is what a caller salvaging an archive after a mid-entry failure needs to knowZipWriter#add()acceptsnullas the reader of an entry with no contentERR_ABORTEDincluded, and an audit in the test suite keeps it that way across the fourteen buildsconfigure()checks the type ofbaseURI,workerURIandwasmURI, which used to fail much later and quietlyBug fixes
outputSize, so the writer advances by the bytes that really reached it. It did not, and the central directory of an archive salvaged after such a failure was written short of the real positions, by 655360 bytes in the measured casepreventCloseno longer makesFileEntry#arrayBuffer()andZipReaderStreamhang forever. Both build their writable internally, exactly like theWriterinstances the option is documented to ignoreentryoption now derives the deflate level bits, the language encoding flag and the unix extra field type of the source entry. It dropped the level bits, cleared bit 11 on an ASCII-named source that carried it, and rewrote a 0x7855 record as a 0x7875 onepassThrough: "compressed", where the entry is encrypted again or not encrypted at all and the date is free to changeZipDirectoryEntry#exportFileSystemHandle()now refuses the"compressed"value ofpassThroughspelled at the top level, as it already did throughreaderOptions. It wrote the raw deflated bytes into the extracted files insteadZipDirectoryEntry#getExportedSize()isasync, so its option validation errors reject instead of throwing synchronously out of a method declared to return a promiseERR_INVALID_UNCOMPRESSED_SIZEerror now carriesoutputSize, which the most common corruption shape did not setpassThroughand no crc32 to declare is refused instead of being written with a wrong one, and AE-2 is written when encrypting passthrough contentDocumentation
extendedTimestampremark no longer claims that EPUB allows an extra field on itsmimetypeentry. OCF states that there must not be one, which is what pins the byte offset ofapplication/epub+zipso a reader can sniff the format without parsing the archive, and epubcheck reports it as an error. ODF and EPUB need the same pair of optionsentryoption reads, which beat the options of theZipWriterrather than being defaults against them; the condition under whichWARNING_CLAMPED_LAST_MODIFICATION_DATEappears; the combinations under whichLocalDirectory#rawFilenameis defined; the status codesERR_HTTP_STATUScovers; whatERR_INVALID_URIvalidates; and the determinability ofgetExportedSize()for names holding a slash, obsolete since implicit directories were exemptedZipWriter#close()are documented as belonging to the caller closing the archive when aZipWriteris passed toexportZip(),globalCommentandsignCentralDirectoryincludedentryoption points at the branch it selects for an encrypted source: it suppliesencrypted, so copying such an entry withpassThroughset totruewrites the ciphertext as-is and keeps the password it was encrypted with, while a password in scope encrypts the other entries only. Re-keying is what"compressed"is forTests and continuous integration
deno lintincluded, and the fidelity harness runs intest-ciZipWriterFull Changelog: gildas-lormeau/zip.js@v2.11.4...v2.12.0
v2.11.4Compare Source
What's Changed in v2.11.4
Bug fixes
AbortSignalalready aborted whenZipWriter#add()orEntry#getData()is called now rejects the call. The signal was only handed topipeTo(), which ignores it on the engines below its support floor, i.e. the oldest browsers the test matrix covers: the whole entry was then written and there was nothing left to abort. Both methods now check the signal before starting, and reject withsignal.reasonwhen it is set, so the error is unchanged on the engines that already honored it, or with anAbortErrorwhose message isERR_ABORTEDotherwise,signal.reasonnot existing before Chrome 98. A pre-abortedadd()also rejects before the temporary stream of a buffered entry is created, so nothing is allocated to disposeZipReaderStreamnow expose the properties deposited on an entry while its data is read, i.e.EntryMetaData#warningsandEntryMetaData#localDirectory. The chunk was built from a copy of the entry taken before the read started, so those two were permanently absent from it, and the warnings channel added in v2.8.x was unreachable fromZipReaderStreamalthough the types promise it. The chunk now shares them with the entry, so they are readable on it once itsreadableproperty has been consumedBlobReaderno longer fails withsourceBlob.stream is not a functionwhen its source is aBlob-like object exposing onlysize,sliceandarrayBuffer. It reads withstream()when the source has it and falls back to theslice()/arrayBuffer()path otherwise, which the reader already implemented for the engines whoseBlob#sliceis unreliableDocumentation
signaloption of the reader and of the writer documents that a signal already aborted rejects the call, and with which errorTests and continuous integration
add()andgetData()are called, with and without a reason, registered without thepipeToSignalfeature gate so that it runs on the engines the fix is forBlobReaderover a source withoutstream()ZipReaderStreamchunk carries the local directory and the warnings of its entryReaderinstead; a second case pins that a pre-abortedadd()creates nonev2.11.3Compare Source
What's Changed in v2.11.3
Bug fixes
ZipWriterStreamand anyReadableStreamsource produce, no longer make the archive unreadable by the macOS extractors. The size of such an entry is only known once it has been written, so the writer has to pick the layout of the data descriptor before writing the first byte and commits to the ZIP64 one. The central directory is written last, when the real sizes are known, but it kept that layout: the 32-bit size fields stayed at0xFFFFFFFFand the real sizes went to the ZIP64 extra field of the entry. Archive Utility anddittoonly read that extra field when the archive carries a ZIP64 end of central directory record, which was not written for an archive small enough not to need one, so they read0xFFFFFFFFas the size of the entry. A stored entry then failed withCouldn't read pkzip signature, a deflated one survived because the inflater ends on its own and never uses the size.unzip, 7-Zip and Windows Explorer read all of them. The central directory now drops the ZIP64 layout of an entry whose sizes turned out to fit in 32 bits, and an archive that does keep an entry in the ZIP64 layout now ends with a ZIP64 end of central directory record. An archive of one stored 1 MB entry written throughZipWriterStreamis also 20 bytes smaller (#678)ZipDirectoryEntry#getExportedSize()no longer refuses to predict the size of a filesystem holding implicit directories. Those are the intermediate directories created by a name such asa/b/c.txt, they are not written to the archive, so they cannot change the order the entries are written in. The check that rejects abufferedWriteexport whose write order is not determined counted them as real directories, so it gave up on almost every filesystem built byaddBlob()and friends. An explicit directory entry with children still throwsERR_UNDETERMINED_SIZE, as it mustlastModDateof the entry returned byZipWriter#add()is now the date the archive actually stores. It reported the date rounded and clamped to the MS-DOS range even when the entry carries an extended timestamp or an NTFS timestamp, which hold the date at a higher resolution and without an upper bound. Reading the entry back gave a date theadd()call had not reportedError handling
ZipWriter#add()throwsERR_INVALID_READERwhen its second argument is neither aReaderinstance, aReadableStreaminstance, nor an object exposing areadableproperty. Passing aBlob, a string or aUint8Arraydirectly, which has to be wrapped inBlobReader,TextReaderorUint8ArrayReader, wrote an empty entry with no error at allERR_UNSUPPORTED_SPLIT_USDZ. It used to write the split archive and silently break the 64-byte alignment USDZ requires, the offset of the breakage depending on where the disks happen to roll over. A USDZ file is a single package anyway, and a.zip/.z01/.z02set is not oneDocumentation
leveloption documents that an entry is stored instead of being compressed, rather than failing, when the environment provides no usableCompressionStreamand the embedded implementation cannot be loaded. ThecompressionMethodof the entry returned byZipWriter#add()is0in that case, which is how the fallback is detectedzip64option documents why an entry of unknown size is written with ZIP64 in its local header, and that its central directory record drops ZIP64 when the actual sizes fit in 32 bits. Thezip64option ofZipWriter#close()documents that ZIP64 is also used when an entry is stored with ZIP64@seelinks in the types rendered with their label pasted inside the URL in the generated documentationTests and continuous integration
zip64set totrueZipWriter#add()past the MS-DOS ceiling, and the readersZipWriter#add()rejectsCredits
ZipWriterStreamcannot be opened by the macOS archiver, and for the minimal repository that reproduced it (#678)v2.11.2Compare Source
What's Changed in v2.11.2
Bug fixes
ZipWriter#add()compress concurrently again. Since v2.10.0 every entry of a batch took the path that writes directly into the zip file, and each of them then waited for the previous entry to be written, so the batch was compressed one entry at a time. The writer now records that choice in the same step that makes it, so the first entry is written directly into the file and the others are buffered, as before. Measured on 8 entries of 8 MB with the nativeCompressionStream, the same batch of concurrentadd()calls goes from 2211 ms to 607 ms. The archive is unchanged, only the scheduling was wrongReaderthat declares its size and always returns the number of bytes it is asked for no longer makesZipWriter#add()read it forever. The writer did not pass that size when it built the readable stream, so the stream ended only when the reader returned an empty array. The stream also advances by the number of bytes actually returned instead of by the requested chunk size, so a reader that returns a short chunk in the middle of the data no longer skips the rest of the chunkDocumentation
keepOrderoption no longer states that concurrent calls toZipWriter#add()compress one entry at a time and needbufferedWriteto overlap. That described the bug above, not the intended behaviorBenchmarks
bench-codecs.jscompares the codecs alone, sorted by output size. A compression level is not a unit shared between libraries, so a table matched on level reads a difference in compression ratio as a difference in speedv2.11.1Compare Source
What's Changed in v2.11.1
Bug fixes
RangeError: offset is out of bounds. Thedeflate_process,inflate_processandinflate9_processfunctions pack the number of bytes produced in the low 24 bits and the zlib status code in the top byte, but their two error paths returned a bare negative code, read as1677721bytes produced and copied out of the module heap into a 64KB buffer. Reaching it takes the codec running out of its fixed 16MB heap, which needsuseCompressionStreamanduseWebWorkersboth set tofalse, so that every entry shares one module instance, andmaxWorkersraised above the number of streams the heap holds, 42 measured when compressing at level 6deflate()reports no byte produced and no byte consumed, which the loop reads as the end of the data, so the rest of the entry was dropped without an error. The status is also checked before the number of bytes produced is used, so a status code can no longer be read as a byte count whatever the codec returnsTests and continuous integration
v2.11.0Compare Source
What's Changed in v2.11.0
Breaking changes
ERR_INVALID_CRC32andERR_INVALID_AUTHENTICATION_CODEnow hold distinct values,"Invalid CRC32"and"Invalid authentication code". Both were aliases ofERR_INVALID_SIGNATUREsince v2.8.44, added as aliases so the two errors could be told apart later without breaking the code comparing them at the time.ERR_INVALID_SIGNATUREis removed, the term naming a CRC-32 check and an AES authentication code, neither of which is a signature. Code comparing an error message to it must now compare to the constant naming the check that failedexternalFileAttributeandinternalFileAttributenames are removed, from the entry properties and from the writer options. They were renamed toexternalFileAttributesandinternalFileAttributesin January 2025 and kept as aliases since. The other names deprecated in the 2.8 releases are kept. The minified files shrink by 354 bytesBug fixes
Z_BUF_ERRORat the default chunk size, or with an invalid uncompressed size when the chunks were small enough for the loss to pass unnoticed until the end. Only Deflate64 allows such a match, its maximum length being 65538 bytes against the 258 of Deflate, and 7-Zip does not produce one, its Deflate64 encoder capping the matches at 257 bytes. The JavaScript codec was unaffecteddeflateandgzipreported the corruption as an invalid checksum,deflate-rawreturned the expected number of bytes with a few of them wrong. The entries of a zip file are read asdeflate-rawandcheckCrc32is not set by default, so the wrong bytes were returned with no error at all. The codec is the one theindex-nativeand legacy builds use, including to read Deflate64Performance
CompressionStreamAPI is unavailable or turned off with theuseCompressionStreamoption, and always when reading Deflate64 (#677)Documentation
keepOrderoption no longer claims that setting it totrueimproves the use of web workers, which is the opposite of what it does. Keeping the order writes the entries one after another, so concurrent calls toadd()compress one entry at a time. The remark now says so and points tobufferedWrite, which restores the concurrency while still keeping the orderTests and continuous integration
Credits
v2.10.0Compare Source
What's Changed in v2.10.0
New features
duplicatesoption on theimport*()methods of the filesystem API, set to"throw","keep-first"or"keep-last". A zip file stores a flat list of filenames while the filesystem API indexes the entries by path, so two entries can claim the same node of the tree: they can hold the same filename, hold filenames differing only by the path components ignored when building the tree such as"a/b.txt"and"./a/b.txt", or one can be a file and the other a directory holding it such as"a"and"a/b.txt". The three cases are now governed by one option instead of aborting the import in every case. The default stays"throw", an archive holding the same name twice being also the shape making an extractor and a scanner disagree on the file they see."keep-last"is the behavior of most zip tools, verified against Info-ZIP, 7-Zip, libarchive,ditto, Pythonzipfile, fflate and JSZipadd*()method of the filesystem API is now split into path components, like the filename of an imported entry already was.addText("a/b.txt", text)adds"b.txt"to the"a"directory and creates that directory when it does not exist, instead of adding one entry whose name holds a"/". The directories created that way are implicit, they are not written when the tree is exported, so the exported zip file is unchanged.rename()splits the name the same way and moves the entry accordinglyERR_DUPLICATE_IMPORTED_ENTRYandERR_INVALID_DUPLICATESerrors, and newZipDirectoryEntryImportOptionstype.ERR_DUPLICATE_IMPORTED_ENTRYreplacesERR_ENTRY_EXISTSwhen an import is refused, the former reading as an error made by the caller while the caller only passed a zip fileBug fixes
ZipFSinstance held before the import is restored instead of being discarded before the first entry is readreplace*()methods of the filesystem API now update the size of the entry, which kept describing the content held before the call. The archive was written correctly, onlygetExportedSize()was affected: replacing 1 byte of text with 5000 bytes predicted 127 bytes for an export of 5126.replaceReadable()reports an undetermined size, likeaddReadable()does, instead of returning a prediction it cannot make. The five methods also clear the pass-through state of an entry imported with thepassThroughoption, the bytes copied verbatim being goneZipFS#find()no longer throws aTypeErrorwhen a component of the path it is given is a file entry rather than a directoryDocumentation
Hello world with the filesystem APIexample in the README. The filesystem API needs a single import, infers the Reader and the Writer from the type of the data, and reaches an entry from its name, which is what the five other examples never showedgetExportedSize()unable to predict a size mention that a name holding"/"builds a nested treeTests and continuous integration
"/", the two duplicate policies and the entries whose imported content is replacedv2.9.0Compare Source
What's Changed in v2.9.0
New features
WARNING_PREPENDED_CENTRAL_DIRECTORYwarning, deposited when the data found before the archive holds a central directory of its own. It tells apart the two shapes producing theWARNING_PREPENDED_DATAwarning, a self-extracting stub carrying the archive and several archives concatenated, which were indistinguishable until now. The distinction matters because the readers disagree on the archive to read in the second case: zip.js, Info-ZIP and Python read the last one, 7-Zip reads the first one. The new warning costs no additional read, it reports what the search of the end of central directory already sawBug fixes
TextDecoder, which decodes UTF-8, so every byte past ASCII became a replacement character instead of the expected name. The minified files grow by 438 bytes and shrink by 177 bytes once compressedTests and continuous integration
Configuration
📅 Schedule: (UTC)
🚦 Automerge: Disabled by config. Please merge this manually once you are satisfied.
♻ Rebasing: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.
🔕 Ignore: Close this PR and you won't be reminded about this update again.
This PR was generated by Mend Renovate. View the repository job log.