Bug 1470790 - Update pdf.js to version 2.0.625. r=bdahl
authorRyan VanderMeulen <ryanvm@gmail.com>
Sun, 24 Jun 2018 20:42:59 -0400
changeset 477702 6d0dcae0268b98e9c43bbed077502a51afed2311
parent 477699 15c95df467be553beb39f2e8102c206639e05fde
child 477703 4f6e597104dabedfecfafa2ab63dc79fd7f8bc7a
child 478621 5e6723170dbf56ad7fbdf9b2efa1405fbe80f194
push id9387
push useraciure@mozilla.com
push dateMon, 25 Jun 2018 14:15:12 +0000
treeherdermozilla-beta@1716b76aa7b8 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbdahl
bugs1470790
milestone62.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 1470790 - Update pdf.js to version 2.0.625. r=bdahl
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/viewer.js
--- 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.0.602
+Current extension version is: 2.0.625
 
-Taken from upstream commit: 3b07147d
+Taken from upstream commit: e8b50883
--- 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.0.602';
-var pdfjsBuild = '3b07147d';
+var pdfjsVersion = '2.0.625';
+var pdfjsBuild = 'e8b50883';
 var pdfjsSharedUtil = __w_pdfjs_require__(1);
 var pdfjsDisplayAPI = __w_pdfjs_require__(6);
 var pdfjsDisplayTextLayer = __w_pdfjs_require__(18);
 var pdfjsDisplayAnnotationLayer = __w_pdfjs_require__(19);
 var pdfjsDisplayDOMUtils = __w_pdfjs_require__(7);
 var pdfjsDisplaySVG = __w_pdfjs_require__(20);
 let pdfjsDisplayWorkerOptions = __w_pdfjs_require__(12);
 let pdfjsDisplayAPICompatibility = __w_pdfjs_require__(9);
@@ -820,21 +820,16 @@ var Util = function UtilClosure() {
     romanBuf.push(ROMAN_NUMBER_MAP[pos]);
     pos = number / 10 | 0;
     number %= 10;
     romanBuf.push(ROMAN_NUMBER_MAP[10 + pos]);
     romanBuf.push(ROMAN_NUMBER_MAP[20 + number]);
     var romanStr = romanBuf.join('');
     return lowerCase ? romanStr.toLowerCase() : romanStr;
   };
-  Util.extendObj = function extendObj(obj1, obj2) {
-    for (var key in obj2) {
-      obj1[key] = obj2[key];
-    }
-  };
   Util.inherit = function Util_inherit(sub, base, prototype) {
     sub.prototype = Object.create(base.prototype);
     sub.prototype.constructor = sub;
     for (var prop in prototype) {
       sub.prototype[prop] = prototype[prop];
     }
   };
   return Util;
@@ -4150,20 +4145,20 @@ function getDocument(src) {
   }
   if (typeof params.isEvalSupported !== 'boolean') {
     params.isEvalSupported = true;
   }
   if (typeof params.disableFontFace !== 'boolean') {
     params.disableFontFace = _api_compatibility.apiCompatibilityParams.disableFontFace || false;
   }
   if (typeof params.disableRange !== 'boolean') {
-    params.disableRange = _api_compatibility.apiCompatibilityParams.disableRange || false;
+    params.disableRange = false;
   }
   if (typeof params.disableStream !== 'boolean') {
-    params.disableStream = _api_compatibility.apiCompatibilityParams.disableStream || false;
+    params.disableStream = false;
   }
   if (typeof params.disableAutoFetch !== 'boolean') {
     params.disableAutoFetch = false;
   }
   if (typeof params.disableCreateObjectURL !== 'boolean') {
     params.disableCreateObjectURL = _api_compatibility.apiCompatibilityParams.disableCreateObjectURL || false;
   }
   (0, _util.setVerbosityLevel)(params.verbosity);
