tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

commit 0b21972a78f8915f73ce5579eeee2aa8c9c7d67e
parent b4524db074672784ca5cc6e73a2e9a56db138a15
Author: Updatebot <updatebot@mozilla.com>
Date:   Thu, 30 Oct 2025 12:17:24 +0000

Bug 1997227 - Update PDF.js to 7fc5706e16ad76e04b66257882764caa2c9db7bd r=pdfjs-reviewers,calixte

Differential Revision: https://phabricator.services.mozilla.com/D270630

Diffstat:
Mtoolkit/components/pdfjs/content/build/pdf.mjs | 13++++++++-----
Mtoolkit/components/pdfjs/content/build/pdf.scripting.mjs | 4++--
Mtoolkit/components/pdfjs/content/build/pdf.worker.mjs | 79+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----
Mtoolkit/components/pdfjs/content/web/viewer-geckoview.mjs | 42++++++++++++++++++++++++++++++++++++++----
Mtoolkit/components/pdfjs/content/web/viewer.mjs | 42++++++++++++++++++++++++++++++++++++++----
Mtoolkit/components/pdfjs/moz.yaml | 4++--
6 files changed, 163 insertions(+), 21 deletions(-)

diff --git a/toolkit/components/pdfjs/content/build/pdf.mjs b/toolkit/components/pdfjs/content/build/pdf.mjs @@ -21,8 +21,8 @@ */ /** - * pdfjsVersion = 5.4.370 - * pdfjsBuild = f6317ddbb + * pdfjsVersion = 5.4.385 + * pdfjsBuild = 7fc5706e1 */ /******/ // The require scope /******/ var __webpack_require__ = {}; @@ -524,6 +524,9 @@ class util_FeatureTest { static get isFloat16ArraySupported() { return shadow(this, "isFloat16ArraySupported", typeof Float16Array !== "undefined"); } + static get isSanitizerSupported() { + return shadow(this, "isSanitizerSupported", typeof Sanitizer !== "undefined"); + } static get platform() { const { platform, @@ -13032,7 +13035,7 @@ function getDocument(src = {}) { } const docParams = { docId, - apiVersion: "5.4.370", + apiVersion: "5.4.385", data, password, disableAutoFetch, @@ -14612,8 +14615,8 @@ class InternalRenderTask { } } } -const version = "5.4.370"; -const build = "f6317ddbb"; +const version = "5.4.385"; +const build = "7fc5706e1"; ;// ./src/display/editor/color_picker.js diff --git a/toolkit/components/pdfjs/content/build/pdf.scripting.mjs b/toolkit/components/pdfjs/content/build/pdf.scripting.mjs @@ -21,8 +21,8 @@ */ /** - * pdfjsVersion = 5.4.370 - * pdfjsBuild = f6317ddbb + * pdfjsVersion = 5.4.385 + * pdfjsBuild = 7fc5706e1 */ var __webpack_exports__ = {}; diff --git a/toolkit/components/pdfjs/content/build/pdf.worker.mjs b/toolkit/components/pdfjs/content/build/pdf.worker.mjs @@ -21,8 +21,8 @@ */ /** - * pdfjsVersion = 5.4.370 - * pdfjsBuild = f6317ddbb + * pdfjsVersion = 5.4.385 + * pdfjsBuild = 7fc5706e1 */ /******/ // The require scope /******/ var __webpack_require__ = {}; @@ -524,6 +524,9 @@ class FeatureTest { static get isFloat16ArraySupported() { return shadow(this, "isFloat16ArraySupported", typeof Float16Array !== "undefined"); } + static get isSanitizerSupported() { + return shadow(this, "isSanitizerSupported", typeof Sanitizer !== "undefined"); + } static get platform() { const { platform, @@ -30593,7 +30596,7 @@ const BOLDITALIC = { weight: "bold" }; const substitutionMap = new Map([["Times-Roman", { - local: ["Times New Roman", "Times-Roman", "Times", "Liberation Serif", "Nimbus Roman", "Nimbus Roman L", "Tinos", "Thorndale", "TeX Gyre Termes", "FreeSerif", "Linux Libertine O", "Libertinus Serif", "DejaVu Serif", "Bitstream Vera Serif", "Ubuntu"], + local: ["Times New Roman", "Times-Roman", "Times", "Liberation Serif", "Nimbus Roman", "Nimbus Roman L", "Tinos", "Thorndale", "TeX Gyre Termes", "FreeSerif", "Linux Libertine O", "Libertinus Serif", "PT Astra Serif", "DejaVu Serif", "Bitstream Vera Serif", "Ubuntu"], style: NORMAL, ultimate: "serif" }], ["Times-Bold", { @@ -37052,6 +37055,7 @@ class MetadataParser { + const MAX_DEPTH = 40; const StructElementType = { PAGE_CONTENT: 1, @@ -37553,6 +37557,48 @@ class StructElementNode { } = this.tree; return root.roleMap.get(name) ?? name; } + get mathML() { + let AFs = this.dict.get("AF") || []; + if (!Array.isArray(AFs)) { + AFs = [AFs]; + } + for (let af of AFs) { + af = this.xref.fetchIfRef(af); + if (!(af instanceof Dict)) { + continue; + } + if (!isName(af.get("Type"), "Filespec")) { + continue; + } + if (!isName(af.get("AFRelationship"), "Supplement")) { + continue; + } + const ef = af.get("EF"); + if (!(ef instanceof Dict)) { + continue; + } + const fileStream = ef.get("UF") || ef.get("F"); + if (!(fileStream instanceof BaseStream)) { + continue; + } + if (!isName(fileStream.dict.get("Type"), "EmbeddedFile")) { + continue; + } + if (!isName(fileStream.dict.get("Subtype"), "application/mathml+xml")) { + continue; + } + return fileStream.getString(); + } + const A = this.dict.get("A"); + if (A instanceof Dict) { + const O = A.get("O"); + if (isName(O, "MSFT_Office")) { + const mathml = A.get("MSFT_MathML"); + return mathml ? stringToPDFString(mathml) : null; + } + } + return null; + } parseKids() { let pageObjId = null; const objRef = this.dict.getRaw("Pg"); @@ -37719,6 +37765,23 @@ class StructTreePage { } const element = new StructElementNode(this, dict); map.set(dict, element); + switch (element.role) { + case "L": + case "LBody": + case "LI": + case "Table": + case "THead": + case "TBody": + case "TFoot": + case "TR": + { + for (const kid of element.kids) { + if (kid.type === StructElementType.ELEMENT) { + this.addNode(kid.dict, map, level - 1); + } + } + } + } const parent = dict.get("P"); if (!(parent instanceof Dict) || isName(parent.get("Type"), "StructTreeRoot")) { if (!this.addTopLevelNode(dict, element)) { @@ -37769,6 +37832,14 @@ class StructTreePage { if (typeof alt === "string") { obj.alt = stringToPDFString(alt); } + if (obj.role === "Formula") { + const { + mathML + } = node; + if (mathML) { + obj.mathML = mathML; + } + } const a = node.dict.get("A"); if (a instanceof Dict) { const bbox = lookupNormalRect(a.getArray("BBox"), null); @@ -58378,7 +58449,7 @@ class WorkerMessageHandler { docId, apiVersion } = docParams; - const workerVersion = "5.4.370"; + const workerVersion = "5.4.385"; if (apiVersion !== workerVersion) { throw new Error(`The API version "${apiVersion}" does not match ` + `the Worker version "${workerVersion}".`); } diff --git a/toolkit/components/pdfjs/content/web/viewer-geckoview.mjs b/toolkit/components/pdfjs/content/web/viewer-geckoview.mjs @@ -21,8 +21,8 @@ */ /** - * pdfjsVersion = 5.4.370 - * pdfjsBuild = f6317ddbb + * pdfjsVersion = 5.4.385 + * pdfjsBuild = 7fc5706e1 */ /******/ // The require scope /******/ var __webpack_require__ = {}; @@ -6615,6 +6615,7 @@ class PDFPageDetailView extends BasePDFPageView { ;// ./web/struct_tree_layer_builder.js + const PDF_ROLE_TO_HTML_ROLE = { Document: null, DocumentFragment: null, @@ -6657,6 +6658,27 @@ const PDF_ROLE_TO_HTML_ROLE = { Formula: null, Artifact: null }; +const MathMLElements = new Set(["math", "merror", "mfrac", "mi", "mmultiscripts", "mn", "mo", "mover", "mpadded", "mprescripts", "mroot", "mrow", "ms", "mspace", "msqrt", "mstyle", "msub", "msubsup", "msup", "mtable", "mtd", "mtext", "mtr", "munder", "munderover", "semantics"]); +const MathMLNamespace = "http://www.w3.org/1998/Math/MathML"; +class MathMLSanitizer { + static get sanitizer() { + return shadow(this, "sanitizer", FeatureTest.isSanitizerSupported ? new Sanitizer({ + elements: [...MathMLElements].map(name => ({ + name, + namespace: MathMLNamespace + })), + replaceWithChildrenElements: [{ + name: "maction", + namespace: MathMLNamespace + }], + attributes: ["dir", "displaystyle", "mathbackground", "mathcolor", "mathsize", "scriptlevel", "encoding", "display", "linethickness", "intent", "arg", "form", "fence", "separator", "lspace", "rspace", "stretchy", "symmetric", "maxsize", "minsize", "largeop", "movablelimits", "width", "height", "depth", "voffset", "accent", "accentunder", "columnspan", "rowspan"].map(name => ({ + name, + namespace: MathMLNamespace + })), + comments: false + }) : null); + } +} const HEADING_PATTERN = /^H(\d+)$/; class StructTreeLayerBuilder { #promise; @@ -6787,11 +6809,12 @@ class StructTreeLayerBuilder { if (!node) { return null; } - const element = document.createElement("span"); + let element; if ("role" in node) { const { role } = node; + element = MathMLElements.has(role) ? document.createElementNS(MathMLNamespace, role) : document.createElement("span"); const match = role.match(HEADING_PATTERN); if (match) { element.setAttribute("role", "heading"); @@ -6802,7 +6825,18 @@ class StructTreeLayerBuilder { if (role === "Figure" && this.#addImageInTextLayer(node, element)) { return element; } + if (role === "Formula") { + if (node.mathML && MathMLSanitizer.sanitizer) { + element.setHTML(node.mathML, { + sanitizer: MathMLSanitizer.sanitizer + }); + } + if (!node.mathML && node.children.length === 1 && node.children[0].role !== "math") { + element = document.createElementNS(MathMLNamespace, "math"); + } + } } + element ||= document.createElement("span"); this.#setAttributes(node, element); if (node.children) { if (node.children.length === 1 && "id" in node.children[0]) { @@ -8220,7 +8254,7 @@ class PDFViewer { #textLayerMode = TextLayerMode.ENABLE; #viewerAlert = null; constructor(options) { - const viewerVersion = "5.4.370"; + const viewerVersion = "5.4.385"; if (version !== viewerVersion) { throw new Error(`The API version "${version}" does not match the Viewer version "${viewerVersion}".`); } diff --git a/toolkit/components/pdfjs/content/web/viewer.mjs b/toolkit/components/pdfjs/content/web/viewer.mjs @@ -21,8 +21,8 @@ */ /** - * pdfjsVersion = 5.4.370 - * pdfjsBuild = f6317ddbb + * pdfjsVersion = 5.4.385 + * pdfjsBuild = 7fc5706e1 */ /******/ // The require scope /******/ var __webpack_require__ = {}; @@ -9800,6 +9800,7 @@ class PDFPageDetailView extends BasePDFPageView { ;// ./web/struct_tree_layer_builder.js + const PDF_ROLE_TO_HTML_ROLE = { Document: null, DocumentFragment: null, @@ -9842,6 +9843,27 @@ const PDF_ROLE_TO_HTML_ROLE = { Formula: null, Artifact: null }; +const MathMLElements = new Set(["math", "merror", "mfrac", "mi", "mmultiscripts", "mn", "mo", "mover", "mpadded", "mprescripts", "mroot", "mrow", "ms", "mspace", "msqrt", "mstyle", "msub", "msubsup", "msup", "mtable", "mtd", "mtext", "mtr", "munder", "munderover", "semantics"]); +const MathMLNamespace = "http://www.w3.org/1998/Math/MathML"; +class MathMLSanitizer { + static get sanitizer() { + return shadow(this, "sanitizer", FeatureTest.isSanitizerSupported ? new Sanitizer({ + elements: [...MathMLElements].map(name => ({ + name, + namespace: MathMLNamespace + })), + replaceWithChildrenElements: [{ + name: "maction", + namespace: MathMLNamespace + }], + attributes: ["dir", "displaystyle", "mathbackground", "mathcolor", "mathsize", "scriptlevel", "encoding", "display", "linethickness", "intent", "arg", "form", "fence", "separator", "lspace", "rspace", "stretchy", "symmetric", "maxsize", "minsize", "largeop", "movablelimits", "width", "height", "depth", "voffset", "accent", "accentunder", "columnspan", "rowspan"].map(name => ({ + name, + namespace: MathMLNamespace + })), + comments: false + }) : null); + } +} const HEADING_PATTERN = /^H(\d+)$/; class StructTreeLayerBuilder { #promise; @@ -9972,11 +9994,12 @@ class StructTreeLayerBuilder { if (!node) { return null; } - const element = document.createElement("span"); + let element; if ("role" in node) { const { role } = node; + element = MathMLElements.has(role) ? document.createElementNS(MathMLNamespace, role) : document.createElement("span"); const match = role.match(HEADING_PATTERN); if (match) { element.setAttribute("role", "heading"); @@ -9987,7 +10010,18 @@ class StructTreeLayerBuilder { if (role === "Figure" && this.#addImageInTextLayer(node, element)) { return element; } + if (role === "Formula") { + if (node.mathML && MathMLSanitizer.sanitizer) { + element.setHTML(node.mathML, { + sanitizer: MathMLSanitizer.sanitizer + }); + } + if (!node.mathML && node.children.length === 1 && node.children[0].role !== "math") { + element = document.createElementNS(MathMLNamespace, "math"); + } + } } + element ||= document.createElement("span"); this.#setAttributes(node, element); if (node.children) { if (node.children.length === 1 && "id" in node.children[0]) { @@ -11405,7 +11439,7 @@ class PDFViewer { #textLayerMode = TextLayerMode.ENABLE; #viewerAlert = null; constructor(options) { - const viewerVersion = "5.4.370"; + const viewerVersion = "5.4.385"; if (version !== viewerVersion) { throw new Error(`The API version "${version}" does not match the Viewer version "${viewerVersion}".`); } diff --git a/toolkit/components/pdfjs/moz.yaml b/toolkit/components/pdfjs/moz.yaml @@ -20,8 +20,8 @@ origin: # Human-readable identifier for this version/release # Generally "version NNN", "tag SSS", "bookmark SSS" - release: f6317ddbbb847b9d6e70aa843f651a93e470257b (2025-10-23T07:01:50Z). - revision: f6317ddbbb847b9d6e70aa843f651a93e470257b + release: 7fc5706e16ad76e04b66257882764caa2c9db7bd (2025-10-29T20:09:52Z). + revision: 7fc5706e16ad76e04b66257882764caa2c9db7bd # The package's license, where possible using the mnemonic from # https://spdx.org/licenses/