Skip to content

fix(platform): shim the Map method pdfjs needs on Node - #3170

Merged
Israeltheminer merged 1 commit into
mainfrom
fix/3018-pdfjs-map-shim
Sep 3, 2026
Merged

fix(platform): shim the Map method pdfjs needs on Node#3170
Israeltheminer merged 1 commit into
mainfrom
fix/3018-pdfjs-map-shim

Conversation

@Israeltheminer

Copy link
Copy Markdown
Collaborator

Scanned PDFs index thin or empty because image detection never runs.

Closes #3018. Supersedes #3103, whose two files #3125 deleted.

Why

pdfjs 5.x calls Map.prototype.getOrInsertComputed on its own Maps in both the main and worker builds. Node 22 does not ship it:

$ node -e 'console.log(typeof Map.prototype.getOrInsertComputed)'
undefined

So the operator-list read throws once per page — and that read is the path that finds embedded images and decides a page is scanned and needs OCR. Text extraction uses a different call and still runs, which is why the damage hides: an ordinary digital PDF indexes fine and only produces log noise, while a scanned one indexes with almost nothing and a warning nobody reads.

What changed

The shim goes in ensureEs2025Shims, beside the Promise.try and base64-codec fills that already exist for the same reason and use the same typeof guard plus defineProperty idiom. lib.esnext declares the method, so no local type declaration is needed — the same reason the neighbouring fills need none.

Spec shape: return the existing value when the key is present, otherwise compute, insert, and return. Presence rather than truthiness, so a callback returning undefined still counts and a second call does not recompute. set runs after the callback, as the proposal does, because the callback may have inserted the key itself and the computed value wins.

Also corrects the module docstring, which still described the Convex node action runtime that no longer exists.

Tests

Five assertions on the shim: it installs, it computes-and-inserts, it does not call the callback when the key is present (pdfjs depends on that — the callback builds an intent state, and calling it twice would discard the one in flight), it stores an undefined result, and it refuses a non-callable callback.

Mutation: with the shim deleted, 4 of the 7 assertions in the file go red.

Worth stating because it nearly made the test worthless — Bun ships this method natively and Node does not. The suite runs under Node, which is also the shipping runtime, so the test exercises the real gap. Had it run under Bun it would have passed against the native implementation and proven nothing.

Gate: typecheck, oxlint --type-aware, oxfmt --check, lint:sast green; branched from origin/main at 5f9dc6eb2.

Scanned PDFs index thin or empty because image detection never runs.

pdfjs 5.x calls Map.prototype.getOrInsertComputed on its own Maps in both
the main and worker builds. Node 22 does not ship it, so the operator-list
read throws once per page — and that read is what finds embedded images and
decides a page is scanned and needs OCR. Text extraction still runs, so a
digital PDF looks fine while a scanned one indexes with almost nothing and
only a warning to say so.

The shim goes in ensureEs2025Shims beside the Promise.try and base64
codec fills, which already use the same typeof guard and defineProperty
idiom for the same reason: lib.esnext declares the method, so no local type
declaration is needed, and a real runtime implementation wins the guard.

Also corrects the module docstring, which still described the Convex node
action runtime that no longer exists.

Closes #3018. Supersedes #3103, whose files #3125 deleted.
@Israeltheminer
Israeltheminer merged commit e616480 into main Sep 3, 2026
48 checks passed
@Israeltheminer
Israeltheminer deleted the fix/3018-pdfjs-map-shim branch September 3, 2026 11:21
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.

Bug: pdf.js operator-list read fails on every page it indexes

1 participant