Bug 1614330 - Update pdf.js to version 2.4.349. r=bdahl
authorRyan VanderMeulen <ryanvm@gmail.com>
Mon, 10 Feb 2020 21:13:02 +0000
changeset 513148 201ebe0f644940b528da2f54a419f2fe6ac1b724
parent 513147 cad4ca428d3540c43835bb3f96f974d012c95ce1
child 513149 8c683ce02fbafdef694b4283dd860dc560fee43f
push id37110
push usernbeleuzu@mozilla.com
push dateTue, 11 Feb 2020 09:46:07 +0000
treeherdermozilla-central@11c9c5ce3955 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbdahl
bugs1614330
milestone75.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1614330 - Update pdf.js to version 2.4.349. r=bdahl Differential Revision: https://phabricator.services.mozilla.com/D62255
browser/extensions/pdfjs/README.mozilla
browser/extensions/pdfjs/content/build/pdf.js
browser/extensions/pdfjs/content/build/pdf.worker.js
browser/extensions/pdfjs/content/web/debugger.js
browser/extensions/pdfjs/content/web/viewer.css
browser/extensions/pdfjs/content/web/viewer.js
browser/extensions/pdfjs/moz.yaml
--- a/browser/extensions/pdfjs/README.mozilla
+++ b/browser/extensions/pdfjs/README.mozilla
@@ -1,5 +1,5 @@
 This is the PDF.js project output, https://github.com/mozilla/pdf.js
 
-Current extension version is: 2.4.326
+Current extension version is: 2.4.349
 
