850 Commits

Author SHA1 Message Date
Jonas Jenwald
8142937ac4
Merge pull request #20961 from calixteman/use_image_decoder_chrome
[api-minor] Use the ImageDecoder by default on Chrome
2026-05-01 13:09:43 +02:00
Jonas Jenwald
270b68feb9 [api-major] Update the minimum supported browsers, and remove no longer needed polyfills
By removing support for older browsers it's possible to simplify both the code and the build-scripts, in addition to removing manually implemented polyfills.
Using the PDF.js library/viewer will now require native support for the following features:
 - The `AbortSignal.any()` static method, see https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal/any_static#browser_compatibility
 - The `:dir()` CSS pseudo-class, see https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Selectors/:dir#browser_compatibility
 - The `light-dark()` CSS function, see https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Values/color_value/light-dark#browser_compatibility
 - The CSS `&` nesting selector, see https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Selectors/Nesting_selector#browser_compatibility

This patch updates the minimum supported browsers as follows:
 - Google Chrome 125, which was released on 2024-05-15; see https://chromereleases.googleblog.com/2024/05/stable-channel-update-for-desktop_15.html
 - Safari 18, which was released on 2024-09-16; see https://developer.apple.com/documentation/safari-release-notes/safari-18-release-notes
   *Note:* This version is the first with experimental support for the `CanvasRenderingContext2D.filter` property, which is a long-standing missing feature in Safari, however it must be *manually enabled*; see https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/filter#browser_compatibility

Note that nowadays we usually try, where feasible and possible, to support browsers that are about two years old. By limiting support to only "recent" browsers we reduce the risk of holding back improvements of the *built-in* Firefox PDF Viewer, and also (significantly) reduce the maintenance/support burden for the PDF.js contributors.

*Please note:* As always, the minimum supported browser version assumes that a `legacy`-build of the PDF.js library is being used; see https://github.com/mozilla/pdf.js/wiki/Frequently-Asked-Questions#faq-support
2026-04-30 20:32:08 +02:00
Calixte Denizet
cffb19e266 Send 'Terminate' to the worker when destroy races the load-time handshake (bug 1942304)
If `PDFDocumentLoadingTask.destroy` ran while `workerIdPromise` was
pending, the inner `.then` in `getDocument` threw "Loading aborted"
before `WorkerTransport` was constructed, so `_transport` was never set
and the "Terminate" message was never posted.
2026-04-27 17:14:45 +02:00
Calixte Denizet
64b25a8f47
Fix merging a PDF after a page deletion (bug 2034804)
When pages carry explicit pageIndices (e.g. after a delete),
resolve insertAfter against that layout instead of the empty
base sequence. Also reject partial pageIndices combined with
insertAfter, which would race against the extraction's auto-fill.
2026-04-26 22:37:22 +02:00
Jonas Jenwald
b01eeaf8e1 Improve the "CopyLocalImage" unit-tests
Rather than relying on the time it takes to parse/render the pages, which leads to intermittent failures, add a test-only property and use it to check if the "CopyLocalImage" code-path was exercised.
2026-04-21 11:43:08 +02:00
Mario
9dd30474c2 Fix saveDocument JSDoc return type
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 14:51:39 +02:00
calixteman
a9f142c796
Unconditionally create a gpu device
One drawback of the current implementation is that the GPU device can be
unavailable at the time of the first pattern fill, which causes the
GPU-accelerated canvas to be move on the main thread because of putImageData.

Most of the shading patterns stuff will be moved to the GPU and in order
to avoid creating some useless data we've to know if the GPU is available or not.

So in this patch we create the GPU device during the worker initialization
and pass a flag to the evaluator to know if the GPU is available or not.
2026-04-06 13:23:29 +02:00
Jonas Jenwald
f6bac014ea [api-minor] Remove PostScriptCompiler and PostScriptEvaluator, since it's now dead code (PR 21023 follow-up)
These classes, and various related code, became unused after PR 21023 with only unit-tests actually running that code now.

Also removes the `isEvalSupported` API option, since the `PostScriptCompiler` was the only remaining code where `eval` was used.
2026-04-03 22:14:14 +02:00
Tim van der Meij
255c3e7c14
Merge pull request #21028 from Snuffleupagus/PDFDataRangeTransport-listener
[api-minor] Change `PDFDataRangeTransport` to use a single (internal)  listener
2026-04-03 19:53:39 +02:00
Tim van der Meij
bb1033053c
Merge pull request #21029 from Snuffleupagus/Object-hasOwn
Replace all `Object.prototype.hasOwnProperty` usage with `Object.hasOwn`
2026-04-03 19:51:09 +02:00
Jonas Jenwald
cbfe2abc53 Replace all Object.prototype.hasOwnProperty usage with Object.hasOwn
The newer `Object.hasOwn` method is intended as a replacement for `Object.prototype.hasOwnProperty`, since that one may be problematical; please see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/hasOwn#problematic_cases_for_hasownproperty

