Skip to content

Comments

fix(api): resolve indirect refs in resource subdictionaries#32

Merged
Mythie merged 1 commit intomainfrom
fix/indirect-resource-subdict-resolution
Feb 20, 2026
Merged

fix(api): resolve indirect refs in resource subdictionaries#32
Mythie merged 1 commit intomainfrom
fix/indirect-resource-subdict-resolution

Conversation

@Mythie
Copy link
Contributor

@Mythie Mythie commented Feb 20, 2026

addXObjectResource and registerResource called resources.get()
without a resolver, so when a resource subdictionary (e.g. /XObject)
was stored as an indirect PdfRef, it failed the instanceof PdfDict
check and silently replaced the existing dict with an empty one.

This dropped all pre-existing resource entries. Scanner-produced PDFs
(e.g. Konica Minolta) commonly store /Resources /XObject as an
indirect object, so embedPage + drawPage on those PDFs would erase
the original page content entirely.

addFontResource already passed the resolver correctly; this aligns
the other two methods to match.

addXObjectResource and registerResource called resources.get()
without a resolver, so when a resource subdictionary (e.g. /XObject)
was stored as an indirect PdfRef, it failed the instanceof PdfDict
check and silently replaced the existing dict with an empty one.

This dropped all pre-existing resource entries. Scanner-produced PDFs
(e.g. Konica Minolta) commonly store /Resources /XObject as an
indirect object, so embedPage + drawPage on those PDFs would erase
the original page content entirely.

addFontResource already passed the resolver correctly; this aligns
the other two methods to match.
@vercel
Copy link
Contributor

vercel bot commented Feb 20, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
core Ready Ready Preview, Comment Feb 20, 2026 11:54am

@github-actions
Copy link
Contributor

Benchmark Results

Comparison

Load PDF

Benchmark Mean p99 RME Samples
libpdf 2.29ms 3.33ms ±1.2% 219
pdf-lib 39.13ms 44.53ms ±3.9% 13

Create blank PDF

Benchmark Mean p99 RME Samples
libpdf 56μs 109μs ±1.4% 8960
pdf-lib 408μs 1.28ms ±2.2% 1225

Add 10 pages

Benchmark Mean p99 RME Samples
libpdf 98μs 196μs ±1.0% 5090
pdf-lib 499μs 1.70ms ±2.4% 1002

Draw 50 rectangles

Benchmark Mean p99 RME Samples
libpdf 332μs 899μs ±1.7% 1507
pdf-lib 1.68ms 6.20ms ±6.4% 298

Load and save PDF

Benchmark Mean p99 RME Samples
libpdf 2.34ms 3.02ms ±1.3% 215
pdf-lib 87.41ms 97.13ms ±4.8% 10

Load, modify, and save PDF

Benchmark Mean p99 RME Samples
libpdf 54.83ms 62.04ms ±5.9% 10
pdf-lib 89.25ms 96.98ms ±4.7% 10

Extract single page from 100-page PDF

Benchmark Mean p99 RME Samples
libpdf 3.94ms 6.33ms ±2.1% 127
pdf-lib 9.48ms 12.27ms ±2.9% 53

Split 100-page PDF into single-page PDFs

Benchmark Mean p99 RME Samples
libpdf 34.60ms 40.08ms ±2.8% 15
pdf-lib 89.61ms 104.95ms ±9.3% 6

Split 2000-page PDF into single-page PDFs (0.9MB)

Benchmark Mean p99 RME Samples
libpdf 633.47ms 633.47ms ±0.0% 1
pdf-lib 1.63s 1.63s ±0.0% 1

Copy 10 pages between documents

Benchmark Mean p99 RME Samples
libpdf 4.75ms 5.53ms ±1.1% 106
pdf-lib 11.80ms 13.65ms ±1.4% 43

Merge 2 x 100-page PDFs

Benchmark Mean p99 RME Samples
libpdf 15.22ms 21.95ms ±3.0% 33
pdf-lib 53.37ms 54.15ms ±0.7% 10
Copying

Copy pages between documents

Benchmark Mean p99 RME Samples
copy 1 page 1.07ms 2.35ms ±3.3% 466
copy 10 pages from 100-page PDF 4.80ms 6.88ms ±2.0% 105
copy all 100 pages 7.85ms 8.50ms ±0.7% 64

Duplicate pages within same document

Benchmark Mean p99 RME Samples
duplicate page 0 940μs 1.69ms ±1.1% 532
duplicate all pages (double the document) 936μs 1.71ms ±1.2% 535

Merge PDFs

Benchmark Mean p99 RME Samples
merge 2 small PDFs 1.53ms 2.31ms ±1.1% 326
merge 10 small PDFs 8.04ms 9.50ms ±1.2% 63
merge 2 x 100-page PDFs 14.72ms 15.22ms ±0.6% 34
Drawing

benchmarks/drawing.bench.ts

Benchmark Mean p99 RME Samples
draw 100 rectangles 541μs 1.10ms ±1.5% 925
draw 100 circles 1.30ms 2.78ms ±2.7% 386
draw 100 lines 497μs 1.08ms ±1.4% 1007
draw 100 text lines (standard font) 1.59ms 2.35ms ±1.3% 315
create 10 pages with mixed content 1.36ms 2.35ms ±1.7% 368
Forms

benchmarks/forms.bench.ts

Benchmark Mean p99 RME Samples
get form fields 3.59ms 6.52ms ±3.8% 140
fill text fields 11.64ms 16.17ms ±3.8% 43
read field values 3.20ms 5.76ms ±1.8% 157
flatten form 8.80ms 13.34ms ±2.5% 57
Loading

benchmarks/loading.bench.ts

Benchmark Mean p99 RME Samples
load small PDF (888B) 67μs 163μs ±0.8% 7505
load medium PDF (19KB) 100μs 209μs ±0.7% 4985
load form PDF (116KB) 1.42ms 2.58ms ±1.8% 352
load heavy PDF (9.9MB) 2.40ms 2.92ms ±0.9% 209
Saving

benchmarks/saving.bench.ts

Benchmark Mean p99 RME Samples
save unmodified (19KB) 116μs 267μs ±0.9% 4322
save with modifications (19KB) 781μs 1.44ms ±1.0% 640
incremental save (19KB) 183μs 375μs ±1.0% 2732
save heavy PDF (9.9MB) 2.49ms 2.99ms ±1.2% 201
incremental save heavy PDF (9.9MB) 5.74ms 10.11ms ±1.8% 88
Splitting

Extract single page

Benchmark Mean p99 RME Samples
extractPages (1 page from small PDF) 1.05ms 2.45ms ±3.0% 475
extractPages (1 page from 100-page PDF) 3.74ms 6.82ms ±2.1% 134
extractPages (1 page from 2000-page PDF) 58.78ms 60.48ms ±1.3% 10

Split into single-page PDFs

Benchmark Mean p99 RME Samples
split 100-page PDF (0.1MB) 32.71ms 37.10ms ±3.6% 16
split 2000-page PDF (0.9MB) 589.48ms 589.48ms ±0.0% 1

Batch page extraction

Benchmark Mean p99 RME Samples
extract first 10 pages from 2000-page PDF 60.24ms 61.36ms ±1.1% 9
extract first 100 pages from 2000-page PDF 63.86ms 64.69ms ±0.7% 8
extract every 10th page from 2000-page PDF (200 pages) 69.33ms 81.63ms ±6.3% 8
Environment
  • Runner: Linux (X64)
  • Runtime: Bun 1.3.9

Results are machine-dependent.

@Mythie Mythie merged commit 04644ee into main Feb 20, 2026
6 checks passed
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