-Taken from upstream commit: d6754d1e
+Taken from upstream commit: dced0a38
--- a/browser/extensions/pdfjs/content/build/pdf.js
+++ b/browser/extensions/pdfjs/content/build/pdf.js
@@ -118,18 +118,18 @@ return /******/ (function(modules) { // 
 /************************************************************************/
 /******/ ([
 /* 0 */
 /***/ (function(module, exports, __w_pdfjs_require__) {
 
 "use strict";
 
 
-var pdfjsVersion = '2.4.326';
-var pdfjsBuild = 'd6754d1e';
+var pdfjsVersion = '2.4.349';
+var pdfjsBuild = 'dced0a38';
 
 var pdfjsSharedUtil = __w_pdfjs_require__(1);
 
 var pdfjsDisplayAPI = __w_pdfjs_require__(3);
 
 var pdfjsDisplayTextLayer = __w_pdfjs_require__(16);
 
 var pdfjsDisplayAnnotationLayer = __w_pdfjs_require__(17);
@@ -1200,17 +1200,17 @@ function _fetchDocument(worker, source, 
   if (pdfDataRangeTransport) {
     source.length = pdfDataRangeTransport.length;
     source.initialData = pdfDataRangeTransport.initialData;
     source.progressiveDone = pdfDataRangeTransport.progressiveDone;
   }
 
   return worker.messageHandler.sendWithPromise("GetDocRequest", {
     docId,
-    apiVersion: '2.4.326',
+    apiVersion: '2.4.349',
     source: {
       data: source.data,
       url: source.url,
       password: source.password,
       disableAutoFetch: source.disableAutoFetch,
       rangeChunkSize: source.rangeChunkSize,
       length: source.length
     },
@@ -1423,17 +1423,17 @@ class PDFDocumentProxy {
     return this._transport.downloadInfoCapability.promise;
   }
 
   getStats() {
     return this._transport.getStats();
   }
 
   cleanup() {
-    this._transport.startCleanup();
+    return this._transport.startCleanup();
   }
 
   destroy() {
     return this.loadingTask.destroy();
   }
 
   get loadingParams() {
     return this._transport.loadingParams;
@@ -1754,39 +1754,39 @@ class PDFPageProxy {
     this.objs.clear();
     this.annotationsPromise = null;
     this.pendingCleanup = false;
     return Promise.all(waitOn);
   }
 
   cleanup(resetStats = false) {
     this.pendingCleanup = true;
-
-    this._tryCleanup(resetStats);
+    return this._tryCleanup(resetStats);
   }
 
   _tryCleanup(resetStats = false) {
     if (!this.pendingCleanup || Object.keys(this.intentStates).some(intent => {
       const intentState = this.intentStates[intent];
       return intentState.renderTasks.length !== 0 || !intentState.operatorList.lastChunk;
     })) {
-      return;
+      return false;
     }
 
     Object.keys(this.intentStates).forEach(intent => {
       delete this.intentStates[intent];
     });
     this.objs.clear();
     this.annotationsPromise = null;
 
     if (resetStats && this._stats) {
       this._stats = new _display_utils.StatTimer();
     }
 
     this.pendingCleanup = false;
+    return true;
   }
 
   _startRenderPage(transparency, intent) {
     const intentState = this.intentStates[intent];
 
     if (!intentState) {
       return;
     }
@@ -2869,22 +2869,26 @@ class WorkerTransport {
     });
   }
 
   getStats() {
     return this.messageHandler.sendWithPromise("GetStats", null);
   }
 
   startCleanup() {
-    this.messageHandler.sendWithPromise("Cleanup", null).then(() => {
+    return this.messageHandler.sendWithPromise("Cleanup", null).then(() => {
       for (let i = 0, ii = this.pageCache.length; i < ii; i++) {
         const page = this.pageCache[i];
 
         if (page) {
-          page.cleanup();
+          const cleanupSuccessful = page.cleanup();
+
+          if (!cleanupSuccessful) {
+            throw new Error(`startCleanup: Page ${i + 1} is currently rendering.`);
+          }
         }
       }
 
       this.commonObjs.clear();
       this.fontLoader.clear();
     });
   }
 
@@ -3143,19 +3147,19 @@ const InternalRenderTask = function Inte
       }
     }
 
   }
 
   return InternalRenderTask;
 }();
 
-const version = '2.4.326';
+const version = '2.4.349';
 exports.version = version;
-const build = 'd6754d1e';
+const build = 'dced0a38';
 exports.build = build;
 
 /***/ }),
 /* 4 */
 /***/ (function(module, exports, __w_pdfjs_require__) {
 
 "use strict";
 
--- a/browser/extensions/pdfjs/content/build/pdf.worker.js
+++ b/browser/extensions/pdfjs/content/build/pdf.worker.js
@@ -118,18 +118,18 @@ return /******/ (function(modules) { // 
 /************************************************************************/
 /******/ ([
 /* 0 */
 /***/ (function(module, exports, __w_pdfjs_require__) {
 
 "use strict";
 
 
-const pdfjsVersion = '2.4.326';
-const pdfjsBuild = 'd6754d1e';
+const pdfjsVersion = '2.4.349';
+const pdfjsBuild = 'dced0a38';
 
 const pdfjsCoreWorker = __w_pdfjs_require__(1);
 
 exports.WorkerMessageHandler = pdfjsCoreWorker.WorkerMessageHandler;
 
 /***/ }),
 /* 1 */
 /***/ (function(module, exports, __w_pdfjs_require__) {
@@ -218,17 +218,17 @@ var WorkerMessageHandler = {
 
   createDocumentHandler(docParams, port) {
     var pdfManager;
     var terminated = false;
     var cancelXHRs = null;
     var WorkerTasks = [];
     const verbosity = (0, _util.getVerbosityLevel)();
     const apiVersion = docParams.apiVersion;
-    const workerVersion = '2.4.326';
+    const workerVersion = '2.4.349';
 
     if (apiVersion !== workerVersion) {
       throw new Error(`The API version "${apiVersion}" does not match ` + `the Worker version "${workerVersion}".`);
     }
 
     var docId = docParams.docId;
     var docBaseUrl = docParams.docBaseUrl;
     var workerHandlerName = docParams.docId + "_worker";
@@ -3092,16 +3092,17 @@ class Page {
 }
 
 exports.Page = Page;
 const PDF_HEADER_SIGNATURE = new Uint8Array([0x25, 0x50, 0x44, 0x46, 0x2d]);
 const STARTXREF_SIGNATURE = new Uint8Array([0x73, 0x74, 0x61, 0x72, 0x74, 0x78, 0x72, 0x65, 0x66]);
 const ENDOBJ_SIGNATURE = new Uint8Array([0x65, 0x6e, 0x64, 0x6f, 0x62, 0x6a]);
 const FINGERPRINT_FIRST_BYTES = 1024;
 const EMPTY_FINGERPRINT = "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00";
+const PDF_HEADER_VERSION_REGEXP = /^[1-9]\.[0-9]$/;
 
 function find(stream, signature, limit = 1024, backwards = false) {
   const signatureLength = signature.length;
   const scanBytes = stream.peekBytes(limit);
   const scanLength = scanBytes.length - signatureLength;
 
   if (scanLength <= 0) {
     return false;
@@ -3333,18 +3334,25 @@ class PDFDocument {
       Subject: _util.isString,
       Keywords: _util.isString,
       Creator: _util.isString,
       Producer: _util.isString,
       CreationDate: _util.isString,
       ModDate: _util.isString,
       Trapped: _primitives.isName
     };
+    let version = this.pdfFormatVersion;
+
+    if (typeof version !== "string" || !PDF_HEADER_VERSION_REGEXP.test(version)) {
+      (0, _util.warn)(`Invalid PDF header version number: ${version}`);
+      version = null;
+    }
+
     const docInfo = {
-      PDFFormatVersion: this.pdfFormatVersion,
+      PDFFormatVersion: version,
       IsLinearized: !!this.linearization,
       IsAcroFormPresent: !!this.acroForm,
       IsXFAPresent: !!this.xfa,
       IsCollectionPresent: !!this.collection
     };
     let infoDict;
 
     try {
@@ -12898,28 +12906,33 @@ var JpegImage = function JpegImageClosur
       var index;
       var offset = 0;
       var output;
       var numComponents = this.components.length;
       var dataLength = width * height * numComponents;
       var data = new Uint8ClampedArray(dataLength);
       var xScaleBlockOffset = new Uint32Array(width);
       var mask3LSB = 0xfffffff8;
+      let lastComponentScaleX;
 
       for (i = 0; i < numComponents; i++) {
         component = this.components[i];
         componentScaleX = component.scaleX * scaleX;
         componentScaleY = component.scaleY * scaleY;
         offset = i;
         output = component.output;
         blocksPerScanline = component.blocksPerLine + 1 << 3;
 
-        for (x = 0; x < width; x++) {
-          j = 0 | x * componentScaleX;
-          xScaleBlockOffset[x] = (j & mask3LSB) << 3 | j & 7;
+        if (componentScaleX !== lastComponentScaleX) {
+          for (x = 0; x < width; x++) {
+            j = 0 | x * componentScaleX;
+            xScaleBlockOffset[x] = (j & mask3LSB) << 3 | j & 7;
+          }
+
+          lastComponentScaleX = componentScaleX;
         }
 
         for (y = 0; y < height; y++) {
           j = 0 | y * componentScaleY;
           index = blocksPerScanline * (j & mask3LSB) | (j & 7) << 3;
 
           for (x = 0; x < width; x++) {
             data[offset] = output[index + xScaleBlockOffset[x]];
@@ -13007,26 +13020,25 @@ var JpegImage = function JpegImageClosur
         data[i + 2] = 481.816 - Y - 1.772 * Cb;
       }
 
       return data;
     },
     _convertCmykToRgb: function convertCmykToRgb(data) {
       var c, m, y, k;
       var offset = 0;
-      var scale = 1 / 255;
 
       for (var i = 0, length = data.length; i < length; i += 4) {
-        c = data[i] * scale;
-        m = data[i + 1] * scale;
-        y = data[i + 2] * scale;
-        k = data[i + 3] * scale;
-        data[offset++] = 255 + c * (-4.387332384609988 * c + 54.48615194189176 * m + 18.82290502165302 * y + 212.25662451639585 * k - 285.2331026137004) + m * (1.7149763477362134 * m - 5.6096736904047315 * y - 17.873870861415444 * k - 5.497006427196366) + y * (-2.5217340131683033 * y - 21.248923337353073 * k + 17.5119270841813) - k * (21.86122147463605 * k + 189.48180835922747);
-        data[offset++] = 255 + c * (8.841041422036149 * c + 60.118027045597366 * m + 6.871425592049007 * y + 31.159100130055922 * k - 79.2970844816548) + m * (-15.310361306967817 * m + 17.575251261109482 * y + 131.35250912493976 * k - 190.9453302588951) + y * (4.444339102852739 * y + 9.8632861493405 * k - 24.86741582555878) - k * (20.737325471181034 * k + 187.80453709719578);
-        data[offset++] = 255 + c * (0.8842522430003296 * c + 8.078677503112928 * m + 30.89978309703729 * y - 0.23883238689178934 * k - 14.183576799673286) + m * (10.49593273432072 * m + 63.02378494754052 * y + 50.606957656360734 * k - 112.23884253719248) + y * (0.03296041114873217 * y + 115.60384449646641 * k - 193.58209356861505) - k * (22.33816807309886 * k + 180.12613974708367);
+        c = data[i];
+        m = data[i + 1];
+        y = data[i + 2];
+        k = data[i + 3];
+        data[offset++] = 255 + c * (-0.00006747147073602441 * c + 0.0008379262121013727 * m + 0.0002894718188643294 * y + 0.003264231057537806 * k - 1.1185611867203937) + m * (0.000026374107616089405 * m - 0.00008626949158638572 * y - 0.0002748769067499491 * k - 0.02155688794978967) + y * (-0.00003878099212869363 * y - 0.0003267808279485286 * k + 0.0686742238595345) - k * (0.0003361971776183937 * k + 0.7430659151342254);
+        data[offset++] = 255 + c * (0.00013596372813588848 * c + 0.000924537132573585 * m + 0.00010567359618683593 * y + 0.0004791864687436512 * k - 0.3109689587515875) + m * (-0.00023545346108370344 * m + 0.0002702845253534714 * y + 0.0020200308977307156 * k - 0.7488052167015494) + y * (0.00006834815998235662 * y + 0.00015168452363460973 * k - 0.09751927774728933) - k * (0.00031891311758832814 * k + 0.7364883807733168);
+        data[offset++] = 255 + c * (0.000013598650411385307 * c + 0.00012423956175490851 * m + 0.0004751985097583589 * y - 0.0000036729317476630422 * k - 0.05562186980264034) + m * (0.00016141380598724676 * m + 0.0009692239130725186 * y + 0.0007782692450036253 * k - 0.44015232367526463) + y * (5.068882914068769e-7 * y + 0.0017778369011375071 * k - 0.7591454649749609) - k * (0.0003435319965105553 * k + 0.7063770186160144);
       }
 
       return data.subarray(0, offset);
     },
 
     getData({
       width,
       height,
@@ -22114,16 +22126,30 @@ var PartialEvaluator = function PartialE
               k += 2;
               var w2 = token.charCodeAt(k) << 8 | token.charCodeAt(k + 1);
               str.push(((w1 & 0x3ff) << 10) + (w2 & 0x3ff) + 0x10000);
             }
 
             map[charCode] = String.fromCodePoint.apply(String, str);
           });
           return new _fonts.ToUnicodeMap(map);
+        }, reason => {
+          if (reason instanceof _util.AbortException) {
+            return null;
+          }
+
+          if (this.options.ignoreErrors) {
+            this.handler.send("UnsupportedFeature", {
+              featureId: _util.UNSUPPORTED_FEATURES.font
+            });
+            (0, _util.warn)(`readToUnicode - ignoring ToUnicode data: "${reason}".`);
+            return null;
+          }
+
+          throw reason;
         });
       }
 
       return Promise.resolve(null);
     },
 
     readCidToGidMap(glyphsData, toUnicode) {
       var result = [];
@@ -22404,16 +22430,18 @@ var PartialEvaluator = function PartialE
     translateFont: function PartialEvaluator_translateFont(preEvaluatedFont) {
       var baseDict = preEvaluatedFont.baseDict;
       var dict = preEvaluatedFont.dict;
       var composite = preEvaluatedFont.composite;
       var descriptor = preEvaluatedFont.descriptor;
       var type = preEvaluatedFont.type;
       var maxCharIndex = composite ? 0xffff : 0xff;
       var properties;
+      const firstChar = dict.get("FirstChar") || 0;
+      const lastChar = dict.get("LastChar") || maxCharIndex;
 
       if (!descriptor) {
         if (type === "Type3") {
           descriptor = new _primitives.Dict(null);
           descriptor.set("FontName", _primitives.Name.get(type));
           descriptor.set("FontBBox", dict.getArray("FontBBox"));
         } else {
           var baseFontName = dict.get("BaseFont");
@@ -22427,28 +22455,39 @@ var PartialEvaluator = function PartialE
           var fontNameWoStyle = baseFontName.split("-")[0];
           var flags = (this.isSerifFont(fontNameWoStyle) ? _fonts.FontFlags.Serif : 0) | (metrics.monospace ? _fonts.FontFlags.FixedPitch : 0) | ((0, _standard_fonts.getSymbolsFonts)()[fontNameWoStyle] ? _fonts.FontFlags.Symbolic : _fonts.FontFlags.Nonsymbolic);
           properties = {
             type,
             name: baseFontName,
             widths: metrics.widths,
             defaultWidth: metrics.defaultWidth,
             flags,
-            firstChar: 0,
-            lastChar: maxCharIndex
+            firstChar,
+            lastChar
           };
+          const widths = dict.get("Widths");
           return this.extractDataStructures(dict, dict, properties).then(properties => {
-            properties.widths = this.buildCharCodeToWidth(metrics.widths, properties);
+            if (widths) {
+              const glyphWidths = [];
+              let j = firstChar;
+
+              for (let i = 0, ii = widths.length; i < ii; i++) {
+                glyphWidths[j++] = this.xref.fetchIfRef(widths[i]);
+              }
+
+              properties.widths = glyphWidths;
+            } else {
+              properties.widths = this.buildCharCodeToWidth(metrics.widths, properties);
+            }
+
             return new _fonts.Font(baseFontName, null, properties);
           });
         }
       }
 
-      var firstChar = dict.get("FirstChar") || 0;
-      var lastChar = dict.get("LastChar") || maxCharIndex;
       var fontName = descriptor.get("FontName");
       var baseFont = dict.get("BaseFont");
 
       if ((0, _util.isString)(fontName)) {
         fontName = _primitives.Name.get(fontName);
       }
 
       if ((0, _util.isString)(baseFont)) {
@@ -24175,17 +24214,17 @@ var CMapFactory = function CMapFactoryCl
         return parseCMap(cMap, lexer, fetchBuiltInCMap, null);
       }
 
       return Promise.reject(new Error("TODO: Only BINARY/NONE CMap compression is currently supported."));
     });
   }
 
   return {
-    create(params) {
+    async create(params) {
       var encoding = params.encoding;
       var fetchBuiltInCMap = params.fetchBuiltInCMap;
       var useCMap = params.useCMap;
 
       if ((0, _primitives.isName)(encoding)) {
         return createBuiltInCMap(encoding.name, fetchBuiltInCMap);
       } else if ((0, _primitives.isStream)(encoding)) {
         var cMap = new CMap();
@@ -24194,17 +24233,17 @@ var CMapFactory = function CMapFactoryCl
           if (parsedCMap.isIdentityCMap) {
             return createBuiltInCMap(parsedCMap.name, fetchBuiltInCMap);
           }
 
           return parsedCMap;
         });
       }
 
-      return Promise.reject(new Error("Encoding required."));
+      throw new Error("Encoding required.");
     }
 
   };
 }();
 
 exports.CMapFactory = CMapFactory;
 
 /***/ }),
@@ -25218,17 +25257,17 @@ var Font = function FontClosure() {
       return data;
     },
     fallbackToSystemFont: function Font_fallbackToSystemFont() {
       this.missingFile = true;
       var charCode, unicode;
       var name = this.name;
       var type = this.type;
       var subtype = this.subtype;
-      var fontName = name.replace(/[,_]/g, "-");
+      let fontName = name.replace(/[,_]/g, "-").replace(/\s/g, "");
       var stdFontMap = (0, _standard_fonts.getStdFontMap)(),
           nonStdFontMap = (0, _standard_fonts.getNonStdFontMap)();
       var isStandardFont = !!stdFontMap[fontName] || !!(nonStdFontMap[fontName] && stdFontMap[nonStdFontMap[fontName]]);
       fontName = stdFontMap[fontName] || nonStdFontMap[fontName] || fontName;
       this.bold = fontName.search(/bold/gi) !== -1;
       this.italic = fontName.search(/oblique/gi) !== -1 || fontName.search(/italic/gi) !== -1;
       this.black = name.search(/Black/g) !== -1;
       this.remeasure = Object.keys(this.widths).length > 0;
@@ -26856,16 +26895,22 @@ var Font = function FontClosure() {
       if (typeof unicode === "number") {
         unicode = String.fromCharCode(unicode);
       }
 
       var isInFont = charcode in this.toFontChar;
       fontCharCode = this.toFontChar[charcode] || charcode;
 
       if (this.missingFile) {
+        const glyphName = this.differences[charcode] || this.defaultEncoding[charcode];
+
+        if ((glyphName === ".notdef" || glyphName === "") && this.type === "Type1") {
+          fontCharCode = 0x20;
+        }
+
         fontCharCode = (0, _unicode.mapSpecialUnicodeValues)(fontCharCode);
       }
 
       if (this.isType3Font) {
         operatorListId = fontCharCode;
       }
 
       var accent = null;
--- a/browser/extensions/pdfjs/content/web/debugger.js
+++ b/browser/extensions/pdfjs/content/web/debugger.js
@@ -62,17 +62,16 @@ var FontInspector = (function FontInspec
   return {
     // Properties/functions needed by PDFBug.
     id: "FontInspector",
     name: "Font Inspector",
     panel: null,
     manager: null,
     init: function init(pdfjsLib) {
       var panel = this.panel;
-      panel.setAttribute("style", "padding: 5px;");
       var tmp = document.createElement("button");
       tmp.addEventListener("click", resetSelection);
       tmp.textContent = "Refresh";
       panel.appendChild(tmp);
 
       fonts = document.createElement("div");
       panel.appendChild(fonts);
     },
@@ -173,17 +172,16 @@ var StepperManager = (function StepperMa
   return {
     // Properties/functions needed by PDFBug.
     id: "Stepper",
     name: "Stepper",
     panel: null,
     manager: null,
     init: function init(pdfjsLib) {
       var self = this;
-      this.panel.setAttribute("style", "padding: 5px;");
       stepperControls = document.createElement("div");
       stepperChooser = document.createElement("select");
       stepperChooser.addEventListener("change", function(event) {
         self.selectStepper(this.value);
       });
       stepperControls.appendChild(stepperChooser);
       stepperDiv = document.createElement("div");
       this.panel.appendChild(stepperControls);
@@ -463,19 +461,17 @@ var Stats = (function Stats() {
     return false;
   }
   return {
     // Properties/functions needed by PDFBug.
     id: "Stats",
     name: "Stats",
     panel: null,
     manager: null,
-    init(pdfjsLib) {
-      this.panel.setAttribute("style", "padding: 5px;");
-    },
+    init(pdfjsLib) {},
     enabled: false,
     active: false,
     // Stats specific functions.
     add(pageNumber, stat) {
       if (!stat) {
         return;
       }
       var statsIndex = getStatIndex(pageNumber);
--- a/browser/extensions/pdfjs/content/web/viewer.css
+++ b/browser/extensions/pdfjs/content/web/viewer.css
@@ -376,16 +376,18 @@
 
 .pdfPresentationMode:fullscreen .pdfViewer .page {
   margin-bottom: 100%;
   border: 0;
 }
 
 :root {
   --sidebar-width: 200px;
+  --sidebar-transition-duration: 200ms;
+  --sidebar-transition-timing-function: ease;
 }
 
 * {
   padding: 0;
   margin: 0;
 }
 
 html {
@@ -446,34 +448,30 @@ select {
   height: 100%;
   position: relative;
 }
 
 #sidebarContainer {
   position: absolute;
   top: 32px;
   bottom: 0;
-  width: 200px; /* Here, and elsewhere below, keep the constant value for compatibility
-                   with older browsers that lack support for CSS variables. */
   width: var(--sidebar-width);
   visibility: hidden;
   z-index: 100;
   border-top: 1px solid rgba(51, 51, 51, 1);
-  transition-duration: 200ms;
-  transition-timing-function: ease;
+  transition-duration: var(--sidebar-transition-duration);
+  transition-timing-function: var(--sidebar-transition-timing-function);
 }
 html[dir='ltr'] #sidebarContainer {
   transition-property: left;
-  left: -200px;
-  left: calc(-1 * var(--sidebar-width));
+  left: calc(0px - var(--sidebar-width));
 }
 html[dir='rtl'] #sidebarContainer {
   transition-property: right;
-  right: -200px;
-  right: calc(-1 * var(--sidebar-width));
+  right: calc(0px - var(--sidebar-width));
 }
 
 .loadingInProgress #sidebarContainer {
   top: 36px;
 }
 
 #outerContainer.sidebarResizing #sidebarContainer {
   /* Improve responsiveness and avoid visual glitches when the sidebar is resized. */
@@ -524,39 +522,37 @@ html[dir='rtl'] #sidebarContent {
   position: absolute;
   top: 32px;
   right: 0;
   bottom: 0;
   left: 0;
   outline: none;
 }
 #viewerContainer:not(.pdfPresentationMode) {
-  transition-duration: 200ms;
-  transition-timing-function: ease;
+  transition-duration: var(--sidebar-transition-duration);
+  transition-timing-function: var(--sidebar-transition-timing-function);
 }
 html[dir='ltr'] #viewerContainer {
   box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.05);
 }
 html[dir='rtl'] #viewerContainer {
   box-shadow: inset -1px 0 0 rgba(255, 255, 255, 0.05);
 }
 
 #outerContainer.sidebarResizing #viewerContainer {
   /* Improve responsiveness and avoid visual glitches when the sidebar is resized. */
   transition-duration: 0s;
 }
 
 html[dir='ltr'] #outerContainer.sidebarOpen #viewerContainer:not(.pdfPresentationMode) {
   transition-property: left;
-  left: 200px;
   left: var(--sidebar-width);
 }
 html[dir='rtl'] #outerContainer.sidebarOpen #viewerContainer:not(.pdfPresentationMode) {
   transition-property: right;
-  right: 200px;
   right: var(--sidebar-width);
 }
 
 .toolbar {
   position: relative;
   left: 0;
   right: 0;
   z-index: 9999;
@@ -1044,31 +1040,31 @@ html[dir='rtl'] .dropdownToolbarButton {
   background-color: rgba(0, 0, 0, 0.4);
   border-color: rgba(0, 0, 0, 0.4) rgba(0, 0, 0, 0.5) rgba(0, 0, 0, 0.55);
   box-shadow: 0 1px 1px rgba(0, 0, 0, 0.2) inset,
               0 0 1px rgba(0, 0, 0, 0.3) inset,
               0 1px 0 rgba(255, 255, 255, 0.05);
 }
 
 .dropdownToolbarButton {
-  width: 120px;
-  max-width: 120px;
+  width: 140px;
   padding: 0;
   overflow: hidden;
   background: url(images/toolbarButton-menuArrows.png) no-repeat;
 }
 html[dir='ltr'] .dropdownToolbarButton {
   background-position: 95%;
 }
 html[dir='rtl'] .dropdownToolbarButton {
   background-position: 5%;
 }
 
 .dropdownToolbarButton > select {
-  min-width: 140px;
+  width: 162px;
+  height: 23px;
   font-size: 12px;
   color: rgba(242, 242, 242, 1);
   margin: 0;
   padding: 3px 2px 2px;
   border: none;
   background: rgba(0,0,0,0); /* Opera does not support 'transparent' <select> background */
 }
 
@@ -1817,16 +1813,19 @@ html[dir='rtl'] #documentPropertiesOverl
 #PDFBug .panels {
   bottom: 0;
   left: 0;
   overflow: auto;
   position: absolute;
   right: 0;
   top: 27px;
 }
+#PDFBug .panels > div {
+  padding: 5px;
+}
 #PDFBug button.active {
   font-weight: bold;
 }
 .debuggerShowText {
   background: none repeat scroll 0 0 rgba(255, 255, 0, 1);
   color: rgba(0, 0, 255, 1);
 }
 .debuggerHideText:hover {
--- a/browser/extensions/pdfjs/content/web/viewer.js
+++ b/browser/extensions/pdfjs/content/web/viewer.js
@@ -3123,17 +3123,17 @@ class ProgressBar {
     if (!viewer) {
       return;
     }
 
     const container = viewer.parentNode;
     const scrollbarWidth = container.offsetWidth - viewer.offsetWidth;
 
     if (scrollbarWidth > 0) {
-      this.bar.setAttribute("style", "width: calc(100% - " + scrollbarWidth + "px);");
+      this.bar.style.width = `calc(100% - ${scrollbarWidth}px)`;
     }
   }
 
   hide() {
     if (!this.visible) {
       return;
     }
 
@@ -6954,28 +6954,22 @@ class PDFOutlineViewer {
       return false;
     };
   }
 
   _setStyles(element, {
     bold,
     italic
   }) {
-    let styleStr = "";
-
     if (bold) {
-      styleStr += "font-weight: bold;";
+      element.style.fontWeight = "bold";
     }
 
     if (italic) {
-      styleStr += "font-style: italic;";
-    }
-
-    if (styleStr) {
-      element.setAttribute("style", styleStr);
+      element.style.fontStyle = "italic";
     }
   }
 
   _addToggleButton(div, {
     count,
     items
   }) {
     const toggler = document.createElement("div");
@@ -10804,17 +10798,17 @@ class SecondaryToolbar {
     }
 
     this.containerHeight = this.mainContainer.clientHeight;
 
     if (this.containerHeight === this.previousContainerHeight) {
       return;
     }
 
-    this.toolbarButtonContainer.setAttribute("style", "max-height: " + (this.containerHeight - _ui_utils.SCROLLBAR_PADDING) + "px;");
+    this.toolbarButtonContainer.style.maxHeight = `${this.containerHeight - _ui_utils.SCROLLBAR_PADDING}px`;
     this.previousContainerHeight = this.containerHeight;
   }
 
 }
 
 exports.SecondaryToolbar = SecondaryToolbar;
 
 /***/ }),
@@ -10948,18 +10942,18 @@ exports.PDFSinglePageViewer = PDFSingleP
 Object.defineProperty(exports, "__esModule", {
   value: true
 });
 exports.Toolbar = void 0;
 
 var _ui_utils = __webpack_require__(2);
 
 const PAGE_NUMBER_LOADING_INDICATOR = "visiblePageIsLoading";
-const SCALE_SELECT_CONTAINER_PADDING = 8;
-const SCALE_SELECT_PADDING = 22;
+const SCALE_SELECT_CONTAINER_WIDTH = 140;
+const SCALE_SELECT_WIDTH = 162;
 
 class Toolbar {
   constructor(options, eventBus, l10n = _ui_utils.NullL10n) {
     this.toolbar = options.container;
     this.eventBus = eventBus;
     this.l10n = l10n;
     this.buttons = [{
       element: options.previous,
@@ -11156,32 +11150,56 @@ class Toolbar {
     });
   }
 
   updateLoadingIndicatorState(loading = false) {
     const pageNumberInput = this.items.pageNumber;
     pageNumberInput.classList.toggle(PAGE_NUMBER_LOADING_INDICATOR, loading);
   }
 
-  _adjustScaleWidth() {
-    const container = this.items.scaleSelectContainer;
-    const select = this.items.scaleSelect;
-
-    _ui_utils.animationStarted.then(function () {
-      if (container.clientWidth === 0) {
-        container.setAttribute("style", "display: inherit;");
-      }
-
-      if (container.clientWidth > 0) {
-        select.setAttribute("style", "min-width: inherit;");
-        const width = select.clientWidth + SCALE_SELECT_CONTAINER_PADDING;
-        select.setAttribute("style", `min-width: ${width + SCALE_SELECT_PADDING}px;`);
-        container.setAttribute("style", `min-width: ${width}px; max-width: ${width}px;`);
-      }
-    });
+  async _adjustScaleWidth() {
+    const {
+      items,
+      l10n
+    } = this;
+    const predefinedValuesPromise = Promise.all([l10n.get("page_scale_auto", null, "Automatic Zoom"), l10n.get("page_scale_actual", null, "Actual Size"), l10n.get("page_scale_fit", null, "Page Fit"), l10n.get("page_scale_width", null, "Page Width")]);
+    let canvas = document.createElement("canvas");
+    canvas.mozOpaque = true;
+    let ctx = canvas.getContext("2d", {
+      alpha: false
+    });
+    await _ui_utils.animationStarted;
+    const {
+      fontSize,
+      fontFamily
+    } = getComputedStyle(items.scaleSelect);
+    ctx.font = `${fontSize} ${fontFamily}`;
+    let maxWidth = 0;
+
+    for (const predefinedValue of await predefinedValuesPromise) {
+      const {
+        width
+      } = ctx.measureText(predefinedValue);
+
+      if (width > maxWidth) {
+        maxWidth = width;
+      }
+    }
+
+    const overflow = SCALE_SELECT_WIDTH - SCALE_SELECT_CONTAINER_WIDTH;
+    maxWidth += 1.5 * overflow;
+
+    if (maxWidth > SCALE_SELECT_CONTAINER_WIDTH) {
+      items.scaleSelect.style.width = `${maxWidth + overflow}px`;
+      items.scaleSelectContainer.style.width = `${maxWidth}px`;
+    }
+
+    canvas.width = 0;
+    canvas.height = 0;
+    canvas = ctx = null;
   }
 
 }
 
 exports.Toolbar = Toolbar;
 
 /***/ }),
 /* 32 */
--- a/browser/extensions/pdfjs/moz.yaml
+++ b/browser/extensions/pdfjs/moz.yaml
@@ -15,15 +15,15 @@ origin:
   description: Portable Document Format (PDF) viewer that is built with HTML5
 
   # Full URL for the package's homepage/etc
   # Usually different from repository url
   url: https://github.com/mozilla/pdf.js
 
   # Human-readable identifier for this version/release
   # Generally "version NNN", "tag SSS", "bookmark SSS"
-  release: version 2.4.326
+  release: version 2.4.349
 
   # The package's license, where possible using the mnemonic from
   # https://spdx.org/licenses/
   # Multiple licenses can be specified (as a YAML list)
   # A "LICENSE" file must exist containing the full license text
   license: Apache-2.0