Skip to content

Dm/drop node dependencies#3397

Draft
diegomura wants to merge 4 commits into
masterfrom
dm/drop-node-dependencies
Draft

Dm/drop node dependencies#3397
diegomura wants to merge 4 commits into
masterfrom
dm/drop-node-dependencies

Conversation

@diegomura
Copy link
Copy Markdown
Owner

@diegomura diegomura commented Apr 18, 2026

Upstream pdfkit PR plan

Incremental, backwards-compatible PRs to propose to
foliojs/pdfkit. Each PR stands alone
and delivers value independently — none touch the public class hierarchy
(PDFDocument extends stream.Readable, PDFReference extends stream.Writable).

Scoped out (stays in fork)

  • Replacing stream.Readable/stream.Writable with a local shim — changes
    public class hierarchy and breaks ref.write(chunk, encoding, cb) callers.
  • Converting ref._write(chunk, encoding, cb)ref.write(chunk) — same reason.

PR 1 — Refactor JPEG/EXIF parser to work on raw bytes

Value: EXIF parser currently uses Buffer.readUInt16BE/LE,
subarray().toString('binary'|'ascii'). Abstracting to byte-level helpers
makes the parser work on any Uint8Array, with clearer intent and no
intermediate string allocations.

Adds: src/binary.js with readUInt16BE/LE, readUInt32BE/LE,
toBinaryString — each helper justified by this PR's use sites.

Changes: image/jpeg.js

Risk: zero — byte-identical output.

PR 2 — Drop Buffer.alloc/Buffer.from in png.js internals

Value: new Uint8Array(n) matches what's being built (raw byte
allocations). zlib.deflateSync accepts Uint8Array in modern Node. Smaller
surface area.

Changes: image/png.js

Risk: zero — Node Buffer is a Uint8Array subclass.

PR 3 — Use byte-level PNG magic check in image.js

Value: Replaces data.toString('ascii', 1, 4) === 'PNG' with four byte
comparisons — avoids a string allocation per image open. Adds fromBase64
to binary.js for the data-URI path (justified by use).

Changes: image.js; extends binary.js with fromBase64.

Risk: zero.

PR 4 — Remove redundant Buffer.from() wrappers in security.js

Value: @noble/ciphers, js-md5, and rc4 already return Uint8Array.
Buffer.from(uint8array) is a zero-copy view that adds nothing. Drops
~a dozen wrappers; smaller and faster.

Changes: security.js

Risk: low — encDict.O/U/OE/UE/Perms values now stored as Uint8Array.
They flow into PDFObject.convert which handles Uint8Array via the
Buffer.isBuffer check — needs verification on upstream. Add an
instanceof Uint8Array co-equal test (purely additive) if needed.

PR 5 — Simplify PDF hex/binary serialization with byte helpers

Value: object.js has scattered Buffer.from(str, 'ascii'),
Buffer.from(utf16str, 'utf16le') + swapBytes, and .toString('hex') calls.
Replacing them with named helpers (fromBinaryString, fromUtf16BEWithBOM,
toHex) removes the swapBytes helper entirely and is more
self-documenting.

Adds: fromBinaryString, fromUtf16BEWithBOM, toHex, fromUtf8String
to binary.js.

Changes: object.js

Risk: low — output byte-identical; needs test coverage for the UTF-16BE
path.

PR 6 — Replace events import in line_wrapper.js with inline emitter

Value: LineWrapper only uses on/once/emit internally. A ~20-line
inline emitter drops one Node-stdlib import and makes the event surface
explicit in the file rather than inherited.

Changes: line_wrapper.js

Risk: low — public on/once/emit API preserved.

PR 7 — Swap zlib for pako

Value: Pure JS, identical output, eliminates Node's zlib from the
browser bundle (no polyfill needed). Single dep swap.

Changes: image/png.js, reference.js (streaming deflate → one-shot at
finalize; simpler), package.json.

Risk: medium — reference.js's streaming pipeline becomes buffered. For
very large streams, peak memory differs. Benchmark in the PR.

diegomura and others added 4 commits April 18, 2026 14:10
Introduce src/binary.js with Uint8Array-native helpers and port the
mechanical callers (object, document._write, png, attachments, metadata,
security) off Node's Buffer. image.js/jpeg.js/reference.js still use
Buffer and will be migrated in a follow-up pass.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
… reference

Convert image.js, image/jpeg.js, and reference.js to use binary.js helpers
instead of Node Buffer methods. Removes another chunk of Buffer dependency
on the path to a Node-free pdfkit core.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Replace Node's zlib with pako in png.js and reference.js. Reference.js
now accumulates raw chunks and deflates once at finalize, dropping the
streaming zlib.Deflate pipeline. line_wrapper.js gains a tiny inline
emitter so it no longer imports Node's 'events' module while keeping
its on/once/emit public API intact.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
PDFDocument now extends a local MiniReadable class that implements only
what the renderer relies on (on/once/emit/push/pipe). PDFReference no
longer extends stream.Writable — write/end are direct methods. Drops
the vite-compatible-readable-stream dep and its rollup alias.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented Apr 18, 2026

⚠️ No Changeset found

Latest commit: b032e53

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

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.

1 participant