Fix putImage mutating the global filters array#3987
Open
douglasmatheus wants to merge 1 commit into
Open
Conversation
The internal getFilters() returns the live reference to the document's
filters array. putImage was calling splice() on that reference to strip
"FlateEncode" before writing image data — but this side-effect persists
between save()/output() calls.
After the first putImage during a save, the document's filters array
becomes empty, so all subsequent page content streams are emitted
uncompressed. Result: the 1st PDF output is normal size, but every
subsequent output() balloons (e.g. 5 KB compressed page stream becomes
95 KB raw, only on documents that contain images).
Fix: copy the array via .slice() before mutating, so putImage's local
view is independent of the document state.
Repro:
const doc = new jsPDF({ compress: true });
doc.addImage(jpg, "JPEG", 10, 10, 100, 75);
const a = doc.output();
const b = doc.output();
console.assert(a.length === b.length); // failed before this fix
Regression covered by new test in test/specs/addimage.spec.js.
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.
Problem
putImagecallssplice()on the array returned bygetFilters()to remove"FlateEncode"before writing image data. ButgetFilters()returns the live reference to the document's internal filters array, not a copy:https://github.com/parallax/jsPDF/blob/master/src/jspdf.js#L1748-L1750
So the splice in
putImagepermanently empties the document's filters array. After the first image is rendered, all subsequent page content streams are emitted without compression.Symptoms
Calling
doc.output()twice in a row on a document containing any image produces PDFs of dramatically different sizes:The first output is correct; every output after that has uncompressed page content streams. The PDF still renders fine in viewers, just much larger than expected.
Cause
src/modules/addimage.jsline 206-208:Since
filterand the document's internalfiltersare the same array reference, the splice strips"FlateEncode"from the document-wide configuration.Fix
One-line change: copy the array before mutating.
putImagestill gets its local "filters minus FlateEncode" list, and the document'sfiltersarray is unaffected.Test
Added a regression test in
test/specs/addimage.spec.jsthat asserts repeateddoc.output()calls return identical buffers. All 541 unit tests pass locally.Notes
dist/per the CONTRIBUTING guideline.canvas-editor-pdf. Happy to add more context if useful.