4645 Commits

Author SHA1 Message Date
Tim van der Meij
42db304268
Merge pull request #21305 from Snuffleupagus/integration-test-EventBus-on
Don't use "internal" `EventBus` methods in the integration-tests
2026-05-21 20:17:28 +02:00
Calixte Denizet
0f90987927 Fix 'Select all' after #20981 2026-05-21 16:39:34 +02:00
Jonas Jenwald
abe8b564a3 Don't use "internal" EventBus methods in the integration-tests
This way *guarantees* that any and all internal viewer state has been updated first, before any test-specific code runs.
2026-05-20 16:39:21 +02:00
calixteman
5a4d93a238
Merge pull request #20981 from wooorm/wooorm/hcm
Make text selection more visible (bug 1879559)
2026-05-20 15:49:01 +02:00
Titus Wormer
957e004e38
Make text selection more visible (bug 1879559)
References <https://bugzilla.mozilla.org/show_bug.cgi?id=1879559>
(“In HCM, the text selection is barely visible”).

Continues work from @calixteman who had a partial patch.

This PR improves viewer text-selection highlighting by rendering
selection shapes in the draw layer.

* add selection overlay rendering in the draw layer
  * significant code relates to selections spanning multiple text
    layers/pages, and edges/end-of-content boundaries
* clear selection on rotate/scale/scroll/spread changes

My main question is: how should it appear?
I don’t have access to the Figma file linked on bugzilla.

In the CSS (`draw_layer-builder.css`) there are 3 blocks:

* default
* `@supports` for browsers supporting `backdrop-filter`
* `forced-colors` mode

So it’s possible to design for those (or more).
Personally, the `backdrop-filter: invert(1)` is the most contrast,
so perhaps it’s better to use something else as the default,
and to use `invert(1)` if high contrast mode is used (maybe with a
`prefers-contrast` media query instead)?
2026-05-19 21:10:12 +02:00
Tim van der Meij
60591388a8
Disable hardware acceleration for Chrome tests
This commit fixes the rendering issue that makes the "must update an
existing annotation" ink editor integration test permafail locally in
Chrome. Note that we already do this for Firefox tests, so this also
improves consistency between the two browsers.

Moreover, improve how we define Chrome options to (similar to their
Firefox counterparts) provide them in a single array, and document the
reasoning for why these options are being set more explicitly.

Fixes #21272.
2026-05-19 21:07:26 +02:00
Tim van der Meij
0d69cc4dcf
Introduce integration tests for the presentation mode functionality
This commit provides coverage for the happy flows of basic operations
like entering/exiting and changing pages.
2026-05-18 20:52:00 +02:00
Tim van der Meij
00af75905f
Merge pull request #21295 from Snuffleupagus/PDFDocumentProperties-more-tests
Add more integration-tests, with multi-page documents, for the `PDFDocumentProperties` dialog
2026-05-18 20:24:41 +02:00
calixteman
abb8e31408
Merge pull request #21261 from calixteman/bug1960363
Add a Content-Security-Policy to pdf.js' viewer.html (bug 1960363)
2026-05-18 18:24:38 +02:00
Jonas Jenwald
1e62f01773 Improve handling of corrupt pages in the PDFDocumentProperties dialog
If the active page is corrupt that currently results in the entire dialog being "blank", thus providing no information, which seems unfortunate and it's easy enough to only skip `pageSizeField` in that rare case.
2026-05-18 17:38:43 +02:00
Jonas Jenwald
e05b6d6f59 Add more integration-tests, with multi-page documents, for the PDFDocumentProperties dialog
Improve test coverage for multi-page documents, to ensure that:
 - Unnecessary re-parsing is avoided where possible.
 - Rotation, in the viewer, is handled correctly.
 - Different page sizes are handled correctly.
2026-05-18 14:24:05 +02:00
Jonas Jenwald
1e9e8fad7e Add helper functions for opening/closing the document properties dialog during testing
This reduces duplication in the various integration-tests.
2026-05-18 13:31:26 +02:00
calixteman
deb532334f
Merge pull request #21290 from calixteman/issue20633
Recover CFF private dict defaults zeroed by Ghostscript
2026-05-17 21:57:16 +02:00
calixteman
cd8a78c4e2
Recover CFF private dict defaults zeroed by Ghostscript
It fixes the issue #20633.
2026-05-17 20:51:35 +02:00
Tim van der Meij
2fb2bc13e0
Merge pull request #21275 from timvandermeij/integration-tests-optimize
Optimize runtime and memory usage of the integration tests
2026-05-17 20:41:43 +02:00
Tim van der Meij
f2bf57f444
Merge pull request #21288 from timvandermeij/unskip-test
Enable the `must check that an existing highlight is ignored on hovering` integration test on Windows
2026-05-17 20:19:42 +02:00
Jonas Jenwald
2cef900834 Add an integration-test for documents without contentLength available in the PDFDocumentProperties dialog 2026-05-17 16:55:48 +02:00
Tim van der Meij
af65d7f930
Enable the must check that an existing highlight is ignored on hovering integration test on Windows
It looks like this test passes consistently again, most likely after a
combination of browser/Puppeteer/configuration updates and the completed
switch to the WebDriver BiDi protocol.

