Bug 1527714 - Update pdf.js to version 2.1.266. r=bdahl
authorRyan VanderMeulen <ryanvm@gmail.com>
Wed, 13 Feb 2019 15:17:21 -0500
changeset 516860 6448f6a14609745b0f4d18f539123576efa32abe
parent 516859 f405cc68a129277e3532d364f09134ddf3238175
child 516861 6d917b008b34ffec42c5679c581b231da28bea68
push id10862
push userffxbld-merge
push dateMon, 11 Mar 2019 13:01:11 +0000
treeherdermozilla-beta@a2e7f5c935da [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbdahl
bugs1527714
milestone67.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 1527714 - Update pdf.js to version 2.1.266. 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/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.2.8
+Current extension version is: 2.1.266
 
-Taken from upstream commit: dfe7d9bc
+Taken from upstream commit: 81f5835c
--- 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.2.8';
-var pdfjsBuild = 'dfe7d9bc';
+var pdfjsVersion = '2.1.266';
+var pdfjsBuild = '81f5835c';
 
 var pdfjsSharedUtil = __w_pdfjs_require__(1);
 
 var pdfjsDisplayAPI = __w_pdfjs_require__(6);
 
 var pdfjsDisplayTextLayer = __w_pdfjs_require__(18);
 
 var pdfjsDisplayAnnotationLayer = __w_pdfjs_require__(19);
@@ -1406,17 +1406,17 @@ function _fetchDocument(worker, source, 
 
   if (pdfDataRangeTransport) {
     source.length = pdfDataRangeTransport.length;
     source.initialData = pdfDataRangeTransport.initialData;
   }
 
   return worker.messageHandler.sendWithPromise('GetDocRequest', {
     docId,
-    apiVersion: '2.2.8',
+    apiVersion: '2.1.266',
     source: {
       data: source.data,
       url: source.url,
       password: source.password,
       disableAutoFetch: source.disableAutoFetch,
       rangeChunkSize: source.rangeChunkSize,
       length: source.length
     },
@@ -2334,17 +2334,20 @@ const PDFWorker = function PDFWorkerClos
 
 exports.PDFWorker = PDFWorker;
 
 class WorkerTransport {
   constructor(messageHandler, loadingTask, networkStream, params) {
     this.messageHandler = messageHandler;
     this.loadingTask = loadingTask;
     this.commonObjs = new PDFObjects();
-    this.fontLoader = new _font_loader.FontLoader(loadingTask.docId);
+    this.fontLoader = new _font_loader.FontLoader({
+      docId: loadingTask.docId,
+      onUnsupportedFeature: this._onUnsupportedFeature.bind(this)
+    });
     this._params = params;
     this.CMapReaderFactory = new params.CMapReaderFactory({
       baseUrl: params.cMapUrl,
       isCompressed: params.cMapPacked
     });
     this.destroyed = false;
     this.destroyCapability = null;
     this._passwordCapability = null;
@@ -2595,22 +2598,25 @@ class WorkerTransport {
 
           const font = new _font_loader.FontFaceObject(exportedData, {
             isEvalSupported: params.isEvalSupported,
             disableFontFace: params.disableFontFace,
             ignoreErrors: params.ignoreErrors,
             onUnsupportedFeature: this._onUnsupportedFeature.bind(this),
             fontRegistry
           });
-
-          const fontReady = fontObjs => {
+          this.fontLoader.bind(font).then(() => {
             this.commonObjs.resolve(id, font);
-          };
-
-          this.fontLoader.bind([font], fontReady);
+          }, reason => {
+            messageHandler.sendWithPromise('FontFallback', {
+              id
+            }).finally(() => {
+              this.commonObjs.resolve(id, font);
+            });
+          });
           break;
 
         case 'FontPath':
           this.commonObjs.resolve(id, exportedData);
           break;
 
         default:
           throw new Error(`Got unknown common object type ${type}`);
@@ -3137,19 +3143,19 @@ const InternalRenderTask = function Inte
       }
     }
 
   }
 
   return InternalRenderTask;
 }();
 
-const version = '2.2.8';
+const version = '2.1.266';
 exports.version = version;
-const build = 'dfe7d9bc';
+const build = '81f5835c';
 exports.build = build;
 
 /***/ }),
 /* 7 */
 /***/ (function(module, exports, __w_pdfjs_require__) {
 
 "use strict";
 
@@ -3554,28 +3560,28 @@ function loadScript(src) {
 Object.defineProperty(exports, "__esModule", {
   value: true
 });
 exports.FontLoader = exports.FontFaceObject = void 0;
 
 var _util = __w_pdfjs_require__(1);
 
 class BaseFontLoader {
-  constructor(docId) {
+  constructor({
+    docId,
+    onUnsupportedFeature
+  }) {
     if (this.constructor === BaseFontLoader) {
       (0, _util.unreachable)('Cannot initialize BaseFontLoader.');
     }
 
     this.docId = docId;
+    this._onUnsupportedFeature = onUnsupportedFeature;
     this.nativeFontFaces = [];
     this.styleElement = null;
-    this.loadingContext = {
-      requests: [],
-      nextRequestId: 0
-    };
   }
 
   addNativeFontFace(nativeFontFace) {
     this.nativeFontFaces.push(nativeFontFace);
     document.fonts.add(nativeFontFace);
   }
 
   insertRule(rule) {
@@ -3598,83 +3604,64 @@ class BaseFontLoader {
     this.nativeFontFaces.length = 0;
 
     if (this.styleElement) {
       this.styleElement.remove();
       this.styleElement = null;
     }
   }
 
-  bind(fonts, callback) {
-    const rules = [];
-    const fontsToLoad = [];
-    const fontLoadPromises = [];
-
-    const getNativeFontPromise = function (nativeFontFace) {
-      return nativeFontFace.loaded.catch(function (reason) {
-        (0, _util.warn)(`Failed to load font "${nativeFontFace.family}": ${reason}`);
-      });
-    };
-
-    for (const font of fonts) {
-      if (font.attached || font.missingFile) {
-        continue;
-      }
-
-      font.attached = true;
-
-      if (this.isFontLoadingAPISupported) {
-        const nativeFontFace = font.createNativeFontFace();
-
-        if (nativeFontFace) {
-          this.addNativeFontFace(nativeFontFace);
-          fontLoadPromises.push(getNativeFontPromise(nativeFontFace));
-        }
-      } else {
-        const rule = font.createFontFaceRule();
-
-        if (rule) {
-          this.insertRule(rule);
-          rules.push(rule);
-          fontsToLoad.push(font);
-        }
-      }
-    }
-
-    const request = this._queueLoadingCallback(callback);
+  async bind(font) {
+    if (font.attached || font.missingFile) {
+      return;
+    }
+
+    font.attached = true;
 
     if (this.isFontLoadingAPISupported) {
-      Promise.all(fontLoadPromises).then(request.complete);
-    } else if (rules.length > 0 && !this.isSyncFontLoadingSupported) {
-      this._prepareFontLoadEvent(rules, fontsToLoad, request);
-    } else {
-      request.complete();
+      const nativeFontFace = font.createNativeFontFace();
+
+      if (nativeFontFace) {
+        this.addNativeFontFace(nativeFontFace);
+
+        try {
+          await nativeFontFace.loaded;
+        } catch (ex) {
+          this._onUnsupportedFeature({
+            featureId: _util.UNSUPPORTED_FEATURES.font
+          });
+
+          (0, _util.warn)(`Failed to load font '${nativeFontFace.family}': '${ex}'.`);
+          font.disableFontFace = true;
+          throw ex;
+        }
+      }
+
+      return;
+    }
+
+    const rule = font.createFontFaceRule();
+
+    if (rule) {
+      this.insertRule(rule);
+
+      if (this.isSyncFontLoadingSupported) {
+        return;
+      }
+
+      return new Promise(resolve => {
+        const request = this._queueLoadingCallback(resolve);
+
+        this._prepareFontLoadEvent([rule], [font], request);
+      });
     }
   }
 
   _queueLoadingCallback(callback) {
-    function completeRequest() {
-      (0, _util.assert)(!request.done, 'completeRequest() cannot be called twice.');
-      request.done = true;
-
-      while (context.requests.length > 0 && context.requests[0].done) {
-        const otherRequest = context.requests.shift();
-        setTimeout(otherRequest.callback, 0);
-      }
-    }
-
-    const context = this.loadingContext;
-    const request = {
-      id: `pdfjs-font-loading-${context.nextRequestId++}`,
-      done: false,
-      complete: completeRequest,
-      callback
-    };
-    context.requests.push(request);
-    return request;
+    (0, _util.unreachable)('Abstract method `_queueLoadingCallback`.');
   }
 
   get isFontLoadingAPISupported() {
     (0, _util.unreachable)('Abstract method `isFontLoadingAPISupported`.');
   }
 
   get isSyncFontLoadingSupported() {
     (0, _util.unreachable)('Abstract method `isSyncFontLoadingSupported`.');
--- 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.2.8';
-const pdfjsBuild = 'dfe7d9bc';
+const pdfjsVersion = '2.1.266';
+const pdfjsBuild = '81f5835c';
 
 const pdfjsCoreWorker = __w_pdfjs_require__(1);
 
 exports.WorkerMessageHandler = pdfjsCoreWorker.WorkerMessageHandler;
 
 /***/ }),
 /* 1 */
 /***/ (function(module, exports, __w_pdfjs_require__) {
@@ -370,17 +370,17 @@ var WorkerMessageHandler = {
   },
 
   createDocumentHandler(docParams, port) {
     var pdfManager;
     var terminated = false;
     var cancelXHRs = null;
     var WorkerTasks = [];
     let apiVersion = docParams.apiVersion;
-    let workerVersion = '2.2.8';
+    let workerVersion = '2.1.266';
 
     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';
@@ -761,16 +761,19 @@ var WorkerMessageHandler = {
             return;
           }
 
           sink.error(reason);
           throw reason;
         });
       });
     });
+    handler.on('FontFallback', function (data) {
+      return pdfManager.fontFallback(data.id, handler);
+    });
     handler.on('Cleanup', function wphCleanup(data) {
       return pdfManager.cleanup();
     });
     handler.on('Terminate', function wphTerminate(data) {
       terminated = true;
 
       if (pdfManager) {
         pdfManager.terminate();
@@ -1900,16 +1903,20 @@ class BasePdfManager {
   ensureCatalog(prop, args) {
     return this.ensure(this.pdfDocument.catalog, prop, args);
   }
 
   getPage(pageIndex) {
     return this.pdfDocument.getPage(pageIndex);
   }
 
+  fontFallback(id, handler) {
+    return this.pdfDocument.fontFallback(id, handler);
+  }
+
   cleanup() {
     return this.pdfDocument.cleanup();
   }
 
   async ensure(obj, prop, args) {
     (0, _util.unreachable)('Abstract method `ensure` called');
   }
 
@@ -3264,16 +3271,20 @@ class PDFDocument {
       if (reason instanceof _util.XRefEntryException) {
         this._pagePromises.length = 0;
         this.cleanup();
         throw new _util.XRefParseException();
       }
     });
   }
 
+  fontFallback(id, handler) {
+    return this.catalog.fontFallback(id, handler);
+  }
+
   cleanup() {
     return this.catalog.cleanup();
   }
 
 }
 
 exports.PDFDocument = PDFDocument;
 
@@ -3809,16 +3820,31 @@ class Catalog {
       } else {
         appendIfJavaScriptDict(openActionDict);
       }
     }
 
     return (0, _util.shadow)(this, 'javaScript', javaScript);
   }
 
+  fontFallback(id, handler) {
+    const promises = [];
+    this.fontCache.forEach(function (promise) {
+      promises.push(promise);
+    });
+    return Promise.all(promises).then(translatedFonts => {
+      for (const translatedFont of translatedFonts) {
+        if (translatedFont.loadedName === id) {
+          translatedFont.fallback(handler);
+          return;
+        }
+      }
+    });
+  }
+
   cleanup() {
     this.pageKidsCountCache.clear();
     const promises = [];
     this.fontCache.forEach(function (promise) {
       promises.push(promise);
     });
     return Promise.all(promises).then(translatedFonts => {
       for (let i = 0, ii = translatedFonts.length; i < ii; i++) {
@@ -20062,42 +20088,32 @@ var PartialEvaluator = function PartialE
           return new TranslatedFont('g_font_error', new _fonts.ErrorFont('Type3 font load error: ' + reason), translated.font);
         });
       }).then(translated => {
         state.font = translated.font;
         translated.send(this.handler);
         return translated.loadedName;
       });
     },
-    handleText: function PartialEvaluator_handleText(chars, state) {
-      var font = state.font;
-      var glyphs = font.charsToGlyphs(chars);
-      var isAddToPathSet = !!(state.textRenderingMode & _util.TextRenderingMode.ADD_TO_PATH_FLAG);
-
-      if (font.data && (isAddToPathSet || this.options.disableFontFace || state.fillColorSpace.name === 'Pattern')) {
-        var buildPath = fontChar => {
-          if (!font.renderer.hasBuiltPath(fontChar)) {
-            var path = font.renderer.getPathJs(fontChar);
-            this.handler.send('commonobj', [font.loadedName + '_path_' + fontChar, 'FontPath', path]);
-          }
-        };
-
-        for (var i = 0, ii = glyphs.length; i < ii; i++) {
-          var glyph = glyphs[i];
-          buildPath(glyph.fontChar);
-          var accent = glyph.accent;
-
-          if (accent && accent.fontChar) {
-            buildPath(accent.fontChar);
-          }
+
+    handleText(chars, state) {
+      const font = state.font;
+      const glyphs = font.charsToGlyphs(chars);
+
+      if (font.data) {
+        const isAddToPathSet = !!(state.textRenderingMode & _util.TextRenderingMode.ADD_TO_PATH_FLAG);
+
+        if (isAddToPathSet || state.fillColorSpace.name === 'Pattern' || font.disableFontFace || this.options.disableFontFace) {
+          PartialEvaluator.buildFontPaths(font, glyphs, this.handler);
         }
       }
 
       return glyphs;
     },
+
     setGState: function PartialEvaluator_setGState(resources, gState, operatorList, task, stateManager) {
       var gStateObj = [];
       var gStateKeys = gState.getKeys();
       var promise = Promise.resolve();
 
       for (var i = 0, ii = gStateKeys.length; i < ii; i++) {
         let key = gStateKeys[i];
         let value = gState.get(key);
@@ -22006,16 +22022,36 @@ var PartialEvaluator = function PartialE
         if (type === 'Type3') {
           properties.isType3Font = true;
         }
 
         return new _fonts.Font(fontName.name, fontFile, properties);
       });
     }
   };
+
+  PartialEvaluator.buildFontPaths = function (font, glyphs, handler) {
+    function buildPath(fontChar) {
+      if (font.renderer.hasBuiltPath(fontChar)) {
+        return;
+      }
+
+      handler.send('commonobj', [`${font.loadedName}_path_${fontChar}`, 'FontPath', font.renderer.getPathJs(fontChar)]);
+    }
+
+    for (const glyph of glyphs) {
+      buildPath(glyph.fontChar);
+      const accent = glyph.accent;
+
+      if (accent && accent.fontChar) {
+        buildPath(accent.fontChar);
+      }
+    }
+  };
+
   return PartialEvaluator;
 }();
 
 exports.PartialEvaluator = PartialEvaluator;
 
 var TranslatedFont = function TranslatedFontClosure() {
   function TranslatedFont(loadedName, font, dict) {
     this.loadedName = loadedName;
@@ -22026,19 +22062,28 @@ var TranslatedFont = function Translated
   }
 
   TranslatedFont.prototype = {
     send(handler) {
       if (this.sent) {
         return;
       }
 
-      var fontData = this.font.exportData();
-      handler.send('commonobj', [this.loadedName, 'Font', fontData]);
       this.sent = true;
+      handler.send('commonobj', [this.loadedName, 'Font', this.font.exportData()]);
+    },
+
+    fallback(handler) {
+      if (!this.font.data) {
+        return;
+      }
+
+      this.font.disableFontFace = true;
+      const glyphs = this.font.glyphCacheValues;
+      PartialEvaluator.buildFontPaths(this.font, glyphs, handler);
     },
 
     loadType3Data(evaluator, resources, parentOperatorList, task) {
       if (!this.font.isType3Font) {
         throw new Error('Must be a Type3 font.');
       }
 
       if (this.type3Loaded) {
@@ -24592,16 +24637,17 @@ var Font = function FontClosure() {
     return nameTable;
   }
 
   Font.prototype = {
     name: null,
     font: null,
     mimetype: null,
     encoding: null,
+    disableFontFace: false,
 
     get renderer() {
       var renderer = _font_renderer.FontRendererFactory.create(this, SEAC_ANALYSIS_ENABLED);
 
       return (0, _util.shadow)(this, 'renderer', renderer);
     },
 
     exportData: function Font_exportData() {
@@ -26283,17 +26329,22 @@ var Font = function FontClosure() {
         for (i = 0, ii = chars.length; i < ii; ++i) {
           charcode = chars.charCodeAt(i);
           glyph = this.charToGlyph(charcode, charcode === 0x20);
           glyphs.push(glyph);
         }
       }
 
       return charsCache[charsCacheKey] = glyphs;
-    }
+    },
+
+    get glyphCacheValues() {
+      return Object.values(this.glyphCache);
+    }
+
   };
   return Font;
 }();
 
 exports.Font = Font;
 
 var ErrorFont = function ErrorFontClosure() {
   function ErrorFont(error) {
--- 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.2.8
+  release: version 2.1.266
 
   # 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