Compared to regular Objects there's a number of advantages to using Maps:
- They support proper iteration.
- They have a simple way to check for the existence of data.
- They have a simple/efficient way to check the number of elements.
If this functionality was added today, I cannot imagine that we'd choose an Object for this data.
In the Firefox PDF Viewer sending Maps to the scripting-implementation should be fine, since it uses the browser `Cu.cloneInto` functionality; see https://searchfox.org/firefox-main/source/toolkit/components/pdfjs/content/PdfSandbox.sys.mjs
However with QuickJS, used by the GENERIC viewer, all data needs to be stringified and Maps are converted into regular Objects (see also PR 21664). Hence the `objects` property, in the scripting-implementation, is converted back into a Map using the (renamed) `createMap` helper function.
In PR 12569 the `_actions` class-field was changed from an Object into a Map, with *most* of the code updated to reflect that.
However, in the `setAction` method it's still treated as an Object which means that any added script will simply be ignored. Most likely that part of the scripting-implementation isn't being used, since this code has been "wrong" for close to six years now.
Scanning to the end of the string for every "&" made the entity
resolution quadratic. Stopping at the next "&" also fixes a bare
ampersand swallowing the reference which follows it.
Finding the word to delete with a regex is quadratic in the value
length, so each "delete word backward" keystroke could take a long
time in a large field.
Searching for a name followed by ".pdf" is quadratic on a hash which
doesn't contain one, so locate the last ".pdf" first and then extend
it to the left.
Removing the trailing whitespace with a `$`-anchored regex is
quadratic in the length of the run, which a server controls.
The helper lives in network_utils.js, to be unit testable.
`String.fromCodePoint` throws on anything which isn't a code point,
so e.g. "&#xZZ;" or "�" aborted the whole parsing. Such a
reference is now kept as-is, like an unknown named entity.
During two-finger gestures, keep preventing the default action on pointerup/pointercancel, but don't stop propagation. Resize/drag sessions need those bubble events to clean up.
`TouchManager` computes the pinch distances with the screen coordinates, but it
was passing the pinch center in that space too, while the viewer expects a
client coordinate, like the origin coming from a wheel event.
Since a two-finger gesture can be synthesized with WebDriver BiDi, the
pinch-zoom test doesn't have to rely on CDP anymore and can run in Chrome, where
it fails without the above fix.
In a couple of cases, where a boolean is returned, it's also possible to use an OR operator rather a ternary.
*Note:* This patch reduces the size of the `gulp mozcentral` bundle by `960` bytes.
The chrome is now authored against Firefox design-token names with the shipped
value as a fallback `var(--fx-token, <literal>)` so colors, borders and radii
follow Firefox instead of having to be re-synced by hand.
In MOZCENTRAL viewer.css imports chrome://global/skin/design-system/tokens-brand.css,
gated on the new pdfjs.enableNova pref (default false, read straight from CSS via -moz-pref()).
With the pref off the sheet isn't applied, every fallback resolves, and the
viewer renders as before, as it also does in the GENERIC and components builds,
which never see the chrome sheet.
Consuming a token means never declaring its name in an unlayered rule, which
would shadow Firefox's for the whole subtree; --focus-outline, --border-color and
--text-color/--button-border-color are therefore renamed to
--editor-selection-outline, --signature-border-color and --views-*. In forced
colors each state reads a matching background/foreground/border triple so it
can't collapse to a single system color.
The dialog button styling also moves out of `.dialog .mainContainer button` into
a shared .primaryButton/.secondaryButton primitive (buttons.css, imported from
pdf_viewer.css so the components build gets it too). The password,
document-properties, print and undo-bar buttons use it in place of .dialogButton,
and the custom radio appearance gives way to native controls tinted with
accent-color.
The draw layer keeps a reference on the text layer div in order to render the
selection, but it was destroyed only along with the annotation editor layer.
Hence, when the editor is disabled, like in Firefox for Android, scrolling far
enough to destroy a page view left the draw layer with a reference on a removed
text layer: the new one was never registered, consequently no selection was
rendered anymore on that page.
Compared to regular Objects there's a number of advantages to using Maps:
- They support proper iteration.
- They have a simple way to check for the existence of data.
- They have a simple/efficient way to check the number of elements.
If this functionality was added today, I cannot imagine that we'd choose an Object for this data.
Note also how in the scripting-implementation the `actions` were already converted into a Map, via the `createActionsMap` helper.
In the Firefox PDF Viewer sending `Map`s to the scripting-implementation should be fine, since it uses the browser `Cu.cloneInto` functionality; see https://searchfox.org/firefox-main/source/toolkit/components/pdfjs/content/PdfSandbox.sys.mjs
However with QuickJS, used by the GENERIC viewer, all data needs to be stringified and unfortunately `JSON.stringify()` doesn't support Maps. Hence we convert Maps to Objects, via a [`replacer` function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify#replacer), since the existing `createActionsMap` usage will convert the actions-Objects back to Maps.
`AnnotationEditor.remove()` destroys the editor's `TouchManager`, but `remove()`
is also the undo half of an edit: deleting a drawing and undoing it, or undoing
the drawing itself and redoing it, brings the very same editor back.