From dcc7f33ee7ee0790ee34e2106a8d04254bc66c8c Mon Sep 17 00:00:00 2001
From: Jonas Jenwald <jonas.jenwald@gmail.com>
Date: Fri, 1 Jun 2018 12:52:06 +0200
Subject: [PATCH 1/4] Prevent "ReferenceError: window is not defined" errors,
 from `web/ui_utils.js`, when running the unit-tests in Node.js/Travis

---
 web/ui_utils.js | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/web/ui_utils.js b/web/ui_utils.js
index 0c506f983..1728d8b8c 100644
--- a/web/ui_utils.js
+++ b/web/ui_utils.js
@@ -681,6 +681,13 @@ function waitOnEventOrTimeout({ target, name, delay = 0, }) {
  * Promise that is resolved when DOM window becomes visible.
  */
 let animationStarted = new Promise(function (resolve) {
+  if ((typeof PDFJSDev !== 'undefined' && PDFJSDev.test('LIB')) &&
+      typeof window === 'undefined') {
+    // Prevent "ReferenceError: window is not defined" errors when running the
+    // unit-tests in Node.js/Travis.
+    setTimeout(resolve, 20);
+    return;
+  }
   window.requestAnimationFrame(resolve);
 });
 

From 0ecc22cb04b54e57bbe0e498791f9a604c8c2e57 Mon Sep 17 00:00:00 2001
From: Jonas Jenwald <jonas.jenwald@gmail.com>
Date: Fri, 1 Jun 2018 12:52:29 +0200
Subject: [PATCH 2/4] Attempt to provide better default values for the
 `disableFontFace`/`nativeImageDecoderSupport` API options in Node.js

This should provide a better out-of-the-box experience when using PDF.js in a Node.js environment, since it's missing native support for both `@font-face` and `Image`.
Please note that this change *only* affects the default values, hence it's still possible for an API consumer to override those values when calling `getDocument`.

Also, prevents "ReferenceError: document is not defined" errors, when running the unit-tests in Node.js/Travis.
---
 examples/node/pdf2png/pdf2png.js | 10 ++--------
 src/display/api.js               |  8 ++++++--
 src/display/api_compatibility.js | 18 +++++++++++++-----
 web/viewer_compatibility.js      |  5 +----
 4 files changed, 22 insertions(+), 19 deletions(-)

diff --git a/examples/node/pdf2png/pdf2png.js b/examples/node/pdf2png/pdf2png.js
index d42ba4b40..ae739a35b 100644
--- a/examples/node/pdf2png/pdf2png.js
+++ b/examples/node/pdf2png/pdf2png.js
@@ -56,14 +56,8 @@ var pdfURL = '../../../web/compressed.tracemonkey-pldi-09.pdf';
 // Read the PDF file into a typed array so PDF.js can load it.
 var rawData = new Uint8Array(fs.readFileSync(pdfURL));
 
-// Load the PDF file. The `disableFontFace` and `nativeImageDecoderSupport`
-// options must be passed because Node.js has no native `@font-face` and
-// `Image` support.
-pdfjsLib.getDocument({
-  data: rawData,
-  disableFontFace: true,
-  nativeImageDecoderSupport: 'none',
-}).then(function (pdfDocument) {
+// Load the PDF file.
+pdfjsLib.getDocument(rawData).then(function (pdfDocument) {
   console.log('# PDF document loaded.');
 
   // Get the first page.
diff --git a/src/display/api.js b/src/display/api.js
index 4f7259c50..ca673438b 100644
--- a/src/display/api.js
+++ b/src/display/api.js
@@ -274,7 +274,9 @@ function getDocument(src) {
   const NativeImageDecoderValues = Object.values(NativeImageDecoding);
   if (params.nativeImageDecoderSupport === undefined ||
       !NativeImageDecoderValues.includes(params.nativeImageDecoderSupport)) {
-    params.nativeImageDecoderSupport = NativeImageDecoding.DECODE;
+    params.nativeImageDecoderSupport =
+      (apiCompatibilityParams.nativeImageDecoderSupport ||
+       NativeImageDecoding.DECODE);
   }
   if (!Number.isInteger(params.maxImageSize)) {
     params.maxImageSize = -1;
@@ -283,7 +285,7 @@ function getDocument(src) {
     params.isEvalSupported = true;
   }
   if (typeof params.disableFontFace !== 'boolean') {
-    params.disableFontFace = false;
+    params.disableFontFace = apiCompatibilityParams.disableFontFace || false;
   }
 
   if (typeof params.disableRange !== 'boolean') {
@@ -2168,6 +2170,8 @@ var WorkerTransport = (function WorkerTransportClosure() {
         disableStream: params.disableStream,
         disableAutoFetch: params.disableAutoFetch,
         disableCreateObjectURL: params.disableCreateObjectURL,
+        disableFontFace: params.disableFontFace,
+        nativeImageDecoderSupport: params.nativeImageDecoderSupport,
       });
     },
   };
diff --git a/src/display/api_compatibility.js b/src/display/api_compatibility.js
index 09e283e75..beb49fe65 100644
--- a/src/display/api_compatibility.js
+++ b/src/display/api_compatibility.js
@@ -15,6 +15,8 @@
 
 let compatibilityParams = Object.create(null);
 if (typeof PDFJSDev === 'undefined' || PDFJSDev.test('GENERIC')) {
+  const isNodeJS = require('../shared/is_node');
+
   const userAgent =
     (typeof navigator !== 'undefined' && navigator.userAgent) || '';
   const isIE = /Trident/.test(userAgent);
@@ -42,9 +44,15 @@ if (typeof PDFJSDev === 'undefined' || PDFJSDev.test('GENERIC')) {
       compatibilityParams.disableStream = true;
     }
   })();
-}
-const apiCompatibilityParams = Object.freeze(compatibilityParams);
 
-export {
-  apiCompatibilityParams,
-};
+  // Support: Node.js
+  (function checkFontFaceAndImage() {
+    // Node.js is missing native support for `@font-face` and `Image`.
+    if (isNodeJS()) {
+      compatibilityParams.disableFontFace = true;
+      compatibilityParams.nativeImageDecoderSupport = 'none';
+    }
+  })();
+}
+
+exports.apiCompatibilityParams = Object.freeze(compatibilityParams);
diff --git a/web/viewer_compatibility.js b/web/viewer_compatibility.js
index e6aadea80..2debdc412 100644
--- a/web/viewer_compatibility.js
+++ b/web/viewer_compatibility.js
@@ -37,8 +37,5 @@ if (typeof PDFJSDev === 'undefined' || PDFJSDev.test('GENERIC')) {
     }
   })();
 }