Fixes #20136.
2026-05-17 14:47:14 +02:00
Jonas Jenwald
afa9b6ef9b Add an integration-test for the page-name fuzzy matching in the PDFDocumentProperties dialog
Also, test that closing the dialog works correctly.
2026-05-17 14:40:09 +02:00
Tim van der Meij
600a4bb1ee
Fix missing page closing for two viewer integration tests
This caused the tab to remain open after the tests ran, which meant
that a total of ~120 MB of memory was not being freed.
2026-05-16 19:30:42 +02:00
Tim van der Meij
c66f9f2497
Reduce the protocol delay for Chrome in the integration tests
Originally we introduced a small delay for Puppeteer operations in
Chrome to avoid intermittent failures where protocol calls were
happening too quickly in succession. However, since then a number of
improvements were made, both locally and upstream, that reduce the need
for this delay:

- the integration tests have been hardened to remove (potential) sources
  of intermittent failures in many places;
- the browsers and Puppeteer have been updated to improve performance
  and support for testing infrastructure;
- the conversion to WebDriver BiDi has been completed, which replaced
  the Chrome-specific CDP protocol with a formalized protocol that could
  provide more safety guarantees.

This commit therefore reduces the Chrome-specific delay from 5 to 3
milliseconds, which should nowadays be a better value to speed up the
Chrome tests and bring them closer to Firefox in terms of runtime.
2026-05-16 19:30:42 +02:00
Tim van der Meij
62b88aa56e
Use Puppeteer's ElementHandle.boundingBox() API in the integration tests
The custom solution for obtaining the bounding box of a given element
that we have now was necessary during the original introduction of the
integration tests because at the time the `ElementHandle.boundingBox()`
API in Puppeteer didn't work correctly in Chrome.

However, `getRect`, where this is used, is a hot utility function
because most tests call it multiple times, either directly or indirectly
via other utility functions, and it turns out that the approach we use
is slower than the native `ElementHandle.boundingBox()` API.

Fortunately, most likely after a combination of Chrome/Puppeteer updates
and the conversion to the formalized WebDriver BiDi protocol the custom
solution is no longer necessary because all tests pass without it too,
so this commit converts `getRect` to use `ElementHandle.boundingBox()`
instead to speed up the tests.
2026-05-16 19:30:34 +02:00
Jonas Jenwald
7f2bb0e991 Add a couple of very basic ColorConverters unit-tests
These tests could obviously be improved/extended, but it's at least a start to ensure that `ColorConverters` is tested since it's used in both the annotation-layer and the scripting-implementation.
2026-05-16 17:17:41 +02:00
Jonas Jenwald
e8f07d7ca3 [api-minor] Move the getXfaPageViewport helper into the XfaLayer class
This small helper function only exists to support printing of XFA documents, in the viewer, hence it seems like a good idea to (ever so slightly) reduce the official API surface a little bit.
2026-05-16 12:31:53 +02:00
Jonas Jenwald
eda97fe8fc Move the PageViewport class into its own file
This is necessary to prevent import cycles with the next patch.