To ensure that `Object.hasOwn` is used in the future, the ESLint "no-restricted-syntax" rule is extended to catch the old method.
2026-04-02 13:40:10 +02:00
Jonas Jenwald
f3a2ca08d0 [api-minor] Change PDFDataRangeTransport to use a single (internal) listener
The `PDFDataTransportStream` constructor has always registered exactly one listener for each type of data that an `PDFDataRangeTransport` instance can receive.
Given that an end-user of the `PDFDataRangeTransport` class will supply data through its `onData...` methods, it's also somewhat difficult to understand why additional end-user registered listeners would be needed (since the data is already, by definition, available to the user).
Furthermore, since TypedArray data is being transferred nowadays it's not even clear that multiple listeners (of the same kind) would generally work.

All in all, let's simplify this old code a little bit by using *a single* (internal) listener in the `PDFDataRangeTransport` class.
2026-04-02 12:38:58 +02:00
Jonas Jenwald
68366e31e4 Move the MathClamp helper function to its own file
This allows using it in the `src/scripting_api/` folder, without increasing the size of the scripting-bundle by also importing a bunch of unused code.
2026-04-02 11:22:28 +02:00
Jonas Jenwald
777251da85
Merge pull request #20968 from Snuffleupagus/getNetworkStream
Move the `NetworkStream` choice from `src/display/api.js` and into a separate file
2026-03-25 08:33:08 +01:00
Jonas Jenwald
a0102abe76 Move the NetworkStream choice from src/display/api.js and into a separate file
This code already isn't used (or even bundled) in the Firefox PDF Viewer, and it also slightly reduces the number of import maps that need to be maintained.
2026-03-24 17:08:04 +01:00
Calixte Denizet
f578c7e299 Use the ImageDecoder by default on Chrome
The two mentioned bugs have been fixed a while back. So it should be fine to use this feature now.
2026-03-23 18:02:12 +01:00
Jonas Jenwald
ca8f8074a2 Remove the deprecated PDFWorker.fromPort method (PR 19943 follow-up)
This has been deprecated in ten releases, so let's just remove it now.
2026-03-23 17:24:54 +01:00
Jonas Jenwald
3a372fde94 [api-minor] Replace the CMapReaderFactory, StandardFontDataFactory, and WasmFactory API options with a single factory/option
Currently we have no less than three different, but very similar, factories for reading built-in CMap files, standard font files, and wasm files on the main-thread.[1]
These factories were added at different points in time, since I cannot imagine that we'd add essentially three copies of the same code otherwise.

Nowadays these factories are often not even used[2], since worker-thread fetching is used whenever possible to improve performance. In particular, they will *only* be used when either:
 - The PDF.js library runs in Node.js environments.
 - The user manually sets `useWorkerFetch = false` when calling `getDocument`.
 - The user provides custom `CMapReaderFactory`, `StandardFontDataFactory`, and/or `WasmFactory` instances when calling `getDocument`.

By replacing these factories with *a single* new `BinaryDataFactory` factory/option the number of `getDocument` options are thus reduced, which cannot hurt.
This also reduces the total bundle-size of the Firefox PDF Viewer a little bit, and it slightly reduces the number of import maps that need to be maintained.

