Merge pull request #19710 from Snuffleupagus/Math-sumPrecise

Introduce `Math.sumPrecise` usage in the code-base
This commit is contained in:
Jonas Jenwald 2025-03-23 13:34:28 +01:00 committed by GitHub
commit c7c08bbd07
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 40 additions and 35 deletions

View File

@ -2572,11 +2572,7 @@ class WidgetAnnotation extends Annotation {
} }
_getTextWidth(text, font) { _getTextWidth(text, font) {
return ( return Math.sumPrecise(font.charsToGlyphs(text).map(g => g.width)) / 1000;
font
.charsToGlyphs(text)
.reduce((width, glyph) => width + glyph.width, 0) / 1000
);
} }
_computeFontSize(height, width, text, font, lineCount) { _computeFontSize(height, width, text, font, lineCount) {

View File

@ -720,7 +720,7 @@ class PDF20 extends PDFBase {
// The number is e0 + 256 * e1 + 256^2 * e2... and 256 % 3 === 1, hence // The number is e0 + 256 * e1 + 256^2 * e2... and 256 % 3 === 1, hence
// the powers of 256 are === 1 modulo 3 and finally the number modulo 3 // the powers of 256 are === 1 modulo 3 and finally the number modulo 3
// is equal to the remainder modulo 3 of the sum of the e_n. // is equal to the remainder modulo 3 of the sum of the e_n.
const remainder = e.slice(0, 16).reduce((a, b) => a + b, 0) % 3; const remainder = Math.sumPrecise(e.slice(0, 16)) % 3;
if (remainder === 0) { if (remainder === 0) {
k = calculateSHA256(e, 0, e.length); k = calculateSHA256(e, 0, e.length);
} else if (remainder === 1) { } else if (remainder === 1) {

View File

@ -81,11 +81,10 @@ class GlyfTable {
} }
getSize() { getSize() {
return this.glyphs.reduce((a, g) => { return Math.sumPrecise(
const size = g.getSize();
// Round to next multiple of 4 if needed. // Round to next multiple of 4 if needed.
return a + ((size + 3) & ~3); this.glyphs.map(g => (g.getSize() + 3) & ~3)
}, 0); );
} }
write() { write() {
@ -169,7 +168,7 @@ class Glyph {
} }
const size = this.simple const size = this.simple
? this.simple.getSize() ? this.simple.getSize()
: this.composites.reduce((a, c) => a + c.getSize(), 0); : Math.sumPrecise(this.composites.map(c => c.getSize()));
return this.header.getSize() + size; return this.header.getSize() + size;
} }

View File

@ -184,7 +184,7 @@ function computeMD5(filesize, xrefInfo) {
filesize.toString(), filesize.toString(),
...Object.values(xrefInfo.info), ...Object.values(xrefInfo.info),
]; ];
const md5BufferLen = md5Buffer.reduce((a, str) => a + str.length, 0); const md5BufferLen = Math.sumPrecise(md5Buffer.map(str => str.length));
const array = new Uint8Array(md5BufferLen); const array = new Uint8Array(md5BufferLen);
let offset = 0; let offset = 0;
@ -352,7 +352,7 @@ async function getXRefStreamTable(
newXref.set("W", sizes); newXref.set("W", sizes);
computeIDs(baseOffset, xrefInfo, newXref); computeIDs(baseOffset, xrefInfo, newXref);
const structSize = sizes.reduce((a, x) => a + x, 0); const structSize = Math.sumPrecise(sizes);
const data = new Uint8Array(structSize * xrefTableData.length); const data = new Uint8Array(structSize * xrefTableData.length);
const stream = new Stream(data); const stream = new Stream(data);
stream.dict = newXref; stream.dict = newXref;
@ -467,10 +467,8 @@ async function incrementalUpdate({
? getXRefStreamTable(xrefInfo, baseOffset, newRefs, newXref, buffer) ? getXRefStreamTable(xrefInfo, baseOffset, newRefs, newXref, buffer)
: getXRefTable(xrefInfo, baseOffset, newRefs, newXref, buffer)); : getXRefTable(xrefInfo, baseOffset, newRefs, newXref, buffer));
const totalLength = buffer.reduce( const totalLength =
(a, str) => a + str.length, originalData.length + Math.sumPrecise(buffer.map(str => str.length));
originalData.length
);
const array = new Uint8Array(totalLength); const array = new Uint8Array(totalLength);
// Original data // Original data

View File

@ -86,14 +86,15 @@ const converters = {
const colSpan = node.colSpan; const colSpan = node.colSpan;
let w; let w;
if (colSpan === -1) { if (colSpan === -1) {
w = extra.columnWidths w = Math.sumPrecise(extra.columnWidths.slice(extra.currentColumn));
.slice(extra.currentColumn)
.reduce((a, x) => a + x, 0);
extra.currentColumn = 0; extra.currentColumn = 0;
} else { } else {
w = extra.columnWidths w = Math.sumPrecise(
.slice(extra.currentColumn, extra.currentColumn + colSpan) extra.columnWidths.slice(
.reduce((a, x) => a + x, 0); extra.currentColumn,
extra.currentColumn + colSpan
)
);
extra.currentColumn = extra.currentColumn =
(extra.currentColumn + node.colSpan) % extra.columnWidths.length; (extra.currentColumn + node.colSpan) % extra.columnWidths.length;
} }
@ -328,13 +329,14 @@ function fixDimensions(node) {
const colSpan = node.colSpan; const colSpan = node.colSpan;
let width; let width;
if (colSpan === -1) { if (colSpan === -1) {
width = extra.columnWidths width = Math.sumPrecise(extra.columnWidths.slice(extra.currentColumn));
.slice(extra.currentColumn)
.reduce((a, w) => a + w, 0);
} else { } else {
width = extra.columnWidths width = Math.sumPrecise(
.slice(extra.currentColumn, extra.currentColumn + colSpan) extra.columnWidths.slice(
.reduce((a, w) => a + w, 0); extra.currentColumn,
extra.currentColumn + colSpan
)
);
} }
if (!isNaN(width)) { if (!isNaN(width)) {
node.w = width; node.w = width;
@ -348,7 +350,7 @@ function fixDimensions(node) {
if (node.layout === "table") { if (node.layout === "table") {
if (node.w === "" && Array.isArray(node.columnWidths)) { if (node.w === "" && Array.isArray(node.columnWidths)) {
node.w = node.columnWidths.reduce((a, x) => a + x, 0); node.w = Math.sumPrecise(node.columnWidths);
} }
} }
} }

View File

@ -183,9 +183,9 @@ function getAvailableSpace(node) {
}; };
case "rl-row": case "rl-row":
case "row": case "row":
const width = node[$extra].columnWidths const width = Math.sumPrecise(
.slice(node[$extra].currentColumn) node[$extra].columnWidths.slice(node[$extra].currentColumn)
.reduce((a, x) => a + x); );
return { width, height: availableSpace.height - marginH }; return { width, height: availableSpace.height - marginH };
case "table": case "table":
case "tb": case "tb":

View File

@ -718,7 +718,7 @@ class FreeTextEditor extends AnnotationEditor {
// Set the caret at the right position. // Set the caret at the right position.
const newRange = new Range(); const newRange = new Range();
let beforeLength = bufferBefore.reduce((acc, line) => acc + line.length, 0); let beforeLength = Math.sumPrecise(bufferBefore.map(line => line.length));
for (const { firstChild } of this.editorDiv.childNodes) { for (const { firstChild } of this.editorDiv.childNodes) {
// Each child is either a div with a text node or a br element. // Each child is either a div with a text node or a br element.
if (firstChild.nodeType === Node.TEXT_NODE) { if (firstChild.nodeType === Node.TEXT_NODE) {

View File

@ -1130,6 +1130,16 @@ if (
}; };
} }
// TODO: Remove this once the `javascript.options.experimental.math_sumprecise`
// preference is removed from Firefox.
if (typeof Math.sumPrecise !== "function") {
// Note that this isn't a "proper" polyfill, but since we're only using it to
// replace `Array.prototype.reduce()` invocations it should be fine.
Math.sumPrecise = function (numbers) {
return numbers.reduce((a, b) => a + b, 0);
};
}
if ( if (
typeof PDFJSDev !== "undefined" && typeof PDFJSDev !== "undefined" &&
!PDFJSDev.test("SKIP_BABEL") && !PDFJSDev.test("SKIP_BABEL") &&

View File

@ -128,7 +128,7 @@ function testSearch({
} }
} }
const totalMatches = matchesPerPage.reduce((a, b) => a + b); const totalMatches = Math.sumPrecise(matchesPerPage);
if (updateFindControlState) { if (updateFindControlState) {
eventBus.on( eventBus.on(