-const viewerCompatibilityParams = Object.freeze(compatibilityParams);
 
-export {
-  viewerCompatibilityParams,
-};
+exports.viewerCompatibilityParams = Object.freeze(compatibilityParams);

From ef081a053182bb323d3c769e8f6ed11b35c4357c Mon Sep 17 00:00:00 2001
From: Jonas Jenwald <jonas.jenwald@gmail.com>
Date: Fri, 1 Jun 2018 12:52:47 +0200
Subject: [PATCH 3/4] Ensure that the `WorkerTransport._passwordCapability` is
 always rejected, even when errors are thrown in
 `PDFDocumentLoadingTask.onPassword` callback

Please note that while the current code works, both in the viewer and the unit-tests, it can leave the `WorkerTransport._passwordCapability` Promise in a pending state.
In the `PasswordRequest` handler, in src/display/api.js, we're returning the Promise from a `capability` object (rather than just a "plain" Promise). While an error thrown anywhere within this handler was fortunately enough to propagate it to the Worker side, it won't cause the Promise (in `WorkerTransport._passwordCapability`) to actually be rejected.
Finally note that while we're now catching errors in the `PasswordRequest` handler, those errors are still propagated to the Worker side via the (now) rejected Promise and the existing `return this._passwordCapability.promise;` line.

This prevents warnings about uncaught Promises, with messages such as "Error: Worker was destroyed during onPassword callback", when running the unit-tests both in browsers *and* in Node.js/Travis.
---
 src/core/worker.js | 4 ++--
 src/display/api.js | 6 +++++-
 2 files changed, 7 insertions(+), 3 deletions(-)

diff --git a/src/core/worker.js b/src/core/worker.js
index 742718aad..72c381a60 100644
--- a/src/core/worker.js
+++ b/src/core/worker.js
@@ -574,9 +574,9 @@ var WorkerMessageHandler = {
             finishWorkerTask(task);
             pdfManager.updatePassword(data.password);
             pdfManagerReady();
-          }).catch(function (ex) {
+          }).catch(function (boundException) {
             finishWorkerTask(task);
-            handler.send('PasswordException', ex);
+            handler.send('PasswordException', boundException);
           }.bind(null, e));
         } else if (e instanceof InvalidPDFException) {
           handler.send('InvalidPDF', e);
diff --git a/src/display/api.js b/src/display/api.js
index ca673438b..0003b8090 100644
--- a/src/display/api.js
+++ b/src/display/api.js
@@ -1788,7 +1788,11 @@ var WorkerTransport = (function WorkerTransportClosure() {
               password,
             });
           };
-          loadingTask.onPassword(updatePassword, exception.code);
+          try {
+            loadingTask.onPassword(updatePassword, exception.code);
+          } catch (ex) {
+            this._passwordCapability.reject(ex);
+          }
         } else {
           this._passwordCapability.reject(
             new PasswordException(exception.message, exception.code));

From 11b4613e203d48c896fc66a24f228ca4e40549f5 Mon Sep 17 00:00:00 2001
From: Jonas Jenwald <jonas.jenwald@gmail.com>
Date: Fri, 1 Jun 2018 12:56:46 +0200
Subject: [PATCH 4/4] Reduce the amount of console "spam", by ignoring
 `info`/`warn` calls, when running the unit-tests in Node.js/Travis

Compared to running the unit-tests in "regular" browsers, where any console output won't get mixed up with test output, in Node.js/Travis the test output looks quite noisy.
By ignoring `info`/`warn` calls, when running unit-tests in Node.js/Travis, the test output is a lot smaller not to mention that any *actual* failures are more easily spotted.
---
 test/unit/clitests_helper.js | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/test/unit/clitests_helper.js b/test/unit/clitests_helper.js
index 15f6ffa2d..11d9475e9 100644
--- a/test/unit/clitests_helper.js
+++ b/test/unit/clitests_helper.js
@@ -13,6 +13,7 @@
  * limitations under the License.
  */
 
+import { setVerbosityLevel, VerbosityLevel } from '../../src/shared/util';
 import isNodeJS from '../../src/shared/is_node';
 import { PDFNodeStream } from '../../src/display/node_stream';
 import { setPDFNetworkStreamFactory } from '../../src/display/api';
@@ -23,6 +24,10 @@ if (!isNodeJS()) {
                   'Node.js environments.');
 }
 
+// Reduce the amount of console "spam", by ignoring `info`/`warn` calls,
+// when running the unit-tests in Node.js/Travis.
+setVerbosityLevel(VerbosityLevel.ERRORS);
+
 // Set the network stream factory for the unit-tests.
 setPDFNetworkStreamFactory(function(params) {
   return new PDFNodeStream(params);