It also shouldn't hurt to reduce the size of `src/display/display_utils.js` a little bit, since utility-files have a tendency to increase in size over time.
2026-05-16 12:31:40 +02:00
Jonas Jenwald
e5330f06fa Move the stringToPDFString helper function into the src/core/string_utils.js file
Given that this function is only ever used during *parsing* of the PDF document, which happens in the worker-thread, this has always added (a little bit of) dead code in the built `pdf.mjs` file.
2026-05-15 12:10:30 +02:00
Jonas Jenwald
153cef615e Move a couple of src/core/ string helper functions into their own file
Given that the various utility-files naturally increase in size over time, it shouldn't hurt to shorten `src/core/core_utils.js` a little bit by moving a few of its string helper functions to their own file.
2026-05-15 11:49:54 +02:00
Tim van der Meij
b708f59d04
Merge pull request #21271 from Snuffleupagus/unittest-BrotliDecode
Add a simple API unit-test for /BrotliDecode
2026-05-14 16:05:34 +02:00
Jonas Jenwald
949497a3c4 Add a simple API unit-test for /BrotliDecode
This is a new feature in PDF documents, hence it shouldn't hurt to complement the existing ref-test with a simple unit-test as well.
This should also improve test coverage for the `external/` folder, which can't hurt since the other external decoders are already fairly well covered.
2026-05-14 15:44:42 +02:00
Tim van der Meij
7ade637449
Merge pull request #21268 from calixteman/lint_chmod
Add a lint-chmod task to catch stray executable bits
2026-05-14 15:16:08 +02:00
Calixte Denizet
f8f497a03a
Add a lint-chmod task to catch stray executable bits 2026-05-14 13:55:14 +02:00
Calixte Denizet
94de952b65
Add a Content-Security-Policy to pdf.js' viewer.html (bug 1960363) 2026-05-14 12:50:07 +02:00
Tim van der Meij
26dc195a65
Collect coverage information for the integration tests
Note that for the integration tests the coverage information ends up
being processed in the Node.js context where `window` is not available,
so we use `globalThis` instead for the function that merges individual
test's coverage information into the global object because that is
available in all contexts we support. For clarity we also rename said
function since we're not exclusively dealing with `window` nor worker
data anymore.
2026-05-14 12:34:12 +02:00
calixteman
bf9ae7622f
Merge pull request #21267 from timvandermeij/test-pdf-executable-bit
Remove the executable bit from test PDF files
2026-05-13 09:29:02 +02:00
calixteman
7f151c777b
Merge pull request #21262 from calixteman/issue18032
Fix nested non-isolated groups in knockout rendering
2026-05-12 22:37:31 +02:00
Calixte Denizet
0e335d53ee Fix nested non-isolated groups in knockout rendering
It fixes #18032.