*Please note:* For users that provide custom `CMapReaderFactory`, `StandardFontDataFactory`, and `WasmFactory` instances when calling `getDocument` this will be a breaking change, however it's unlikely that (many) such users exist.
(The *internal* format data-format of `CMapReaderFactory` was changed in PR 18951, and there hasn't been a single question/complaint about it in well over a year.)

---

[1] Any new functionality could easily lead to more such factories being added in the future, which wouldn't be great.

[2] Note that the Firefox PDF Viewer no longer use these factories, since it "forcibly" sets `useWorkerFetch = true` during building.
2026-03-22 15:49:06 +01:00
Jonas Jenwald
262aeef3fa [api-minor] Simplify BaseCMapReaderFactory by having the worker-thread create the filename
The `BaseCMapReaderFactory`, `BaseStandardFontDataFactory`, and `BaseWasmFactory` classes are all very similar, and the only difference is really in their respective `fetch` methods.
By have the worker-thread "compute" the complete `filename` it's possible to simplify the `BaseCMapReaderFactory.prototype.fetch` method, which will allow future improvements to all of these classes.

A couple of things to note:
 - This code is unused, and it's not even bundled, in the Firefox PDF Viewer.
 - In browsers it's unused by default, and worker-thread fetching will always be used when possible since that's more efficient.

*Please note:* For users that provide a custom `CMapReaderFactory` instance when calling `getDocument` this could be a breaking change, however it's unlikely that any such users exist.
(The *internal* format of this data was changed previously in PR 18951, and there hasn't been a single question/complaint about it in well over a year.)
2026-03-21 15:54:40 +01:00
calixteman
86441e9eb8
Implement Gouraud-based shading using WebGPU.
The WebGPU feature hasn't been released yet but it's interesting to see how
we can use it in order to speed up the rendering of some objects.
This patch allows to render mesh patterns using WebGPU.

I didn't see any significant performance improvement on my machine (mac M2)
but it may be different on other platforms.
2026-03-21 14:34:32 +01:00
calixteman
dabb2b960d
Merge pull request #20927 from Snuffleupagus/Firefox-enforce-worker-binary-fetch
[Firefox] Ensure that worker-thread fetching is used for built-in CMap, standard font, and wasm data
2026-03-20 17:45:43 +01:00
Jonas Jenwald
652822bef0 [Firefox] Ensure that worker-thread fetching is used for built-in CMap, standard font, and wasm data
Given that we "forcibly" set `useWorkerFetch = true` for the MOZCENTRAL build-target there's a small amount of dead code as a result, which we can thus remove during building.
2026-03-20 16:58:57 +01:00
Calixte Denizet
04272de41d
Add the possibility to save added annotations when reorganizing a pdf (bug 2023086) 2026-03-20 10:55:47 +01:00
calixteman
e65d643af5
Merge pull request #20907 from calixteman/fix_bad_bugs
Fix various bug around copy/paste/delete/undo (bug 2022586, bug 2022824, bug 2022884, bug 2023171, bug 2023176)
2026-03-18 21:38:15 +01:00
Jonas Jenwald
8f8bd6a0bc
Merge pull request #20909 from Snuffleupagus/getDocument-check-data
Ensure that `getDocument` is called with one of the `data`, `range`, or `url` parameters provided
2026-03-18 18:29:56 +01:00
Calixte Denizet
75cb69eef2
Fix various bug around copy/paste/delete/undo (bug 2022586, bug 2022824, bug 2022884, bug 2023171, bug 2023176)
Those bugs are more or less related so it's why they're all fixed together in the same patch.
2026-03-18 13:57:20 +01:00
Jonas Jenwald
bdc16f8999
Merge pull request #20868 from Snuffleupagus/exportData-compileFontInfo
Move the `compileFontInfo` call into the `Font.prototype.exportData` method (PR 20197 follow-up)
2026-03-18 11:14:46 +01:00
Jonas Jenwald
1cd7e481ce Ensure that getDocument is called with one of the data, range, or url parameters provided
Providing one of these parameters is necessary when calling `getDocument`, since otherwise there's nothing to actually load. However, we currently don't enforce that properly and if there's more than one of these parameters provided the behaviour isn't well defined.[1]

The new behaviour is thus, in order:
 1. Use the `data` parameter, since the PDF is already available and no additional loading is necessary.
 2. Use the `range` parameter, for custom PDF loading (e.g. the Firefox PDF Viewer).
 3. Use the `url` parameter, and have the PDF.js library load the PDF with a suitable `networkStream`.
 4. Throw an error, since there's no way to load the PDF.

---

[1] E.g. if both `data` and `range` is provided, we'd load the document directly (since it's available) and also initialize a pointless `PDFDataTransportStream` instance.
2026-03-18 11:09:46 +01:00
calixteman
b7d71eb7f8 Don't throw when printing with pdfBug enabled
It fixes #20847.
2026-03-17 10:54:32 +01:00
Jonas Jenwald
7d963ddc7c Move the compileFontInfo call into the Font.prototype.exportData method (PR 20197 follow-up)
After the changes in PR 20197 the code in the `TranslatedFont.prototype.send` method is not all that readable[1] given how it handles e.g. the `charProcOperatorList` data used with Type3 fonts.
Since this is the only spot where `Font.prototype.exportData` is used, it seems much simpler to move the `compileFontInfo` call there and *directly* return the intended data rather than messing with it after the fact.

Finally, while it doesn't really matter, the patch flips the order of the `charProcOperatorList` and `extra` properties throughout the code-base since the former is used with Type3 fonts while the latter (effectively) requires that debugging is enabled.

---

[1] I had to re-read it twice, also looking at all the involved methods, in order to convince myself that it's actually correct.
2026-03-16 09:29:17 +01:00
Tim van der Meij
315491dd32
Merge pull request #20840 from Snuffleupagus/getDocument-rm-length
[api-minor] Remove the `length` parameter from `getDocument`
2026-03-15 11:48:02 +01:00
Jonas Jenwald
09a9a7bd0b [api-minor] Remove the length parameter from getDocument
This is an old API-parameter that is now unused within the PDF.js project itself, and its description says that it's (partly) being used for "range requests operations".
Note that the `length` API-parameter is used to set the *initial* `contentLength` in various `BasePDFStreamReader` implementations, however it's always overridden by the "Content-Length" header (sent by the server) when that one exists *and* is a valid number. While we currently fallback to the keep the initial `contentLength` otherwise, note however how in that case range requests will always be *disabled* and thus the only spot in the code-base [where `fullReader.contentLength` is necessary](873378b718/src/core/worker.js (L230-L236)) cannot actually be reached.

Hence the only possible reason to use the `length` API-parameter would be for improved progress reporting[1] during streaming of PDF data in rare cases where the "Content-Length" header is missing/invalid, but the user *somehow* has information from another source about the correct `length` of the PDF document.
That situation feels very much like an edge-case, but it's obviously impossible to know if someone is depending on it. However, please note that there's a work-around available for users affected by this removal:
 - Implement a `PDFDataRangeTransport` instance together with custom data-fetching[2], since in that case its `length`-parameter will always be used as-is.

Finally, updates various `BasePDFStreamReader` implementations to only set the `_isRangeSupported` field once the headers are available (since previously we'd just overwrite the "initial" value anyway).

---

[1] I.e. to avoid the "indeterminate" loadingBar being displayed in the viewer.

[2] This is what e.g. the Firefox PDF Viewer uses.
2026-03-13 23:42:45 +01:00
Jonas Jenwald
3842936edf Split the src/shared/obj-bin-transform.js file into separate files for the main/worker threads (PR 20197 follow-up)
On the worker-thread only the static `write` methods are actually used, and on the main-thread only class instances are being created.
Hence this, after PR 20197, leads to a bunch of dead code in both of the *built* `pdf.mjs` and `pdf.worker.js` files.

This patch reduces the size of the `gulp mozcentral` output by `21 419` bytes, i.e. `21` kilo-bytes, which I believe is way too large of a saving to not do this.
(I can't even remember the last time we managed to reduce build-size this much with a single patch.)
2026-03-13 11:21:24 +01:00
Tim van der Meij
decbce7b9b
Merge pull request #20856 from Snuffleupagus/fix-font-clearData
Fix the `FontInfo.prototype.clearData` method to actually remove the data as intended (PR 20197 follow-up)
2026-03-12 20:39:02 +01:00
Jonas Jenwald
e88a5652de Fix the FontInfo.prototype.clearData method to actually remove the data as intended (PR 20197 follow-up)
The purpose of PR 11844 was to reduce memory usage once fonts have been attached to the DOM, since the font-data can be quite large in many cases.

Unfortunately the new `clearData` method added in PR 20197 doesn't actually remove *anything*, it just replaces the font-data with zeros which doesn't help when the underlying `ArrayBuffer` itself isn't modified.
The method does include a commented-out `resize` call[1], but uncommenting that just breaks rendering completely.

To address this regression, without having to make large or possibly complex changes, this patch simply changes the `clearData` method to replace the internal buffer/view with its contents *before* the font-data.
While this does lead to a data copy, the size of this data is usually orders of magnitude smaller than the font-data that we're removing.

---

[1] Slightly off-topic, but I don't think that patches should include commented-out code since there's a very real risk that those things never get found/fixed.
At the very least such cases should be clearly marked with `// TODO: ...` comments, and should possibly also have an issue filed about fixing the TODO.
2026-03-12 18:15:42 +01:00
Jonas Jenwald
9aa1ce8f14 Move the PagesMapper class into its own file
The `PagesMapper` class currently makes up one third of the `src/display/display_utils.js` file size, and since its introduction it's grown (a fair bit) in size.
Note that the intention with files such as `src/display/display_utils.js` was to have somewhere to place functionality too small/simple to deserve its own file.
2026-03-11 12:28:13 +01:00
calixteman
9d093d9607
Merge pull request #20626 from nicolo-ribaudo/images-right-click
Add support for right-clicking on images (bug 1012805)
2026-03-11 11:45:51 +01:00
Tim van der Meij
44a63549b0
Merge pull request #20831 from calixteman/internal_viewer
Add a new internal viewer to explore the structure of PDF files.
2026-03-10 20:48:40 +01:00
Jonas Jenwald
5ef582fb20 Use optional chaining a little bit more in the src/display/api.js file
That format is preferred where possible, since it leads to ever so slightly shorter code overall.
2026-03-10 15:51:05 +01:00
Nicolò Ribaudo
4f7a025e21
Separate bbox tracking from dependencies tracking
When recording bboxes for images, it's enough to record their
clip box / bounding box without needing to run the full bbox
tracking of the image's dependencies.
2026-03-10 14:51:03 +01:00
Nicolò Ribaudo
886c90d1a5
Add support for right-clicking on images
This patch adds right-click support for images in the PDF, allowing
users to download them. To minimize memory consumption, we:
- Do not store the images separately, and instead crop them out of the
  PDF page canvas
- Only extract the images when needed (i.e. when the user right-clicks
  on them), rather than eagery having all of them available.

To do so, we layer one empty 0x0 canvas per image, stretched to cover
the whole image, and only populate its contents on right click.
These images need to be inside the text layer: they cannot be _behind_
it, otherwise they would be covered by the text layer's container and
not be clickable, and they cannot be in front of it, otherwise they
would make the text spans unselectable.

This feature is managed by a new preference, `imagesRightClickMinSize`:
- when it's set to `-1`, right-click support is disabled
- when set to `0`, all images are available for right click
- when set to a positive integer, only images whose width and height are
  greater than or equal to that value (in the PDF page frame of
  reference) are available for right click.

This features is disabled by default outside of MOZCENTRAL, as it
significantly degrades the text selection experience in non-Firefox
browsers.
2026-03-10 14:51:03 +01:00
calixteman
9d81fafa8c
Add a new internal viewer to explore the structure of PDF files.
The one from pdf.js.utils is a bit too old: a lot of bugs have been fixed
in the code that parses PDF files since then.
It's just an internal development tool, so it doesn't need to be perfect,
but it should be good enough to be useful.
2026-03-09 14:16:12 +01:00
Calixte Denizet
0e48c16c3c
Add a UI to undo cut/delete and cancel a copy (bug 2021352, bug 2010832)
This happens in a bar on top of the thumbnails sidebar.
The label depending on the selected thumbnails is fixed.
2026-03-09 10:44:11 +01:00
Jonas Jenwald
1f69cf964c Ensure that percent === NaN is consistently reported by the onProgress callback
With these changes `0`, `NaN`, `null`, and `undefined` in the `total`-property all result in `percent === NaN` being reported by the callback, since previously e.g. `0` would result in `percent === 100` being reported unconditionally which doesn't make a lot of sense.

Also, remove the "indeterminate" loadingBar (in the viewer) if the `PDFDocumentLoadingTask` fails since there won't be any more data arriving and displaying the animation thus seems wrong.
2026-03-08 10:21:55 +01:00
Jonas Jenwald
82fc2c94f0 Include transfers correctly in the "GetOperatorList" message (PR 16588 follow-up)
Currently the transfers aren't actually being used with the "GetOperatorList" message, since the placement of the parameter is wrong; note the method signature: 909a700afa/src/shared/message_handler.js (L219-L229)
This goes back to PR 16588, which added the transfers parameter, and unfortunately we all missed that :-(

Simply fixing the parameter isn't enough however, since that broke printing of Stamp-editors (and possibly others). The solution here is to *not* transfer data during printing, given that a single `PrintAnnotationStorage` instance is being used for all pages.
2026-02-25 15:55:43 +01:00
Jonas Jenwald
2e07715c9d Reduce function creation when using Map.prototype.getOrInsertComputed()
With the exception of the first invocation the callback function is unused, which means that a lot of pointless functions may be created.
To avoid this we introduce helper functions for simple cases, such as creating `Map`s and `Objects`s.
2026-02-24 08:58:28 +01:00
Jonas Jenwald
e2c8fc6140 Use Map.prototype.getOrInsertComputed() in the src/display/api.js file 2026-02-22 21:01:13 +01:00
Calixte Denizet
d755fba96a
Add support for deleting, cutting, copying and pasting pages (bug 2010830, 2010831) 2026-02-18 16:43:00 +01:00
Jonas Jenwald
c1b824f2e5 Convert PDFPageProxy.prototype.getTextContent to an asynchronous method
This is a tiny bit shorter, which cannot hurt.
2026-02-11 19:14:10 +01:00
calixteman
4b4ab10c54
Set a pages mapper per loaded document
It fixes #20629.
2026-02-08 21:09:27 +01:00