@@ -4223,17 +4218,17 @@ function _fetchDocument(worker, source, 
     return Promise.reject(new Error('Worker was destroyed'));
   }
   if (pdfDataRangeTransport) {
     source.length = pdfDataRangeTransport.length;
     source.initialData = pdfDataRangeTransport.initialData;
   }
   return worker.messageHandler.sendWithPromise('GetDocRequest', {
     docId,
-    apiVersion: '2.0.602',
+    apiVersion: '2.0.625',
     source: {
       data: source.data,
       url: source.url,
       password: source.password,
       disableAutoFetch: source.disableAutoFetch,
       rangeChunkSize: source.rangeChunkSize,
       length: source.length
     },
@@ -4560,17 +4555,17 @@ var PDFPageProxy = function PDFPageProxy
       let readableStream = this.streamTextContent(params);
       return new Promise(function (resolve, reject) {
         function pump() {
           reader.read().then(function ({ value, done }) {
             if (done) {
               resolve(textContent);
               return;
             }
-            _util.Util.extendObj(textContent.styles, value.styles);
+            Object.assign(textContent.styles, value.styles);
             textContent.items.push(...value.items);
             pump();
           }, reject);
         }
         let reader = readableStream.getReader();
         let textContent = {
           items: [],
           styles: Object.create(null)
@@ -5357,18 +5352,16 @@ var WorkerTransport = function WorkerTra
         }
         this.commonObjs.clear();
         this.fontLoader.clear();
       });
     },
     get loadingParams() {
       let params = this._params;
       return (0, _util.shadow)(this, 'loadingParams', {
-        disableRange: params.disableRange,
-        disableStream: params.disableStream,
         disableAutoFetch: params.disableAutoFetch,
         disableCreateObjectURL: params.disableCreateObjectURL,
         disableFontFace: params.disableFontFace,
         nativeImageDecoderSupport: params.nativeImageDecoderSupport
       });
     }
   };
   return WorkerTransport;
@@ -5564,18 +5557,18 @@ var InternalRenderTask = function Intern
         }
       });
     }
   };
   return InternalRenderTask;
 }();
 var version, build;
 {
-  exports.version = version = '2.0.602';
-  exports.build = build = '3b07147d';
+  exports.version = version = '2.0.625';
+  exports.build = build = 'e8b50883';
 }
 exports.getDocument = getDocument;
 exports.LoopbackPort = LoopbackPort;
 exports.PDFDataRangeTransport = PDFDataRangeTransport;
 exports.PDFWorker = PDFWorker;
 exports.PDFDocumentProxy = PDFDocumentProxy;
 exports.PDFPageProxy = PDFPageProxy;
 exports.setPDFNetworkStreamFactory = setPDFNetworkStreamFactory;
