Note that PR 21247 did include "local" unit-tests, however they don't cover all of the relevant API/Worker code-paths (which is noticeable in the coverage data).
The new unit-test added here uses a PDF document already present in the test-suite, and generally speaking testing a real-world PDF shouldn't hurt.
Note that the `prettier` update introduces a handful of formatting
changes (see https://prettier.io/blog/2026/06/27/3.9.0).
Moreover, the `tsc-alias` update requires explicitly defining the root
URL in the compiler options now, otherwise it errors with `tsc-alias
error: compilerOptions.rootDir is required with implicit baseUrl` (see
https://github.com/justkey007/tsc-alias/pull/259/changes).
This has a couple of advantages:
- It allows accessing and iterating `this.#results` directly, without having to (needlessly) create a temporary array.
- By moving the "worst status" computation into its own getter, it can be re-used from the `#updateButtonState` method as well which reduces code duplication.
The warn and error state badges shipped as byte-identical files (an
X-in-circle glyph). Drop the redundant
toolbarButton-signaturePropertiesWarn.svg and point the warn state at
the error icon instead; the amber-vs-red distinction is preserved via
background-color (--sig-icon-warn vs --sig-icon-error), not the glyph.
Currently the GeckoView development viewer, i.e. http://localhost:8888/web/viewer-geckoview.html, is completely broken with the following error:
```
Uncaught TypeError: The specifier “web-digital_signature_properties_manager” was a bare specifier, but was not remapped to anything. Relative module specifiers must start with “./”, “../” or “/”. app.js:97:44
```
encodeToXmlString skips surrogate pairs with the guard
`char > 0xd7ff && (char < 0xe000 || char > 0xfffd)` and then does `i++` to step
over the low surrogate. That predicate is also true for U+FFFE and U+FFFF, which
are single UTF-16 code units, not surrogate pairs. The `i++` then skips the
character that follows them, so it is silently dropped.
For example, encodeToXmlString of U+FFFF followed by "A" returned ""
instead of "A". The function serializes XML text nodes and attribute
values in xml_parser.js and xfa_object.js, so this corrupts round-tripped XML
and XFA content.
The correct test for a surrogate pair is `char > 0xffff`, since codePointAt
returns a value at or above 0x10000 only for a real pair. This preserves the
existing behavior for emoji, the U+FFFD boundary, and lone surrogates, and stops
dropping the character after U+FFFE and U+FFFF.
The font size (Tf) and the text matrix (Tm) can appear in any order in an
appearance stream. Applying the scale factor eagerly in setFont missed the
case where Tf precedes Tm (e.g. Skia-generated FreeText), yielding a wrong
guessed font size.
- Replace the `loadFromDocument` and `reset` methods with a single `setDocument` method, since that's consistent with many other viewer components.
- Replace the internal `#loadToken` field with simple `pdfDocument` checks, when checking if the document is still current, which again is consistent with (all) other viewer components.
- Remove a couple of comments, which didn't add a lot of value and sounded a whole lot like "AI speak".
escapePDFName emitted a single hex digit for character codes below 0x10
(TAB became #9, not #09). PDF 32000-1 7.3.5 requires exactly two hex digits
after #. On re-save (annotations, form fields, font names) such a Name is
written malformed and the lexer mis-parses it on reload, dropping bytes.
Pad the hex to two digits; a no-op for codes 0x10 to 0xFF.
Chromium 148+ improved their selection behavior when it comes to absolutely
positioned elements, thus making text selectino in PDF.js much better.
Unfortunately this does not only mean that the workaround we currently have
for Chromium is unnecessary, but it actually become harmful. It conflicts
with Chromium's new behavior, making text selection *worse* on mobile.
As the change has been released in Chrome only a month ago, this patch keeps
the workaround for older Chromium versions. There is no easy way to
feture-detect is, so unfortunately we need to do user agent version detection.