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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
The delay between chunks when testing streaming is necessary to avoid the entire PDF document arriving all at once, since that would render those unit-tests somewhat pointless.
However, the delay is unnecessarily large which causes these unit-tests to be slower than necessary.
Also, update the range unit-tests to check the expected number of fetches *exactly* since those values are not supposed to vary.
Prepare reusable soft-mask canvases for filtered and backdrop-dependent masks,
and use a faster destination-in composition path where possible.
Handle Alpha SMask /BC correctly, preserve OOB alpha behavior, and mirror canvas path
operations needed while rendering inside soft-mask mode (mirrored clip was buggy).
Add reftest PDFs covering Alpha masks, transfer functions, backdrop/OOB
alpha, and the optimized composition paths.
The find controller tests consistently show up in the list of slowest
tests reported by Jasmine. Profiling shows that most of the time is
spent waiting for the find results to arrive, even though the find
command itself is quite fast.
It turns out that the slowdown occurs between receiving the `find` event
and actually triggering the search. The find controller has a hardcoded
delay of 250 milliseconds built in, which was introduced for viewer
performance many years ago because otherwise every keystroke would
trigger a search even though the user's query was not complete yet.
For the unit tests we don't need this delay because, contrary to the
viewer use case, we don't have to account for user interaction and
instead dispatch complete `find` events on the event bus ourselves.
However, since the unit tests were introduced well over a year after
the delay was introduced, due to an oversight it was never made
configurable so we could skip it for the unit tests.
This commit fixes the issue, which locally results in the runtime of
`npx gulp unittest --noChrome` dropping from 39.991 seconds before this
patch to 29.116 seconds afterwards, which is a 27% speedup.
In a previous commit the time-based checks, which were based on
statistics provided by the `pdfBug: true` flag, got replaced by
test-only property checks that don't use said statistics anymore.
Fixes b01eeaf8.
This commit fixes a number of missing cleanup steps in the unit tests
that kept state alive for longer than necessary:
- the loading tasks were not all being destroyed;
- the find controllers were not being reset;
- the state set in `beforeAll`/`beforeEach` was not all being nulled in
the correspoding `afterAll`/`afterEach` blocks.
Combined this resulted in a steady increase in memory usage of the test
process as the tests ran, climbing up to ~1.5 GB. After this patch the
memory usage remains stable at ~800 MB.
The thumbnails are only available if the first page is ready, and not
awaiting that causes the drag-and-drop action to be performed using
incorrect thumbnail viewer state (see the analysis in #21184 for more
details).
Fixes#21184.
Supersedes #20902.
Unblocks #21173.
The `textLayerImagePlaceholder` canvas added in #20626 covers scanned
pages and was not recognized as a valid pointerdown target by
`#textLayerPointerDown`, so free highlights couldn't start.
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.