Only use the special inner-backdrop compositing path for nested non-isolated groups that actually need isolation.
This preserves the parent/page backdrop for simple nested groups inside knockout groups, preventing later group
compositing from erasing existing backdrop content.
2026-05-12 22:00:44 +02:00
Tim van der Meij
41e47c8b6f
Remove the executable bit from test PDF files
Test PDF files should never be executable because we only read their
contents, so this commit makes sure that all test PDFs have the same
permissions, namely 0644 (read-only for all groups, and writable for the
owner), to limit their permissions for a least-privilege approach.
2026-05-12 20:59:07 +02:00
Tim van der Meij
a5027bf5e2
Merge pull request #21256 from timvandermeij/updates
Update dependencies to the most recent versions
2026-05-12 20:27:16 +02:00
calixteman
0c66063cd4
Merge pull request #21242 from calixteman/knockout
Render knockout transparency groups
2026-05-12 12:02:10 +02:00
Jonas Jenwald
5bc5791a86
Merge pull request #21257 from Snuffleupagus/deepCompare-Refs
Update the `deepCompare` helper function to handle `Ref`s and `Name`s correctly
2026-05-12 11:53:02 +02:00
calixteman
d1e9194e1f
Render knockout transparency groups
In a knockout (KO) group each painting operator ("element") composites against
the group's initial backdrop instead of accumulating onto prior elements
of the same group. The backend renders each element to a per-group pooled
temp canvas (keyed off `#groupStackMeta`), builds a binary alpha mask via
a new `feFuncA` filter (`addKnockoutFilter`), `destination-out`s the
group canvas through that mask, restores the initial backdrop into the
cleared footprint for non-isolated groups (cropped to the same mask so
sparse groups don't bleed the whole rectangle), and finally paints the
element on top with the parent's blend mode. Path / clip / transform ops
are mirrored back to the group canvas via `mirrorContextOperations` so
graphics state stays in sync between elements; only the raster pixels
land on the temp canvas.

The temp canvas is forced to source-over for the element raster (`multiply`
on a transparent backdrop would zero the color) and the original GCO is
restored before `copyCtxState` writes back, so the parent's blend mode
survives for the final composite.

Also handled:
  - Nested KO groups (the level is incremented for KO, reset to 0 for
    non-KO subgroups so an ancestor KO doesn't leak in).
  - Non-isolated non-KO subgroups inside a KO parent (`hasInnerBackdrop`
    path: blend the elements against the subgroup's running backdrop for
    color, mask with the elements-only canvas).
  - Soft masks installed inside a KO element (`applySMaskInPlace` in
    `compose`, which runs the SMask destination-in directly on the temp
    canvas; the existing blit-to-suspended step is gated by `if (!ctx)`).
  - Type-3 text, shading fills, image-mask groups, inline images and the
    solid-color mask path: each is wrapped in `#begin/#endKnockoutElement`.
  - `endDrawing` cleanup so cancelled rendering doesn't leak pooled
    canvases or stale knockout state.
2026-05-11 23:08:06 +02:00
Tim van der Meij
4da7a9aa29
Upgrade typescript to version 6.0.3
This is a major version bump containing two breaking changes for us:

- the `baseUrl` option is removed;
- the `moduleResolution` option doesn't support `node10` (or the `node`
  alias) anymore.

The migration guide at https://github.com/microsoft/TypeScript/issues/62508
indicates that we can remove `baseUrl` and change `moduleResolution` to
`bundler` (the latter is consistent with what other projects do that are
linked to the issue, and more details on that configuration option can
be found at https://www.typescriptlang.org/tsconfig/#moduleResolution).

Note that this is enough to get `npx gulp typestest` green and that is
all validation we can do on our side, so as usual if any follow-up fixes
for types are necessary we rely on the community to provide patches and
extend the types test where possible to improve validation.
2026-05-11 21:05:11 +02:00
Jonas Jenwald
aecb571ea6 Move the getModificationDate helper function into src/core/core_utils.js
Given that this function is only ever used in `src/core/` code, let's avoid a little bit of dead code in the *built* `pdf.mjs` file.

Also, place the `AnnotationPrefix` and `AnnotationEditorPrefix` constants together in `src/shared/util.js` since that should aid readability.
2026-05-11 14:13:23 +02:00
Jonas Jenwald
326df1f711 Update the deepCompare helper function to handle Refs and Names correctly
Note that `Ref`s and `Name`s are cached globally[1], since that helps reduce object creation (a lot) during parsing.
That cache will be cleared after a period of inactivity in the viewer[2], which is why those primitives cannot *safely* be compared with just `===`/`!==` and also (partially) why abstractions such as `RefSet`/`RefSetCache` are necessary.

Currently `deepCompare` doesn't handle `Ref`s and `Name`s correctly, which may lead to future *intermittent* bugs in any code using the `deepCompare` helper function.

---

[1] This applies to `Cmd` as well, however that doesn't matter in the context of this patch.

[2] Currently, and for more than a decade, set to 30 seconds.
2026-05-11 13:18:54 +02:00
Tim van der Meij
702d60aa18
Merge pull request #21230 from calixteman/avoid_cycles
Avoid cycles when getting operator list in patterns
2026-05-10 18:15:01 +02:00
Tim van der Meij
02c9051b64
Merge pull request #21245 from Snuffleupagus/getDocument-only-DocumentInitParameters
[api-major] Remove support for calling `getDocument` without  a parameter object, and remove the `PDFDocumentProxy.prototype.destroy` method
2026-05-10 14:30:15 +02:00
Tim van der Meij
47e32709b3
Merge pull request #21246 from Snuffleupagus/crypto_spec-fromHex
Use `Uint8Array.fromHex` in `test/unit/crypto_spec.js`
2026-05-10 14:12:33 +02:00
Jonas Jenwald
eb184851a8 Use Uint8Array.fromHex in test/unit/crypto_spec.js
This replaces the old `hex2binary` helper function with the native `Uint8Array.fromHex` method.
2026-05-09 17:17:50 +02:00
Jonas Jenwald
43ce1bb491 [api-major] Remove the PDFDocumentProxy.prototype.destroy method
This is a left-over from very old code, which pre-dates the introduction of the `PDFDocumentLoadingTask` and it's nothing more than an alias for its `destroy` method.
Given that `PDFDocumentProxy` already provides a way to access the underlying `PDFDocumentLoadingTask` instance, it shouldn't be necessary to have an alias for one of its methods.

*Please note:* For any existing code relying on the removed method, updating it should be as simple as replacing `pdfDocument.destroy()` with `pdfDocument.loadingTask.destroy()`.

---

[1] If the `PDFDocumentProxy` class was added today, there's no chance that it'd include a `destroy` method.
2026-05-09 13:20:39 +02:00
Jonas Jenwald
2e7a2215e3 [api-major] Remove support for calling getDocument without a parameter object
This is a left-over from very old code[1], before there were a lot of `getDocument` options and when most of the library configuration was done via the (since removed) `PDFJS` global.
Given all the functionality added through the years, which require configuration[2], in practice it's now unlikely that calling `getDocument` without additional options will work except for the most trivial PDFs.

---

[1] If the `getDocument` function was added today, there's no chance that it'd support anything other than a parameter object.

[2] Note things such as CMaps, standard fonts, wasm-based image decoders, and ICC-based colour spaces.
2026-05-09 13:00:27 +02:00