@@ -10062,17 +10055,17 @@ var renderTextLayer = function renderTex
         capability.resolve();
       } else if (this._textContentStream) {
         let pump = () => {
           this._reader.read().then(({ value, done }) => {
             if (done) {
               capability.resolve();
               return;
             }
-            _util.Util.extendObj(styleCache, value.styles);
+            Object.assign(styleCache, value.styles);
             this._processItems(value.items, styleCache);
             pump();
           }, capability.reject);
         };
         this._reader = this._textContentStream.getReader();
         pump();
       } else {
         throw new Error('Neither "textContent" nor "textContentStream"' + ' parameters specified.');
--- 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";
 
 
-var pdfjsVersion = '2.0.602';
-var pdfjsBuild = '3b07147d';
+var pdfjsVersion = '2.0.625';
+var pdfjsBuild = 'e8b50883';
 var pdfjsCoreWorker = __w_pdfjs_require__(1);
 exports.WorkerMessageHandler = pdfjsCoreWorker.WorkerMessageHandler;
 
 /***/ }),
 /* 1 */
 /***/ (function(module, exports, __w_pdfjs_require__) {
 
 "use strict";
@@ -322,17 +322,17 @@ var WorkerMessageHandler = {
     });
   },
   createDocumentHandler(docParams, port) {
     var pdfManager;
     var terminated = false;
     var cancelXHRs = null;
     var WorkerTasks = [];
     let apiVersion = docParams.apiVersion;
-    let workerVersion = '2.0.602';
+    let workerVersion = '2.0.625';
     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';
     var handler = new _message_handler.MessageHandler(workerHandlerName, docId, port);
     handler.postMessageTransfers = docParams.postMessageTransfers;
@@ -1359,21 +1359,16 @@ var Util = function UtilClosure() {
     romanBuf.push(ROMAN_NUMBER_MAP[pos]);
     pos = number / 10 | 0;
     number %= 10;
     romanBuf.push(ROMAN_NUMBER_MAP[10 + pos]);
     romanBuf.push(ROMAN_NUMBER_MAP[20 + number]);
     var romanStr = romanBuf.join('');
     return lowerCase ? romanStr.toLowerCase() : romanStr;
   };
-  Util.extendObj = function extendObj(obj1, obj2) {
-    for (var key in obj2) {
-      obj1[key] = obj2[key];
-    }
-  };
   Util.inherit = function Util_inherit(sub, base, prototype) {
     sub.prototype = Object.create(base.prototype);
     sub.prototype.constructor = sub;
     for (var prop in prototype) {
       sub.prototype[prop] = prototype[prop];
     }
   };
   return Util;
@@ -6461,24 +6456,46 @@ var XRef = function XRefClosure() {
       if (!recoveryMode) {
         trailerDict = this.readXRef();
       } else {
         (0, _util.warn)('Indexing all PDF objects');
         trailerDict = this.indexObjects();
       }
       trailerDict.assignXref(this);
       this.trailer = trailerDict;
-      var encrypt = trailerDict.get('Encrypt');
+      let encrypt;
+      try {
+        encrypt = trailerDict.get('Encrypt');
+      } catch (ex) {
+        if (ex instanceof _util.MissingDataException) {
+          throw ex;
+        }
+        (0, _util.warn)(`XRef.parse - Invalid "Encrypt" reference: "${ex}".`);
+      }
       if ((0, _primitives.isDict)(encrypt)) {
         var ids = trailerDict.get('ID');
         var fileId = ids && ids.length ? ids[0] : '';
         encrypt.suppressEncryption = true;
         this.encrypt = new _crypto.CipherTransformFactory(encrypt, fileId, this.pdfManager.password);
       }
-      if (!(this.root = trailerDict.get('Root'))) {
+      let root;
+      try {
+        root = trailerDict.get('Root');
+      } catch (ex) {
+        if (ex instanceof _util.MissingDataException) {
+          throw ex;
+        }
+        (0, _util.warn)(`XRef.parse - Invalid "Root" reference: "${ex}".`);
+      }
+      if ((0, _primitives.isDict)(root) && root.has('Pages')) {
+        this.root = root;
+      } else {
+        if (!recoveryMode) {
+          throw new _util.XRefParseException();
+        }
         throw new _util.FormatError('Invalid root reference');
       }
     },
     processXRefTable: function XRef_processXRefTable(parser) {
       if (!('tableState' in this)) {
         this.tableState = {
           entryNum: 0,
           streamPos: parser.lexer.stream.pos,
@@ -6729,17 +6746,17 @@ var XRef = function XRefClosure() {
             } else {
               let objToken = nestedObjRegExp.exec(tokenStr);
               if (objToken && objToken[1]) {
                 (0, _util.warn)('indexObjects: Found new "obj" inside of another "obj", ' + 'caused by missing "endobj" -- trying to recover.');
                 contentLength -= objToken[1].length;
                 break;
               }
             }
-            startPos += contentLength;
+            startPos = endPos;
           }
           let content = buffer.subarray(position, position + contentLength);
           var xrefTagOffset = skipUntil(content, 0, xrefBytes);
           if (xrefTagOffset < contentLength && content[xrefTagOffset + 5] < 64) {
             xrefStms.push(position - stream.start);
             this.xrefstms[position - stream.start] = 1;
           }
           position += contentLength;
@@ -6750,34 +6767,47 @@ var XRef = function XRefClosure() {
           position += token.length + 1;
         }
       }
       var i, ii;
       for (i = 0, ii = xrefStms.length; i < ii; ++i) {
         this.startXRefQueue.push(xrefStms[i]);
         this.readXRef(true);
       }
-      var dict;
+      let trailerDict;
       for (i = 0, ii = trailers.length; i < ii; ++i) {
         stream.pos = trailers[i];
         var parser = new _parser.Parser(new _parser.Lexer(stream), true, this, true);
         var obj = parser.getObj();
         if (!(0, _primitives.isCmd)(obj, 'trailer')) {
           continue;
         }
-        dict = parser.getObj();
+        let dict = parser.getObj();
         if (!(0, _primitives.isDict)(dict)) {
           continue;
         }
+        let rootDict;
+        try {
+          rootDict = dict.get('Root');
+        } catch (ex) {
+          if (ex instanceof _util.MissingDataException) {
+            throw ex;
+          }
+          continue;
+        }
+        if (!(0, _primitives.isDict)(rootDict) || !rootDict.has('Pages')) {
+          continue;
+        }
         if (dict.has('ID')) {
           return dict;
         }
-      }
-      if (dict) {
-        return dict;
+        trailerDict = dict;
+      }
+      if (trailerDict) {
+        return trailerDict;
       }
       throw new _util.InvalidPDFException('Invalid PDF structure');
     },
     readXRef: function XRef_readXRef(recoveryMode) {
       var stream = this.stream;
       let startXRefParsedCache = Object.create(null);
       try {
         while (this.startXRefQueue.length) {
@@ -8110,38 +8140,44 @@ var Lexer = function LexerClosure() {
     },
     peekChar: function Lexer_peekChar() {
       return this.stream.peekByte();
     },
     getNumber: function Lexer_getNumber() {
       var ch = this.currentChar;
       var eNotation = false;
       var divideBy = 0;
-      var sign = 1;
+      var sign = 0;
       if (ch === 0x2D) {
         sign = -1;
         ch = this.nextChar();
         if (ch === 0x2D) {
           ch = this.nextChar();
         }
       } else if (ch === 0x2B) {
-        ch = this.nextChar();
-      }
-      if (ch === 0x2E) {
-        divideBy = 10;
+        sign = 1;
         ch = this.nextChar();
       }
       if (ch === 0x0A || ch === 0x0D) {
         do {
           ch = this.nextChar();
         } while (ch === 0x0A || ch === 0x0D);
       }
+      if (ch === 0x2E) {
+        divideBy = 10;
+        ch = this.nextChar();
+      }
       if (ch < 0x30 || ch > 0x39) {
+        if (divideBy === 10 && sign === 0 && ((0, _util.isSpace)(ch) || ch === -1)) {
+          (0, _util.warn)('Lexer.getNumber - treating a single decimal point as zero.');
+          return 0;
+        }
         throw new _util.FormatError(`Invalid number: ${String.fromCharCode(ch)} (charCode ${ch})`);
       }
+      sign = sign || 1;
       var baseValue = ch - 0x30;
       var powerValue = 0;
       var powerValueSign = 1;
       while ((ch = this.nextChar()) >= 0) {
         if (0x30 <= ch && ch <= 0x39) {
           var currentDigit = ch - 0x30;
           if (eNotation) {
             powerValue = powerValue * 10 + currentDigit;
@@ -18797,17 +18833,17 @@ var OperatorList = function OperatorList
       this.addOp(_util.OPS.dependency, [dependency]);
     },
     addDependencies(dependencies) {
       for (var key in dependencies) {
         this.addDependency(key);
       }
     },
     addOpList(opList) {
-      _util.Util.extendObj(this.dependencies, opList.dependencies);
+      Object.assign(this.dependencies, opList.dependencies);
       for (var i = 0, ii = opList.length; i < ii; i++) {
         this.addOp(opList.fnArray[i], opList.argsArray[i]);
       }
     },
     getIR() {
       return {
         fnArray: this.fnArray,
         argsArray: this.argsArray,
--- a/browser/extensions/pdfjs/content/web/viewer.js
+++ b/browser/extensions/pdfjs/content/web/viewer.js
@@ -3201,20 +3201,16 @@ const defaultOptions = {
   externalLinkTarget: {
     value: 0,
     kind: OptionKind.VIEWER
   },
   imageResourcesPath: {
     value: './images/',
     kind: OptionKind.VIEWER
   },
-  locale: {
-    value: typeof navigator !== 'undefined' ? navigator.language : 'en-US',
-    kind: OptionKind.VIEWER
-  },
   maxCanvasPixels: {
     value: _viewer_compatibility.viewerCompatibilityParams.maxCanvasPixels || 16777216,
     kind: OptionKind.VIEWER
   },
   pdfBugEnabled: {
     value: false,
     kind: OptionKind.VIEWER
   },
@@ -3258,21 +3254,21 @@ const defaultOptions = {
     value: _pdfjsLib.apiCompatibilityParams.disableCreateObjectURL || false,
     kind: OptionKind.API
   },
   disableFontFace: {
     value: false,
     kind: OptionKind.API
   },
   disableRange: {
-    value: _pdfjsLib.apiCompatibilityParams.disableRange || false,
+    value: false,
     kind: OptionKind.API
   },
   disableStream: {
-    value: _pdfjsLib.apiCompatibilityParams.disableStream || false,
+    value: false,
     kind: OptionKind.API
   },
   isEvalSupported: {
     value: true,
     kind: OptionKind.API
   },
   maxImageSize: {
     value: -1,
@@ -3294,16 +3290,17 @@ const defaultOptions = {
     value: null,
     kind: OptionKind.WORKER
   },
   workerSrc: {
     value: '../build/pdf.worker.js',
     kind: OptionKind.WORKER
   }
 };
+;
 const userOptions = Object.create(null);
 class AppOptions {
   constructor() {
     throw new Error('Cannot initialize AppOptions.');
   }
   static get(name) {
     let defaultOption = defaultOptions[name],
         userOption = userOptions[name];
@@ -6344,17 +6341,17 @@ var _ui_utils = __webpack_require__(2);
 
 var _pdfjsLib = __webpack_require__(3);
 
 class PDFViewer extends _base_viewer.BaseViewer {
   get _setDocumentViewerElement() {
     return (0, _pdfjsLib.shadow)(this, '_setDocumentViewerElement', this.viewer);
   }
   _scrollIntoView({ pageDiv, pageSpot = null }) {
-    if (!pageSpot) {
+    if (!pageSpot && !this.isInPresentationMode) {
       const left = pageDiv.offsetLeft + pageDiv.clientLeft;
       const right = left + pageDiv.clientWidth;
       const { scrollLeft, clientWidth } = this.container;
       if (this.scrollMode === _base_viewer.ScrollMode.HORIZONTAL || left < scrollLeft || right > scrollLeft + clientWidth) {
         pageSpot = {
           left: 0,
           top: 0
         };
@@ -6405,37 +6402,79 @@ class PDFViewer extends _base_viewer.Bas
       this._setCurrentPageNumber(currentId);
     }
     this._updateLocation(visible.first);
     this.eventBus.dispatch('updateviewarea', {
       source: this,
       location: this._location
     });
   }
+  get _isScrollModeHorizontal() {
+    return this.isInPresentationMode ? false : this.scrollMode === _base_viewer.ScrollMode.HORIZONTAL;
+  }
+  setScrollMode(mode) {
+    if (mode === this.scrollMode) {
+      return;
+    }
+    super.setScrollMode(mode);
+    this.eventBus.dispatch('scrollmodechanged', { mode });
+    this._updateScrollModeClasses();
+    if (!this.pdfDocument) {
+      return;
+    }
+    const pageNumber = this._currentPageNumber;
+    if (isNaN(this._currentScaleValue)) {
+      this._setScale(this._currentScaleValue, true);
+    }
+    this.scrollPageIntoView({ pageNumber });
+    this.update();
+  }
+  _updateScrollModeClasses() {
+    const { scrollMode, viewer } = this;
+    if (scrollMode === _base_viewer.ScrollMode.HORIZONTAL) {
+      viewer.classList.add('scrollHorizontal');
+    } else {
+      viewer.classList.remove('scrollHorizontal');
+    }
+    if (scrollMode === _base_viewer.ScrollMode.WRAPPED) {
+      viewer.classList.add('scrollWrapped');
+    } else {
+      viewer.classList.remove('scrollWrapped');
+    }
+  }
+  setSpreadMode(mode) {
+    if (mode === this.spreadMode) {
+      return;
+    }
+    super.setSpreadMode(mode);
+    this.eventBus.dispatch('spreadmodechanged', { mode });
+    this._regroupSpreads();
+  }
   _regroupSpreads() {
-    const container = this._setDocumentViewerElement,
+    if (!this.pdfDocument) {
+      return;
+    }
+    const viewer = this.viewer,
           pages = this._pages;
-    while (container.firstChild) {
-      container.firstChild.remove();
-    }
+    viewer.textContent = '';
     if (this.spreadMode === _base_viewer.SpreadMode.NONE) {
       for (let i = 0, iMax = pages.length; i < iMax; ++i) {
-        container.appendChild(pages[i].div);
+        viewer.appendChild(pages[i].div);
       }
     } else {
       const parity = this.spreadMode - 1;
       let spread = null;
       for (let i = 0, iMax = pages.length; i < iMax; ++i) {
         if (spread === null) {
           spread = document.createElement('div');
           spread.className = 'spread';
-          container.appendChild(spread);
+          viewer.appendChild(spread);
         } else if (i % 2 === parity) {
           spread = spread.cloneNode(false);
-          container.appendChild(spread);
+          viewer.appendChild(spread);
         }
         spread.appendChild(pages[i].div);
       }
     }
     this.scrollPageIntoView({ pageNumber: this._currentPageNumber });
     this.update();
   }
 }
@@ -6549,17 +6588,19 @@ class BaseViewer {
       this.renderingQueue = options.renderingQueue;
     }
     this.scroll = (0, _ui_utils.watchScroll)(this.container, this._scrollUpdate.bind(this));
     this.presentationModeState = _ui_utils.PresentationModeState.UNKNOWN;
     this._resetView();
     if (this.removePageBorders) {
       this.viewer.classList.add('removePageBorders');
     }
-    this._updateScrollModeClasses();
+    if (this.scrollMode !== ScrollMode.VERTICAL) {
+      this._updateScrollModeClasses();
+    }
   }
   get pagesCount() {
     return this._pages.length;
   }
   getPageView(index) {
     return this._pages[index];
   }
   get pageViewsReady() {
@@ -6853,19 +6894,20 @@ class BaseViewer {
     let scale = parseFloat(value);
     if (scale > 0) {
       this._setScaleUpdatePages(scale, value, noScroll, false);
     } else {
       let currentPage = this._pages[this._currentPageNumber - 1];
       if (!currentPage) {
         return;
       }
-      let hPadding = this.isInPresentationMode || this.removePageBorders ? 0 : _ui_utils.SCROLLBAR_PADDING;
-      let vPadding = this.isInPresentationMode || this.removePageBorders ? 0 : _ui_utils.VERTICAL_PADDING;
-      if (this.scrollMode === ScrollMode.HORIZONTAL) {
+      const noPadding = this.isInPresentationMode || this.removePageBorders;
+      let hPadding = noPadding ? 0 : _ui_utils.SCROLLBAR_PADDING;
+      let vPadding = noPadding ? 0 : _ui_utils.VERTICAL_PADDING;
+      if (!noPadding && this._isScrollModeHorizontal) {
         const temp = hPadding;
         hPadding = vPadding;
         vPadding = temp;
       }
       let pageWidthScale = (this.container.clientWidth - hPadding) / currentPage.width * currentPage.scale;
       let pageHeightScale = (this.container.clientHeight - vPadding) / currentPage.height * currentPage.scale;
       switch (value) {
         case 'page-actual':
@@ -7025,16 +7067,19 @@ class BaseViewer {
     throw new Error('Not implemented: update');
   }
   containsElement(element) {
     return this.container.contains(element);
   }
   focus() {
     this.container.focus();
   }
+  get _isScrollModeHorizontal() {
+    throw new Error('Not implemented: _isScrollModeHorizontal');
+  }
   get isInPresentationMode() {
     return this.presentationModeState === _ui_utils.PresentationModeState.FULLSCREEN;
   }
   get isChangingPresentationMode() {
     return this.presentationModeState === _ui_utils.PresentationModeState.CHANGING;
   }
   get isHorizontalScrollbarEnabled() {
     return this.isInPresentationMode ? false : this.container.scrollWidth > this.container.clientWidth;
@@ -7077,17 +7122,17 @@ class BaseViewer {
       console.error('Unable to get page for page view', reason);
       this._pagesRequests[pageNumber] = null;
     });
     this._pagesRequests[pageNumber] = promise;
     return promise;
   }
   forceRendering(currentlyVisiblePages) {
     let visiblePages = currentlyVisiblePages || this._getVisiblePages();
-    let scrollAhead = this.scrollMode === ScrollMode.HORIZONTAL ? this.scroll.right : this.scroll.down;
+    let scrollAhead = this._isScrollModeHorizontal ? this.scroll.right : this.scroll.down;
     let pageView = this.renderingQueue.getHighestPriority(visiblePages, this._pages, scrollAhead);
     if (pageView) {
       this._ensurePdfPageLoaded(pageView).then(() => {
         this.renderingQueue.renderView(pageView);
       });
       return true;
     }
     return false;
@@ -7151,40 +7196,27 @@ class BaseViewer {
       return {
         width: size.height,
         height: size.width,
         rotation: (size.rotation + 90) % 360
       };
     });
   }
   setScrollMode(mode) {
-    if (mode !== this.scrollMode) {
-      this.scrollMode = mode;
-      this._updateScrollModeClasses();
-      this.eventBus.dispatch('scrollmodechanged', { mode });
-      const pageNumber = this._currentPageNumber;
-      if (isNaN(this._currentScaleValue)) {
-        this._setScale(this._currentScaleValue, this.isInPresentationMode);
-      }
-      this.scrollPageIntoView({ pageNumber });
-      this.update();
-    }
-  }
-  _updateScrollModeClasses() {
-    const mode = this.scrollMode,
-          { classList } = this.viewer;
-    classList.toggle('scrollHorizontal', mode === ScrollMode.HORIZONTAL);
-    classList.toggle('scrollWrapped', mode === ScrollMode.WRAPPED);
-  }
+    if (!Number.isInteger(mode) || !Object.values(ScrollMode).includes(mode)) {
+      throw new Error(`Invalid scroll mode: ${mode}`);
+    }
+    this.scrollMode = mode;
+  }
+  _updateScrollModeClasses() {}
   setSpreadMode(mode) {
-    if (mode !== this.spreadMode) {
-      this.spreadMode = mode;
-      this.eventBus.dispatch('spreadmodechanged', { mode });
-      this._regroupSpreads();
-    }
+    if (!Number.isInteger(mode) || !Object.values(SpreadMode).includes(mode)) {
+      throw new Error(`Invalid spread mode: ${mode}`);
+    }
+    this.spreadMode = mode;
   }
   _regroupSpreads() {}
 }
 exports.BaseViewer = BaseViewer;
 exports.ScrollMode = ScrollMode;
 exports.SpreadMode = SpreadMode;
 
 /***/ }),
@@ -8171,26 +8203,48 @@ class SecondaryToolbar {
         case _pdf_cursor_tools.CursorTool.HAND:
           buttons.cursorHandToolButton.classList.add('toggled');
           break;
       }
     });
   }
   _bindScrollModeListener(buttons) {
     this.eventBus.on('scrollmodechanged', function (evt) {
-      buttons.scrollVerticalButton.classList.toggle('toggled', evt.mode === _base_viewer.ScrollMode.VERTICAL);
-      buttons.scrollHorizontalButton.classList.toggle('toggled', evt.mode === _base_viewer.ScrollMode.HORIZONTAL);
-      buttons.scrollWrappedButton.classList.toggle('toggled', evt.mode === _base_viewer.ScrollMode.WRAPPED);
+      buttons.scrollVerticalButton.classList.remove('toggled');
+      buttons.scrollHorizontalButton.classList.remove('toggled');
+      buttons.scrollWrappedButton.classList.remove('toggled');
+      switch (evt.mode) {
+        case _base_viewer.ScrollMode.VERTICAL:
+          buttons.scrollVerticalButton.classList.add('toggled');
+          break;
+        case _base_viewer.ScrollMode.HORIZONTAL:
+          buttons.scrollHorizontalButton.classList.add('toggled');
+          break;
+        case _base_viewer.ScrollMode.WRAPPED:
+          buttons.scrollWrappedButton.classList.add('toggled');
+          break;
+      }
     });
   }
   _bindSpreadModeListener(buttons) {
     this.eventBus.on('spreadmodechanged', function (evt) {
-      buttons.spreadNoneButton.classList.toggle('toggled', evt.mode === _base_viewer.SpreadMode.NONE);
-      buttons.spreadOddButton.classList.toggle('toggled', evt.mode === _base_viewer.SpreadMode.ODD);
-      buttons.spreadEvenButton.classList.toggle('toggled', evt.mode === _base_viewer.SpreadMode.EVEN);
+      buttons.spreadNoneButton.classList.remove('toggled');
+      buttons.spreadOddButton.classList.remove('toggled');
+      buttons.spreadEvenButton.classList.remove('toggled');
+      switch (evt.mode) {
+        case _base_viewer.SpreadMode.NONE:
+          buttons.spreadNoneButton.classList.add('toggled');
+          break;
+        case _base_viewer.SpreadMode.ODD:
+          buttons.spreadOddButton.classList.add('toggled');
+          break;
+        case _base_viewer.SpreadMode.EVEN:
+          buttons.spreadEvenButton.classList.add('toggled');
+          break;
+      }
     });
   }
   open() {
     if (this.opened) {
       return;
     }
     this.opened = true;
     this._setMaxHeight();