Browse Source

PDF.js version 2.8.335 - See https://github.com/mozilla/pdf.js/releases/tag/v2.8.335

pdfjsbot 4 years ago
parent
commit
75158b4de0
100 changed files with 7803 additions and 4369 deletions
  1. 1 1
      README.md
  2. 1 1
      bower.json
  3. 242 433
      build/pdf.js
  4. 0 0
      build/pdf.js.map
  5. 1 1
      build/pdf.min.js
  6. 39 0
      build/pdf.sandbox.js
  7. 0 0
      build/pdf.sandbox.js.map
  8. 21 0
      build/pdf.sandbox.min.js
  9. 1 1
      build/pdf.worker.entry.js
  10. 381 218
      build/pdf.worker.js
  11. 0 0
      build/pdf.worker.js.map
  12. 1 1
      build/pdf.worker.min.js
  13. 0 0
      es5/build/pdf.js.map
  14. 0 21
      es5/build/pdf.min.js
  15. 0 0
      es5/build/pdf.worker.js.map
  16. 0 21
      es5/build/pdf.worker.min.js
  17. 0 0
      es5/image_decoders/pdf.image_decoders.js.map
  18. 0 21
      es5/image_decoders/pdf.image_decoders.min.js
  19. 0 0
      es5/web/pdf_viewer.js.map
  20. 185 169
      image_decoders/pdf.image_decoders.js
  21. 0 0
      image_decoders/pdf.image_decoders.js.map
  22. 1 1
      image_decoders/pdf.image_decoders.min.js
  23. 0 0
      legacy/build/pdf.d.ts
  24. 224 407
      legacy/build/pdf.js
  25. 0 0
      legacy/build/pdf.js.map
  26. 21 0
      legacy/build/pdf.min.js
  27. 39 0
      legacy/build/pdf.sandbox.js
  28. 0 0
      legacy/build/pdf.sandbox.js.map
  29. 21 0
      legacy/build/pdf.sandbox.min.js
  30. 1 1
      legacy/build/pdf.worker.entry.js
  31. 230 225
      legacy/build/pdf.worker.js
  32. 0 0
      legacy/build/pdf.worker.js.map
  33. 21 0
      legacy/build/pdf.worker.min.js
  34. 212 253
      legacy/image_decoders/pdf.image_decoders.js
  35. 0 0
      legacy/image_decoders/pdf.image_decoders.js.map
  36. 21 0
      legacy/image_decoders/pdf.image_decoders.min.js
  37. 0 0
      legacy/web/images/annotation-check.svg
  38. 0 0
      legacy/web/images/annotation-comment.svg
  39. 0 0
      legacy/web/images/annotation-help.svg
  40. 0 0
      legacy/web/images/annotation-insert.svg
  41. 0 0
      legacy/web/images/annotation-key.svg
  42. 0 0
      legacy/web/images/annotation-newparagraph.svg
  43. 0 0
      legacy/web/images/annotation-noicon.svg
  44. 0 0
      legacy/web/images/annotation-note.svg
  45. 0 0
      legacy/web/images/annotation-paragraph.svg
  46. 0 0
      legacy/web/images/loading-icon.gif
  47. 0 0
      legacy/web/images/shadow.png
  48. 178 6
      legacy/web/pdf_viewer.css
  49. 1046 1296
      legacy/web/pdf_viewer.js
  50. 0 0
      legacy/web/pdf_viewer.js.map
  51. 316 126
      lib/core/annotation.js
  52. 1 1
      lib/core/arithmetic_decoder.js
  53. 1 1
      lib/core/bidi.js
  54. 1 1
      lib/core/ccitt.js
  55. 2 2
      lib/core/ccitt_stream.js
  56. 1 2
      lib/core/cff_parser.js
  57. 1 1
      lib/core/charsets.js
  58. 1 1
      lib/core/chunked_stream.js
  59. 65 75
      lib/core/cmap.js
  60. 2 2
      lib/core/colorspace.js
  61. 83 21
      lib/core/core_utils.js
  62. 122 110
      lib/core/crypto.js
  63. 8 8
      lib/core/default_appearance.js
  64. 125 5
      lib/core/document.js
  65. 1 1
      lib/core/encodings.js
  66. 47 43
      lib/core/evaluator.js
  67. 59 59
      lib/core/font_renderer.js
  68. 15 8
      lib/core/fonts.js
  69. 366 353
      lib/core/function.js
  70. 2 2
      lib/core/glyphlist.js
  71. 1 1
      lib/core/image.js
  72. 50 8
      lib/core/image_utils.js
  73. 1 1
      lib/core/jbig2.js
  74. 1 1
      lib/core/jbig2_stream.js
  75. 1 1
      lib/core/jpeg_stream.js
  76. 1 1
      lib/core/jpg.js
  77. 1 1
      lib/core/jpx.js
  78. 1 1
      lib/core/jpx_stream.js
  79. 155 0
      lib/core/metadata_parser.js
  80. 2 2
      lib/core/metrics.js
  81. 1 1
      lib/core/murmurhash3.js
  82. 36 15
      lib/core/obj.js
  83. 121 122
      lib/core/operator_list.js
  84. 1 1
      lib/core/parser.js
  85. 142 149
      lib/core/pattern.js
  86. 22 18
      lib/core/pdf_manager.js
  87. 10 10
      lib/core/primitives.js
  88. 1 1
      lib/core/ps_parser.js
  89. 1 1
      lib/core/standard_fonts.js
  90. 10 4
      lib/core/stream.js
  91. 119 108
      lib/core/type1_parser.js
  92. 10 10
      lib/core/unicode.js
  93. 21 10
      lib/core/worker.js
  94. 1 1
      lib/core/worker_stream.js
  95. 2 2
      lib/core/writer.js
  96. 535 0
      lib/core/xfa/bind.js
  97. 232 0
      lib/core/xfa/builder.js
  98. 1905 0
      lib/core/xfa/config.js
  99. 230 0
      lib/core/xfa/connection_set.js
  100. 82 0
      lib/core/xfa/datasets.js

+ 1 - 1
README.md

@@ -9,6 +9,6 @@ generated by the build scripts.
 
 
 For usage with older browsers or environments, without support for modern
 For usage with older browsers or environments, without support for modern
 features such as e.g. `async`/`await`, `ReadableStream`, optional chaining, and
 features such as e.g. `async`/`await`, `ReadableStream`, optional chaining, and
-nullish coalescing; please see the `es5` folder.
+nullish coalescing; please see the `legacy` folder.
 
 
 See https://github.com/mozilla/pdf.js for learning and contributing.
 See https://github.com/mozilla/pdf.js for learning and contributing.

+ 1 - 1
bower.json

@@ -1,6 +1,6 @@
 {
 {
   "name": "pdfjs-dist",
   "name": "pdfjs-dist",
-  "version": "2.7.570",
+  "version": "2.8.335",
   "main": [
   "main": [
     "build/pdf.js",
     "build/pdf.js",
     "build/pdf.worker.js"
     "build/pdf.worker.js"

File diff suppressed because it is too large
+ 242 - 433
build/pdf.js


File diff suppressed because it is too large
+ 0 - 0
build/pdf.js.map


File diff suppressed because it is too large
+ 1 - 1
build/pdf.min.js


File diff suppressed because it is too large
+ 39 - 0
build/pdf.sandbox.js


File diff suppressed because it is too large
+ 0 - 0
build/pdf.sandbox.js.map


File diff suppressed because it is too large
+ 21 - 0
build/pdf.sandbox.min.js


+ 1 - 1
build/pdf.worker.entry.js

@@ -1,4 +1,4 @@
-/* Copyright 2020 Mozilla Foundation
+/* Copyright 2021 Mozilla Foundation
  *
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * you may not use this file except in compliance with the License.

File diff suppressed because it is too large
+ 381 - 218
build/pdf.worker.js


File diff suppressed because it is too large
+ 0 - 0
build/pdf.worker.js.map


File diff suppressed because it is too large
+ 1 - 1
build/pdf.worker.min.js


File diff suppressed because it is too large
+ 0 - 0
es5/build/pdf.js.map


File diff suppressed because it is too large
+ 0 - 21
es5/build/pdf.min.js


File diff suppressed because it is too large
+ 0 - 0
es5/build/pdf.worker.js.map


File diff suppressed because it is too large
+ 0 - 21
es5/build/pdf.worker.min.js


File diff suppressed because it is too large
+ 0 - 0
es5/image_decoders/pdf.image_decoders.js.map


File diff suppressed because it is too large
+ 0 - 21
es5/image_decoders/pdf.image_decoders.min.js


File diff suppressed because it is too large
+ 0 - 0
es5/web/pdf_viewer.js.map


+ 185 - 169
image_decoders/pdf.image_decoders.js

@@ -2,7 +2,7 @@
  * @licstart The following is the entire license notice for the
  * @licstart The following is the entire license notice for the
  * Javascript code in this page
  * Javascript code in this page
  *
  *
- * Copyright 2020 Mozilla Foundation
+ * Copyright 2021 Mozilla Foundation
  *
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * you may not use this file except in compliance with the License.
@@ -33,57 +33,7 @@
 return /******/ (() => { // webpackBootstrap
 return /******/ (() => { // webpackBootstrap
 /******/ 	"use strict";
 /******/ 	"use strict";
 /******/ 	var __webpack_modules__ = ([
 /******/ 	var __webpack_modules__ = ([
-/* 0 */
-/***/ ((__unused_webpack_module, exports, __w_pdfjs_require__) => {
-
-
-
-Object.defineProperty(exports, "__esModule", ({
-  value: true
-}));
-Object.defineProperty(exports, "getVerbosityLevel", ({
-  enumerable: true,
-  get: function () {
-    return _util.getVerbosityLevel;
-  }
-}));
-Object.defineProperty(exports, "setVerbosityLevel", ({
-  enumerable: true,
-  get: function () {
-    return _util.setVerbosityLevel;
-  }
-}));
-Object.defineProperty(exports, "Jbig2mage", ({
-  enumerable: true,
-  get: function () {
-    return _jbig.Jbig2mage;
-  }
-}));
-Object.defineProperty(exports, "JpegImage", ({
-  enumerable: true,
-  get: function () {
-    return _jpg.JpegImage;
-  }
-}));
-Object.defineProperty(exports, "JpxImage", ({
-  enumerable: true,
-  get: function () {
-    return _jpx.JpxImage;
-  }
-}));
-
-var _util = __w_pdfjs_require__(1);
-
-var _jbig = __w_pdfjs_require__(4);
-
-var _jpg = __w_pdfjs_require__(9);
-
-var _jpx = __w_pdfjs_require__(10);
-
-const pdfjsVersion = '2.7.570';
-const pdfjsBuild = 'f2c7338b0';
-
-/***/ }),
+/* 0 */,
 /* 1 */
 /* 1 */
 /***/ ((__unused_webpack_module, exports, __w_pdfjs_require__) => {
 /***/ ((__unused_webpack_module, exports, __w_pdfjs_require__) => {
 
 
@@ -96,9 +46,9 @@ exports.arrayByteLength = arrayByteLength;
 exports.arraysToBytes = arraysToBytes;
 exports.arraysToBytes = arraysToBytes;
 exports.assert = assert;
 exports.assert = assert;
 exports.bytesToString = bytesToString;
 exports.bytesToString = bytesToString;
+exports.createObjectURL = createObjectURL;
 exports.createPromiseCapability = createPromiseCapability;
 exports.createPromiseCapability = createPromiseCapability;
 exports.createValidAbsoluteUrl = createValidAbsoluteUrl;
 exports.createValidAbsoluteUrl = createValidAbsoluteUrl;
-exports.encodeToXmlString = encodeToXmlString;
 exports.escapeString = escapeString;
 exports.escapeString = escapeString;
 exports.getModificationDate = getModificationDate;
 exports.getModificationDate = getModificationDate;
 exports.getVerbosityLevel = getVerbosityLevel;
 exports.getVerbosityLevel = getVerbosityLevel;
@@ -110,7 +60,7 @@ exports.isBool = isBool;
 exports.isNum = isNum;
 exports.isNum = isNum;
 exports.isSameOrigin = isSameOrigin;
 exports.isSameOrigin = isSameOrigin;
 exports.isString = isString;
 exports.isString = isString;
-exports.objectFromEntries = objectFromEntries;
+exports.objectFromMap = objectFromMap;
 exports.objectSize = objectSize;
 exports.objectSize = objectSize;
 exports.removeNullCharacters = removeNullCharacters;
 exports.removeNullCharacters = removeNullCharacters;
 exports.setVerbosityLevel = setVerbosityLevel;
 exports.setVerbosityLevel = setVerbosityLevel;
@@ -123,7 +73,7 @@ exports.stringToUTF8String = stringToUTF8String;
 exports.unreachable = unreachable;
 exports.unreachable = unreachable;
 exports.utf8StringToString = utf8StringToString;
 exports.utf8StringToString = utf8StringToString;
 exports.warn = warn;
 exports.warn = warn;
-exports.VerbosityLevel = exports.Util = exports.UNSUPPORTED_FEATURES = exports.UnknownErrorException = exports.UnexpectedResponseException = exports.TextRenderingMode = exports.StreamType = exports.PermissionFlag = exports.PasswordResponses = exports.PasswordException = exports.PageActionEventType = exports.OPS = exports.MissingPDFException = exports.IsLittleEndianCached = exports.IsEvalSupportedCached = exports.InvalidPDFException = exports.ImageKind = exports.IDENTITY_MATRIX = exports.FormatError = exports.FontType = exports.FONT_IDENTITY_MATRIX = exports.DocumentActionEventType = exports.createObjectURL = exports.CMapCompressionType = exports.BaseException = exports.AnnotationType = exports.AnnotationStateModelType = exports.AnnotationReviewState = exports.AnnotationReplyType = exports.AnnotationMarkedState = exports.AnnotationFlag = exports.AnnotationFieldFlag = exports.AnnotationBorderStyleType = exports.AnnotationActionEventType = exports.AbortException = void 0;
+exports.VerbosityLevel = exports.Util = exports.UNSUPPORTED_FEATURES = exports.UnknownErrorException = exports.UnexpectedResponseException = exports.TextRenderingMode = exports.StreamType = exports.PermissionFlag = exports.PasswordResponses = exports.PasswordException = exports.PageActionEventType = exports.OPS = exports.MissingPDFException = exports.IsLittleEndianCached = exports.IsEvalSupportedCached = exports.InvalidPDFException = exports.ImageKind = exports.IDENTITY_MATRIX = exports.FormatError = exports.FontType = exports.FONT_IDENTITY_MATRIX = exports.DocumentActionEventType = exports.CMapCompressionType = exports.BaseException = exports.AnnotationType = exports.AnnotationStateModelType = exports.AnnotationReviewState = exports.AnnotationReplyType = exports.AnnotationMarkedState = exports.AnnotationFlag = exports.AnnotationFieldFlag = exports.AnnotationBorderStyleType = exports.AnnotationActionEventType = exports.AbortException = void 0;
 
 
 __w_pdfjs_require__(2);
 __w_pdfjs_require__(2);
 
 
@@ -698,8 +648,14 @@ function objectSize(obj) {
   return Object.keys(obj).length;
   return Object.keys(obj).length;
 }
 }
 
 
-function objectFromEntries(iterable) {
-  return Object.assign(Object.create(null), Object.fromEntries(iterable));
+function objectFromMap(map) {
+  const obj = Object.create(null);
+
+  for (const [key, value] of map) {
+    obj[key] = value;
+  }
+
+  return obj;
 }
 }
 
 
 function isLittleEndian() {
 function isLittleEndian() {
@@ -781,7 +737,7 @@ class Util {
     const c = m[2] * transpose[0] + m[3] * transpose[2];
     const c = m[2] * transpose[0] + m[3] * transpose[2];
     const d = m[2] * transpose[1] + m[3] * transpose[3];
     const d = m[2] * transpose[1] + m[3] * transpose[3];
     const first = (a + d) / 2;
     const first = (a + d) / 2;
-    const second = Math.sqrt((a + d) * (a + d) - 4 * (a * d - c * b)) / 2;
+    const second = Math.sqrt((a + d) ** 2 - 4 * (a * d - c * b)) / 2;
     const sx = first + second || 1;
     const sx = first + second || 1;
     const sy = first - second || 1;
     const sy = first - second || 1;
     return [Math.sqrt(sx), Math.sqrt(sy)];
     return [Math.sqrt(sx), Math.sqrt(sy)];
@@ -915,9 +871,13 @@ function isArrayEqual(arr1, arr2) {
     return false;
     return false;
   }
   }
 
 
-  return arr1.every(function (element, index) {
-    return element === arr2[index];
-  });
+  for (let i = 0, ii = arr1.length; i < ii; i++) {
+    if (arr1[i] !== arr2[i]) {
+      return false;
+    }
+  }
+
+  return true;
 }
 }
 
 
 function getModificationDate(date = new Date()) {
 function getModificationDate(date = new Date()) {
@@ -948,84 +908,28 @@ function createPromiseCapability() {
   return capability;
   return capability;
 }
 }
 
 
-const createObjectURL = function createObjectURLClosure() {
-  const digits = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
-  return function createObjectURL(data, contentType, forceDataSchema = false) {
-    if (!forceDataSchema && URL.createObjectURL) {
-      const blob = new Blob([data], {
-        type: contentType
-      });
-      return URL.createObjectURL(blob);
-    }
-
-    let buffer = `data:${contentType};base64,`;
-
-    for (let i = 0, ii = data.length; i < ii; i += 3) {
-      const b1 = data[i] & 0xff;
-      const b2 = data[i + 1] & 0xff;
-      const b3 = data[i + 2] & 0xff;
-      const d1 = b1 >> 2,
-            d2 = (b1 & 3) << 4 | b2 >> 4;
-      const d3 = i + 1 < ii ? (b2 & 0xf) << 2 | b3 >> 6 : 64;
-      const d4 = i + 2 < ii ? b3 & 0x3f : 64;
-      buffer += digits[d1] + digits[d2] + digits[d3] + digits[d4];
-    }
-
-    return buffer;
-  };
-}();
-
-exports.createObjectURL = createObjectURL;
-const XMLEntities = {
-  0x3c: "&lt;",
-  0x3e: "&gt;",
-  0x26: "&amp;",
-  0x22: "&quot;",
-  0x27: "&apos;"
-};
-
-function encodeToXmlString(str) {
-  const buffer = [];
-  let start = 0;
-
-  for (let i = 0, ii = str.length; i < ii; i++) {
-    const char = str.codePointAt(i);
-
-    if (0x20 <= char && char <= 0x7e) {
-      const entity = XMLEntities[char];
-
-      if (entity) {
-        if (start < i) {
-          buffer.push(str.substring(start, i));
-        }
-
-        buffer.push(entity);
-        start = i + 1;
-      }
-    } else {
-      if (start < i) {
-        buffer.push(str.substring(start, i));
-      }
-
-      buffer.push(`&#x${char.toString(16).toUpperCase()};`);
-
-      if (char > 0xd7ff && (char < 0xe000 || char > 0xfffd)) {
-        i++;
-      }
-
-      start = i + 1;
-    }
+function createObjectURL(data, contentType = "", forceDataSchema = false) {
+  if (URL.createObjectURL && !forceDataSchema) {
+    return URL.createObjectURL(new Blob([data], {
+      type: contentType
+    }));
   }
   }
 
 
-  if (buffer.length === 0) {
-    return str;
-  }
+  const digits = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
+  let buffer = `data:${contentType};base64,`;
 
 
-  if (start < str.length) {
-    buffer.push(str.substring(start, str.length));
+  for (let i = 0, ii = data.length; i < ii; i += 3) {
+    const b1 = data[i] & 0xff;
+    const b2 = data[i + 1] & 0xff;
+    const b3 = data[i + 2] & 0xff;
+    const d1 = b1 >> 2,
+          d2 = (b1 & 3) << 4 | b2 >> 4;
+    const d3 = i + 1 < ii ? (b2 & 0xf) << 2 | b3 >> 6 : 64;
+    const d4 = i + 2 < ii ? b3 & 0x3f : 64;
+    buffer += digits[d1] + digits[d2] + digits[d3] + digits[d4];
   }
   }
 
 
-  return buffer.join("");
+  return buffer;
 }
 }
 
 
 /***/ }),
 /***/ }),
@@ -3268,6 +3172,7 @@ Object.defineProperty(exports, "__esModule", ({
   value: true
   value: true
 }));
 }));
 exports.collectActions = collectActions;
 exports.collectActions = collectActions;
+exports.encodeToXmlString = encodeToXmlString;
 exports.escapePDFName = escapePDFName;
 exports.escapePDFName = escapePDFName;
 exports.getArrayLookupTableFactory = getArrayLookupTableFactory;
 exports.getArrayLookupTableFactory = getArrayLookupTableFactory;
 exports.getInheritableProperty = getInheritableProperty;
 exports.getInheritableProperty = getInheritableProperty;
@@ -3342,11 +3247,14 @@ function getInheritableProperty({
   getArray = false,
   getArray = false,
   stopWhenFound = true
   stopWhenFound = true
 }) {
 }) {
-  const LOOP_LIMIT = 100;
-  let loopCount = 0;
   let values;
   let values;
+  const visited = new _primitives.RefSet();
+
+  while (dict instanceof _primitives.Dict && !(dict.objId && visited.has(dict.objId))) {
+    if (dict.objId) {
+      visited.put(dict.objId);
+    }
 
 
-  while (dict) {
     const value = getArray ? dict.getArray(key) : dict.get(key);
     const value = getArray ? dict.getArray(key) : dict.get(key);
 
 
     if (value !== undefined) {
     if (value !== undefined) {
@@ -3361,11 +3269,6 @@ function getInheritableProperty({
       values.push(value);
       values.push(value);
     }
     }
 
 
-    if (++loopCount > LOOP_LIMIT) {
-      (0, _util.warn)(`getInheritableProperty: maximum loop count exceeded for "${key}"`);
-      break;
-    }
-
     dict = dict.get("Parent");
     dict = dict.get("Parent");
   }
   }
 
 
@@ -3515,25 +3418,36 @@ function _collectJS(entry, xref, list, parents) {
 
 
 function collectActions(xref, dict, eventType) {
 function collectActions(xref, dict, eventType) {
   const actions = Object.create(null);
   const actions = Object.create(null);
+  const additionalActionsDicts = getInheritableProperty({
+    dict,
+    key: "AA",
+    stopWhenFound: false
+  });
 
 
-  if (dict.has("AA")) {
-    const additionalActions = dict.get("AA");
-
-    for (const key of additionalActions.getKeys()) {
-      const action = eventType[key];
+  if (additionalActionsDicts) {
+    for (let i = additionalActionsDicts.length - 1; i >= 0; i--) {
+      const additionalActions = additionalActionsDicts[i];
 
 
-      if (!action) {
+      if (!(additionalActions instanceof _primitives.Dict)) {
         continue;
         continue;
       }
       }
 
 
-      const actionDict = additionalActions.getRaw(key);
-      const parents = new _primitives.RefSet();
-      const list = [];
+      for (const key of additionalActions.getKeys()) {
+        const action = eventType[key];
+
+        if (!action) {
+          continue;
+        }
+
+        const actionDict = additionalActions.getRaw(key);
+        const parents = new _primitives.RefSet();
+        const list = [];
 
 
-      _collectJS(actionDict, xref, list, parents);
+        _collectJS(actionDict, xref, list, parents);
 
 
-      if (list.length > 0) {
-        actions[action] = list;
+        if (list.length > 0) {
+          actions[action] = list;
+        }
       }
       }
     }
     }
   }
   }
@@ -3553,6 +3467,58 @@ function collectActions(xref, dict, eventType) {
   return (0, _util.objectSize)(actions) > 0 ? actions : null;
   return (0, _util.objectSize)(actions) > 0 ? actions : null;
 }
 }
 
 
+const XMLEntities = {
+  0x3c: "&lt;",
+  0x3e: "&gt;",
+  0x26: "&amp;",
+  0x22: "&quot;",
+  0x27: "&apos;"
+};
+
+function encodeToXmlString(str) {
+  const buffer = [];
+  let start = 0;
+
+  for (let i = 0, ii = str.length; i < ii; i++) {
+    const char = str.codePointAt(i);
+
+    if (0x20 <= char && char <= 0x7e) {
+      const entity = XMLEntities[char];
+
+      if (entity) {
+        if (start < i) {
+          buffer.push(str.substring(start, i));
+        }
+
+        buffer.push(entity);
+        start = i + 1;
+      }
+    } else {
+      if (start < i) {
+        buffer.push(str.substring(start, i));
+      }
+
+      buffer.push(`&#x${char.toString(16).toUpperCase()};`);
+
+      if (char > 0xd7ff && (char < 0xe000 || char > 0xfffd)) {
+        i++;
+      }
+
+      start = i + 1;
+    }
+  }
+
+  if (buffer.length === 0) {
+    return str;
+  }
+
+  if (start < str.length) {
+    buffer.push(str.substring(start, str.length));
+  }
+
+  return buffer.join("");
+}
+
 /***/ }),
 /***/ }),
 /* 6 */
 /* 6 */
 /***/ ((__unused_webpack_module, exports, __w_pdfjs_require__) => {
 /***/ ((__unused_webpack_module, exports, __w_pdfjs_require__) => {
@@ -3574,10 +3540,10 @@ exports.RefSetCache = exports.RefSet = exports.Ref = exports.Name = exports.EOF
 
 
 var _util = __w_pdfjs_require__(1);
 var _util = __w_pdfjs_require__(1);
 
 
-var EOF = {};
+const EOF = {};
 exports.EOF = EOF;
 exports.EOF = EOF;
 
 
-var Name = function NameClosure() {
+const Name = function NameClosure() {
   let nameCache = Object.create(null);
   let nameCache = Object.create(null);
 
 
   function Name(name) {
   function Name(name) {
@@ -3587,7 +3553,7 @@ var Name = function NameClosure() {
   Name.prototype = {};
   Name.prototype = {};
 
 
   Name.get = function Name_get(name) {
   Name.get = function Name_get(name) {
-    var nameValue = nameCache[name];
+    const nameValue = nameCache[name];
     return nameValue ? nameValue : nameCache[name] = new Name(name);
     return nameValue ? nameValue : nameCache[name] = new Name(name);
   };
   };
 
 
@@ -3600,7 +3566,7 @@ var Name = function NameClosure() {
 
 
 exports.Name = Name;
 exports.Name = Name;
 
 
-var Cmd = function CmdClosure() {
+const Cmd = function CmdClosure() {
   let cmdCache = Object.create(null);
   let cmdCache = Object.create(null);
 
 
   function Cmd(cmd) {
   function Cmd(cmd) {
@@ -3610,7 +3576,7 @@ var Cmd = function CmdClosure() {
   Cmd.prototype = {};
   Cmd.prototype = {};
 
 
   Cmd.get = function Cmd_get(cmd) {
   Cmd.get = function Cmd_get(cmd) {
-    var cmdValue = cmdCache[cmd];
+    const cmdValue = cmdCache[cmd];
     return cmdValue ? cmdValue : cmdCache[cmd] = new Cmd(cmd);
     return cmdValue ? cmdValue : cmdCache[cmd] = new Cmd(cmd);
   };
   };
 
 
@@ -3623,8 +3589,8 @@ var Cmd = function CmdClosure() {
 
 
 exports.Cmd = Cmd;
 exports.Cmd = Cmd;
 
 
-var Dict = function DictClosure() {
-  var nonSerializable = function nonSerializableClosure() {
+const Dict = function DictClosure() {
+  const nonSerializable = function nonSerializableClosure() {
     return nonSerializable;
     return nonSerializable;
   };
   };
 
 
@@ -3717,7 +3683,7 @@ var Dict = function DictClosure() {
       return this._map[key] !== undefined;
       return this._map[key] !== undefined;
     },
     },
     forEach: function Dict_forEach(callback) {
     forEach: function Dict_forEach(callback) {
-      for (var key in this._map) {
+      for (const key in this._map) {
         callback(key, this.get(key));
         callback(key, this.get(key));
       }
       }
     }
     }
@@ -3809,7 +3775,7 @@ var Dict = function DictClosure() {
 
 
 exports.Dict = Dict;
 exports.Dict = Dict;
 
 
-var Ref = function RefClosure() {
+const Ref = function RefClosure() {
   let refCache = Object.create(null);
   let refCache = Object.create(null);
 
 
   function Ref(num, gen) {
   function Ref(num, gen) {
@@ -8594,8 +8560,9 @@ exports.JpxImage = JpxImage;
 /******/ 	// The require function
 /******/ 	// The require function
 /******/ 	function __w_pdfjs_require__(moduleId) {
 /******/ 	function __w_pdfjs_require__(moduleId) {
 /******/ 		// Check if module is in cache
 /******/ 		// Check if module is in cache
-/******/ 		if(__webpack_module_cache__[moduleId]) {
-/******/ 			return __webpack_module_cache__[moduleId].exports;
+/******/ 		var cachedModule = __webpack_module_cache__[moduleId];
+/******/ 		if (cachedModule !== undefined) {
+/******/ 			return cachedModule.exports;
 /******/ 		}
 /******/ 		}
 /******/ 		// Create a new module (and put it into the cache)
 /******/ 		// Create a new module (and put it into the cache)
 /******/ 		var module = __webpack_module_cache__[moduleId] = {
 /******/ 		var module = __webpack_module_cache__[moduleId] = {
@@ -8612,10 +8579,59 @@ exports.JpxImage = JpxImage;
 /******/ 	}
 /******/ 	}
 /******/ 	
 /******/ 	
 /************************************************************************/
 /************************************************************************/
-/******/ 	// module exports must be returned from runtime so entry inlining is disabled
-/******/ 	// startup
-/******/ 	// Load entry module and return exports
-/******/ 	return __w_pdfjs_require__(0);
+var __webpack_exports__ = {};
+// This entry need to be wrapped in an IIFE because it need to be isolated against other modules in the chunk.
+(() => {
+var exports = __webpack_exports__;
+
+
+Object.defineProperty(exports, "__esModule", ({
+  value: true
+}));
+Object.defineProperty(exports, "getVerbosityLevel", ({
+  enumerable: true,
+  get: function () {
+    return _util.getVerbosityLevel;
+  }
+}));
+Object.defineProperty(exports, "setVerbosityLevel", ({
+  enumerable: true,
+  get: function () {
+    return _util.setVerbosityLevel;
+  }
+}));
+Object.defineProperty(exports, "Jbig2mage", ({
+  enumerable: true,
+  get: function () {
+    return _jbig.Jbig2mage;
+  }
+}));
+Object.defineProperty(exports, "JpegImage", ({
+  enumerable: true,
+  get: function () {
+    return _jpg.JpegImage;
+  }
+}));
+Object.defineProperty(exports, "JpxImage", ({
+  enumerable: true,
+  get: function () {
+    return _jpx.JpxImage;
+  }
+}));
+
+var _util = __w_pdfjs_require__(1);
+
+var _jbig = __w_pdfjs_require__(4);
+
+var _jpg = __w_pdfjs_require__(9);
+
+var _jpx = __w_pdfjs_require__(10);
+
+const pdfjsVersion = '2.8.335';
+const pdfjsBuild = '228adbf67';
+})();
+
+/******/ 	return __webpack_exports__;
 /******/ })()
 /******/ })()
 ;
 ;
 });
 });

File diff suppressed because it is too large
+ 0 - 0
image_decoders/pdf.image_decoders.js.map


File diff suppressed because it is too large
+ 1 - 1
image_decoders/pdf.image_decoders.min.js


+ 0 - 0
es5/build/pdf.d.ts → legacy/build/pdf.d.ts


File diff suppressed because it is too large
+ 224 - 407
legacy/build/pdf.js


File diff suppressed because it is too large
+ 0 - 0
legacy/build/pdf.js.map


File diff suppressed because it is too large
+ 21 - 0
legacy/build/pdf.min.js


File diff suppressed because it is too large
+ 39 - 0
legacy/build/pdf.sandbox.js


File diff suppressed because it is too large
+ 0 - 0
legacy/build/pdf.sandbox.js.map


File diff suppressed because it is too large
+ 21 - 0
legacy/build/pdf.sandbox.min.js


+ 1 - 1
es5/build/pdf.worker.entry.js → legacy/build/pdf.worker.entry.js

@@ -1,4 +1,4 @@
-/* Copyright 2020 Mozilla Foundation
+/* Copyright 2021 Mozilla Foundation
  *
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * you may not use this file except in compliance with the License.

File diff suppressed because it is too large
+ 230 - 225
legacy/build/pdf.worker.js


File diff suppressed because it is too large
+ 0 - 0
legacy/build/pdf.worker.js.map


File diff suppressed because it is too large
+ 21 - 0
legacy/build/pdf.worker.min.js


File diff suppressed because it is too large
+ 212 - 253
legacy/image_decoders/pdf.image_decoders.js


File diff suppressed because it is too large
+ 0 - 0
legacy/image_decoders/pdf.image_decoders.js.map


File diff suppressed because it is too large
+ 21 - 0
legacy/image_decoders/pdf.image_decoders.min.js


+ 0 - 0
es5/web/images/annotation-check.svg → legacy/web/images/annotation-check.svg


+ 0 - 0
es5/web/images/annotation-comment.svg → legacy/web/images/annotation-comment.svg


+ 0 - 0
es5/web/images/annotation-help.svg → legacy/web/images/annotation-help.svg


+ 0 - 0
es5/web/images/annotation-insert.svg → legacy/web/images/annotation-insert.svg


+ 0 - 0
es5/web/images/annotation-key.svg → legacy/web/images/annotation-key.svg


+ 0 - 0
es5/web/images/annotation-newparagraph.svg → legacy/web/images/annotation-newparagraph.svg


+ 0 - 0
es5/web/images/annotation-noicon.svg → legacy/web/images/annotation-noicon.svg


+ 0 - 0
es5/web/images/annotation-note.svg → legacy/web/images/annotation-note.svg


+ 0 - 0
es5/web/images/annotation-paragraph.svg → legacy/web/images/annotation-paragraph.svg


+ 0 - 0
es5/web/images/loading-icon.gif → legacy/web/images/loading-icon.gif


+ 0 - 0
es5/web/images/shadow.png → legacy/web/images/shadow.png


+ 178 - 6
es5/web/pdf_viewer.css → legacy/web/pdf_viewer.css

@@ -74,7 +74,6 @@
   cursor: default;
   cursor: default;
   -webkit-user-select: none;
   -webkit-user-select: none;
      -moz-user-select: none;
      -moz-user-select: none;
-      -ms-user-select: none;
           user-select: none;
           user-select: none;
 }
 }
 
 
@@ -278,6 +277,184 @@
   cursor: pointer;
   cursor: pointer;
 }
 }
 
 
+*/* Copyright 2021 Mozilla Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+.xfaLayer {
+  position: absolute;
+  top: 0;
+  left: 0;
+  z-index: 200;
+  transform-origin: 0 0;
+}
+
+.xfaLayer * {
+  color: inherit;
+  font: inherit;
+  -webkit-font-kerning: inherit;
+          font-kerning: inherit;
+  letter-spacing: inherit;
+  text-align: inherit;
+  text-decoration: inherit;
+  vertical-align: inherit;
+  box-sizing: border-box;
+}
+
+.xfaFont {
+  color: black;
+  font-weight: normal;
+  -webkit-font-kerning: none;
+          font-kerning: none;
+  font-size: 10px;
+  font-style: normal;
+  letter-spacing: 0;
+  text-decoration: none;
+  vertical-align: 0;
+}
+
+.xfaDraw {
+  z-index: 200;
+}
+
+.xfaExclgroup {
+  z-index: 300;
+}
+
+.xfaField {
+  z-index: 300;
+}
+
+.xfaSubform {
+  z-index: 100;
+}
+
+.xfaLabel {
+  display: flex;
+  flex-direction: row;
+  align-items: center;
+  width: 100%;
+  height: 100%;
+}
+
+.xfaCaption {
+  flex: 1 1 auto;
+}
+
+.xfaTextfield,
+.xfaSelect {
+  width: 100%;
+  height: 100%;
+  flex: 1 1 auto;
+  border: none;
+}
+
+.xfaLabel > input[type="checkbox"] {
+  /* Use this trick to make the checkbox invisible but
+       but still focusable. */
+  position: absolute;
+  left: -99999px;
+}
+
+.xfaLabel > input[type="checkbox"]:focus + .xfaCheckboxMark {
+  box-shadow: 0 0 5px rgba(0, 0, 0, 0.7);
+}
+
+.xfaCheckboxMark {
+  cursor: pointer;
+  flex: 0 0 auto;
+  border-style: solid;
+  border-width: 2px;
+  border-color: #8f8f9d;
+  font-size: 10px;
+  line-height: 10px;
+  width: 10px;
+  height: 10px;
+  text-align: center;
+  vertical-align: middle;
+  display: flex;
+  flex-direction: row;
+  align-items: center;
+}
+
+.xfaCheckbox:checked + .xfaCheckboxMark::after {
+  content: attr(mark);
+}
+
+.xfaButton {
+  cursor: pointer;
+  width: 100%;
+  height: 100%;
+  border: none;
+  text-align: center;
+}
+
+.xfaButton:hover {
+  background: Highlight;
+}
+
+.xfaLrTb,
+.xfaRlTb,
+.xfaTb,
+.xfaPosition {
+  display: block;
+}
+
+.xfaPosition {
+  position: relative;
+}
+
+.xfaValignMiddle {
+  display: flex;
+  align-items: center;
+}
+
+.xfaLrTb > div {
+  display: inline;
+  float: left;
+}
+
+.xfaRlTb > div {
+  display: inline;
+  float: right;
+}
+
+.xfaTable {
+  display: flex;
+  flex-direction: column;
+}
+
+.xfaTable .xfaRow {
+  display: flex;
+  flex-direction: row;
+  flex: 1 1 auto;
+}
+
+.xfaTable .xfaRow > div {
+  flex: 1 1 auto;
+}
+
+.xfaTable .xfaRlRow {
+  display: flex;
+  flex-direction: row-reverse;
+  flex: 1;
+}
+
+.xfaTable .xfaRlRow > div {
+  flex: 1;
+}
+
 .pdfViewer .canvasWrapper {
 .pdfViewer .canvasWrapper {
   overflow: hidden;
   overflow: hidden;
 }
 }
@@ -398,11 +575,6 @@
   border: 0;
   border: 0;
 }
 }
 
 
-.pdfPresentationMode:-ms-fullscreen .pdfViewer .page {
-  margin-bottom: 100%;
-  border: 0;
-}
-
 .pdfPresentationMode:fullscreen .pdfViewer .page {
 .pdfPresentationMode:fullscreen .pdfViewer .page {
   margin-bottom: 100%;
   margin-bottom: 100%;
   border: 0;
   border: 0;

File diff suppressed because it is too large
+ 1046 - 1296
legacy/web/pdf_viewer.js


File diff suppressed because it is too large
+ 0 - 0
legacy/web/pdf_viewer.js.map


+ 316 - 126
lib/core/annotation.js

@@ -2,7 +2,7 @@
  * @licstart The following is the entire license notice for the
  * @licstart The following is the entire license notice for the
  * Javascript code in this page
  * Javascript code in this page
  *
  *
- * Copyright 2020 Mozilla Foundation
+ * Copyright 2021 Mozilla Foundation
  *
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * you may not use this file except in compliance with the License.
@@ -46,13 +46,13 @@ var _stream = require("./stream.js");
 var _writer = require("./writer.js");
 var _writer = require("./writer.js");
 
 
 class AnnotationFactory {
 class AnnotationFactory {
-  static create(xref, ref, pdfManager, idFactory) {
+  static create(xref, ref, pdfManager, idFactory, collectFields) {
     return pdfManager.ensureCatalog("acroForm").then(acroForm => {
     return pdfManager.ensureCatalog("acroForm").then(acroForm => {
-      return pdfManager.ensure(this, "_create", [xref, ref, pdfManager, idFactory, acroForm]);
+      return pdfManager.ensure(this, "_create", [xref, ref, pdfManager, idFactory, acroForm, collectFields]);
     });
     });
   }
   }
 
 
-  static _create(xref, ref, pdfManager, idFactory, acroForm) {
+  static _create(xref, ref, pdfManager, idFactory, acroForm, collectFields) {
     const dict = xref.fetchIfRef(ref);
     const dict = xref.fetchIfRef(ref);
 
 
     if (!(0, _primitives.isDict)(dict)) {
     if (!(0, _primitives.isDict)(dict)) {
@@ -69,7 +69,8 @@ class AnnotationFactory {
       subtype,
       subtype,
       id,
       id,
       pdfManager,
       pdfManager,
-      acroForm: acroForm instanceof _primitives.Dict ? acroForm : _primitives.Dict.empty
+      acroForm: acroForm instanceof _primitives.Dict ? acroForm : _primitives.Dict.empty,
+      collectFields
     };
     };
 
 
     switch (subtype) {
     switch (subtype) {
@@ -97,7 +98,7 @@ class AnnotationFactory {
             return new ChoiceWidgetAnnotation(parameters);
             return new ChoiceWidgetAnnotation(parameters);
         }
         }
 
 
-        (0, _util.warn)('Unimplemented widget field type "' + fieldType + '", ' + "falling back to base field type.");
+        (0, _util.warn)(`Unimplemented widget field type "${fieldType}", ` + "falling back to base field type.");
         return new WidgetAnnotation(parameters);
         return new WidgetAnnotation(parameters);
 
 
       case "Popup":
       case "Popup":
@@ -146,10 +147,12 @@ class AnnotationFactory {
         return new FileAttachmentAnnotation(parameters);
         return new FileAttachmentAnnotation(parameters);
 
 
       default:
       default:
-        if (!subtype) {
-          (0, _util.warn)("Annotation is missing the required /Subtype.");
-        } else {
-          (0, _util.warn)('Unimplemented annotation type "' + subtype + '", ' + "falling back to base annotation.");
+        if (!collectFields) {
+          if (!subtype) {
+            (0, _util.warn)("Annotation is missing the required /Subtype.");
+          } else {
+            (0, _util.warn)(`Unimplemented annotation type "${subtype}", ` + "falling back to base annotation.");
+          }
         }
         }
 
 
         return new Annotation(parameters);
         return new Annotation(parameters);
@@ -160,6 +163,37 @@ class AnnotationFactory {
 
 
 exports.AnnotationFactory = AnnotationFactory;
 exports.AnnotationFactory = AnnotationFactory;
 
 
+function getRgbColor(color) {
+  const rgbColor = new Uint8ClampedArray(3);
+
+  if (!Array.isArray(color)) {
+    return rgbColor;
+  }
+
+  switch (color.length) {
+    case 0:
+      return null;
+
+    case 1:
+      _colorspace.ColorSpace.singletons.gray.getRgbItem(color, 0, rgbColor, 0);
+
+      return rgbColor;
+
+    case 3:
+      _colorspace.ColorSpace.singletons.rgb.getRgbItem(color, 0, rgbColor, 0);
+
+      return rgbColor;
+
+    case 4:
+      _colorspace.ColorSpace.singletons.cmyk.getRgbItem(color, 0, rgbColor, 0);
+
+      return rgbColor;
+
+    default:
+      return rgbColor;
+  }
+}
+
 function getQuadPoints(dict, rect) {
 function getQuadPoints(dict, rect) {
   if (!dict.has("QuadPoints")) {
   if (!dict.has("QuadPoints")) {
     return null;
     return null;
@@ -248,6 +282,28 @@ class Annotation {
       rect: this.rectangle,
       rect: this.rectangle,
       subtype: params.subtype
       subtype: params.subtype
     };
     };
+
+    if (params.collectFields) {
+      const kids = dict.get("Kids");
+
+      if (Array.isArray(kids)) {
+        const kidIds = [];
+
+        for (const kid of kids) {
+          if ((0, _primitives.isRef)(kid)) {
+            kidIds.push(kid.toString());
+          }
+        }
+
+        if (kidIds.length !== 0) {
+          this.data.kidIds = kidIds;
+        }
+      }
+
+      this.data.actions = (0, _core_utils.collectActions)(params.xref, dict, _util.AnnotationActionEventType);
+      this.data.fieldName = this._constructFieldName(dict);
+    }
+
     this._fallbackFontDict = null;
     this._fallbackFontDict = null;
   }
   }
 
 
@@ -264,10 +320,10 @@ class Annotation {
   }
   }
 
 
   isHidden(annotationStorage) {
   isHidden(annotationStorage) {
-    const data = annotationStorage && annotationStorage[this.data.id];
+    const storageEntry = annotationStorage && annotationStorage.get(this.data.id);
 
 
-    if (data && "hidden" in data) {
-      return data.hidden;
+    if (storageEntry && storageEntry.hidden !== undefined) {
+      return storageEntry.hidden;
     }
     }
 
 
     return this._hasFlag(this.flags, _util.AnnotationFlag.HIDDEN);
     return this._hasFlag(this.flags, _util.AnnotationFlag.HIDDEN);
@@ -322,40 +378,7 @@ class Annotation {
   }
   }
 
 
   setColor(color) {
   setColor(color) {
-    const rgbColor = new Uint8ClampedArray(3);
-
-    if (!Array.isArray(color)) {
-      this.color = rgbColor;
-      return;
-    }
-
-    switch (color.length) {
-      case 0:
-        this.color = null;
-        break;
-
-      case 1:
-        _colorspace.ColorSpace.singletons.gray.getRgbItem(color, 0, rgbColor, 0);
-
-        this.color = rgbColor;
-        break;
-
-      case 3:
-        _colorspace.ColorSpace.singletons.rgb.getRgbItem(color, 0, rgbColor, 0);
-
-        this.color = rgbColor;
-        break;
-
-      case 4:
-        _colorspace.ColorSpace.singletons.cmyk.getRgbItem(color, 0, rgbColor, 0);
-
-        this.color = rgbColor;
-        break;
-
-      default:
-        this.color = rgbColor;
-        break;
-    }
+    this.color = getRgbColor(color);
   }
   }
 
 
   setBorderStyle(borderStyle) {
   setBorderStyle(borderStyle) {
@@ -466,6 +489,16 @@ class Annotation {
   }
   }
 
 
   getFieldObject() {
   getFieldObject() {
+    if (this.data.kidIds) {
+      return {
+        id: this.data.id,
+        actions: this.data.actions,
+        name: this.data.fieldName,
+        type: "",
+        kidIds: this.data.kidIds
+      };
+    }
+
     return null;
     return null;
   }
   }
 
 
@@ -475,6 +508,48 @@ class Annotation {
     }
     }
   }
   }
 
 
+  _constructFieldName(dict) {
+    if (!dict.has("T") && !dict.has("Parent")) {
+      (0, _util.warn)("Unknown field name, falling back to empty field name.");
+      return "";
+    }
+
+    if (!dict.has("Parent")) {
+      return (0, _util.stringToPDFString)(dict.get("T"));
+    }
+
+    const fieldName = [];
+
+    if (dict.has("T")) {
+      fieldName.unshift((0, _util.stringToPDFString)(dict.get("T")));
+    }
+
+    let loopDict = dict;
+    const visited = new _primitives.RefSet();
+
+    if (dict.objId) {
+      visited.put(dict.objId);
+    }
+
+    while (loopDict.has("Parent")) {
+      loopDict = loopDict.get("Parent");
+
+      if (!(loopDict instanceof _primitives.Dict) || loopDict.objId && visited.has(loopDict.objId)) {
+        break;
+      }
+
+      if (loopDict.objId) {
+        visited.put(loopDict.objId);
+      }
+
+      if (loopDict.has("T")) {
+        fieldName.unshift((0, _util.stringToPDFString)(loopDict.get("T")));
+      }
+    }
+
+    return fieldName.join(".");
+  }
+
 }
 }
 
 
 exports.Annotation = Annotation;
 exports.Annotation = Annotation;
@@ -664,7 +739,25 @@ class MarkupAnnotation extends Annotation {
       buffer.push(`${fillColor[0]} ${fillColor[1]} ${fillColor[2]} rg`);
       buffer.push(`${fillColor[0]} ${fillColor[1]} ${fillColor[2]} rg`);
     }
     }
 
 
-    for (const points of this.data.quadPoints) {
+    let pointsArray = this.data.quadPoints;
+
+    if (!pointsArray) {
+      pointsArray = [[{
+        x: this.rectangle[0],
+        y: this.rectangle[3]
+      }, {
+        x: this.rectangle[2],
+        y: this.rectangle[3]
+      }, {
+        x: this.rectangle[0],
+        y: this.rectangle[1]
+      }, {
+        x: this.rectangle[2],
+        y: this.rectangle[1]
+      }]];
+    }
+
+    for (const points of pointsArray) {
       const [mX, MX, mY, MY] = pointsCallback(buffer, points);
       const [mX, MX, mY, MY] = pointsCallback(buffer, points);
       minX = Math.min(minX, mX);
       minX = Math.min(minX, mX);
       maxX = Math.max(maxX, MX);
       maxX = Math.max(maxX, MX);
@@ -711,8 +804,15 @@ class WidgetAnnotation extends Annotation {
     const data = this.data;
     const data = this.data;
     this.ref = params.ref;
     this.ref = params.ref;
     data.annotationType = _util.AnnotationType.WIDGET;
     data.annotationType = _util.AnnotationType.WIDGET;
-    data.fieldName = this._constructFieldName(dict);
-    data.actions = (0, _core_utils.collectActions)(params.xref, dict, _util.AnnotationActionEventType);
+
+    if (data.fieldName === undefined) {
+      data.fieldName = this._constructFieldName(dict);
+    }
+
+    if (data.actions === undefined) {
+      data.actions = (0, _core_utils.collectActions)(params.xref, dict, _util.AnnotationActionEventType);
+    }
+
     const fieldValue = (0, _core_utils.getInheritableProperty)({
     const fieldValue = (0, _core_utils.getInheritableProperty)({
       dict,
       dict,
       key: "V",
       key: "V",
@@ -729,9 +829,9 @@ class WidgetAnnotation extends Annotation {
     const defaultAppearance = (0, _core_utils.getInheritableProperty)({
     const defaultAppearance = (0, _core_utils.getInheritableProperty)({
       dict,
       dict,
       key: "DA"
       key: "DA"
-    }) || params.acroForm.get("DA") || "";
-    data.defaultAppearance = (0, _util.isString)(defaultAppearance) ? defaultAppearance : "";
-    data.defaultAppearanceData = (0, _default_appearance.parseDefaultAppearance)(data.defaultAppearance);
+    }) || params.acroForm.get("DA");
+    this._defaultAppearance = (0, _util.isString)(defaultAppearance) ? defaultAppearance : "";
+    data.defaultAppearanceData = (0, _default_appearance.parseDefaultAppearance)(this._defaultAppearance);
     const fieldType = (0, _core_utils.getInheritableProperty)({
     const fieldType = (0, _core_utils.getInheritableProperty)({
       dict,
       dict,
       key: "FT"
       key: "FT"
@@ -772,39 +872,6 @@ class WidgetAnnotation extends Annotation {
     }
     }
   }
   }
 
 
-  _constructFieldName(dict) {
-    if (!dict.has("T") && !dict.has("Parent")) {
-      (0, _util.warn)("Unknown field name, falling back to empty field name.");
-      return "";
-    }
-
-    if (!dict.has("Parent")) {
-      return (0, _util.stringToPDFString)(dict.get("T"));
-    }
-
-    const fieldName = [];
-
-    if (dict.has("T")) {
-      fieldName.unshift((0, _util.stringToPDFString)(dict.get("T")));
-    }
-
-    let loopDict = dict;
-
-    while (loopDict.has("Parent")) {
-      loopDict = loopDict.get("Parent");
-
-      if (!(0, _primitives.isDict)(loopDict)) {
-        break;
-      }
-
-      if (loopDict.has("T")) {
-        fieldName.unshift((0, _util.stringToPDFString)(loopDict.get("T")));
-      }
-    }
-
-    return fieldName.join(".");
-  }
-
   _decodeFormValue(formValue) {
   _decodeFormValue(formValue) {
     if (Array.isArray(formValue)) {
     if (Array.isArray(formValue)) {
       return formValue.filter(item => (0, _util.isString)(item)).map(item => (0, _util.stringToPDFString)(item));
       return formValue.filter(item => (0, _util.isString)(item)).map(item => (0, _util.stringToPDFString)(item));
@@ -837,7 +904,7 @@ class WidgetAnnotation extends Annotation {
 
 
       const operatorList = new _operator_list.OperatorList();
       const operatorList = new _operator_list.OperatorList();
 
 
-      if (!this.data.defaultAppearance || content === null) {
+      if (!this._defaultAppearance || content === null) {
         return operatorList;
         return operatorList;
       }
       }
 
 
@@ -859,7 +926,12 @@ class WidgetAnnotation extends Annotation {
   }
   }
 
 
   async save(evaluator, task, annotationStorage) {
   async save(evaluator, task, annotationStorage) {
-    const value = annotationStorage[this.data.id] && annotationStorage[this.data.id].value;
+    if (!annotationStorage) {
+      return null;
+    }
+
+    const storageEntry = annotationStorage.get(this.data.id);
+    const value = storageEntry && storageEntry.value;
 
 
     if (value === this.data.fieldValue || value === undefined) {
     if (value === this.data.fieldValue || value === undefined) {
       return null;
       return null;
@@ -932,30 +1004,37 @@ class WidgetAnnotation extends Annotation {
       return null;
       return null;
     }
     }
 
 
-    const value = annotationStorage[this.data.id] && annotationStorage[this.data.id].value;
+    const storageEntry = annotationStorage.get(this.data.id);
+    let value = storageEntry && storageEntry.value;
 
 
     if (value === undefined) {
     if (value === undefined) {
       return null;
       return null;
     }
     }
 
 
+    value = value.trim();
+
     if (value === "") {
     if (value === "") {
       return "";
       return "";
     }
     }
 
 
+    let lineCount = -1;
+
+    if (this.data.multiLine) {
+      lineCount = value.split(/\r\n|\r|\n/).length;
+    }
+
     const defaultPadding = 2;
     const defaultPadding = 2;
     const hPadding = defaultPadding;
     const hPadding = defaultPadding;
     const totalHeight = this.data.rect[3] - this.data.rect[1];
     const totalHeight = this.data.rect[3] - this.data.rect[1];
     const totalWidth = this.data.rect[2] - this.data.rect[0];
     const totalWidth = this.data.rect[2] - this.data.rect[0];
 
 
-    if (!this.data.defaultAppearance) {
-      this.data.defaultAppearance = "/Helvetica 0 Tf 0 g";
-      this.data.defaultAppearanceData = (0, _default_appearance.parseDefaultAppearance)(this.data.defaultAppearance);
+    if (!this._defaultAppearance) {
+      this.data.defaultAppearanceData = (0, _default_appearance.parseDefaultAppearance)(this._defaultAppearance = "/Helvetica 0 Tf 0 g");
     }
     }
 
 
-    const font = await this._getFontData(evaluator, task);
-
-    const fontSize = this._computeFontSize(font, totalHeight);
+    const [defaultAppearance, fontSize] = this._computeFontSize(totalHeight, lineCount);
 
 
+    const font = await this._getFontData(evaluator, task);
     let descent = font.descent;
     let descent = font.descent;
 
 
     if (isNaN(descent)) {
     if (isNaN(descent)) {
@@ -963,7 +1042,6 @@ class WidgetAnnotation extends Annotation {
     }
     }
 
 
     const vPadding = defaultPadding + Math.abs(descent) * fontSize;
     const vPadding = defaultPadding + Math.abs(descent) * fontSize;
-    const defaultAppearance = this.data.defaultAppearance;
     const alignment = this.data.textAlignment;
     const alignment = this.data.textAlignment;
 
 
     if (this.data.multiLine) {
     if (this.data.multiLine) {
@@ -999,42 +1077,43 @@ class WidgetAnnotation extends Annotation {
       fontName,
       fontName,
       fontSize
       fontSize
     } = this.data.defaultAppearanceData;
     } = this.data.defaultAppearanceData;
-    await evaluator.handleSetFont(this._fieldResources.mergedResources, [fontName, fontSize], null, operatorList, task, initialState, null);
+    await evaluator.handleSetFont(this._fieldResources.mergedResources, [fontName && _primitives.Name.get(fontName), fontSize], null, operatorList, task, initialState, null);
     return initialState.font;
     return initialState.font;
   }
   }
 
 
-  _computeFontSize(font, height) {
-    let fontSize = this.data.defaultAppearanceData.fontSize;
+  _computeFontSize(height, lineCount) {
+    let {
+      fontSize
+    } = this.data.defaultAppearanceData;
 
 
     if (!fontSize) {
     if (!fontSize) {
-      const {
-        fontColor,
-        fontName
-      } = this.data.defaultAppearanceData;
-      let capHeight;
+      const roundWithOneDigit = x => Math.round(x * 10) / 10;
 
 
-      if (font.capHeight) {
-        capHeight = font.capHeight;
-      } else {
-        const glyphs = font.charsToGlyphs(font.encodeString("M").join(""));
+      const FONT_FACTOR = 0.8;
 
 
-        if (glyphs.length === 1 && glyphs[0].width) {
-          const em = glyphs[0].width / 1000;
-          capHeight = 0.7 * em;
-        } else {
-          capHeight = 0.7;
-        }
+      if (lineCount === -1) {
+        fontSize = roundWithOneDigit(FONT_FACTOR * height);
+      } else {
+        fontSize = 10;
+        let lineHeight = fontSize / FONT_FACTOR;
+        let numberOfLines = Math.round(height / lineHeight);
+        numberOfLines = Math.max(numberOfLines, lineCount);
+        lineHeight = height / numberOfLines;
+        fontSize = roundWithOneDigit(FONT_FACTOR * lineHeight);
       }
       }
 
 
-      fontSize = Math.max(1, Math.floor(height / (1.5 * capHeight)));
-      this.data.defaultAppearance = (0, _default_appearance.createDefaultAppearance)({
+      const {
+        fontName,
+        fontColor
+      } = this.data.defaultAppearanceData;
+      this._defaultAppearance = (0, _default_appearance.createDefaultAppearance)({
         fontSize,
         fontSize,
         fontName,
         fontName,
         fontColor
         fontColor
       });
       });
     }
     }
 
 
-    return fontSize;
+    return [this._defaultAppearance, fontSize];
   }
   }
 
 
   _renderText(text, font, fontSize, totalWidth, alignment, hPadding, vPadding) {
   _renderText(text, font, fontSize, totalWidth, alignment, hPadding, vPadding) {
@@ -1067,9 +1146,9 @@ class WidgetAnnotation extends Annotation {
       appearanceResources,
       appearanceResources,
       acroFormResources
       acroFormResources
     } = this._fieldResources;
     } = this._fieldResources;
-    const fontNameStr = this.data.defaultAppearanceData && this.data.defaultAppearanceData.fontName.name;
+    const fontName = this.data.defaultAppearanceData && this.data.defaultAppearanceData.fontName;
 
 
-    if (!fontNameStr) {
+    if (!fontName) {
       return localResources || _primitives.Dict.empty;
       return localResources || _primitives.Dict.empty;
     }
     }
 
 
@@ -1077,7 +1156,7 @@ class WidgetAnnotation extends Annotation {
       if (resources instanceof _primitives.Dict) {
       if (resources instanceof _primitives.Dict) {
         const localFont = resources.get("Font");
         const localFont = resources.get("Font");
 
 
-        if (localFont instanceof _primitives.Dict && localFont.has(fontNameStr)) {
+        if (localFont instanceof _primitives.Dict && localFont.has(fontName)) {
           return resources;
           return resources;
         }
         }
       }
       }
@@ -1086,9 +1165,9 @@ class WidgetAnnotation extends Annotation {
     if (acroFormResources instanceof _primitives.Dict) {
     if (acroFormResources instanceof _primitives.Dict) {
       const acroFormFont = acroFormResources.get("Font");
       const acroFormFont = acroFormResources.get("Font");
 
 
-      if (acroFormFont instanceof _primitives.Dict && acroFormFont.has(fontNameStr)) {
+      if (acroFormFont instanceof _primitives.Dict && acroFormFont.has(fontName)) {
         const subFontDict = new _primitives.Dict(xref);
         const subFontDict = new _primitives.Dict(xref);
-        subFontDict.set(fontNameStr, acroFormFont.getRaw(fontNameStr));
+        subFontDict.set(fontName, acroFormFont.getRaw(fontName));
         const subResourcesDict = new _primitives.Dict(xref);
         const subResourcesDict = new _primitives.Dict(xref);
         subResourcesDict.set("Font", subFontDict);
         subResourcesDict.set("Font", subFontDict);
         return _primitives.Dict.merge({
         return _primitives.Dict.merge({
@@ -1289,7 +1368,8 @@ class ButtonWidgetAnnotation extends WidgetAnnotation {
     }
     }
 
 
     if (annotationStorage) {
     if (annotationStorage) {
-      const value = annotationStorage[this.data.id] && annotationStorage[this.data.id].value;
+      const storageEntry = annotationStorage.get(this.data.id);
+      const value = storageEntry && storageEntry.value;
 
 
       if (value === undefined) {
       if (value === undefined) {
         return super.getOperatorList(evaluator, task, renderForms, annotationStorage);
         return super.getOperatorList(evaluator, task, renderForms, annotationStorage);
@@ -1330,7 +1410,12 @@ class ButtonWidgetAnnotation extends WidgetAnnotation {
   }
   }
 
 
   async _saveCheckbox(evaluator, task, annotationStorage) {
   async _saveCheckbox(evaluator, task, annotationStorage) {
-    const value = annotationStorage[this.data.id] && annotationStorage[this.data.id].value;
+    if (!annotationStorage) {
+      return null;
+    }
+
+    const storageEntry = annotationStorage.get(this.data.id);
+    const value = storageEntry && storageEntry.value;
 
 
     if (value === undefined) {
     if (value === undefined) {
       return null;
       return null;
@@ -1376,7 +1461,12 @@ class ButtonWidgetAnnotation extends WidgetAnnotation {
   }
   }
 
 
   async _saveRadioButton(evaluator, task, annotationStorage) {
   async _saveRadioButton(evaluator, task, annotationStorage) {
-    const value = annotationStorage[this.data.id] && annotationStorage[this.data.id].value;
+    if (!annotationStorage) {
+      return null;
+    }
+
+    const storageEntry = annotationStorage.get(this.data.id);
+    const value = storageEntry && storageEntry.value;
 
 
     if (value === undefined) {
     if (value === undefined) {
       return null;
       return null;
@@ -1629,6 +1719,7 @@ class ChoiceWidgetAnnotation extends WidgetAnnotation {
       multipleSelection: this.data.multiSelect,
       multipleSelection: this.data.multiSelect,
       hidden: this.data.hidden,
       hidden: this.data.hidden,
       actions: this.data.actions,
       actions: this.data.actions,
+      items: this.data.options,
       type
       type
     };
     };
   }
   }
@@ -1749,7 +1840,29 @@ class LineAnnotation extends MarkupAnnotation {
   constructor(parameters) {
   constructor(parameters) {
     super(parameters);
     super(parameters);
     this.data.annotationType = _util.AnnotationType.LINE;
     this.data.annotationType = _util.AnnotationType.LINE;
-    this.data.lineCoordinates = _util.Util.normalizeRect(parameters.dict.getArray("L"));
+    const lineCoordinates = parameters.dict.getArray("L");
+    this.data.lineCoordinates = _util.Util.normalizeRect(lineCoordinates);
+
+    if (!this.appearance) {
+      const strokeColor = this.color ? Array.from(this.color).map(c => c / 255) : [0, 0, 0];
+      const borderWidth = this.borderStyle.width;
+
+      if ((0, _util.isArrayEqual)(this.rectangle, [0, 0, 0, 0])) {
+        this.rectangle = [this.data.lineCoordinates[0] - 2 * borderWidth, this.data.lineCoordinates[1] - 2 * borderWidth, this.data.lineCoordinates[2] + 2 * borderWidth, this.data.lineCoordinates[3] + 2 * borderWidth];
+      }
+
+      this._setDefaultAppearance({
+        xref: parameters.xref,
+        extra: `${borderWidth} w`,
+        strokeColor,
+        pointsCallback: (buffer, points) => {
+          buffer.push(`${lineCoordinates[0]} ${lineCoordinates[1]} m`);
+          buffer.push(`${lineCoordinates[2]} ${lineCoordinates[3]} l`);
+          buffer.push("S");
+          return [points[0].x - borderWidth, points[1].x + borderWidth, points[3].y - borderWidth, points[1].y + borderWidth];
+        }
+      });
+    }
   }
   }
 
 
 }
 }
@@ -1758,6 +1871,39 @@ class SquareAnnotation extends MarkupAnnotation {
   constructor(parameters) {
   constructor(parameters) {
     super(parameters);
     super(parameters);
     this.data.annotationType = _util.AnnotationType.SQUARE;
     this.data.annotationType = _util.AnnotationType.SQUARE;
+
+    if (!this.appearance) {
+      const strokeColor = this.color ? Array.from(this.color).map(c => c / 255) : [0, 0, 0];
+      let fillColor = null;
+      let interiorColor = parameters.dict.getArray("IC");
+
+      if (interiorColor) {
+        interiorColor = getRgbColor(interiorColor);
+        fillColor = interiorColor ? Array.from(interiorColor).map(c => c / 255) : null;
+      }
+
+      this._setDefaultAppearance({
+        xref: parameters.xref,
+        extra: `${this.borderStyle.width} w`,
+        strokeColor,
+        fillColor,
+        pointsCallback: (buffer, points) => {
+          const x = points[2].x + this.borderStyle.width / 2;
+          const y = points[2].y + this.borderStyle.width / 2;
+          const width = points[3].x - points[2].x - this.borderStyle.width;
+          const height = points[1].y - points[3].y - this.borderStyle.width;
+          buffer.push(`${x} ${y} ${width} ${height} re`);
+
+          if (fillColor) {
+            buffer.push("B");
+          } else {
+            buffer.push("S");
+          }
+
+          return [points[0].x, points[1].x, points[3].y, points[1].y];
+        }
+      });
+    }
   }
   }
 
 
 }
 }
@@ -1766,6 +1912,50 @@ class CircleAnnotation extends MarkupAnnotation {
   constructor(parameters) {
   constructor(parameters) {
     super(parameters);
     super(parameters);
     this.data.annotationType = _util.AnnotationType.CIRCLE;
     this.data.annotationType = _util.AnnotationType.CIRCLE;
+
+    if (!this.appearance) {
+      const strokeColor = this.color ? Array.from(this.color).map(c => c / 255) : [0, 0, 0];
+      let fillColor = null;
+      let interiorColor = parameters.dict.getArray("IC");
+
+      if (interiorColor) {
+        interiorColor = getRgbColor(interiorColor);
+        fillColor = interiorColor ? Array.from(interiorColor).map(c => c / 255) : null;
+      }
+
+      const controlPointsDistance = 4 / 3 * Math.tan(Math.PI / (2 * 4));
+
+      this._setDefaultAppearance({
+        xref: parameters.xref,
+        extra: `${this.borderStyle.width} w`,
+        strokeColor,
+        fillColor,
+        pointsCallback: (buffer, points) => {
+          const x0 = points[0].x + this.borderStyle.width / 2;
+          const y0 = points[0].y - this.borderStyle.width / 2;
+          const x1 = points[3].x - this.borderStyle.width / 2;
+          const y1 = points[3].y + this.borderStyle.width / 2;
+          const xMid = x0 + (x1 - x0) / 2;
+          const yMid = y0 + (y1 - y0) / 2;
+          const xOffset = (x1 - x0) / 2 * controlPointsDistance;
+          const yOffset = (y1 - y0) / 2 * controlPointsDistance;
+          buffer.push(`${xMid} ${y1} m`);
+          buffer.push(`${xMid + xOffset} ${y1} ${x1} ${yMid + yOffset} ${x1} ${yMid} c`);
+          buffer.push(`${x1} ${yMid - yOffset} ${xMid + xOffset} ${y0} ${xMid} ${y0} c`);
+          buffer.push(`${xMid - xOffset} ${y0} ${x0} ${yMid - yOffset} ${x0} ${yMid} c`);
+          buffer.push(`${x0} ${yMid + yOffset} ${xMid - xOffset} ${y1} ${xMid} ${y1} c`);
+          buffer.push("h");
+
+          if (fillColor) {
+            buffer.push("B");
+          } else {
+            buffer.push("S");
+          }
+
+          return [points[0].x, points[1].x, points[3].y, points[1].y];
+        }
+      });
+    }
   }
   }
 
 
 }
 }

+ 1 - 1
lib/core/arithmetic_decoder.js

@@ -2,7 +2,7 @@
  * @licstart The following is the entire license notice for the
  * @licstart The following is the entire license notice for the
  * Javascript code in this page
  * Javascript code in this page
  *
  *
- * Copyright 2020 Mozilla Foundation
+ * Copyright 2021 Mozilla Foundation
  *
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * you may not use this file except in compliance with the License.

+ 1 - 1
lib/core/bidi.js

@@ -2,7 +2,7 @@
  * @licstart The following is the entire license notice for the
  * @licstart The following is the entire license notice for the
  * Javascript code in this page
  * Javascript code in this page
  *
  *
- * Copyright 2020 Mozilla Foundation
+ * Copyright 2021 Mozilla Foundation
  *
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * you may not use this file except in compliance with the License.

+ 1 - 1
lib/core/ccitt.js

@@ -2,7 +2,7 @@
  * @licstart The following is the entire license notice for the
  * @licstart The following is the entire license notice for the
  * Javascript code in this page
  * Javascript code in this page
  *
  *
- * Copyright 2020 Mozilla Foundation
+ * Copyright 2021 Mozilla Foundation
  *
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * you may not use this file except in compliance with the License.

+ 2 - 2
lib/core/ccitt_stream.js

@@ -2,7 +2,7 @@
  * @licstart The following is the entire license notice for the
  * @licstart The following is the entire license notice for the
  * Javascript code in this page
  * Javascript code in this page
  *
  *
- * Copyright 2020 Mozilla Foundation
+ * Copyright 2021 Mozilla Foundation
  *
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * you may not use this file except in compliance with the License.
@@ -32,7 +32,7 @@ var _ccitt = require("./ccitt.js");
 
 
 var _stream = require("./stream.js");
 var _stream = require("./stream.js");
 
 
-var CCITTFaxStream = function CCITTFaxStreamClosure() {
+const CCITTFaxStream = function CCITTFaxStreamClosure() {
   function CCITTFaxStream(str, maybeLength, params) {
   function CCITTFaxStream(str, maybeLength, params) {
     this.str = str;
     this.str = str;
     this.dict = str.dict;
     this.dict = str.dict;

File diff suppressed because it is too large
+ 1 - 2
lib/core/cff_parser.js


+ 1 - 1
lib/core/charsets.js

@@ -2,7 +2,7 @@
  * @licstart The following is the entire license notice for the
  * @licstart The following is the entire license notice for the
  * Javascript code in this page
  * Javascript code in this page
  *
  *
- * Copyright 2020 Mozilla Foundation
+ * Copyright 2021 Mozilla Foundation
  *
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * you may not use this file except in compliance with the License.

+ 1 - 1
lib/core/chunked_stream.js

@@ -2,7 +2,7 @@
  * @licstart The following is the entire license notice for the
  * @licstart The following is the entire license notice for the
  * Javascript code in this page
  * Javascript code in this page
  *
  *
- * Copyright 2020 Mozilla Foundation
+ * Copyright 2021 Mozilla Foundation
  *
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * you may not use this file except in compliance with the License.

+ 65 - 75
lib/core/cmap.js

@@ -2,7 +2,7 @@
  * @licstart The following is the entire license notice for the
  * @licstart The following is the entire license notice for the
  * Javascript code in this page
  * Javascript code in this page
  *
  *
- * Copyright 2020 Mozilla Foundation
+ * Copyright 2021 Mozilla Foundation
  *
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * you may not use this file except in compliance with the License.
@@ -319,21 +319,21 @@ var BinaryCMapReader = function BinaryCMapReaderClosure() {
   var MAX_NUM_SIZE = 16;
   var MAX_NUM_SIZE = 16;
   var MAX_ENCODED_NUM_SIZE = 19;
   var MAX_ENCODED_NUM_SIZE = 19;
 
 
-  function BinaryCMapStream(data) {
-    this.buffer = data;
-    this.pos = 0;
-    this.end = data.length;
-    this.tmpBuf = new Uint8Array(MAX_ENCODED_NUM_SIZE);
-  }
+  class BinaryCMapStream {
+    constructor(data) {
+      this.buffer = data;
+      this.pos = 0;
+      this.end = data.length;
+      this.tmpBuf = new Uint8Array(MAX_ENCODED_NUM_SIZE);
+    }
 
 
-  BinaryCMapStream.prototype = {
     readByte() {
     readByte() {
       if (this.pos >= this.end) {
       if (this.pos >= this.end) {
         return -1;
         return -1;
       }
       }
 
 
       return this.buffer[this.pos++];
       return this.buffer[this.pos++];
-    },
+    }
 
 
     readNumber() {
     readNumber() {
       var n = 0;
       var n = 0;
@@ -351,17 +351,17 @@ var BinaryCMapReader = function BinaryCMapReaderClosure() {
       } while (!last);
       } while (!last);
 
 
       return n;
       return n;
-    },
+    }
 
 
     readSigned() {
     readSigned() {
       var n = this.readNumber();
       var n = this.readNumber();
       return n & 1 ? ~(n >>> 1) : n >>> 1;
       return n & 1 ? ~(n >>> 1) : n >>> 1;
-    },
+    }
 
 
     readHex(num, size) {
     readHex(num, size) {
       num.set(this.buffer.subarray(this.pos, this.pos + size + 1));
       num.set(this.buffer.subarray(this.pos, this.pos + size + 1));
       this.pos += size + 1;
       this.pos += size + 1;
-    },
+    }
 
 
     readHexNumber(num, size) {
     readHexNumber(num, size) {
       var last;
       var last;
@@ -394,7 +394,7 @@ var BinaryCMapReader = function BinaryCMapReaderClosure() {
         buffer >>= 8;
         buffer >>= 8;
         bufferSize -= 8;
         bufferSize -= 8;
       }
       }
-    },
+    }
 
 
     readHexSigned(num, size) {
     readHexSigned(num, size) {
       this.readHexNumber(num, size);
       this.readHexNumber(num, size);
@@ -405,7 +405,7 @@ var BinaryCMapReader = function BinaryCMapReaderClosure() {
         c = (c & 1) << 8 | num[i];
         c = (c & 1) << 8 | num[i];
         num[i] = c >> 1 ^ sign;
         num[i] = c >> 1 ^ sign;
       }
       }
-    },
+    }
 
 
     readString() {
     readString() {
       var len = this.readNumber();
       var len = this.readNumber();
@@ -418,10 +418,10 @@ var BinaryCMapReader = function BinaryCMapReaderClosure() {
       return s;
       return s;
     }
     }
 
 
-  };
+  }
 
 
-  function processBinaryCMap(data, cMap, extend) {
-    return new Promise(function (resolve, reject) {
+  class BinaryCMapReader {
+    async process(data, cMap, extend) {
       var stream = new BinaryCMapStream(data);
       var stream = new BinaryCMapStream(data);
       var header = stream.readByte();
       var header = stream.readByte();
       cMap.vertical = !!(header & 1);
       cMap.vertical = !!(header & 1);
@@ -455,7 +455,7 @@ var BinaryCMapReader = function BinaryCMapReaderClosure() {
         var dataSize = b & 15;
         var dataSize = b & 15;
 
 
         if (dataSize + 1 > MAX_NUM_SIZE) {
         if (dataSize + 1 > MAX_NUM_SIZE) {
-          throw new Error("processBinaryCMap: Invalid dataSize.");
+          throw new Error("BinaryCMapReader.process: Invalid dataSize.");
         }
         }
 
 
         var ucs2DataSize = 1;
         var ucs2DataSize = 1;
@@ -588,25 +588,19 @@ var BinaryCMapReader = function BinaryCMapReaderClosure() {
             break;
             break;
 
 
           default:
           default:
-            reject(new Error("processBinaryCMap: Unknown type: " + type));
-            return;
+            throw new Error(`BinaryCMapReader.process - unknown type: ${type}`);
         }
         }
       }
       }
 
 
       if (useCMap) {
       if (useCMap) {
-        resolve(extend(useCMap));
-        return;
+        return extend(useCMap);
       }
       }
 
 
-      resolve(cMap);
-    });
-  }
+      return cMap;
+    }
 
 
-  function BinaryCMapReader() {}
+  }
 
 
-  BinaryCMapReader.prototype = {
-    process: processBinaryCMap
-  };
   return BinaryCMapReader;
   return BinaryCMapReader;
 }();
 }();
 
 
@@ -785,7 +779,7 @@ var CMapFactory = function CMapFactoryClosure() {
     }
     }
   }
   }
 
 
-  function parseCMap(cMap, lexer, fetchBuiltInCMap, useCMap) {
+  async function parseCMap(cMap, lexer, fetchBuiltInCMap, useCMap) {
     var previous;
     var previous;
     var embeddedUseCMap;
     var embeddedUseCMap;
 
 
@@ -854,65 +848,63 @@ var CMapFactory = function CMapFactoryClosure() {
       return extendCMap(cMap, fetchBuiltInCMap, useCMap);
       return extendCMap(cMap, fetchBuiltInCMap, useCMap);
     }
     }
 
 
-    return Promise.resolve(cMap);
+    return cMap;
   }
   }
 
 
-  function extendCMap(cMap, fetchBuiltInCMap, useCMap) {
-    return createBuiltInCMap(useCMap, fetchBuiltInCMap).then(function (newCMap) {
-      cMap.useCMap = newCMap;
+  async function extendCMap(cMap, fetchBuiltInCMap, useCMap) {
+    cMap.useCMap = await createBuiltInCMap(useCMap, fetchBuiltInCMap);
 
 
-      if (cMap.numCodespaceRanges === 0) {
-        var useCodespaceRanges = cMap.useCMap.codespaceRanges;
+    if (cMap.numCodespaceRanges === 0) {
+      var useCodespaceRanges = cMap.useCMap.codespaceRanges;
 
 
-        for (var i = 0; i < useCodespaceRanges.length; i++) {
-          cMap.codespaceRanges[i] = useCodespaceRanges[i].slice();
-        }
-
-        cMap.numCodespaceRanges = cMap.useCMap.numCodespaceRanges;
+      for (var i = 0; i < useCodespaceRanges.length; i++) {
+        cMap.codespaceRanges[i] = useCodespaceRanges[i].slice();
       }
       }
 
 
-      cMap.useCMap.forEach(function (key, value) {
-        if (!cMap.contains(key)) {
-          cMap.mapOne(key, cMap.useCMap.lookup(key));
-        }
-      });
-      return cMap;
+      cMap.numCodespaceRanges = cMap.useCMap.numCodespaceRanges;
+    }
+
+    cMap.useCMap.forEach(function (key, value) {
+      if (!cMap.contains(key)) {
+        cMap.mapOne(key, cMap.useCMap.lookup(key));
+      }
     });
     });
+    return cMap;
   }
   }
 
 
-  function createBuiltInCMap(name, fetchBuiltInCMap) {
+  async function createBuiltInCMap(name, fetchBuiltInCMap) {
     if (name === "Identity-H") {
     if (name === "Identity-H") {
-      return Promise.resolve(new IdentityCMap(false, 2));
+      return new IdentityCMap(false, 2);
     } else if (name === "Identity-V") {
     } else if (name === "Identity-V") {
-      return Promise.resolve(new IdentityCMap(true, 2));
+      return new IdentityCMap(true, 2);
     }
     }
 
 
     if (!BUILT_IN_CMAPS.includes(name)) {
     if (!BUILT_IN_CMAPS.includes(name)) {
-      return Promise.reject(new Error("Unknown CMap name: " + name));
+      throw new Error("Unknown CMap name: " + name);
     }
     }
 
 
     if (!fetchBuiltInCMap) {
     if (!fetchBuiltInCMap) {
-      return Promise.reject(new Error("Built-in CMap parameters are not provided."));
+      throw new Error("Built-in CMap parameters are not provided.");
     }
     }
 
 
-    return fetchBuiltInCMap(name).then(function (data) {
-      var cMapData = data.cMapData,
-          compressionType = data.compressionType;
-      var cMap = new CMap(true);
+    const {
+      cMapData,
+      compressionType
+    } = await fetchBuiltInCMap(name);
+    var cMap = new CMap(true);
 
 
-      if (compressionType === _util.CMapCompressionType.BINARY) {
-        return new BinaryCMapReader().process(cMapData, cMap, function (useCMap) {
-          return extendCMap(cMap, fetchBuiltInCMap, useCMap);
-        });
-      }
+    if (compressionType === _util.CMapCompressionType.BINARY) {
+      return new BinaryCMapReader().process(cMapData, cMap, useCMap => {
+        return extendCMap(cMap, fetchBuiltInCMap, useCMap);
+      });
+    }
 
 
-      if (compressionType === _util.CMapCompressionType.NONE) {
-        var lexer = new _parser.Lexer(new _stream.Stream(cMapData));
-        return parseCMap(cMap, lexer, fetchBuiltInCMap, null);
-      }
+    if (compressionType === _util.CMapCompressionType.NONE) {
+      var lexer = new _parser.Lexer(new _stream.Stream(cMapData));
+      return parseCMap(cMap, lexer, fetchBuiltInCMap, null);
+    }
 
 
-      return Promise.reject(new Error("TODO: Only BINARY/NONE CMap compression is currently supported."));
-    });
+    throw new Error("TODO: Only BINARY/NONE CMap compression is currently supported.");
   }
   }
 
 
   return {
   return {
@@ -924,15 +916,13 @@ var CMapFactory = function CMapFactoryClosure() {
       if ((0, _primitives.isName)(encoding)) {
       if ((0, _primitives.isName)(encoding)) {
         return createBuiltInCMap(encoding.name, fetchBuiltInCMap);
         return createBuiltInCMap(encoding.name, fetchBuiltInCMap);
       } else if ((0, _primitives.isStream)(encoding)) {
       } else if ((0, _primitives.isStream)(encoding)) {
-        var cMap = new CMap();
-        var lexer = new _parser.Lexer(encoding);
-        return parseCMap(cMap, lexer, fetchBuiltInCMap, useCMap).then(function (parsedCMap) {
-          if (parsedCMap.isIdentityCMap) {
-            return createBuiltInCMap(parsedCMap.name, fetchBuiltInCMap);
-          }
+        const parsedCMap = await parseCMap(new CMap(), new _parser.Lexer(encoding), fetchBuiltInCMap, useCMap);
+
+        if (parsedCMap.isIdentityCMap) {
+          return createBuiltInCMap(parsedCMap.name, fetchBuiltInCMap);
+        }
 
 
-          return parsedCMap;
-        });
+        return parsedCMap;
       }
       }
 
 
       throw new Error("Encoding required.");
       throw new Error("Encoding required.");

+ 2 - 2
lib/core/colorspace.js

@@ -2,7 +2,7 @@
  * @licstart The following is the entire license notice for the
  * @licstart The following is the entire license notice for the
  * Javascript code in this page
  * Javascript code in this page
  *
  *
- * Copyright 2020 Mozilla Foundation
+ * Copyright 2021 Mozilla Foundation
  *
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * you may not use this file except in compliance with the License.
@@ -954,7 +954,7 @@ const LabCS = function LabCSClosure() {
     let result;
     let result;
 
 
     if (x >= 6 / 29) {
     if (x >= 6 / 29) {
-      result = x * x * x;
+      result = x ** 3;
     } else {
     } else {
       result = 108 / 841 * (x - 4 / 29);
       result = 108 / 841 * (x - 4 / 29);
     }
     }

+ 83 - 21
lib/core/core_utils.js

@@ -2,7 +2,7 @@
  * @licstart The following is the entire license notice for the
  * @licstart The following is the entire license notice for the
  * Javascript code in this page
  * Javascript code in this page
  *
  *
- * Copyright 2020 Mozilla Foundation
+ * Copyright 2021 Mozilla Foundation
  *
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * you may not use this file except in compliance with the License.
@@ -25,6 +25,7 @@ Object.defineProperty(exports, "__esModule", {
   value: true
   value: true
 });
 });
 exports.collectActions = collectActions;
 exports.collectActions = collectActions;
+exports.encodeToXmlString = encodeToXmlString;
 exports.escapePDFName = escapePDFName;
 exports.escapePDFName = escapePDFName;
 exports.getArrayLookupTableFactory = getArrayLookupTableFactory;
 exports.getArrayLookupTableFactory = getArrayLookupTableFactory;
 exports.getInheritableProperty = getInheritableProperty;
 exports.getInheritableProperty = getInheritableProperty;
@@ -99,11 +100,14 @@ function getInheritableProperty({
   getArray = false,
   getArray = false,
   stopWhenFound = true
   stopWhenFound = true
 }) {
 }) {
-  const LOOP_LIMIT = 100;
-  let loopCount = 0;
   let values;
   let values;
+  const visited = new _primitives.RefSet();
+
+  while (dict instanceof _primitives.Dict && !(dict.objId && visited.has(dict.objId))) {
+    if (dict.objId) {
+      visited.put(dict.objId);
+    }
 
 
-  while (dict) {
     const value = getArray ? dict.getArray(key) : dict.get(key);
     const value = getArray ? dict.getArray(key) : dict.get(key);
 
 
     if (value !== undefined) {
     if (value !== undefined) {
@@ -118,11 +122,6 @@ function getInheritableProperty({
       values.push(value);
       values.push(value);
     }
     }
 
 
-    if (++loopCount > LOOP_LIMIT) {
-      (0, _util.warn)(`getInheritableProperty: maximum loop count exceeded for "${key}"`);
-      break;
-    }
-
     dict = dict.get("Parent");
     dict = dict.get("Parent");
   }
   }
 
 
@@ -272,25 +271,36 @@ function _collectJS(entry, xref, list, parents) {
 
 
 function collectActions(xref, dict, eventType) {
 function collectActions(xref, dict, eventType) {
   const actions = Object.create(null);
   const actions = Object.create(null);
+  const additionalActionsDicts = getInheritableProperty({
+    dict,
+    key: "AA",
+    stopWhenFound: false
+  });
 
 
-  if (dict.has("AA")) {
-    const additionalActions = dict.get("AA");
-
-    for (const key of additionalActions.getKeys()) {
-      const action = eventType[key];
+  if (additionalActionsDicts) {
+    for (let i = additionalActionsDicts.length - 1; i >= 0; i--) {
+      const additionalActions = additionalActionsDicts[i];
 
 
-      if (!action) {
+      if (!(additionalActions instanceof _primitives.Dict)) {
         continue;
         continue;
       }
       }
 
 
-      const actionDict = additionalActions.getRaw(key);
-      const parents = new _primitives.RefSet();
-      const list = [];
+      for (const key of additionalActions.getKeys()) {
+        const action = eventType[key];
+
+        if (!action) {
+          continue;
+        }
+
+        const actionDict = additionalActions.getRaw(key);
+        const parents = new _primitives.RefSet();
+        const list = [];
 
 
-      _collectJS(actionDict, xref, list, parents);
+        _collectJS(actionDict, xref, list, parents);
 
 
-      if (list.length > 0) {
-        actions[action] = list;
+        if (list.length > 0) {
+          actions[action] = list;
+        }
       }
       }
     }
     }
   }
   }
@@ -308,4 +318,56 @@ function collectActions(xref, dict, eventType) {
   }
   }
 
 
   return (0, _util.objectSize)(actions) > 0 ? actions : null;
   return (0, _util.objectSize)(actions) > 0 ? actions : null;
+}
+
+const XMLEntities = {
+  0x3c: "&lt;",
+  0x3e: "&gt;",
+  0x26: "&amp;",
+  0x22: "&quot;",
+  0x27: "&apos;"
+};
+
+function encodeToXmlString(str) {
+  const buffer = [];
+  let start = 0;
+
+  for (let i = 0, ii = str.length; i < ii; i++) {
+    const char = str.codePointAt(i);
+
+    if (0x20 <= char && char <= 0x7e) {
+      const entity = XMLEntities[char];
+
+      if (entity) {
+        if (start < i) {
+          buffer.push(str.substring(start, i));
+        }
+
+        buffer.push(entity);
+        start = i + 1;
+      }
+    } else {
+      if (start < i) {
+        buffer.push(str.substring(start, i));
+      }
+
+      buffer.push(`&#x${char.toString(16).toUpperCase()};`);
+
+      if (char > 0xd7ff && (char < 0xe000 || char > 0xfffd)) {
+        i++;
+      }
+
+      start = i + 1;
+    }
+  }
+
+  if (buffer.length === 0) {
+    return str;
+  }
+
+  if (start < str.length) {
+    buffer.push(str.substring(start, str.length));
+  }
+
+  return buffer.join("");
 }
 }

File diff suppressed because it is too large
+ 122 - 110
lib/core/crypto.js


+ 8 - 8
lib/core/default_appearance.js

@@ -2,7 +2,7 @@
  * @licstart The following is the entire license notice for the
  * @licstart The following is the entire license notice for the
  * Javascript code in this page
  * Javascript code in this page
  *
  *
- * Copyright 2020 Mozilla Foundation
+ * Copyright 2021 Mozilla Foundation
  *
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * you may not use this file except in compliance with the License.
@@ -27,8 +27,6 @@ Object.defineProperty(exports, "__esModule", {
 exports.createDefaultAppearance = createDefaultAppearance;
 exports.createDefaultAppearance = createDefaultAppearance;
 exports.parseDefaultAppearance = parseDefaultAppearance;
 exports.parseDefaultAppearance = parseDefaultAppearance;
 
 
-var _primitives = require("./primitives.js");
-
 var _util = require("../shared/util.js");
 var _util = require("../shared/util.js");
 
 
 var _colorspace = require("./colorspace.js");
 var _colorspace = require("./colorspace.js");
@@ -37,6 +35,8 @@ var _core_utils = require("./core_utils.js");
 
 
 var _evaluator = require("./evaluator.js");
 var _evaluator = require("./evaluator.js");
 
 
+var _primitives = require("./primitives.js");
+
 var _stream = require("./stream.js");
 var _stream = require("./stream.js");
 
 
 class DefaultAppearanceEvaluator extends _evaluator.EvaluatorPreprocessor {
 class DefaultAppearanceEvaluator extends _evaluator.EvaluatorPreprocessor {
@@ -51,8 +51,8 @@ class DefaultAppearanceEvaluator extends _evaluator.EvaluatorPreprocessor {
     };
     };
     const result = {
     const result = {
       fontSize: 0,
       fontSize: 0,
-      fontName: _primitives.Name.get(""),
-      fontColor: new Uint8ClampedArray([0, 0, 0])
+      fontName: "",
+      fontColor: new Uint8ClampedArray(3)
     };
     };
 
 
     try {
     try {
@@ -76,8 +76,8 @@ class DefaultAppearanceEvaluator extends _evaluator.EvaluatorPreprocessor {
           case _util.OPS.setFont:
           case _util.OPS.setFont:
             const [fontName, fontSize] = args;
             const [fontName, fontSize] = args;
 
 
-            if ((0, _primitives.isName)(fontName)) {
-              result.fontName = fontName;
+            if (fontName instanceof _primitives.Name) {
+              result.fontName = fontName.name;
             }
             }
 
 
             if (typeof fontSize === "number" && fontSize > 0) {
             if (typeof fontSize === "number" && fontSize > 0) {
@@ -128,5 +128,5 @@ function createDefaultAppearance({
     colorCmd = Array.from(fontColor).map(c => (c / 255).toFixed(2)).join(" ") + " rg";
     colorCmd = Array.from(fontColor).map(c => (c / 255).toFixed(2)).join(" ") + " rg";
   }
   }
 
 
-  return `/${(0, _core_utils.escapePDFName)(fontName.name)} ${fontSize} Tf ${colorCmd}`;
+  return `/${(0, _core_utils.escapePDFName)(fontName)} ${fontSize} Tf ${colorCmd}`;
 }
 }

+ 125 - 5
lib/core/document.js

@@ -2,7 +2,7 @@
  * @licstart The following is the entire license notice for the
  * @licstart The following is the entire license notice for the
  * Javascript code in this page
  * Javascript code in this page
  *
  *
- * Copyright 2020 Mozilla Foundation
+ * Copyright 2021 Mozilla Foundation
  *
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * you may not use this file except in compliance with the License.
@@ -46,6 +46,8 @@ var _operator_list = require("./operator_list.js");
 
 
 var _evaluator = require("./evaluator.js");
 var _evaluator = require("./evaluator.js");
 
 
+var _factory = require("./xfa/factory.js");
+
 const DEFAULT_USER_UNIT = 1.0;
 const DEFAULT_USER_UNIT = 1.0;
 const LETTER_SIZE_MEDIABOX = [0, 0, 612, 792];
 const LETTER_SIZE_MEDIABOX = [0, 0, 612, 792];
 
 
@@ -64,7 +66,8 @@ class Page {
     fontCache,
     fontCache,
     builtInCMapCache,
     builtInCMapCache,
     globalImageCache,
     globalImageCache,
-    nonBlendModesSet
+    nonBlendModesSet,
+    xfaFactory
   }) {
   }) {
     this.pdfManager = pdfManager;
     this.pdfManager = pdfManager;
     this.pageIndex = pageIndex;
     this.pageIndex = pageIndex;
@@ -77,6 +80,7 @@ class Page {
     this.nonBlendModesSet = nonBlendModesSet;
     this.nonBlendModesSet = nonBlendModesSet;
     this.evaluatorOptions = pdfManager.evaluatorOptions;
     this.evaluatorOptions = pdfManager.evaluatorOptions;
     this.resourcesPromise = null;
     this.resourcesPromise = null;
+    this.xfaFactory = xfaFactory;
     const idCounters = {
     const idCounters = {
       obj: 0
       obj: 0
     };
     };
@@ -119,6 +123,14 @@ class Page {
   }
   }
 
 
   _getBoundingBox(name) {
   _getBoundingBox(name) {
+    if (this.xfaData) {
+      const {
+        width,
+        height
+      } = this.xfaData.attributes.style;
+      return [0, 0, parseInt(width), parseInt(height)];
+    }
+
     const box = this._getInheritableProperty(name, true);
     const box = this._getInheritableProperty(name, true);
 
 
     if (Array.isArray(box) && box.length === 4) {
     if (Array.isArray(box) && box.length === 4) {
@@ -208,6 +220,14 @@ class Page {
     return stream;
     return stream;
   }
   }
 
 
+  get xfaData() {
+    if (this.xfaFactory) {
+      return (0, _util.shadow)(this, "xfaData", this.xfaFactory.getPage(this.pageIndex));
+    }
+
+    return (0, _util.shadow)(this, "xfaData", null);
+  }
+
   save(handler, task, annotationStorage) {
   save(handler, task, annotationStorage) {
     const partialEvaluator = new _evaluator.PartialEvaluator({
     const partialEvaluator = new _evaluator.PartialEvaluator({
       xref: this.xref,
       xref: this.xref,
@@ -377,7 +397,7 @@ class Page {
       const annotationPromises = [];
       const annotationPromises = [];
 
 
       for (const annotationRef of this.annotations) {
       for (const annotationRef of this.annotations) {
-        annotationPromises.push(_annotation.AnnotationFactory.create(this.xref, annotationRef, this.pdfManager, this._localIdFactory).catch(function (reason) {
+        annotationPromises.push(_annotation.AnnotationFactory.create(this.xref, annotationRef, this.pdfManager, this._localIdFactory, false).catch(function (reason) {
           (0, _util.warn)(`_parsedAnnotations: "${reason}".`);
           (0, _util.warn)(`_parsedAnnotations: "${reason}".`);
           return null;
           return null;
         }));
         }));
@@ -603,6 +623,10 @@ class PDFDocument {
   }
   }
 
 
   get numPages() {
   get numPages() {
+    if (this.xfaFactory) {
+      return (0, _util.shadow)(this, "numPages", this.xfaFactory.numberPages);
+    }
+
     const linearization = this.linearization;
     const linearization = this.linearization;
     const num = linearization ? linearization.numPages : this.catalog.numPages;
     const num = linearization ? linearization.numPages : this.catalog.numPages;
     return (0, _util.shadow)(this, "numPages", num);
     return (0, _util.shadow)(this, "numPages", num);
@@ -638,6 +662,84 @@ class PDFDocument {
     });
     });
   }
   }
 
 
+  get xfaData() {
+    const acroForm = this.catalog.acroForm;
+
+    if (!acroForm) {
+      return null;
+    }
+
+    const xfa = acroForm.get("XFA");
+    const entries = {
+      "xdp:xdp": "",
+      template: "",
+      datasets: "",
+      config: "",
+      connectionSet: "",
+      localeSet: "",
+      stylesheet: "",
+      "/xdp:xdp": ""
+    };
+
+    if ((0, _primitives.isStream)(xfa) && !xfa.isEmpty) {
+      try {
+        entries["xdp:xdp"] = (0, _util.stringToUTF8String)((0, _util.bytesToString)(xfa.getBytes()));
+        return entries;
+      } catch (_) {
+        (0, _util.warn)("XFA - Invalid utf-8 string.");
+        return null;
+      }
+    }
+
+    if (!Array.isArray(xfa) || xfa.length === 0) {
+      return null;
+    }
+
+    for (let i = 0, ii = xfa.length; i < ii; i += 2) {
+      let name;
+
+      if (i === 0) {
+        name = "xdp:xdp";
+      } else if (i === ii - 2) {
+        name = "/xdp:xdp";
+      } else {
+        name = xfa[i];
+      }
+
+      if (!entries.hasOwnProperty(name)) {
+        continue;
+      }
+
+      const data = this.xref.fetchIfRef(xfa[i + 1]);
+
+      if (!(0, _primitives.isStream)(data) || data.isEmpty) {
+        continue;
+      }
+
+      try {
+        entries[name] = (0, _util.stringToUTF8String)((0, _util.bytesToString)(data.getBytes()));
+      } catch (_) {
+        (0, _util.warn)("XFA - Invalid utf-8 string.");
+        return null;
+      }
+    }
+
+    return entries;
+  }
+
+  get xfaFactory() {
+    if (this.pdfManager.enableXfa && this.formInfo.hasXfa && !this.formInfo.hasAcroForm) {
+      const data = this.xfaData;
+      return (0, _util.shadow)(this, "xfaFactory", data ? new _factory.XFAFactory(data) : null);
+    }
+
+    return (0, _util.shadow)(this, "xfaFaxtory", null);
+  }
+
+  get isPureXfa() {
+    return this.xfaFactory !== null;
+  }
+
   get formInfo() {
   get formInfo() {
     const formInfo = {
     const formInfo = {
       hasFields: false,
       hasFields: false,
@@ -797,6 +899,23 @@ class PDFDocument {
       catalog,
       catalog,
       linearization
       linearization
     } = this;
     } = this;
+
+    if (this.xfaFactory) {
+      return Promise.resolve(new Page({
+        pdfManager: this.pdfManager,
+        xref: this.xref,
+        pageIndex,
+        pageDict: _primitives.Dict.empty,
+        ref: null,
+        globalIdFactory: this._globalIdFactory,
+        fontCache: catalog.fontCache,
+        builtInCMapCache: catalog.builtInCMapCache,
+        globalImageCache: catalog.globalImageCache,
+        nonBlendModesSet: catalog.nonBlendModesSet,
+        xfaFactory: this.xfaFactory
+      }));
+    }
+
     const promise = linearization && linearization.pageFirst === pageIndex ? this._getLinearizationPage(pageIndex) : catalog.getPageDict(pageIndex);
     const promise = linearization && linearization.pageFirst === pageIndex ? this._getLinearizationPage(pageIndex) : catalog.getPageDict(pageIndex);
     return this._pagePromises[pageIndex] = promise.then(([pageDict, ref]) => {
     return this._pagePromises[pageIndex] = promise.then(([pageDict, ref]) => {
       return new Page({
       return new Page({
@@ -809,7 +928,8 @@ class PDFDocument {
         fontCache: catalog.fontCache,
         fontCache: catalog.fontCache,
         builtInCMapCache: catalog.builtInCMapCache,
         builtInCMapCache: catalog.builtInCMapCache,
         globalImageCache: catalog.globalImageCache,
         globalImageCache: catalog.globalImageCache,
-        nonBlendModesSet: catalog.nonBlendModesSet
+        nonBlendModesSet: catalog.nonBlendModesSet,
+        xfaFactory: null
       });
       });
     });
     });
   }
   }
@@ -849,7 +969,7 @@ class PDFDocument {
       promises.set(name, []);
       promises.set(name, []);
     }
     }
 
 
-    promises.get(name).push(_annotation.AnnotationFactory.create(this.xref, fieldRef, this.pdfManager, this._localIdFactory).then(annotation => annotation && annotation.getFieldObject()).catch(function (reason) {
+    promises.get(name).push(_annotation.AnnotationFactory.create(this.xref, fieldRef, this.pdfManager, this._localIdFactory, true).then(annotation => annotation && annotation.getFieldObject()).catch(function (reason) {
       (0, _util.warn)(`_collectFieldObjects: "${reason}".`);
       (0, _util.warn)(`_collectFieldObjects: "${reason}".`);
       return null;
       return null;
     }));
     }));

+ 1 - 1
lib/core/encodings.js

@@ -2,7 +2,7 @@
  * @licstart The following is the entire license notice for the
  * @licstart The following is the entire license notice for the
  * Javascript code in this page
  * Javascript code in this page
  *
  *
- * Copyright 2020 Mozilla Foundation
+ * Copyright 2021 Mozilla Foundation
  *
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * you may not use this file except in compliance with the License.

+ 47 - 43
lib/core/evaluator.js

@@ -2,7 +2,7 @@
  * @licstart The following is the entire license notice for the
  * @licstart The following is the entire license notice for the
  * Javascript code in this page
  * Javascript code in this page
  *
  *
- * Copyright 2020 Mozilla Foundation
+ * Copyright 2021 Mozilla Foundation
  *
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * you may not use this file except in compliance with the License.
@@ -32,12 +32,12 @@ var _cmap = require("./cmap.js");
 
 
 var _primitives = require("./primitives.js");
 var _primitives = require("./primitives.js");
 
 
+var _stream = require("./stream.js");
+
 var _fonts = require("./fonts.js");
 var _fonts = require("./fonts.js");
 
 
 var _encodings = require("./encodings.js");
 var _encodings = require("./encodings.js");
 
 
-var _core_utils = require("./core_utils.js");
-
 var _unicode = require("./unicode.js");
 var _unicode = require("./unicode.js");
 
 
 var _standard_fonts = require("./standard_fonts.js");
 var _standard_fonts = require("./standard_fonts.js");
@@ -54,10 +54,10 @@ var _bidi = require("./bidi.js");
 
 
 var _colorspace = require("./colorspace.js");
 var _colorspace = require("./colorspace.js");
 
 
-var _stream = require("./stream.js");
-
 var _glyphlist = require("./glyphlist.js");
 var _glyphlist = require("./glyphlist.js");
 
 
+var _core_utils = require("./core_utils.js");
+
 var _metrics = require("./metrics.js");
 var _metrics = require("./metrics.js");
 
 
 var _murmurhash = require("./murmurhash3.js");
 var _murmurhash = require("./murmurhash3.js");
@@ -258,10 +258,6 @@ class PartialEvaluator {
             try {
             try {
               graphicState = xref.fetch(graphicState);
               graphicState = xref.fetch(graphicState);
             } catch (ex) {
             } catch (ex) {
-              if (ex instanceof _core_utils.MissingDataException) {
-                throw ex;
-              }
-
               processed.put(graphicState);
               processed.put(graphicState);
               (0, _util.info)(`hasBlendModes - ignoring ExtGState: "${ex}".`);
               (0, _util.info)(`hasBlendModes - ignoring ExtGState: "${ex}".`);
               continue;
               continue;
@@ -311,10 +307,6 @@ class PartialEvaluator {
           try {
           try {
             xObject = xref.fetch(xObject);
             xObject = xref.fetch(xObject);
           } catch (ex) {
           } catch (ex) {
-            if (ex instanceof _core_utils.MissingDataException) {
-              throw ex;
-            }
-
             processed.put(xObject);
             processed.put(xObject);
             (0, _util.info)(`hasBlendModes - ignoring XObject: "${ex}".`);
             (0, _util.info)(`hasBlendModes - ignoring XObject: "${ex}".`);
             continue;
             continue;
@@ -578,6 +570,11 @@ class PartialEvaluator {
       localColorSpaceCache
       localColorSpaceCache
     }).then(imageObj => {
     }).then(imageObj => {
       imgData = imageObj.createImageData(false);
       imgData = imageObj.createImageData(false);
+
+      if (cacheKey && imageRef && cacheGlobally) {
+        this.globalImageCache.addByteSize(imageRef, imgData.data.length);
+      }
+
       return this._sendImgData(objId, imgData, cacheGlobally);
       return this._sendImgData(objId, imgData, cacheGlobally);
     }).catch(reason => {
     }).catch(reason => {
       (0, _util.warn)(`Unable to decode image "${objId}": "${reason}".`);
       (0, _util.warn)(`Unable to decode image "${objId}": "${reason}".`);
@@ -600,7 +597,8 @@ class PartialEvaluator {
           this.globalImageCache.setData(imageRef, {
           this.globalImageCache.setData(imageRef, {
             objId,
             objId,
             fn: _util.OPS.paintImageXObject,
             fn: _util.OPS.paintImageXObject,
-            args
+            args,
+            byteSize: 0
           });
           });
         }
         }
       }
       }
@@ -730,13 +728,7 @@ class PartialEvaluator {
   }
   }
 
 
   handleSetFont(resources, fontArgs, fontRef, operatorList, task, state, fallbackFontDict = null) {
   handleSetFont(resources, fontArgs, fontRef, operatorList, task, state, fallbackFontDict = null) {
-    var fontName;
-
-    if (fontArgs) {
-      fontArgs = fontArgs.slice();
-      fontName = fontArgs[0].name;
-    }
-
+    const fontName = fontArgs && fontArgs[0] instanceof _primitives.Name ? fontArgs[0].name : null;
     return this.loadFont(fontName, fontRef, resources, fallbackFontDict).then(translated => {
     return this.loadFont(fontName, fontRef, resources, fallbackFontDict).then(translated => {
       if (!translated.font.isType3Font) {
       if (!translated.font.isType3Font) {
         return translated;
         return translated;
@@ -969,7 +961,7 @@ class PartialEvaluator {
     try {
     try {
       preEvaluatedFont = this.preEvaluateFont(font);
       preEvaluatedFont = this.preEvaluateFont(font);
     } catch (reason) {
     } catch (reason) {
-      (0, _util.warn)(`loadFont - ignoring preEvaluateFont errors: "${reason}".`);
+      (0, _util.warn)(`loadFont - preEvaluateFont failed: "${reason}".`);
       return errorFont();
       return errorFont();
     }
     }
 
 
@@ -1040,6 +1032,7 @@ class PartialEvaluator {
       this.handler.send("UnsupportedFeature", {
       this.handler.send("UnsupportedFeature", {
         featureId: _util.UNSUPPORTED_FEATURES.errorFontTranslate
         featureId: _util.UNSUPPORTED_FEATURES.errorFontTranslate
       });
       });
+      (0, _util.warn)(`loadFont - translateFont failed: "${reason}".`);
 
 
       try {
       try {
         var fontFile3 = descriptor && descriptor.get("FontFile3");
         var fontFile3 = descriptor && descriptor.get("FontFile3");
@@ -1125,11 +1118,7 @@ class PartialEvaluator {
           const tilingPatternIR = (0, _pattern.getTilingPatternIR)(localTilingPattern.operatorListIR, localTilingPattern.dict, color);
           const tilingPatternIR = (0, _pattern.getTilingPatternIR)(localTilingPattern.operatorListIR, localTilingPattern.dict, color);
           operatorList.addOp(fn, tilingPatternIR);
           operatorList.addOp(fn, tilingPatternIR);
           return undefined;
           return undefined;
-        } catch (ex) {
-          if (ex instanceof _core_utils.MissingDataException) {
-            throw ex;
-          }
-        }
+        } catch (ex) {}
       }
       }
 
 
       let pattern = patterns.get(name);
       let pattern = patterns.get(name);
@@ -1766,7 +1755,7 @@ class PartialEvaluator {
     normalizeWhitespace = false,
     normalizeWhitespace = false,
     combineTextItems = false,
     combineTextItems = false,
     sink,
     sink,
-    seenStyles = Object.create(null)
+    seenStyles = new Set()
   }) {
   }) {
     resources = resources || _primitives.Dict.empty;
     resources = resources || _primitives.Dict.empty;
     stateManager = stateManager || new StateManager(new TextState());
     stateManager = stateManager || new StateManager(new TextState());
@@ -1808,11 +1797,12 @@ class PartialEvaluator {
         return textContentItem;
         return textContentItem;
       }
       }
 
 
-      var font = textState.font;
+      const font = textState.font,
+            loadedName = font.loadedName;
 
 
-      if (!(font.loadedName in seenStyles)) {
-        seenStyles[font.loadedName] = true;
-        textContent.styles[font.loadedName] = {
+      if (!seenStyles.has(loadedName)) {
+        seenStyles.add(loadedName);
+        textContent.styles[loadedName] = {
           fontFamily: font.fallbackName,
           fontFamily: font.fallbackName,
           ascent: font.ascent,
           ascent: font.ascent,
           descent: font.descent,
           descent: font.descent,
@@ -1820,7 +1810,7 @@ class PartialEvaluator {
         };
         };
       }
       }
 
 
-      textContentItem.fontName = font.loadedName;
+      textContentItem.fontName = loadedName;
       var tsm = [textState.fontSize * textState.textHScale, 0, 0, textState.fontSize, 0, textState.textRise];
       var tsm = [textState.fontSize * textState.textHScale, 0, 0, textState.fontSize, 0, textState.textRise];
 
 
       if (font.isType3Font && textState.fontSize <= 1 && !(0, _util.isArrayEqual)(textState.fontMatrix, _util.FONT_IDENTITY_MATRIX)) {
       if (font.isType3Font && textState.fontSize <= 1 && !(0, _util.isArrayEqual)(textState.fontMatrix, _util.FONT_IDENTITY_MATRIX)) {
@@ -1837,20 +1827,16 @@ class PartialEvaluator {
 
 
       if (!font.vertical) {
       if (!font.vertical) {
         textContentItem.width = 0;
         textContentItem.width = 0;
-        textContentItem.height = Math.sqrt(trm[2] * trm[2] + trm[3] * trm[3]);
+        textContentItem.height = Math.hypot(trm[2], trm[3]);
         textContentItem.vertical = false;
         textContentItem.vertical = false;
       } else {
       } else {
-        textContentItem.width = Math.sqrt(trm[0] * trm[0] + trm[1] * trm[1]);
+        textContentItem.width = Math.hypot(trm[0], trm[1]);
         textContentItem.height = 0;
         textContentItem.height = 0;
         textContentItem.vertical = true;
         textContentItem.vertical = true;
       }
       }
 
 
-      var a = textState.textLineMatrix[0];
-      var b = textState.textLineMatrix[1];
-      var scaleLineX = Math.sqrt(a * a + b * b);
-      a = textState.ctm[0];
-      b = textState.ctm[1];
-      var scaleCtmX = Math.sqrt(a * a + b * b);
+      const scaleLineX = Math.hypot(textState.textLineMatrix[0], textState.textLineMatrix[1]);
+      const scaleCtmX = Math.hypot(textState.ctm[0], textState.ctm[1]);
       textContentItem.textAdvanceScale = scaleCtmX * scaleLineX;
       textContentItem.textAdvanceScale = scaleCtmX * scaleLineX;
       textContentItem.lastAdvanceWidth = 0;
       textContentItem.lastAdvanceWidth = 0;
       textContentItem.lastAdvanceHeight = 0;
       textContentItem.lastAdvanceHeight = 0;
@@ -2241,6 +2227,13 @@ class PartialEvaluator {
                   return;
                   return;
                 }
                 }
 
 
+                const globalImage = self.globalImageCache.getData(xobj, self.pageIndex);
+
+                if (globalImage) {
+                  resolveXObject();
+                  return;
+                }
+
                 xobj = xref.fetch(xobj);
                 xobj = xref.fetch(xobj);
               }
               }
 
 
@@ -2839,7 +2832,7 @@ class PartialEvaluator {
 
 
   getBaseFontMetrics(name) {
   getBaseFontMetrics(name) {
     var defaultWidth = 0;
     var defaultWidth = 0;
-    var widths = [];
+    var widths = Object.create(null);
     var monospace = false;
     var monospace = false;
     var stdFontMap = (0, _standard_fonts.getStdFontMap)();
     var stdFontMap = (0, _standard_fonts.getStdFontMap)();
     var lookupName = stdFontMap[name] || name;
     var lookupName = stdFontMap[name] || name;
@@ -3074,7 +3067,18 @@ class PartialEvaluator {
       throw new _util.FormatError("invalid font name");
       throw new _util.FormatError("invalid font name");
     }
     }
 
 
-    var fontFile = descriptor.get("FontFile", "FontFile2", "FontFile3");
+    let fontFile;
+
+    try {
+      fontFile = descriptor.get("FontFile", "FontFile2", "FontFile3");
+    } catch (ex) {
+      if (!this.options.ignoreErrors) {
+        throw ex;
+      }
+
+      (0, _util.warn)(`translateFont - fetching "${fontName.name}" font file: "${ex}".`);
+      fontFile = new _stream.NullStream();
+    }
 
 
     if (fontFile) {
     if (fontFile) {
       if (fontFile.dict) {
       if (fontFile.dict) {

+ 59 - 59
lib/core/font_renderer.js

@@ -2,7 +2,7 @@
  * @licstart The following is the entire license notice for the
  * @licstart The following is the entire license notice for the
  * Javascript code in this page
  * Javascript code in this page
  *
  *
- * Copyright 2020 Mozilla Foundation
+ * Copyright 2021 Mozilla Foundation
  *
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * you may not use this file except in compliance with the License.
@@ -36,7 +36,7 @@ var _encodings = require("./encodings.js");
 
 
 var _stream = require("./stream.js");
 var _stream = require("./stream.js");
 
 
-var FontRendererFactory = function FontRendererFactoryClosure() {
+const FontRendererFactory = function FontRendererFactoryClosure() {
   function getLong(data, offset) {
   function getLong(data, offset) {
     return data[offset] << 24 | data[offset + 1] << 16 | data[offset + 2] << 8 | data[offset + 3];
     return data[offset] << 24 | data[offset + 1] << 16 | data[offset + 2] << 8 | data[offset + 3];
   }
   }
@@ -59,13 +59,13 @@ var FontRendererFactory = function FontRendererFactoryClosure() {
   }
   }
 
 
   function parseCmap(data, start, end) {
   function parseCmap(data, start, end) {
-    var offset = getUshort(data, start + 2) === 1 ? getLong(data, start + 8) : getLong(data, start + 16);
-    var format = getUshort(data, start + offset);
-    var ranges, p, i;
+    const offset = getUshort(data, start + 2) === 1 ? getLong(data, start + 8) : getLong(data, start + 16);
+    const format = getUshort(data, start + offset);
+    let ranges, p, i;
 
 
     if (format === 4) {
     if (format === 4) {
       getUshort(data, start + offset + 2);
       getUshort(data, start + offset + 2);
-      var segCount = getUshort(data, start + offset + 6) >> 1;
+      const segCount = getUshort(data, start + offset + 6) >> 1;
       p = start + offset + 14;
       p = start + offset + 14;
       ranges = [];
       ranges = [];
 
 
@@ -86,7 +86,7 @@ var FontRendererFactory = function FontRendererFactoryClosure() {
       }
       }
 
 
       for (i = 0; i < segCount; i++, p += 2) {
       for (i = 0; i < segCount; i++, p += 2) {
-        var idOffset = getUshort(data, p);
+        let idOffset = getUshort(data, p);
 
 
         if (idOffset === 0) {
         if (idOffset === 0) {
           continue;
           continue;
@@ -94,7 +94,7 @@ var FontRendererFactory = function FontRendererFactoryClosure() {
 
 
         ranges[i].ids = [];
         ranges[i].ids = [];
 
 
-        for (var j = 0, jj = ranges[i].end - ranges[i].start + 1; j < jj; j++) {
+        for (let j = 0, jj = ranges[i].end - ranges[i].start + 1; j < jj; j++) {
           ranges[i].ids[j] = getUshort(data, p + idOffset);
           ranges[i].ids[j] = getUshort(data, p + idOffset);
           idOffset += 2;
           idOffset += 2;
         }
         }
@@ -103,7 +103,7 @@ var FontRendererFactory = function FontRendererFactoryClosure() {
       return ranges;
       return ranges;
     } else if (format === 12) {
     } else if (format === 12) {
       getLong(data, start + offset + 4);
       getLong(data, start + offset + 4);
-      var groups = getLong(data, start + offset + 12);
+      const groups = getLong(data, start + offset + 12);
       p = start + offset + 16;
       p = start + offset + 16;
       ranges = [];
       ranges = [];
 
 
@@ -123,9 +123,9 @@ var FontRendererFactory = function FontRendererFactoryClosure() {
   }
   }
 
 
   function parseCff(data, start, end, seacAnalysisEnabled) {
   function parseCff(data, start, end, seacAnalysisEnabled) {
-    var properties = {};
-    var parser = new _cff_parser.CFFParser(new _stream.Stream(data, start, end - start), properties, seacAnalysisEnabled);
-    var cff = parser.parse();
+    const properties = {};
+    const parser = new _cff_parser.CFFParser(new _stream.Stream(data, start, end - start), properties, seacAnalysisEnabled);
+    const cff = parser.parse();
     return {
     return {
       glyphs: cff.charStrings.objects,
       glyphs: cff.charStrings.objects,
       subrs: cff.topDict.privateDict && cff.topDict.privateDict.subrsIndex && cff.topDict.privateDict.subrsIndex.objects,
       subrs: cff.topDict.privateDict && cff.topDict.privateDict.subrsIndex && cff.topDict.privateDict.subrsIndex.objects,
@@ -137,7 +137,7 @@ var FontRendererFactory = function FontRendererFactoryClosure() {
   }
   }
 
 
   function parseGlyfTable(glyf, loca, isGlyphLocationsLong) {
   function parseGlyfTable(glyf, loca, isGlyphLocationsLong) {
-    var itemSize, itemDecode;
+    let itemSize, itemDecode;
 
 
     if (isGlyphLocationsLong) {
     if (isGlyphLocationsLong) {
       itemSize = 4;
       itemSize = 4;
@@ -153,11 +153,11 @@ var FontRendererFactory = function FontRendererFactoryClosure() {
       };
       };
     }
     }
 
 
-    var glyphs = [];
-    var startOffset = itemDecode(loca, 0);
+    const glyphs = [];
+    let startOffset = itemDecode(loca, 0);
 
 
-    for (var j = itemSize; j < loca.length; j += itemSize) {
-      var endOffset = itemDecode(loca, j);
+    for (let j = itemSize; j < loca.length; j += itemSize) {
+      const endOffset = itemDecode(loca, j);
       glyphs.push(glyf.subarray(startOffset, endOffset));
       glyphs.push(glyf.subarray(startOffset, endOffset));
       startOffset = endOffset;
       startOffset = endOffset;
     }
     }
@@ -166,13 +166,13 @@ var FontRendererFactory = function FontRendererFactoryClosure() {
   }
   }
 
 
   function lookupCmap(ranges, unicode) {
   function lookupCmap(ranges, unicode) {
-    var code = unicode.codePointAt(0),
-        gid = 0;
-    var l = 0,
+    const code = unicode.codePointAt(0);
+    let gid = 0,
+        l = 0,
         r = ranges.length - 1;
         r = ranges.length - 1;
 
 
     while (l < r) {
     while (l < r) {
-      var c = l + r + 1 >> 1;
+      const c = l + r + 1 >> 1;
 
 
       if (code < ranges[c].start) {
       if (code < ranges[c].start) {
         r = c - 1;
         r = c - 1;
@@ -213,19 +213,19 @@ var FontRendererFactory = function FontRendererFactoryClosure() {
       });
       });
     }
     }
 
 
-    var i = 0;
-    var numberOfContours = (code[i] << 24 | code[i + 1] << 16) >> 16;
-    var flags;
-    var x = 0,
+    let i = 0;
+    const numberOfContours = (code[i] << 24 | code[i + 1] << 16) >> 16;
+    let flags;
+    let x = 0,
         y = 0;
         y = 0;
     i += 10;
     i += 10;
 
 
     if (numberOfContours < 0) {
     if (numberOfContours < 0) {
       do {
       do {
         flags = code[i] << 8 | code[i + 1];
         flags = code[i] << 8 | code[i + 1];
-        var glyphIndex = code[i + 2] << 8 | code[i + 3];
+        const glyphIndex = code[i + 2] << 8 | code[i + 3];
         i += 4;
         i += 4;
-        var arg1, arg2;
+        let arg1, arg2;
 
 
         if (flags & 0x01) {
         if (flags & 0x01) {
           arg1 = (code[i] << 24 | code[i + 1] << 16) >> 16;
           arg1 = (code[i] << 24 | code[i + 1] << 16) >> 16;
@@ -244,7 +244,7 @@ var FontRendererFactory = function FontRendererFactoryClosure() {
           y = 0;
           y = 0;
         }
         }
 
 
-        var scaleX = 1,
+        let scaleX = 1,
             scaleY = 1,
             scaleY = 1,
             scale01 = 0,
             scale01 = 0,
             scale10 = 0;
             scale10 = 0;
@@ -264,7 +264,7 @@ var FontRendererFactory = function FontRendererFactoryClosure() {
           i += 8;
           i += 8;
         }
         }
 
 
-        var subglyph = font.glyphs[glyphIndex];
+        const subglyph = font.glyphs[glyphIndex];
 
 
         if (subglyph) {
         if (subglyph) {
           cmds.push({
           cmds.push({
@@ -281,22 +281,22 @@ var FontRendererFactory = function FontRendererFactoryClosure() {
         }
         }
       } while (flags & 0x20);
       } while (flags & 0x20);
     } else {
     } else {
-      var endPtsOfContours = [];
-      var j, jj;
+      const endPtsOfContours = [];
+      let j, jj;
 
 
       for (j = 0; j < numberOfContours; j++) {
       for (j = 0; j < numberOfContours; j++) {
         endPtsOfContours.push(code[i] << 8 | code[i + 1]);
         endPtsOfContours.push(code[i] << 8 | code[i + 1]);
         i += 2;
         i += 2;
       }
       }
 
 
-      var instructionLength = code[i] << 8 | code[i + 1];
+      const instructionLength = code[i] << 8 | code[i + 1];
       i += 2 + instructionLength;
       i += 2 + instructionLength;
-      var numberOfPoints = endPtsOfContours[endPtsOfContours.length - 1] + 1;
-      var points = [];
+      const numberOfPoints = endPtsOfContours[endPtsOfContours.length - 1] + 1;
+      const points = [];
 
 
       while (points.length < numberOfPoints) {
       while (points.length < numberOfPoints) {
         flags = code[i++];
         flags = code[i++];
-        var repeat = 1;
+        let repeat = 1;
 
 
         if (flags & 0x08) {
         if (flags & 0x08) {
           repeat += code[i++];
           repeat += code[i++];
@@ -347,18 +347,18 @@ var FontRendererFactory = function FontRendererFactoryClosure() {
         points[j].y = y;
         points[j].y = y;
       }
       }
 
 
-      var startPoint = 0;
+      let startPoint = 0;
 
 
       for (i = 0; i < numberOfContours; i++) {
       for (i = 0; i < numberOfContours; i++) {
-        var endPoint = endPtsOfContours[i];
-        var contour = points.slice(startPoint, endPoint + 1);
+        const endPoint = endPtsOfContours[i];
+        const contour = points.slice(startPoint, endPoint + 1);
 
 
         if (contour[0].flags & 1) {
         if (contour[0].flags & 1) {
           contour.push(contour[0]);
           contour.push(contour[0]);
         } else if (contour[contour.length - 1].flags & 1) {
         } else if (contour[contour.length - 1].flags & 1) {
           contour.unshift(contour[contour.length - 1]);
           contour.unshift(contour[contour.length - 1]);
         } else {
         } else {
-          var p = {
+          const p = {
             flags: 1,
             flags: 1,
             x: (contour[0].x + contour[contour.length - 1].x) / 2,
             x: (contour[0].x + contour[contour.length - 1].x) / 2,
             y: (contour[0].y + contour[contour.length - 1].y) / 2
             y: (contour[0].y + contour[contour.length - 1].y) / 2
@@ -407,18 +407,18 @@ var FontRendererFactory = function FontRendererFactoryClosure() {
       });
       });
     }
     }
 
 
-    var stack = [];
-    var x = 0,
+    const stack = [];
+    let x = 0,
         y = 0;
         y = 0;
-    var stems = 0;
+    let stems = 0;
 
 
     function parse(code) {
     function parse(code) {
-      var i = 0;
+      let i = 0;
 
 
       while (i < code.length) {
       while (i < code.length) {
-        var stackClean = false;
-        var v = code[i++];
-        var xa, xb, ya, yb, y1, y2, y3, n, subrCode;
+        let stackClean = false;
+        let v = code[i++];
+        let xa, xb, ya, yb, y1, y2, y3, n, subrCode;
 
 
         switch (v) {
         switch (v) {
           case 1:
           case 1:
@@ -573,8 +573,8 @@ var FontRendererFactory = function FontRendererFactoryClosure() {
                 break;
                 break;
 
 
               case 37:
               case 37:
-                var x0 = x,
-                    y0 = y;
+                const x0 = x,
+                      y0 = y;
                 xa = x + stack.shift();
                 xa = x + stack.shift();
                 ya = y + stack.shift();
                 ya = y + stack.shift();
                 xb = xa + stack.shift();
                 xb = xa + stack.shift();
@@ -606,8 +606,8 @@ var FontRendererFactory = function FontRendererFactoryClosure() {
 
 
           case 14:
           case 14:
             if (stack.length >= 4) {
             if (stack.length >= 4) {
-              var achar = stack.pop();
-              var bchar = stack.pop();
+              const achar = stack.pop();
+              const bchar = stack.pop();
               y = stack.pop();
               y = stack.pop();
               x = stack.pop();
               x = stack.pop();
               cmds.push({
               cmds.push({
@@ -617,7 +617,7 @@ var FontRendererFactory = function FontRendererFactoryClosure() {
                 cmd: "translate",
                 cmd: "translate",
                 args: [x, y]
                 args: [x, y]
               });
               });
-              var cmap = lookupCmap(font.cmap, String.fromCharCode(font.glyphNameMap[_encodings.StandardEncoding[achar]]));
+              let cmap = lookupCmap(font.cmap, String.fromCharCode(font.glyphNameMap[_encodings.StandardEncoding[achar]]));
               compileCharString(font.glyphs[cmap.glyphId], cmds, font, cmap.glyphId);
               compileCharString(font.glyphs[cmap.glyphId], cmds, font, cmap.glyphId);
               cmds.push({
               cmds.push({
                 cmd: "restore"
                 cmd: "restore"
@@ -935,14 +935,14 @@ var FontRendererFactory = function FontRendererFactoryClosure() {
 
 
   return {
   return {
     create: function FontRendererFactory_create(font, seacAnalysisEnabled) {
     create: function FontRendererFactory_create(font, seacAnalysisEnabled) {
-      var data = new Uint8Array(font.data);
-      var cmap, glyf, loca, cff, indexToLocFormat, unitsPerEm;
-      var numTables = getUshort(data, 4);
+      const data = new Uint8Array(font.data);
+      let cmap, glyf, loca, cff, indexToLocFormat, unitsPerEm;
+      const numTables = getUshort(data, 4);
 
 
-      for (var i = 0, p = 12; i < numTables; i++, p += 16) {
-        var tag = (0, _util.bytesToString)(data.subarray(p, p + 4));
-        var offset = getLong(data, p + 8);
-        var length = getLong(data, p + 12);
+      for (let i = 0, p = 12; i < numTables; i++, p += 16) {
+        const tag = (0, _util.bytesToString)(data.subarray(p, p + 4));
+        const offset = getLong(data, p + 8);
+        const length = getLong(data, p + 12);
 
 
         switch (tag) {
         switch (tag) {
           case "cmap":
           case "cmap":
@@ -969,7 +969,7 @@ var FontRendererFactory = function FontRendererFactoryClosure() {
       }
       }
 
 
       if (glyf) {
       if (glyf) {
-        var fontMatrix = !unitsPerEm ? font.fontMatrix : [1 / unitsPerEm, 0, 0, 1 / unitsPerEm, 0, 0];
+        const fontMatrix = !unitsPerEm ? font.fontMatrix : [1 / unitsPerEm, 0, 0, 1 / unitsPerEm, 0, 0];
         return new TrueTypeCompiled(parseGlyfTable(glyf, loca, indexToLocFormat), cmap, fontMatrix);
         return new TrueTypeCompiled(parseGlyfTable(glyf, loca, indexToLocFormat), cmap, fontMatrix);
       }
       }
 
 

+ 15 - 8
lib/core/fonts.js

@@ -2,7 +2,7 @@
  * @licstart The following is the entire license notice for the
  * @licstart The following is the entire license notice for the
  * Javascript code in this page
  * Javascript code in this page
  *
  *
- * Copyright 2020 Mozilla Foundation
+ * Copyright 2021 Mozilla Foundation
  *
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * you may not use this file except in compliance with the License.
@@ -2425,15 +2425,22 @@ var Font = function FontClosure() {
           }
           }
         }
         }
 
 
-        if (properties.glyphNames && baseEncoding.length) {
+        if (properties.glyphNames && (baseEncoding.length || this.differences.length)) {
           for (let i = 0; i < 256; ++i) {
           for (let i = 0; i < 256; ++i) {
-            if (charCodeToGlyphId[i] === undefined && baseEncoding[i]) {
-              glyphName = baseEncoding[i];
-              const glyphId = properties.glyphNames.indexOf(glyphName);
+            if (charCodeToGlyphId[i] !== undefined) {
+              continue;
+            }
 
 
-              if (glyphId > 0 && hasGlyph(glyphId)) {
-                charCodeToGlyphId[i] = glyphId;
-              }
+            glyphName = this.differences[i] || baseEncoding[i];
+
+            if (!glyphName) {
+              continue;
+            }
+
+            const glyphId = properties.glyphNames.indexOf(glyphName);
+
+            if (glyphId > 0 && hasGlyph(glyphId)) {
+              charCodeToGlyphId[i] = glyphId;
             }
             }
           }
           }
         }
         }

+ 366 - 353
lib/core/function.js

@@ -2,7 +2,7 @@
  * @licstart The following is the entire license notice for the
  * @licstart The following is the entire license notice for the
  * Javascript code in this page
  * Javascript code in this page
  *
  *
- * Copyright 2020 Mozilla Foundation
+ * Copyright 2021 Mozilla Foundation
  *
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * you may not use this file except in compliance with the License.
@@ -670,26 +670,28 @@ function isPDFFunction(v) {
 var PostScriptStack = function PostScriptStackClosure() {
 var PostScriptStack = function PostScriptStackClosure() {
   var MAX_STACK_SIZE = 100;
   var MAX_STACK_SIZE = 100;
 
 
-  function PostScriptStack(initialStack) {
-    this.stack = !initialStack ? [] : Array.prototype.slice.call(initialStack, 0);
-  }
+  class PostScriptStack {
+    constructor(initialStack) {
+      this.stack = !initialStack ? [] : Array.prototype.slice.call(initialStack, 0);
+    }
 
 
-  PostScriptStack.prototype = {
-    push: function PostScriptStack_push(value) {
+    push(value) {
       if (this.stack.length >= MAX_STACK_SIZE) {
       if (this.stack.length >= MAX_STACK_SIZE) {
         throw new Error("PostScript function stack overflow.");
         throw new Error("PostScript function stack overflow.");
       }
       }
 
 
       this.stack.push(value);
       this.stack.push(value);
-    },
-    pop: function PostScriptStack_pop() {
+    }
+
+    pop() {
       if (this.stack.length <= 0) {
       if (this.stack.length <= 0) {
         throw new Error("PostScript function stack underflow.");
         throw new Error("PostScript function stack underflow.");
       }
       }
 
 
       return this.stack.pop();
       return this.stack.pop();
-    },
-    copy: function PostScriptStack_copy(n) {
+    }
+
+    copy(n) {
       if (this.stack.length + n >= MAX_STACK_SIZE) {
       if (this.stack.length + n >= MAX_STACK_SIZE) {
         throw new Error("PostScript function stack overflow.");
         throw new Error("PostScript function stack overflow.");
       }
       }
@@ -699,11 +701,13 @@ var PostScriptStack = function PostScriptStackClosure() {
       for (var i = stack.length - n, j = n - 1; j >= 0; j--, i++) {
       for (var i = stack.length - n, j = n - 1; j >= 0; j--, i++) {
         stack.push(stack[i]);
         stack.push(stack[i]);
       }
       }
-    },
-    index: function PostScriptStack_index(n) {
+    }
+
+    index(n) {
       this.push(this.stack[this.stack.length - n - 1]);
       this.push(this.stack[this.stack.length - n - 1]);
-    },
-    roll: function PostScriptStack_roll(n, p) {
+    }
+
+    roll(n, p) {
       var stack = this.stack;
       var stack = this.stack;
       var l = stack.length - n;
       var l = stack.length - n;
       var r = stack.length - 1,
       var r = stack.length - 1,
@@ -730,406 +734,415 @@ var PostScriptStack = function PostScriptStackClosure() {
         stack[j] = t;
         stack[j] = t;
       }
       }
     }
     }
-  };
+
+  }
+
   return PostScriptStack;
   return PostScriptStack;
 }();
 }();
 
 
-var PostScriptEvaluator = function PostScriptEvaluatorClosure() {
-  function PostScriptEvaluator(operators) {
+class PostScriptEvaluator {
+  constructor(operators) {
     this.operators = operators;
     this.operators = operators;
   }
   }
 
 
-  PostScriptEvaluator.prototype = {
-    execute: function PostScriptEvaluator_execute(initialStack) {
-      var stack = new PostScriptStack(initialStack);
-      var counter = 0;
-      var operators = this.operators;
-      var length = operators.length;
-      var operator, a, b;
-
-      while (counter < length) {
-        operator = operators[counter++];
-
-        if (typeof operator === "number") {
-          stack.push(operator);
-          continue;
-        }
-
-        switch (operator) {
-          case "jz":
-            b = stack.pop();
-            a = stack.pop();
-
-            if (!a) {
-              counter = b;
-            }
-
-            break;
-
-          case "j":
-            a = stack.pop();
-            counter = a;
-            break;
-
-          case "abs":
-            a = stack.pop();
-            stack.push(Math.abs(a));
-            break;
-
-          case "add":
-            b = stack.pop();
-            a = stack.pop();
-            stack.push(a + b);
-            break;
-
-          case "and":
-            b = stack.pop();
-            a = stack.pop();
-
-            if ((0, _util.isBool)(a) && (0, _util.isBool)(b)) {
-              stack.push(a && b);
-            } else {
-              stack.push(a & b);
-            }
-
-            break;
-
-          case "atan":
-            a = stack.pop();
-            stack.push(Math.atan(a));
-            break;
-
-          case "bitshift":
-            b = stack.pop();
-            a = stack.pop();
-
-            if (a > 0) {
-              stack.push(a << b);
-            } else {
-              stack.push(a >> b);
-            }
-
-            break;
-
-          case "ceiling":
-            a = stack.pop();
-            stack.push(Math.ceil(a));
-            break;
-
-          case "copy":
-            a = stack.pop();
-            stack.copy(a);
-            break;
-
-          case "cos":
-            a = stack.pop();
-            stack.push(Math.cos(a));
-            break;
-
-          case "cvi":
-            a = stack.pop() | 0;
-            stack.push(a);
-            break;
+  execute(initialStack) {
+    var stack = new PostScriptStack(initialStack);
+    var counter = 0;
+    var operators = this.operators;
+    var length = operators.length;
+    var operator, a, b;
 
 
-          case "cvr":
-            break;
+    while (counter < length) {
+      operator = operators[counter++];
 
 
-          case "div":
-            b = stack.pop();
-            a = stack.pop();
-            stack.push(a / b);
-            break;
+      if (typeof operator === "number") {
+        stack.push(operator);
+        continue;
+      }
 
 
-          case "dup":
-            stack.copy(1);
-            break;
+      switch (operator) {
+        case "jz":
+          b = stack.pop();
+          a = stack.pop();
 
 
-          case "eq":
-            b = stack.pop();
-            a = stack.pop();
-            stack.push(a === b);
-            break;
+          if (!a) {
+            counter = b;
+          }
 
 
-          case "exch":
-            stack.roll(2, 1);
-            break;
+          break;
 
 
-          case "exp":
-            b = stack.pop();
-            a = stack.pop();
-            stack.push(a ** b);
-            break;
+        case "j":
+          a = stack.pop();
+          counter = a;
+          break;
 
 
-          case "false":
-            stack.push(false);
-            break;
+        case "abs":
+          a = stack.pop();
+          stack.push(Math.abs(a));
+          break;
 
 
-          case "floor":
-            a = stack.pop();
-            stack.push(Math.floor(a));
-            break;
+        case "add":
+          b = stack.pop();
+          a = stack.pop();
+          stack.push(a + b);
+          break;
 
 
-          case "ge":
-            b = stack.pop();
-            a = stack.pop();
-            stack.push(a >= b);
-            break;
+        case "and":
+          b = stack.pop();
+          a = stack.pop();
 
 
-          case "gt":
-            b = stack.pop();
-            a = stack.pop();
-            stack.push(a > b);
-            break;
+          if ((0, _util.isBool)(a) && (0, _util.isBool)(b)) {
+            stack.push(a && b);
+          } else {
+            stack.push(a & b);
+          }
 
 
-          case "idiv":
-            b = stack.pop();
-            a = stack.pop();
-            stack.push(a / b | 0);
-            break;
+          break;
 
 
-          case "index":
-            a = stack.pop();
-            stack.index(a);
-            break;
+        case "atan":
+          a = stack.pop();
+          stack.push(Math.atan(a));
+          break;
 
 
-          case "le":
-            b = stack.pop();
-            a = stack.pop();
-            stack.push(a <= b);
-            break;
+        case "bitshift":
+          b = stack.pop();
+          a = stack.pop();
 
 
-          case "ln":
-            a = stack.pop();
-            stack.push(Math.log(a));
-            break;
+          if (a > 0) {
+            stack.push(a << b);
+          } else {
+            stack.push(a >> b);
+          }
 
 
-          case "log":
-            a = stack.pop();
-            stack.push(Math.log(a) / Math.LN10);
-            break;
+          break;
+
+        case "ceiling":
+          a = stack.pop();
+          stack.push(Math.ceil(a));
+          break;
+
+        case "copy":
+          a = stack.pop();
+          stack.copy(a);
+          break;
+
+        case "cos":
+          a = stack.pop();
+          stack.push(Math.cos(a));
+          break;
+
+        case "cvi":
+          a = stack.pop() | 0;
+          stack.push(a);
+          break;
+
+        case "cvr":
+          break;
+
+        case "div":
+          b = stack.pop();
+          a = stack.pop();
+          stack.push(a / b);
+          break;
+
+        case "dup":
+          stack.copy(1);
+          break;
+
+        case "eq":
+          b = stack.pop();
+          a = stack.pop();
+          stack.push(a === b);
+          break;
+
+        case "exch":
+          stack.roll(2, 1);
+          break;
+
+        case "exp":
+          b = stack.pop();
+          a = stack.pop();
+          stack.push(a ** b);
+          break;
+
+        case "false":
+          stack.push(false);
+          break;
+
+        case "floor":
+          a = stack.pop();
+          stack.push(Math.floor(a));
+          break;
+
+        case "ge":
+          b = stack.pop();
+          a = stack.pop();
+          stack.push(a >= b);
+          break;
+
+        case "gt":
+          b = stack.pop();
+          a = stack.pop();
+          stack.push(a > b);
+          break;
+
+        case "idiv":
+          b = stack.pop();
+          a = stack.pop();
+          stack.push(a / b | 0);
+          break;
+
+        case "index":
+          a = stack.pop();
+          stack.index(a);
+          break;
+
+        case "le":
+          b = stack.pop();
+          a = stack.pop();
+          stack.push(a <= b);
+          break;
+
+        case "ln":
+          a = stack.pop();
+          stack.push(Math.log(a));
+          break;
+
+        case "log":
+          a = stack.pop();
+          stack.push(Math.log(a) / Math.LN10);
+          break;
+
+        case "lt":
+          b = stack.pop();
+          a = stack.pop();
+          stack.push(a < b);
+          break;
+
+        case "mod":
+          b = stack.pop();
+          a = stack.pop();
+          stack.push(a % b);
+          break;
+
+        case "mul":
+          b = stack.pop();
+          a = stack.pop();
+          stack.push(a * b);
+          break;
+
+        case "ne":
+          b = stack.pop();
+          a = stack.pop();
+          stack.push(a !== b);
+          break;
+
+        case "neg":
+          a = stack.pop();
+          stack.push(-a);
+          break;
+
+        case "not":
+          a = stack.pop();
+
+          if ((0, _util.isBool)(a)) {
+            stack.push(!a);
+          } else {
+            stack.push(~a);
+          }
 
 
-          case "lt":
-            b = stack.pop();
-            a = stack.pop();
-            stack.push(a < b);
-            break;
+          break;
 
 
-          case "mod":
-            b = stack.pop();
-            a = stack.pop();
-            stack.push(a % b);
-            break;
+        case "or":
+          b = stack.pop();
+          a = stack.pop();
 
 
-          case "mul":
-            b = stack.pop();
-            a = stack.pop();
-            stack.push(a * b);
-            break;
+          if ((0, _util.isBool)(a) && (0, _util.isBool)(b)) {
+            stack.push(a || b);
+          } else {
+            stack.push(a | b);
+          }
 
 
-          case "ne":
-            b = stack.pop();
-            a = stack.pop();
+          break;
+
+        case "pop":
+          stack.pop();
+          break;
+
+        case "roll":
+          b = stack.pop();
+          a = stack.pop();
+          stack.roll(a, b);
+          break;
+
+        case "round":
+          a = stack.pop();
+          stack.push(Math.round(a));
+          break;
+
+        case "sin":
+          a = stack.pop();
+          stack.push(Math.sin(a));
+          break;
+
+        case "sqrt":
+          a = stack.pop();
+          stack.push(Math.sqrt(a));
+          break;
+
+        case "sub":
+          b = stack.pop();
+          a = stack.pop();
+          stack.push(a - b);
+          break;
+
+        case "true":
+          stack.push(true);
+          break;
+
+        case "truncate":
+          a = stack.pop();
+          a = a < 0 ? Math.ceil(a) : Math.floor(a);
+          stack.push(a);
+          break;
+
+        case "xor":
+          b = stack.pop();
+          a = stack.pop();
+
+          if ((0, _util.isBool)(a) && (0, _util.isBool)(b)) {
             stack.push(a !== b);
             stack.push(a !== b);
-            break;
-
-          case "neg":
-            a = stack.pop();
-            stack.push(-a);
-            break;
-
-          case "not":
-            a = stack.pop();
-
-            if ((0, _util.isBool)(a)) {
-              stack.push(!a);
-            } else {
-              stack.push(~a);
-            }
-
-            break;
-
-          case "or":
-            b = stack.pop();
-            a = stack.pop();
-
-            if ((0, _util.isBool)(a) && (0, _util.isBool)(b)) {
-              stack.push(a || b);
-            } else {
-              stack.push(a | b);
-            }
-
-            break;
-
-          case "pop":
-            stack.pop();
-            break;
-
-          case "roll":
-            b = stack.pop();
-            a = stack.pop();
-            stack.roll(a, b);
-            break;
-
-          case "round":
-            a = stack.pop();
-            stack.push(Math.round(a));
-            break;
-
-          case "sin":
-            a = stack.pop();
-            stack.push(Math.sin(a));
-            break;
-
-          case "sqrt":
-            a = stack.pop();
-            stack.push(Math.sqrt(a));
-            break;
-
-          case "sub":
-            b = stack.pop();
-            a = stack.pop();
-            stack.push(a - b);
-            break;
-
-          case "true":
-            stack.push(true);
-            break;
-
-          case "truncate":
-            a = stack.pop();
-            a = a < 0 ? Math.ceil(a) : Math.floor(a);
-            stack.push(a);
-            break;
-
-          case "xor":
-            b = stack.pop();
-            a = stack.pop();
-
-            if ((0, _util.isBool)(a) && (0, _util.isBool)(b)) {
-              stack.push(a !== b);
-            } else {
-              stack.push(a ^ b);
-            }
+          } else {
+            stack.push(a ^ b);
+          }
 
 
-            break;
+          break;
 
 
-          default:
-            throw new _util.FormatError(`Unknown operator ${operator}`);
-        }
+        default:
+          throw new _util.FormatError(`Unknown operator ${operator}`);
       }
       }
-
-      return stack.stack;
     }
     }
-  };
-  return PostScriptEvaluator;
-}();
+
+    return stack.stack;
+  }
+
+}
 
 
 exports.PostScriptEvaluator = PostScriptEvaluator;
 exports.PostScriptEvaluator = PostScriptEvaluator;
 
 
 var PostScriptCompiler = function PostScriptCompilerClosure() {
 var PostScriptCompiler = function PostScriptCompilerClosure() {
-  function AstNode(type) {
-    this.type = type;
-  }
+  class AstNode {
+    constructor(type) {
+      this.type = type;
+    }
 
 
-  AstNode.prototype.visit = function (visitor) {
-    (0, _util.unreachable)("abstract method");
-  };
+    visit(visitor) {
+      (0, _util.unreachable)("abstract method");
+    }
 
 
-  function AstArgument(index, min, max) {
-    AstNode.call(this, "args");
-    this.index = index;
-    this.min = min;
-    this.max = max;
   }
   }
 
 
-  AstArgument.prototype = Object.create(AstNode.prototype);
+  class AstArgument extends AstNode {
+    constructor(index, min, max) {
+      super("args");
+      this.index = index;
+      this.min = min;
+      this.max = max;
+    }
 
 
-  AstArgument.prototype.visit = function (visitor) {
-    visitor.visitArgument(this);
-  };
+    visit(visitor) {
+      visitor.visitArgument(this);
+    }
 
 
-  function AstLiteral(number) {
-    AstNode.call(this, "literal");
-    this.number = number;
-    this.min = number;
-    this.max = number;
   }
   }
 
 
-  AstLiteral.prototype = Object.create(AstNode.prototype);
+  class AstLiteral extends AstNode {
+    constructor(number) {
+      super("literal");
+      this.number = number;
+      this.min = number;
+      this.max = number;
+    }
 
 
-  AstLiteral.prototype.visit = function (visitor) {
-    visitor.visitLiteral(this);
-  };
+    visit(visitor) {
+      visitor.visitLiteral(this);
+    }
 
 
-  function AstBinaryOperation(op, arg1, arg2, min, max) {
-    AstNode.call(this, "binary");
-    this.op = op;
-    this.arg1 = arg1;
-    this.arg2 = arg2;
-    this.min = min;
-    this.max = max;
   }
   }
 
 
-  AstBinaryOperation.prototype = Object.create(AstNode.prototype);
+  class AstBinaryOperation extends AstNode {
+    constructor(op, arg1, arg2, min, max) {
+      super("binary");
+      this.op = op;
+      this.arg1 = arg1;
+      this.arg2 = arg2;
+      this.min = min;
+      this.max = max;
+    }
 
 
-  AstBinaryOperation.prototype.visit = function (visitor) {
-    visitor.visitBinaryOperation(this);
-  };
+    visit(visitor) {
+      visitor.visitBinaryOperation(this);
+    }
 
 
-  function AstMin(arg, max) {
-    AstNode.call(this, "max");
-    this.arg = arg;
-    this.min = arg.min;
-    this.max = max;
   }
   }
 
 
-  AstMin.prototype = Object.create(AstNode.prototype);
+  class AstMin extends AstNode {
+    constructor(arg, max) {
+      super("max");
+      this.arg = arg;
+      this.min = arg.min;
+      this.max = max;
+    }
 
 
-  AstMin.prototype.visit = function (visitor) {
-    visitor.visitMin(this);
-  };
+    visit(visitor) {
+      visitor.visitMin(this);
+    }
 
 
-  function AstVariable(index, min, max) {
-    AstNode.call(this, "var");
-    this.index = index;
-    this.min = min;
-    this.max = max;
   }
   }
 
 
-  AstVariable.prototype = Object.create(AstNode.prototype);
+  class AstVariable extends AstNode {
+    constructor(index, min, max) {
+      super("var");
+      this.index = index;
+      this.min = min;
+      this.max = max;
+    }
 
 
-  AstVariable.prototype.visit = function (visitor) {
-    visitor.visitVariable(this);
-  };
+    visit(visitor) {
+      visitor.visitVariable(this);
+    }
 
 
-  function AstVariableDefinition(variable, arg) {
-    AstNode.call(this, "definition");
-    this.variable = variable;
-    this.arg = arg;
   }
   }
 
 
-  AstVariableDefinition.prototype = Object.create(AstNode.prototype);
+  class AstVariableDefinition extends AstNode {
+    constructor(variable, arg) {
+      super("definition");
+      this.variable = variable;
+      this.arg = arg;
+    }
 
 
-  AstVariableDefinition.prototype.visit = function (visitor) {
-    visitor.visitVariableDefinition(this);
-  };
+    visit(visitor) {
+      visitor.visitVariableDefinition(this);
+    }
 
 
-  function ExpressionBuilderVisitor() {
-    this.parts = [];
   }
   }
 
 
-  ExpressionBuilderVisitor.prototype = {
+  class ExpressionBuilderVisitor {
+    constructor() {
+      this.parts = [];
+    }
+
     visitArgument(arg) {
     visitArgument(arg) {
       this.parts.push("Math.max(", arg.min, ", Math.min(", arg.max, ", src[srcOffset + ", arg.index, "]))");
       this.parts.push("Math.max(", arg.min, ", Math.min(", arg.max, ", src[srcOffset + ", arg.index, "]))");
-    },
+    }
 
 
     visitVariable(variable) {
     visitVariable(variable) {
       this.parts.push("v", variable.index);
       this.parts.push("v", variable.index);
-    },
+    }
 
 
     visitLiteral(literal) {
     visitLiteral(literal) {
       this.parts.push(literal.number);
       this.parts.push(literal.number);
-    },
+    }
 
 
     visitBinaryOperation(operation) {
     visitBinaryOperation(operation) {
       this.parts.push("(");
       this.parts.push("(");
@@ -1137,7 +1150,7 @@ var PostScriptCompiler = function PostScriptCompilerClosure() {
       this.parts.push(" ", operation.op, " ");
       this.parts.push(" ", operation.op, " ");
       operation.arg2.visit(this);
       operation.arg2.visit(this);
       this.parts.push(")");
       this.parts.push(")");
-    },
+    }
 
 
     visitVariableDefinition(definition) {
     visitVariableDefinition(definition) {
       this.parts.push("var ");
       this.parts.push("var ");
@@ -1145,19 +1158,19 @@ var PostScriptCompiler = function PostScriptCompilerClosure() {
       this.parts.push(" = ");
       this.parts.push(" = ");
       definition.arg.visit(this);
       definition.arg.visit(this);
       this.parts.push(";");
       this.parts.push(";");
-    },
+    }
 
 
     visitMin(max) {
     visitMin(max) {
       this.parts.push("Math.min(");
       this.parts.push("Math.min(");
       max.arg.visit(this);
       max.arg.visit(this);
       this.parts.push(", ", max.max, ")");
       this.parts.push(", ", max.max, ")");
-    },
+    }
 
 
     toString() {
     toString() {
       return this.parts.join("");
       return this.parts.join("");
     }
     }
 
 
-  };
+  }
 
 
   function buildAddOperation(num1, num2) {
   function buildAddOperation(num1, num2) {
     if (num2.type === "literal" && num2.number === 0) {
     if (num2.type === "literal" && num2.number === 0) {
@@ -1225,10 +1238,8 @@ var PostScriptCompiler = function PostScriptCompilerClosure() {
     return new AstMin(num1, max);
     return new AstMin(num1, max);
   }
   }
 
 
-  function PostScriptCompiler() {}
-
-  PostScriptCompiler.prototype = {
-    compile: function PostScriptCompiler_compile(code, domain, range) {
+  class PostScriptCompiler {
+    compile(code, domain, range) {
       var stack = [];
       var stack = [];
       var instructions = [];
       var instructions = [];
       var inputSize = domain.length >> 1,
       var inputSize = domain.length >> 1,
@@ -1426,7 +1437,9 @@ var PostScriptCompiler = function PostScriptCompilerClosure() {
       });
       });
       return result.join("\n");
       return result.join("\n");
     }
     }
-  };
+
+  }
+
   return PostScriptCompiler;
   return PostScriptCompiler;
 }();
 }();
 
 

File diff suppressed because it is too large
+ 2 - 2
lib/core/glyphlist.js


+ 1 - 1
lib/core/image.js

@@ -2,7 +2,7 @@
  * @licstart The following is the entire license notice for the
  * @licstart The following is the entire license notice for the
  * Javascript code in this page
  * Javascript code in this page
  *
  *
- * Copyright 2020 Mozilla Foundation
+ * Copyright 2021 Mozilla Foundation
  *
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * you may not use this file except in compliance with the License.

+ 50 - 8
lib/core/image_utils.js

@@ -2,7 +2,7 @@
  * @licstart The following is the entire license notice for the
  * @licstart The following is the entire license notice for the
  * Javascript code in this page
  * Javascript code in this page
  *
  *
- * Copyright 2020 Mozilla Foundation
+ * Copyright 2021 Mozilla Foundation
  *
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * you may not use this file except in compliance with the License.
@@ -214,8 +214,12 @@ class GlobalImageCache {
     return (0, _util.shadow)(this, "NUM_PAGES_THRESHOLD", 2);
     return (0, _util.shadow)(this, "NUM_PAGES_THRESHOLD", 2);
   }
   }
 
 
-  static get MAX_IMAGES_TO_CACHE() {
-    return (0, _util.shadow)(this, "MAX_IMAGES_TO_CACHE", 10);
+  static get MIN_IMAGES_TO_CACHE() {
+    return (0, _util.shadow)(this, "MIN_IMAGES_TO_CACHE", 10);
+  }
+
+  static get MAX_BYTE_SIZE() {
+    return (0, _util.shadow)(this, "MAX_BYTE_SIZE", 40e6);
   }
   }
 
 
   constructor() {
   constructor() {
@@ -223,6 +227,28 @@ class GlobalImageCache {
     this._imageCache = new _primitives.RefSetCache();
     this._imageCache = new _primitives.RefSetCache();
   }
   }
 
 
+  get _byteSize() {
+    let byteSize = 0;
+
+    this._imageCache.forEach(imageData => {
+      byteSize += imageData.byteSize;
+    });
+
+    return byteSize;
+  }
+
+  get _cacheLimitReached() {
+    if (this._imageCache.size < GlobalImageCache.MIN_IMAGES_TO_CACHE) {
+      return false;
+    }
+
+    if (this._byteSize < GlobalImageCache.MAX_BYTE_SIZE) {
+      return false;
+    }
+
+    return true;
+  }
+
   shouldCache(ref, pageIndex) {
   shouldCache(ref, pageIndex) {
     const pageIndexSet = this._refCache.get(ref);
     const pageIndexSet = this._refCache.get(ref);
 
 
@@ -232,7 +258,7 @@ class GlobalImageCache {
       return false;
       return false;
     }
     }
 
 
-    if (!this._imageCache.has(ref) && this._imageCache.size >= GlobalImageCache.MAX_IMAGES_TO_CACHE) {
+    if (!this._imageCache.has(ref) && this._cacheLimitReached) {
       return false;
       return false;
     }
     }
 
 
@@ -251,6 +277,20 @@ class GlobalImageCache {
     pageIndexSet.add(pageIndex);
     pageIndexSet.add(pageIndex);
   }
   }
 
 
+  addByteSize(ref, byteSize) {
+    const imageData = this._imageCache.get(ref);
+
+    if (!imageData) {
+      return;
+    }
+
+    if (imageData.byteSize) {
+      return;
+    }
+
+    imageData.byteSize = byteSize;
+  }
+
   getData(ref, pageIndex) {
   getData(ref, pageIndex) {
     const pageIndexSet = this._refCache.get(ref);
     const pageIndexSet = this._refCache.get(ref);
 
 
@@ -262,12 +302,14 @@ class GlobalImageCache {
       return null;
       return null;
     }
     }
 
 
-    if (!this._imageCache.has(ref)) {
+    const imageData = this._imageCache.get(ref);
+
+    if (!imageData) {
       return null;
       return null;
     }
     }
 
 
     pageIndexSet.add(pageIndex);
     pageIndexSet.add(pageIndex);
-    return this._imageCache.get(ref);
+    return imageData;
   }
   }
 
 
   setData(ref, data) {
   setData(ref, data) {
@@ -279,8 +321,8 @@ class GlobalImageCache {
       return;
       return;
     }
     }
 
 
-    if (this._imageCache.size >= GlobalImageCache.MAX_IMAGES_TO_CACHE) {
-      (0, _util.info)("GlobalImageCache.setData - ignoring image above MAX_IMAGES_TO_CACHE.");
+    if (this._cacheLimitReached) {
+      (0, _util.warn)("GlobalImageCache.setData - cache limit reached.");
       return;
       return;
     }
     }
 
 

+ 1 - 1
lib/core/jbig2.js

@@ -2,7 +2,7 @@
  * @licstart The following is the entire license notice for the
  * @licstart The following is the entire license notice for the
  * Javascript code in this page
  * Javascript code in this page
  *
  *
- * Copyright 2020 Mozilla Foundation
+ * Copyright 2021 Mozilla Foundation
  *
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * you may not use this file except in compliance with the License.

+ 1 - 1
lib/core/jbig2_stream.js

@@ -2,7 +2,7 @@
  * @licstart The following is the entire license notice for the
  * @licstart The following is the entire license notice for the
  * Javascript code in this page
  * Javascript code in this page
  *
  *
- * Copyright 2020 Mozilla Foundation
+ * Copyright 2021 Mozilla Foundation
  *
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * you may not use this file except in compliance with the License.

+ 1 - 1
lib/core/jpeg_stream.js

@@ -2,7 +2,7 @@
  * @licstart The following is the entire license notice for the
  * @licstart The following is the entire license notice for the
  * Javascript code in this page
  * Javascript code in this page
  *
  *
- * Copyright 2020 Mozilla Foundation
+ * Copyright 2021 Mozilla Foundation
  *
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * you may not use this file except in compliance with the License.

+ 1 - 1
lib/core/jpg.js

@@ -2,7 +2,7 @@
  * @licstart The following is the entire license notice for the
  * @licstart The following is the entire license notice for the
  * Javascript code in this page
  * Javascript code in this page
  *
  *
- * Copyright 2020 Mozilla Foundation
+ * Copyright 2021 Mozilla Foundation
  *
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * you may not use this file except in compliance with the License.

+ 1 - 1
lib/core/jpx.js

@@ -2,7 +2,7 @@
  * @licstart The following is the entire license notice for the
  * @licstart The following is the entire license notice for the
  * Javascript code in this page
  * Javascript code in this page
  *
  *
- * Copyright 2020 Mozilla Foundation
+ * Copyright 2021 Mozilla Foundation
  *
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * you may not use this file except in compliance with the License.

+ 1 - 1
lib/core/jpx_stream.js

@@ -2,7 +2,7 @@
  * @licstart The following is the entire license notice for the
  * @licstart The following is the entire license notice for the
  * Javascript code in this page
  * Javascript code in this page
  *
  *
- * Copyright 2020 Mozilla Foundation
+ * Copyright 2021 Mozilla Foundation
  *
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * you may not use this file except in compliance with the License.

+ 155 - 0
lib/core/metadata_parser.js

@@ -0,0 +1,155 @@
+/**
+ * @licstart The following is the entire license notice for the
+ * Javascript code in this page
+ *
+ * Copyright 2021 Mozilla Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * @licend The above is the entire license notice for the
+ * Javascript code in this page
+ */
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.MetadataParser = void 0;
+
+var _xml_parser = require("./xml_parser.js");
+
+class MetadataParser {
+  constructor(data) {
+    data = this._repair(data);
+    const parser = new _xml_parser.SimpleXMLParser({
+      lowerCaseName: true
+    });
+    const xmlDocument = parser.parseFromString(data);
+    this._metadataMap = new Map();
+    this._data = data;
+
+    if (xmlDocument) {
+      this._parse(xmlDocument);
+    }
+  }
+
+  _repair(data) {
+    return data.replace(/^[^<]+/, "").replace(/>\\376\\377([^<]+)/g, function (all, codes) {
+      const bytes = codes.replace(/\\([0-3])([0-7])([0-7])/g, function (code, d1, d2, d3) {
+        return String.fromCharCode(d1 * 64 + d2 * 8 + d3 * 1);
+      }).replace(/&(amp|apos|gt|lt|quot);/g, function (str, name) {
+        switch (name) {
+          case "amp":
+            return "&";
+
+          case "apos":
+            return "'";
+
+          case "gt":
+            return ">";
+
+          case "lt":
+            return "<";
+
+          case "quot":
+            return '"';
+        }
+
+        throw new Error(`_repair: ${name} isn't defined.`);
+      });
+      const charBuf = [];
+
+      for (let i = 0, ii = bytes.length; i < ii; i += 2) {
+        const code = bytes.charCodeAt(i) * 256 + bytes.charCodeAt(i + 1);
+
+        if (code >= 32 && code < 127 && code !== 60 && code !== 62 && code !== 38) {
+          charBuf.push(String.fromCharCode(code));
+        } else {
+          charBuf.push("&#x" + (0x10000 + code).toString(16).substring(1) + ";");
+        }
+      }
+
+      return ">" + charBuf.join("");
+    });
+  }
+
+  _getSequence(entry) {
+    const name = entry.nodeName;
+
+    if (name !== "rdf:bag" && name !== "rdf:seq" && name !== "rdf:alt") {
+      return null;
+    }
+
+    return entry.childNodes.filter(node => node.nodeName === "rdf:li");
+  }
+
+  _parseArray(entry) {
+    if (!entry.hasChildNodes()) {
+      return;
+    }
+
+    const [seqNode] = entry.childNodes;
+    const sequence = this._getSequence(seqNode) || [];
+
+    this._metadataMap.set(entry.nodeName, sequence.map(node => node.textContent.trim()));
+  }
+
+  _parse(xmlDocument) {
+    let rdf = xmlDocument.documentElement;
+
+    if (rdf.nodeName !== "rdf:rdf") {
+      rdf = rdf.firstChild;
+
+      while (rdf && rdf.nodeName !== "rdf:rdf") {
+        rdf = rdf.nextSibling;
+      }
+    }
+
+    if (!rdf || rdf.nodeName !== "rdf:rdf" || !rdf.hasChildNodes()) {
+      return;
+    }
+
+    for (const desc of rdf.childNodes) {
+      if (desc.nodeName !== "rdf:description") {
+        continue;
+      }
+
+      for (const entry of desc.childNodes) {
+        const name = entry.nodeName;
+
+        switch (name) {
+          case "#text":
+            continue;
+
+          case "dc:creator":
+          case "dc:subject":
+            this._parseArray(entry);
+
+            continue;
+        }
+
+        this._metadataMap.set(name, entry.textContent.trim());
+      }
+    }
+  }
+
+  get serializable() {
+    return {
+      parsedData: this._metadataMap,
+      rawData: this._data
+    };
+  }
+
+}
+
+exports.MetadataParser = MetadataParser;

+ 2 - 2
lib/core/metrics.js

@@ -2,7 +2,7 @@
  * @licstart The following is the entire license notice for the
  * @licstart The following is the entire license notice for the
  * Javascript code in this page
  * Javascript code in this page
  *
  *
- * Copyright 2020 Mozilla Foundation
+ * Copyright 2021 Mozilla Foundation
  *
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * you may not use this file except in compliance with the License.
@@ -28,7 +28,7 @@ exports.getMetrics = void 0;
 
 
 var _core_utils = require("./core_utils.js");
 var _core_utils = require("./core_utils.js");
 
 
-var getMetrics = (0, _core_utils.getLookupTableFactory)(function (t) {
+const getMetrics = (0, _core_utils.getLookupTableFactory)(function (t) {
   t.Courier = 600;
   t.Courier = 600;
   t["Courier-Bold"] = 600;
   t["Courier-Bold"] = 600;
   t["Courier-BoldOblique"] = 600;
   t["Courier-BoldOblique"] = 600;

+ 1 - 1
lib/core/murmurhash3.js

@@ -2,7 +2,7 @@
  * @licstart The following is the entire license notice for the
  * @licstart The following is the entire license notice for the
  * Javascript code in this page
  * Javascript code in this page
  *
  *
- * Copyright 2020 Mozilla Foundation
+ * Copyright 2021 Mozilla Foundation
  *
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * you may not use this file except in compliance with the License.

+ 36 - 15
lib/core/obj.js

@@ -2,7 +2,7 @@
  * @licstart The following is the entire license notice for the
  * @licstart The following is the entire license notice for the
  * Javascript code in this page
  * Javascript code in this page
  *
  *
- * Copyright 2020 Mozilla Foundation
+ * Copyright 2021 Mozilla Foundation
  *
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * you may not use this file except in compliance with the License.
@@ -40,6 +40,8 @@ var _colorspace = require("./colorspace.js");
 
 
 var _image_utils = require("./image_utils.js");
 var _image_utils = require("./image_utils.js");
 
 
+var _metadata_parser = require("./metadata_parser.js");
+
 function fetchDestination(dest) {
 function fetchDestination(dest) {
   return (0, _primitives.isDict)(dest) ? dest.get("D") : dest;
   return (0, _primitives.isDict)(dest) ? dest.get("D") : dest;
 }
 }
@@ -120,15 +122,19 @@ class Catalog {
 
 
     const suppressEncryption = !(this.xref.encrypt && this.xref.encrypt.encryptMetadata);
     const suppressEncryption = !(this.xref.encrypt && this.xref.encrypt.encryptMetadata);
     const stream = this.xref.fetch(streamRef, suppressEncryption);
     const stream = this.xref.fetch(streamRef, suppressEncryption);
-    let metadata;
+    let metadata = null;
 
 
-    if (stream && (0, _primitives.isDict)(stream.dict)) {
+    if ((0, _primitives.isStream)(stream) && (0, _primitives.isDict)(stream.dict)) {
       const type = stream.dict.get("Type");
       const type = stream.dict.get("Type");
       const subtype = stream.dict.get("Subtype");
       const subtype = stream.dict.get("Subtype");
 
 
       if ((0, _primitives.isName)(type, "Metadata") && (0, _primitives.isName)(subtype, "XML")) {
       if ((0, _primitives.isName)(type, "Metadata") && (0, _primitives.isName)(subtype, "XML")) {
         try {
         try {
-          metadata = (0, _util.stringToUTF8String)((0, _util.bytesToString)(stream.getBytes()));
+          const data = (0, _util.stringToUTF8String)((0, _util.bytesToString)(stream.getBytes()));
+
+          if (data) {
+            metadata = new _metadata_parser.MetadataParser(data).serializable;
+          }
         } catch (e) {
         } catch (e) {
           if (e instanceof _core_utils.MissingDataException) {
           if (e instanceof _core_utils.MissingDataException) {
             throw e;
             throw e;
@@ -1388,7 +1394,11 @@ class Catalog {
           }
           }
 
 
         default:
         default:
-          (0, _util.warn)(`parseDestDictionary: unsupported action type "${actionName}".`);
+          if (actionName === "JavaScript" || actionName === "ResetForm" || actionName === "SubmitForm") {
+            break;
+          }
+
+          (0, _util.warn)(`parseDestDictionary - unsupported action: "${actionName}".`);
           break;
           break;
       }
       }
     } else if (destDict.has("Dest")) {
     } else if (destDict.has("Dest")) {
@@ -1894,10 +1904,6 @@ var XRef = function XRefClosure() {
             continue;
             continue;
           }
           }
         } catch (ex) {
         } catch (ex) {
-          if (ex instanceof _core_utils.MissingDataException) {
-            throw ex;
-          }
-
           continue;
           continue;
         }
         }
 
 
@@ -2117,12 +2123,13 @@ var XRef = function XRefClosure() {
         throw new _util.FormatError("invalid first and n parameters for ObjStm stream");
         throw new _util.FormatError("invalid first and n parameters for ObjStm stream");
       }
       }
 
 
-      const parser = new _parser.Parser({
+      let parser = new _parser.Parser({
         lexer: new _parser.Lexer(stream),
         lexer: new _parser.Lexer(stream),
         xref: this,
         xref: this,
         allowStreams: true
         allowStreams: true
       });
       });
       const nums = new Array(n);
       const nums = new Array(n);
+      const offsets = new Array(n);
 
 
       for (let i = 0; i < n; ++i) {
       for (let i = 0; i < n; ++i) {
         const num = parser.getObj();
         const num = parser.getObj();
@@ -2138,18 +2145,27 @@ var XRef = function XRefClosure() {
         }
         }
 
 
         nums[i] = num;
         nums[i] = num;
+        offsets[i] = offset;
       }
       }
 
 
+      const start = (stream.start || 0) + first;
       const entries = new Array(n);
       const entries = new Array(n);
 
 
       for (let i = 0; i < n; ++i) {
       for (let i = 0; i < n; ++i) {
-        const obj = parser.getObj();
-        entries[i] = obj;
+        const length = i < n - 1 ? offsets[i + 1] - offsets[i] : undefined;
 
 
-        if (parser.buf1 instanceof _primitives.Cmd && parser.buf1.cmd === "endobj") {
-          parser.shift();
+        if (length < 0) {
+          throw new _util.FormatError("Invalid offset in the ObjStm stream.");
         }
         }
 
 
+        parser = new _parser.Parser({
+          lexer: new _parser.Lexer(stream.makeSubStream(start + offsets[i], length, stream.dict)),
+          xref: this,
+          allowStreams: true
+        });
+        const obj = parser.getObj();
+        entries[i] = obj;
+
         if ((0, _primitives.isStream)(obj)) {
         if ((0, _primitives.isStream)(obj)) {
           continue;
           continue;
         }
         }
@@ -2518,7 +2534,12 @@ const ObjectLoader = function () {
             currentNode = this.xref.fetch(currentNode);
             currentNode = this.xref.fetch(currentNode);
           } catch (ex) {
           } catch (ex) {
             if (!(ex instanceof _core_utils.MissingDataException)) {
             if (!(ex instanceof _core_utils.MissingDataException)) {
-              throw ex;
+              (0, _util.warn)(`ObjectLoader._walk - requesting all data: "${ex}".`);
+              this.refSet = null;
+              const {
+                manager
+              } = this.xref.stream;
+              return manager.requestAllChunks();
             }
             }
 
 
             nodesToRevisit.push(currentNode);
             nodesToRevisit.push(currentNode);

+ 121 - 122
lib/core/operator_list.js

@@ -2,7 +2,7 @@
  * @licstart The following is the entire license notice for the
  * @licstart The following is the entire license notice for the
  * Javascript code in this page
  * Javascript code in this page
  *
  *
- * Copyright 2020 Mozilla Foundation
+ * Copyright 2021 Mozilla Foundation
  *
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * you may not use this file except in compliance with the License.
@@ -28,12 +28,12 @@ exports.OperatorList = void 0;
 
 
 var _util = require("../shared/util.js");
 var _util = require("../shared/util.js");
 
 
-var QueueOptimizer = function QueueOptimizerClosure() {
+const QueueOptimizer = function QueueOptimizerClosure() {
   function addState(parentState, pattern, checkFn, iterateFn, processFn) {
   function addState(parentState, pattern, checkFn, iterateFn, processFn) {
-    var state = parentState;
+    let state = parentState;
 
 
-    for (var i = 0, ii = pattern.length - 1; i < ii; i++) {
-      var item = pattern[i];
+    for (let i = 0, ii = pattern.length - 1; i < ii; i++) {
+      const item = pattern[i];
       state = state[item] || (state[item] = []);
       state = state[item] || (state[item] = []);
     }
     }
 
 
@@ -45,11 +45,12 @@ var QueueOptimizer = function QueueOptimizerClosure() {
   }
   }
 
 
   function handlePaintSolidColorImageMask(iFirstSave, count, fnArray, argsArray) {
   function handlePaintSolidColorImageMask(iFirstSave, count, fnArray, argsArray) {
-    var iFirstPIMXO = iFirstSave + 2;
+    const iFirstPIMXO = iFirstSave + 2;
+    let i;
 
 
-    for (var i = 0; i < count; i++) {
-      var arg = argsArray[iFirstPIMXO + 4 * i];
-      var imageMask = arg.length === 1 && arg[0];
+    for (i = 0; i < count; i++) {
+      const arg = argsArray[iFirstPIMXO + 4 * i];
+      const imageMask = arg.length === 1 && arg[0];
 
 
       if (imageMask && imageMask.width === 1 && imageMask.height === 1 && (!imageMask.data.length || imageMask.data.length === 1 && imageMask.data[0] === 0)) {
       if (imageMask && imageMask.width === 1 && imageMask.height === 1 && (!imageMask.data.length || imageMask.data.length === 1 && imageMask.data[0] === 0)) {
         fnArray[iFirstPIMXO + 4 * i] = _util.OPS.paintSolidColorImageMask;
         fnArray[iFirstPIMXO + 4 * i] = _util.OPS.paintSolidColorImageMask;
@@ -62,11 +63,11 @@ var QueueOptimizer = function QueueOptimizerClosure() {
     return count - i;
     return count - i;
   }
   }
 
 
-  var InitialState = [];
+  const InitialState = [];
   addState(InitialState, [_util.OPS.save, _util.OPS.transform, _util.OPS.paintInlineImageXObject, _util.OPS.restore], null, function iterateInlineImageGroup(context, i) {
   addState(InitialState, [_util.OPS.save, _util.OPS.transform, _util.OPS.paintInlineImageXObject, _util.OPS.restore], null, function iterateInlineImageGroup(context, i) {
-    var fnArray = context.fnArray;
-    var iFirstSave = context.iCurr - 3;
-    var pos = (i - iFirstSave) % 4;
+    const fnArray = context.fnArray;
+    const iFirstSave = context.iCurr - 3;
+    const pos = (i - iFirstSave) % 4;
 
 
     switch (pos) {
     switch (pos) {
       case 0:
       case 0:
@@ -84,32 +85,31 @@ var QueueOptimizer = function QueueOptimizerClosure() {
 
 
     throw new Error(`iterateInlineImageGroup - invalid pos: ${pos}`);
     throw new Error(`iterateInlineImageGroup - invalid pos: ${pos}`);
   }, function foundInlineImageGroup(context, i) {
   }, function foundInlineImageGroup(context, i) {
-    var MIN_IMAGES_IN_INLINE_IMAGES_BLOCK = 10;
-    var MAX_IMAGES_IN_INLINE_IMAGES_BLOCK = 200;
-    var MAX_WIDTH = 1000;
-    var IMAGE_PADDING = 1;
-    var fnArray = context.fnArray,
-        argsArray = context.argsArray;
-    var curr = context.iCurr;
-    var iFirstSave = curr - 3;
-    var iFirstTransform = curr - 2;
-    var iFirstPIIXO = curr - 1;
-    var count = Math.min(Math.floor((i - iFirstSave) / 4), MAX_IMAGES_IN_INLINE_IMAGES_BLOCK);
+    const MIN_IMAGES_IN_INLINE_IMAGES_BLOCK = 10;
+    const MAX_IMAGES_IN_INLINE_IMAGES_BLOCK = 200;
+    const MAX_WIDTH = 1000;
+    const IMAGE_PADDING = 1;
+    const fnArray = context.fnArray,
+          argsArray = context.argsArray;
+    const curr = context.iCurr;
+    const iFirstSave = curr - 3;
+    const iFirstTransform = curr - 2;
+    const iFirstPIIXO = curr - 1;
+    const count = Math.min(Math.floor((i - iFirstSave) / 4), MAX_IMAGES_IN_INLINE_IMAGES_BLOCK);
 
 
     if (count < MIN_IMAGES_IN_INLINE_IMAGES_BLOCK) {
     if (count < MIN_IMAGES_IN_INLINE_IMAGES_BLOCK) {
       return i - (i - iFirstSave) % 4;
       return i - (i - iFirstSave) % 4;
     }
     }
 
 
-    var maxX = 0;
-    var map = [],
-        maxLineHeight = 0;
-    var currentX = IMAGE_PADDING,
+    let maxX = 0;
+    const map = [];
+    let maxLineHeight = 0;
+    let currentX = IMAGE_PADDING,
         currentY = IMAGE_PADDING;
         currentY = IMAGE_PADDING;
-    var q;
 
 
-    for (q = 0; q < count; q++) {
-      var transform = argsArray[iFirstTransform + (q << 2)];
-      var img = argsArray[iFirstPIIXO + (q << 2)][0];
+    for (let q = 0; q < count; q++) {
+      const transform = argsArray[iFirstTransform + (q << 2)];
+      const img = argsArray[iFirstPIIXO + (q << 2)][0];
 
 
       if (currentX + img.width > MAX_WIDTH) {
       if (currentX + img.width > MAX_WIDTH) {
         maxX = Math.max(maxX, currentX);
         maxX = Math.max(maxX, currentX);
@@ -129,19 +129,19 @@ var QueueOptimizer = function QueueOptimizerClosure() {
       maxLineHeight = Math.max(maxLineHeight, img.height);
       maxLineHeight = Math.max(maxLineHeight, img.height);
     }
     }
 
 
-    var imgWidth = Math.max(maxX, currentX) + IMAGE_PADDING;
-    var imgHeight = currentY + maxLineHeight + IMAGE_PADDING;
-    var imgData = new Uint8ClampedArray(imgWidth * imgHeight * 4);
-    var imgRowSize = imgWidth << 2;
+    const imgWidth = Math.max(maxX, currentX) + IMAGE_PADDING;
+    const imgHeight = currentY + maxLineHeight + IMAGE_PADDING;
+    const imgData = new Uint8ClampedArray(imgWidth * imgHeight * 4);
+    const imgRowSize = imgWidth << 2;
 
 
-    for (q = 0; q < count; q++) {
-      var data = argsArray[iFirstPIIXO + (q << 2)][0].data;
-      var rowSize = map[q].w << 2;
-      var dataOffset = 0;
-      var offset = map[q].x + map[q].y * imgWidth << 2;
+    for (let q = 0; q < count; q++) {
+      const data = argsArray[iFirstPIIXO + (q << 2)][0].data;
+      const rowSize = map[q].w << 2;
+      let dataOffset = 0;
+      let offset = map[q].x + map[q].y * imgWidth << 2;
       imgData.set(data.subarray(0, rowSize), offset - imgRowSize);
       imgData.set(data.subarray(0, rowSize), offset - imgRowSize);
 
 
-      for (var k = 0, kk = map[q].h; k < kk; k++) {
+      for (let k = 0, kk = map[q].h; k < kk; k++) {
         imgData.set(data.subarray(dataOffset, dataOffset + rowSize), offset);
         imgData.set(data.subarray(dataOffset, dataOffset + rowSize), offset);
         dataOffset += rowSize;
         dataOffset += rowSize;
         offset += imgRowSize;
         offset += imgRowSize;
@@ -172,9 +172,9 @@ var QueueOptimizer = function QueueOptimizerClosure() {
     return iFirstSave + 1;
     return iFirstSave + 1;
   });
   });
   addState(InitialState, [_util.OPS.save, _util.OPS.transform, _util.OPS.paintImageMaskXObject, _util.OPS.restore], null, function iterateImageMaskGroup(context, i) {
   addState(InitialState, [_util.OPS.save, _util.OPS.transform, _util.OPS.paintImageMaskXObject, _util.OPS.restore], null, function iterateImageMaskGroup(context, i) {
-    var fnArray = context.fnArray;
-    var iFirstSave = context.iCurr - 3;
-    var pos = (i - iFirstSave) % 4;
+    const fnArray = context.fnArray;
+    const iFirstSave = context.iCurr - 3;
+    const pos = (i - iFirstSave) % 4;
 
 
     switch (pos) {
     switch (pos) {
       case 0:
       case 0:
@@ -192,26 +192,25 @@ var QueueOptimizer = function QueueOptimizerClosure() {
 
 
     throw new Error(`iterateImageMaskGroup - invalid pos: ${pos}`);
     throw new Error(`iterateImageMaskGroup - invalid pos: ${pos}`);
   }, function foundImageMaskGroup(context, i) {
   }, function foundImageMaskGroup(context, i) {
-    var MIN_IMAGES_IN_MASKS_BLOCK = 10;
-    var MAX_IMAGES_IN_MASKS_BLOCK = 100;
-    var MAX_SAME_IMAGES_IN_MASKS_BLOCK = 1000;
-    var fnArray = context.fnArray,
-        argsArray = context.argsArray;
-    var curr = context.iCurr;
-    var iFirstSave = curr - 3;
-    var iFirstTransform = curr - 2;
-    var iFirstPIMXO = curr - 1;
-    var count = Math.floor((i - iFirstSave) / 4);
+    const MIN_IMAGES_IN_MASKS_BLOCK = 10;
+    const MAX_IMAGES_IN_MASKS_BLOCK = 100;
+    const MAX_SAME_IMAGES_IN_MASKS_BLOCK = 1000;
+    const fnArray = context.fnArray,
+          argsArray = context.argsArray;
+    const curr = context.iCurr;
+    const iFirstSave = curr - 3;
+    const iFirstTransform = curr - 2;
+    const iFirstPIMXO = curr - 1;
+    let count = Math.floor((i - iFirstSave) / 4);
     count = handlePaintSolidColorImageMask(iFirstSave, count, fnArray, argsArray);
     count = handlePaintSolidColorImageMask(iFirstSave, count, fnArray, argsArray);
 
 
     if (count < MIN_IMAGES_IN_MASKS_BLOCK) {
     if (count < MIN_IMAGES_IN_MASKS_BLOCK) {
       return i - (i - iFirstSave) % 4;
       return i - (i - iFirstSave) % 4;
     }
     }
 
 
-    var q;
-    var isSameImage = false;
-    var iTransform, transformArgs;
-    var firstPIMXOArg0 = argsArray[iFirstPIMXO][0];
+    let isSameImage = false;
+    let iTransform, transformArgs;
+    const firstPIMXOArg0 = argsArray[iFirstPIMXO][0];
     const firstTransformArg0 = argsArray[iFirstTransform][0],
     const firstTransformArg0 = argsArray[iFirstTransform][0],
           firstTransformArg1 = argsArray[iFirstTransform][1],
           firstTransformArg1 = argsArray[iFirstTransform][1],
           firstTransformArg2 = argsArray[iFirstTransform][2],
           firstTransformArg2 = argsArray[iFirstTransform][2],
@@ -220,9 +219,9 @@ var QueueOptimizer = function QueueOptimizerClosure() {
     if (firstTransformArg1 === firstTransformArg2) {
     if (firstTransformArg1 === firstTransformArg2) {
       isSameImage = true;
       isSameImage = true;
       iTransform = iFirstTransform + 4;
       iTransform = iFirstTransform + 4;
-      var iPIMXO = iFirstPIMXO + 4;
+      let iPIMXO = iFirstPIMXO + 4;
 
 
-      for (q = 1; q < count; q++, iTransform += 4, iPIMXO += 4) {
+      for (let q = 1; q < count; q++, iTransform += 4, iPIMXO += 4) {
         transformArgs = argsArray[iTransform];
         transformArgs = argsArray[iTransform];
 
 
         if (argsArray[iPIMXO][0] !== firstPIMXOArg0 || transformArgs[0] !== firstTransformArg0 || transformArgs[1] !== firstTransformArg1 || transformArgs[2] !== firstTransformArg2 || transformArgs[3] !== firstTransformArg3) {
         if (argsArray[iPIMXO][0] !== firstPIMXOArg0 || transformArgs[0] !== firstTransformArg0 || transformArgs[1] !== firstTransformArg1 || transformArgs[2] !== firstTransformArg2 || transformArgs[3] !== firstTransformArg3) {
@@ -239,10 +238,10 @@ var QueueOptimizer = function QueueOptimizerClosure() {
 
 
     if (isSameImage) {
     if (isSameImage) {
       count = Math.min(count, MAX_SAME_IMAGES_IN_MASKS_BLOCK);
       count = Math.min(count, MAX_SAME_IMAGES_IN_MASKS_BLOCK);
-      var positions = new Float32Array(count * 2);
+      const positions = new Float32Array(count * 2);
       iTransform = iFirstTransform;
       iTransform = iFirstTransform;
 
 
-      for (q = 0; q < count; q++, iTransform += 4) {
+      for (let q = 0; q < count; q++, iTransform += 4) {
         transformArgs = argsArray[iTransform];
         transformArgs = argsArray[iTransform];
         positions[q << 1] = transformArgs[4];
         positions[q << 1] = transformArgs[4];
         positions[(q << 1) + 1] = transformArgs[5];
         positions[(q << 1) + 1] = transformArgs[5];
@@ -252,11 +251,11 @@ var QueueOptimizer = function QueueOptimizerClosure() {
       argsArray.splice(iFirstSave, count * 4, [firstPIMXOArg0, firstTransformArg0, firstTransformArg1, firstTransformArg2, firstTransformArg3, positions]);
       argsArray.splice(iFirstSave, count * 4, [firstPIMXOArg0, firstTransformArg0, firstTransformArg1, firstTransformArg2, firstTransformArg3, positions]);
     } else {
     } else {
       count = Math.min(count, MAX_IMAGES_IN_MASKS_BLOCK);
       count = Math.min(count, MAX_IMAGES_IN_MASKS_BLOCK);
-      var images = [];
+      const images = [];
 
 
-      for (q = 0; q < count; q++) {
+      for (let q = 0; q < count; q++) {
         transformArgs = argsArray[iFirstTransform + (q << 2)];
         transformArgs = argsArray[iFirstTransform + (q << 2)];
-        var maskParams = argsArray[iFirstPIMXO + (q << 2)][0];
+        const maskParams = argsArray[iFirstPIMXO + (q << 2)][0];
         images.push({
         images.push({
           data: maskParams.data,
           data: maskParams.data,
           width: maskParams.width,
           width: maskParams.width,
@@ -272,14 +271,14 @@ var QueueOptimizer = function QueueOptimizerClosure() {
     return iFirstSave + 1;
     return iFirstSave + 1;
   });
   });
   addState(InitialState, [_util.OPS.save, _util.OPS.transform, _util.OPS.paintImageXObject, _util.OPS.restore], function (context) {
   addState(InitialState, [_util.OPS.save, _util.OPS.transform, _util.OPS.paintImageXObject, _util.OPS.restore], function (context) {
-    var argsArray = context.argsArray;
-    var iFirstTransform = context.iCurr - 2;
+    const argsArray = context.argsArray;
+    const iFirstTransform = context.iCurr - 2;
     return argsArray[iFirstTransform][1] === 0 && argsArray[iFirstTransform][2] === 0;
     return argsArray[iFirstTransform][1] === 0 && argsArray[iFirstTransform][2] === 0;
   }, function iterateImageGroup(context, i) {
   }, function iterateImageGroup(context, i) {
-    var fnArray = context.fnArray,
-        argsArray = context.argsArray;
-    var iFirstSave = context.iCurr - 3;
-    var pos = (i - iFirstSave) % 4;
+    const fnArray = context.fnArray,
+          argsArray = context.argsArray;
+    const iFirstSave = context.iCurr - 3;
+    const pos = (i - iFirstSave) % 4;
 
 
     switch (pos) {
     switch (pos) {
       case 0:
       case 0:
@@ -290,9 +289,9 @@ var QueueOptimizer = function QueueOptimizerClosure() {
           return false;
           return false;
         }
         }
 
 
-        var iFirstTransform = context.iCurr - 2;
-        var firstTransformArg0 = argsArray[iFirstTransform][0];
-        var firstTransformArg3 = argsArray[iFirstTransform][3];
+        const iFirstTransform = context.iCurr - 2;
+        const firstTransformArg0 = argsArray[iFirstTransform][0];
+        const firstTransformArg3 = argsArray[iFirstTransform][3];
 
 
         if (argsArray[i][0] !== firstTransformArg0 || argsArray[i][1] !== 0 || argsArray[i][2] !== 0 || argsArray[i][3] !== firstTransformArg3) {
         if (argsArray[i][0] !== firstTransformArg0 || argsArray[i][1] !== 0 || argsArray[i][2] !== 0 || argsArray[i][3] !== firstTransformArg3) {
           return false;
           return false;
@@ -305,8 +304,8 @@ var QueueOptimizer = function QueueOptimizerClosure() {
           return false;
           return false;
         }
         }
 
 
-        var iFirstPIXO = context.iCurr - 1;
-        var firstPIXOArg0 = argsArray[iFirstPIXO][0];
+        const iFirstPIXO = context.iCurr - 1;
+        const firstPIXOArg0 = argsArray[iFirstPIXO][0];
 
 
         if (argsArray[i][0] !== firstPIXOArg0) {
         if (argsArray[i][0] !== firstPIXOArg0) {
           return false;
           return false;
@@ -320,42 +319,42 @@ var QueueOptimizer = function QueueOptimizerClosure() {
 
 
     throw new Error(`iterateImageGroup - invalid pos: ${pos}`);
     throw new Error(`iterateImageGroup - invalid pos: ${pos}`);
   }, function (context, i) {
   }, function (context, i) {
-    var MIN_IMAGES_IN_BLOCK = 3;
-    var MAX_IMAGES_IN_BLOCK = 1000;
-    var fnArray = context.fnArray,
-        argsArray = context.argsArray;
-    var curr = context.iCurr;
-    var iFirstSave = curr - 3;
-    var iFirstTransform = curr - 2;
-    var iFirstPIXO = curr - 1;
-    var firstPIXOArg0 = argsArray[iFirstPIXO][0];
-    var firstTransformArg0 = argsArray[iFirstTransform][0];
-    var firstTransformArg3 = argsArray[iFirstTransform][3];
-    var count = Math.min(Math.floor((i - iFirstSave) / 4), MAX_IMAGES_IN_BLOCK);
+    const MIN_IMAGES_IN_BLOCK = 3;
+    const MAX_IMAGES_IN_BLOCK = 1000;
+    const fnArray = context.fnArray,
+          argsArray = context.argsArray;
+    const curr = context.iCurr;
+    const iFirstSave = curr - 3;
+    const iFirstTransform = curr - 2;
+    const iFirstPIXO = curr - 1;
+    const firstPIXOArg0 = argsArray[iFirstPIXO][0];
+    const firstTransformArg0 = argsArray[iFirstTransform][0];
+    const firstTransformArg3 = argsArray[iFirstTransform][3];
+    const count = Math.min(Math.floor((i - iFirstSave) / 4), MAX_IMAGES_IN_BLOCK);
 
 
     if (count < MIN_IMAGES_IN_BLOCK) {
     if (count < MIN_IMAGES_IN_BLOCK) {
       return i - (i - iFirstSave) % 4;
       return i - (i - iFirstSave) % 4;
     }
     }
 
 
-    var positions = new Float32Array(count * 2);
-    var iTransform = iFirstTransform;
+    const positions = new Float32Array(count * 2);
+    let iTransform = iFirstTransform;
 
 
-    for (var q = 0; q < count; q++, iTransform += 4) {
-      var transformArgs = argsArray[iTransform];
+    for (let q = 0; q < count; q++, iTransform += 4) {
+      const transformArgs = argsArray[iTransform];
       positions[q << 1] = transformArgs[4];
       positions[q << 1] = transformArgs[4];
       positions[(q << 1) + 1] = transformArgs[5];
       positions[(q << 1) + 1] = transformArgs[5];
     }
     }
 
 
-    var args = [firstPIXOArg0, firstTransformArg0, firstTransformArg3, positions];
+    const args = [firstPIXOArg0, firstTransformArg0, firstTransformArg3, positions];
     fnArray.splice(iFirstSave, count * 4, _util.OPS.paintImageXObjectRepeat);
     fnArray.splice(iFirstSave, count * 4, _util.OPS.paintImageXObjectRepeat);
     argsArray.splice(iFirstSave, count * 4, args);
     argsArray.splice(iFirstSave, count * 4, args);
     return iFirstSave + 1;
     return iFirstSave + 1;
   });
   });
   addState(InitialState, [_util.OPS.beginText, _util.OPS.setFont, _util.OPS.setTextMatrix, _util.OPS.showText, _util.OPS.endText], null, function iterateShowTextGroup(context, i) {
   addState(InitialState, [_util.OPS.beginText, _util.OPS.setFont, _util.OPS.setTextMatrix, _util.OPS.showText, _util.OPS.endText], null, function iterateShowTextGroup(context, i) {
-    var fnArray = context.fnArray,
-        argsArray = context.argsArray;
-    var iFirstSave = context.iCurr - 4;
-    var pos = (i - iFirstSave) % 5;
+    const fnArray = context.fnArray,
+          argsArray = context.argsArray;
+    const iFirstSave = context.iCurr - 4;
+    const pos = (i - iFirstSave) % 5;
 
 
     switch (pos) {
     switch (pos) {
       case 0:
       case 0:
@@ -372,9 +371,9 @@ var QueueOptimizer = function QueueOptimizerClosure() {
           return false;
           return false;
         }
         }
 
 
-        var iFirstSetFont = context.iCurr - 3;
-        var firstSetFontArg0 = argsArray[iFirstSetFont][0];
-        var firstSetFontArg1 = argsArray[iFirstSetFont][1];
+        const iFirstSetFont = context.iCurr - 3;
+        const firstSetFontArg0 = argsArray[iFirstSetFont][0];
+        const firstSetFontArg1 = argsArray[iFirstSetFont][1];
 
 
         if (argsArray[i][0] !== firstSetFontArg0 || argsArray[i][1] !== firstSetFontArg1) {
         if (argsArray[i][0] !== firstSetFontArg0 || argsArray[i][1] !== firstSetFontArg1) {
           return false;
           return false;
@@ -388,34 +387,34 @@ var QueueOptimizer = function QueueOptimizerClosure() {
 
 
     throw new Error(`iterateShowTextGroup - invalid pos: ${pos}`);
     throw new Error(`iterateShowTextGroup - invalid pos: ${pos}`);
   }, function (context, i) {
   }, function (context, i) {
-    var MIN_CHARS_IN_BLOCK = 3;
-    var MAX_CHARS_IN_BLOCK = 1000;
-    var fnArray = context.fnArray,
-        argsArray = context.argsArray;
-    var curr = context.iCurr;
-    var iFirstBeginText = curr - 4;
-    var iFirstSetFont = curr - 3;
-    var iFirstSetTextMatrix = curr - 2;
-    var iFirstShowText = curr - 1;
-    var iFirstEndText = curr;
-    var firstSetFontArg0 = argsArray[iFirstSetFont][0];
-    var firstSetFontArg1 = argsArray[iFirstSetFont][1];
-    var count = Math.min(Math.floor((i - iFirstBeginText) / 5), MAX_CHARS_IN_BLOCK);
+    const MIN_CHARS_IN_BLOCK = 3;
+    const MAX_CHARS_IN_BLOCK = 1000;
+    const fnArray = context.fnArray,
+          argsArray = context.argsArray;
+    const curr = context.iCurr;
+    const iFirstBeginText = curr - 4;
+    const iFirstSetFont = curr - 3;
+    const iFirstSetTextMatrix = curr - 2;
+    const iFirstShowText = curr - 1;
+    const iFirstEndText = curr;
+    const firstSetFontArg0 = argsArray[iFirstSetFont][0];
+    const firstSetFontArg1 = argsArray[iFirstSetFont][1];
+    let count = Math.min(Math.floor((i - iFirstBeginText) / 5), MAX_CHARS_IN_BLOCK);
 
 
     if (count < MIN_CHARS_IN_BLOCK) {
     if (count < MIN_CHARS_IN_BLOCK) {
       return i - (i - iFirstBeginText) % 5;
       return i - (i - iFirstBeginText) % 5;
     }
     }
 
 
-    var iFirst = iFirstBeginText;
+    let iFirst = iFirstBeginText;
 
 
     if (iFirstBeginText >= 4 && fnArray[iFirstBeginText - 4] === fnArray[iFirstSetFont] && fnArray[iFirstBeginText - 3] === fnArray[iFirstSetTextMatrix] && fnArray[iFirstBeginText - 2] === fnArray[iFirstShowText] && fnArray[iFirstBeginText - 1] === fnArray[iFirstEndText] && argsArray[iFirstBeginText - 4][0] === firstSetFontArg0 && argsArray[iFirstBeginText - 4][1] === firstSetFontArg1) {
     if (iFirstBeginText >= 4 && fnArray[iFirstBeginText - 4] === fnArray[iFirstSetFont] && fnArray[iFirstBeginText - 3] === fnArray[iFirstSetTextMatrix] && fnArray[iFirstBeginText - 2] === fnArray[iFirstShowText] && fnArray[iFirstBeginText - 1] === fnArray[iFirstEndText] && argsArray[iFirstBeginText - 4][0] === firstSetFontArg0 && argsArray[iFirstBeginText - 4][1] === firstSetFontArg1) {
       count++;
       count++;
       iFirst -= 5;
       iFirst -= 5;
     }
     }
 
 
-    var iEndText = iFirst + 4;
+    let iEndText = iFirst + 4;
 
 
-    for (var q = 1; q < count; q++) {
+    for (let q = 1; q < count; q++) {
       fnArray.splice(iEndText, 3);
       fnArray.splice(iEndText, 3);
       argsArray.splice(iEndText, 3);
       argsArray.splice(iEndText, 3);
       iEndText += 2;
       iEndText += 2;
@@ -522,7 +521,7 @@ var QueueOptimizer = function QueueOptimizerClosure() {
   return QueueOptimizer;
   return QueueOptimizer;
 }();
 }();
 
 
-var NullOptimizer = function NullOptimizerClosure() {
+const NullOptimizer = function NullOptimizerClosure() {
   function NullOptimizer(queue) {
   function NullOptimizer(queue) {
     this.queue = queue;
     this.queue = queue;
   }
   }
@@ -541,9 +540,9 @@ var NullOptimizer = function NullOptimizerClosure() {
   return NullOptimizer;
   return NullOptimizer;
 }();
 }();
 
 
-var OperatorList = function OperatorListClosure() {
-  var CHUNK_SIZE = 1000;
-  var CHUNK_SIZE_ABOUT = CHUNK_SIZE - 5;
+const OperatorList = function OperatorListClosure() {
+  const CHUNK_SIZE = 1000;
+  const CHUNK_SIZE_ABOUT = CHUNK_SIZE - 5;
 
 
   function OperatorList(intent, streamSink) {
   function OperatorList(intent, streamSink) {
     this._streamSink = streamSink;
     this._streamSink = streamSink;
@@ -613,7 +612,7 @@ var OperatorList = function OperatorListClosure() {
         this.dependencies.add(dependency);
         this.dependencies.add(dependency);
       }
       }
 
 
-      for (var i = 0, ii = opList.length; i < ii; i++) {
+      for (let i = 0, ii = opList.length; i < ii; i++) {
         this.addOp(opList.fnArray[i], opList.argsArray[i]);
         this.addOp(opList.fnArray[i], opList.argsArray[i]);
       }
       }
     },
     },

+ 1 - 1
lib/core/parser.js

@@ -2,7 +2,7 @@
  * @licstart The following is the entire license notice for the
  * @licstart The following is the entire license notice for the
  * Javascript code in this page
  * Javascript code in this page
  *
  *
- * Copyright 2020 Mozilla Foundation
+ * Copyright 2021 Mozilla Foundation
  *
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * you may not use this file except in compliance with the License.

+ 142 - 149
lib/core/pattern.js

@@ -2,7 +2,7 @@
  * @licstart The following is the entire license notice for the
  * @licstart The following is the entire license notice for the
  * Javascript code in this page
  * Javascript code in this page
  *
  *
- * Copyright 2020 Mozilla Foundation
+ * Copyright 2021 Mozilla Foundation
  *
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * you may not use this file except in compliance with the License.
@@ -35,7 +35,7 @@ var _primitives = require("./primitives.js");
 
 
 var _core_utils = require("./core_utils.js");
 var _core_utils = require("./core_utils.js");
 
 
-var ShadingType = {
+const ShadingType = {
   FUNCTION_BASED: 1,
   FUNCTION_BASED: 1,
   AXIAL: 2,
   AXIAL: 2,
   RADIAL: 3,
   RADIAL: 3,
@@ -45,7 +45,7 @@ var ShadingType = {
   TENSOR_PATCH_MESH: 7
   TENSOR_PATCH_MESH: 7
 };
 };
 
 
-var Pattern = function PatternClosure() {
+const Pattern = function PatternClosure() {
   function Pattern() {
   function Pattern() {
     (0, _util.unreachable)("should not call Pattern constructor");
     (0, _util.unreachable)("should not call Pattern constructor");
   }
   }
@@ -57,8 +57,8 @@ var Pattern = function PatternClosure() {
   };
   };
 
 
   Pattern.parseShading = function (shading, matrix, xref, res, handler, pdfFunctionFactory, localColorSpaceCache) {
   Pattern.parseShading = function (shading, matrix, xref, res, handler, pdfFunctionFactory, localColorSpaceCache) {
-    var dict = (0, _primitives.isStream)(shading) ? shading.dict : shading;
-    var type = dict.get("ShadingType");
+    const dict = (0, _primitives.isStream)(shading) ? shading.dict : shading;
+    const type = dict.get("ShadingType");
 
 
     try {
     try {
       switch (type) {
       switch (type) {
@@ -92,7 +92,7 @@ var Pattern = function PatternClosure() {
 }();
 }();
 
 
 exports.Pattern = Pattern;
 exports.Pattern = Pattern;
-var Shadings = {};
+const Shadings = {};
 Shadings.SMALL_NUMBER = 1e-6;
 Shadings.SMALL_NUMBER = 1e-6;
 
 
 Shadings.RadialAxial = function RadialAxialClosure() {
 Shadings.RadialAxial = function RadialAxialClosure() {
@@ -119,32 +119,27 @@ Shadings.RadialAxial = function RadialAxialClosure() {
       this.bbox = null;
       this.bbox = null;
     }
     }
 
 
-    var t0 = 0.0,
+    let t0 = 0.0,
         t1 = 1.0;
         t1 = 1.0;
 
 
     if (dict.has("Domain")) {
     if (dict.has("Domain")) {
-      var domainArr = dict.getArray("Domain");
+      const domainArr = dict.getArray("Domain");
       t0 = domainArr[0];
       t0 = domainArr[0];
       t1 = domainArr[1];
       t1 = domainArr[1];
     }
     }
 
 
-    var extendStart = false,
+    let extendStart = false,
         extendEnd = false;
         extendEnd = false;
 
 
     if (dict.has("Extend")) {
     if (dict.has("Extend")) {
-      var extendArr = dict.getArray("Extend");
+      const extendArr = dict.getArray("Extend");
       extendStart = extendArr[0];
       extendStart = extendArr[0];
       extendEnd = extendArr[1];
       extendEnd = extendArr[1];
     }
     }
 
 
     if (this.shadingType === ShadingType.RADIAL && (!extendStart || !extendEnd)) {
     if (this.shadingType === ShadingType.RADIAL && (!extendStart || !extendEnd)) {
-      var x1 = this.coordsArr[0];
-      var y1 = this.coordsArr[1];
-      var r1 = this.coordsArr[2];
-      var x2 = this.coordsArr[3];
-      var y2 = this.coordsArr[4];
-      var r2 = this.coordsArr[5];
-      var distance = Math.sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
+      const [x1, y1, r1, x2, y2, r2] = this.coordsArr;
+      const distance = Math.hypot(x1 - x2, y1 - y2);
 
 
       if (r1 <= r2 + distance && r2 <= r1 + distance) {
       if (r1 <= r2 + distance && r2 <= r1 + distance) {
         (0, _util.warn)("Unsupported radial gradient.");
         (0, _util.warn)("Unsupported radial gradient.");
@@ -153,32 +148,32 @@ Shadings.RadialAxial = function RadialAxialClosure() {
 
 
     this.extendStart = extendStart;
     this.extendStart = extendStart;
     this.extendEnd = extendEnd;
     this.extendEnd = extendEnd;
-    var fnObj = dict.getRaw("Function");
-    var fn = pdfFunctionFactory.createFromArray(fnObj);
+    const fnObj = dict.getRaw("Function");
+    const fn = pdfFunctionFactory.createFromArray(fnObj);
     const NUMBER_OF_SAMPLES = 10;
     const NUMBER_OF_SAMPLES = 10;
     const step = (t1 - t0) / NUMBER_OF_SAMPLES;
     const step = (t1 - t0) / NUMBER_OF_SAMPLES;
-    var colorStops = this.colorStops = [];
+    const colorStops = this.colorStops = [];
 
 
     if (t0 >= t1 || step <= 0) {
     if (t0 >= t1 || step <= 0) {
       (0, _util.info)("Bad shading domain.");
       (0, _util.info)("Bad shading domain.");
       return;
       return;
     }
     }
 
 
-    var color = new Float32Array(cs.numComps),
-        ratio = new Float32Array(1);
-    var rgbColor;
+    const color = new Float32Array(cs.numComps),
+          ratio = new Float32Array(1);
+    let rgbColor;
 
 
     for (let i = 0; i <= NUMBER_OF_SAMPLES; i++) {
     for (let i = 0; i <= NUMBER_OF_SAMPLES; i++) {
       ratio[0] = t0 + i * step;
       ratio[0] = t0 + i * step;
       fn(ratio, 0, color, 0);
       fn(ratio, 0, color, 0);
       rgbColor = cs.getRgb(color, 0);
       rgbColor = cs.getRgb(color, 0);
 
 
-      var cssColor = _util.Util.makeHexColor(rgbColor[0], rgbColor[1], rgbColor[2]);
+      const cssColor = _util.Util.makeHexColor(rgbColor[0], rgbColor[1], rgbColor[2]);
 
 
       colorStops.push([i / NUMBER_OF_SAMPLES, cssColor]);
       colorStops.push([i / NUMBER_OF_SAMPLES, cssColor]);
     }
     }
 
 
-    var background = "transparent";
+    let background = "transparent";
 
 
     if (dict.has("Background")) {
     if (dict.has("Background")) {
       rgbColor = cs.getRgb(dict.get("Background"), 0);
       rgbColor = cs.getRgb(dict.get("Background"), 0);
@@ -200,9 +195,9 @@ Shadings.RadialAxial = function RadialAxialClosure() {
 
 
   RadialAxial.prototype = {
   RadialAxial.prototype = {
     getIR: function RadialAxial_getIR() {
     getIR: function RadialAxial_getIR() {
-      var coordsArr = this.coordsArr;
-      var shadingType = this.shadingType;
-      var type, p0, p1, r0, r1;
+      const coordsArr = this.coordsArr;
+      const shadingType = this.shadingType;
+      let type, p0, p1, r0, r1;
 
 
       if (shadingType === ShadingType.AXIAL) {
       if (shadingType === ShadingType.AXIAL) {
         p0 = [coordsArr[0], coordsArr[1]];
         p0 = [coordsArr[0], coordsArr[1]];
@@ -220,14 +215,14 @@ Shadings.RadialAxial = function RadialAxialClosure() {
         (0, _util.unreachable)(`getPattern type unknown: ${shadingType}`);
         (0, _util.unreachable)(`getPattern type unknown: ${shadingType}`);
       }
       }
 
 
-      var matrix = this.matrix;
+      const matrix = this.matrix;
 
 
       if (matrix) {
       if (matrix) {
         p0 = _util.Util.applyTransform(p0, matrix);
         p0 = _util.Util.applyTransform(p0, matrix);
         p1 = _util.Util.applyTransform(p1, matrix);
         p1 = _util.Util.applyTransform(p1, matrix);
 
 
         if (shadingType === ShadingType.RADIAL) {
         if (shadingType === ShadingType.RADIAL) {
-          var scale = _util.Util.singularValueDecompose2dScale(matrix);
+          const scale = _util.Util.singularValueDecompose2dScale(matrix);
 
 
           r0 *= scale[0];
           r0 *= scale[0];
           r1 *= scale[1];
           r1 *= scale[1];
@@ -246,9 +241,9 @@ Shadings.Mesh = function MeshClosure() {
     this.context = context;
     this.context = context;
     this.buffer = 0;
     this.buffer = 0;
     this.bufferLength = 0;
     this.bufferLength = 0;
-    var numComps = context.numComps;
+    const numComps = context.numComps;
     this.tmpCompsBuf = new Float32Array(numComps);
     this.tmpCompsBuf = new Float32Array(numComps);
-    var csNumComps = context.colorSpace.numComps;
+    const csNumComps = context.colorSpace.numComps;
     this.tmpCsCompsBuf = context.colorFn ? new Float32Array(csNumComps) : this.tmpCompsBuf;
     this.tmpCsCompsBuf = context.colorFn ? new Float32Array(csNumComps) : this.tmpCompsBuf;
   }
   }
 
 
@@ -262,7 +257,7 @@ Shadings.Mesh = function MeshClosure() {
         return true;
         return true;
       }
       }
 
 
-      var nextByte = this.stream.getByte();
+      const nextByte = this.stream.getByte();
 
 
       if (nextByte < 0) {
       if (nextByte < 0) {
         return false;
         return false;
@@ -274,8 +269,8 @@ Shadings.Mesh = function MeshClosure() {
     },
     },
 
 
     readBits: function MeshStreamReader_readBits(n) {
     readBits: function MeshStreamReader_readBits(n) {
-      var buffer = this.buffer;
-      var bufferLength = this.bufferLength;
+      let buffer = this.buffer;
+      let bufferLength = this.bufferLength;
 
 
       if (n === 32) {
       if (n === 32) {
         if (bufferLength === 0) {
         if (bufferLength === 0) {
@@ -283,7 +278,7 @@ Shadings.Mesh = function MeshClosure() {
         }
         }
 
 
         buffer = buffer << 24 | this.stream.getByte() << 16 | this.stream.getByte() << 8 | this.stream.getByte();
         buffer = buffer << 24 | this.stream.getByte() << 16 | this.stream.getByte() << 8 | this.stream.getByte();
-        var nextByte = this.stream.getByte();
+        const nextByte = this.stream.getByte();
         this.buffer = nextByte & (1 << bufferLength) - 1;
         this.buffer = nextByte & (1 << bufferLength) - 1;
         return (buffer << 8 - bufferLength | (nextByte & 0xff) >> bufferLength) >>> 0;
         return (buffer << 8 - bufferLength | (nextByte & 0xff) >> bufferLength) >>> 0;
       }
       }
@@ -310,26 +305,26 @@ Shadings.Mesh = function MeshClosure() {
       return this.readBits(this.context.bitsPerFlag);
       return this.readBits(this.context.bitsPerFlag);
     },
     },
     readCoordinate: function MeshStreamReader_readCoordinate() {
     readCoordinate: function MeshStreamReader_readCoordinate() {
-      var bitsPerCoordinate = this.context.bitsPerCoordinate;
-      var xi = this.readBits(bitsPerCoordinate);
-      var yi = this.readBits(bitsPerCoordinate);
-      var decode = this.context.decode;
-      var scale = bitsPerCoordinate < 32 ? 1 / ((1 << bitsPerCoordinate) - 1) : 2.3283064365386963e-10;
+      const bitsPerCoordinate = this.context.bitsPerCoordinate;
+      const xi = this.readBits(bitsPerCoordinate);
+      const yi = this.readBits(bitsPerCoordinate);
+      const decode = this.context.decode;
+      const scale = bitsPerCoordinate < 32 ? 1 / ((1 << bitsPerCoordinate) - 1) : 2.3283064365386963e-10;
       return [xi * scale * (decode[1] - decode[0]) + decode[0], yi * scale * (decode[3] - decode[2]) + decode[2]];
       return [xi * scale * (decode[1] - decode[0]) + decode[0], yi * scale * (decode[3] - decode[2]) + decode[2]];
     },
     },
     readComponents: function MeshStreamReader_readComponents() {
     readComponents: function MeshStreamReader_readComponents() {
-      var numComps = this.context.numComps;
-      var bitsPerComponent = this.context.bitsPerComponent;
-      var scale = bitsPerComponent < 32 ? 1 / ((1 << bitsPerComponent) - 1) : 2.3283064365386963e-10;
-      var decode = this.context.decode;
-      var components = this.tmpCompsBuf;
-
-      for (var i = 0, j = 4; i < numComps; i++, j += 2) {
-        var ci = this.readBits(bitsPerComponent);
+      const numComps = this.context.numComps;
+      const bitsPerComponent = this.context.bitsPerComponent;
+      const scale = bitsPerComponent < 32 ? 1 / ((1 << bitsPerComponent) - 1) : 2.3283064365386963e-10;
+      const decode = this.context.decode;
+      const components = this.tmpCompsBuf;
+
+      for (let i = 0, j = 4; i < numComps; i++, j += 2) {
+        const ci = this.readBits(bitsPerComponent);
         components[i] = ci * scale * (decode[j + 1] - decode[j]) + decode[j];
         components[i] = ci * scale * (decode[j + 1] - decode[j]) + decode[j];
       }
       }
 
 
-      var color = this.tmpCsCompsBuf;
+      const color = this.tmpCsCompsBuf;
 
 
       if (this.context.colorFn) {
       if (this.context.colorFn) {
         this.context.colorFn(components, 0, color, 0);
         this.context.colorFn(components, 0, color, 0);
@@ -340,16 +335,16 @@ Shadings.Mesh = function MeshClosure() {
   };
   };
 
 
   function decodeType4Shading(mesh, reader) {
   function decodeType4Shading(mesh, reader) {
-    var coords = mesh.coords;
-    var colors = mesh.colors;
-    var operators = [];
-    var ps = [];
-    var verticesLeft = 0;
+    const coords = mesh.coords;
+    const colors = mesh.colors;
+    const operators = [];
+    const ps = [];
+    let verticesLeft = 0;
 
 
     while (reader.hasData) {
     while (reader.hasData) {
-      var f = reader.readFlag();
-      var coord = reader.readCoordinate();
-      var color = reader.readComponents();
+      const f = reader.readFlag();
+      const coord = reader.readCoordinate();
+      const color = reader.readComponents();
 
 
       if (verticesLeft === 0) {
       if (verticesLeft === 0) {
         if (!(0 <= f && f <= 2)) {
         if (!(0 <= f && f <= 2)) {
@@ -390,13 +385,13 @@ Shadings.Mesh = function MeshClosure() {
   }
   }
 
 
   function decodeType5Shading(mesh, reader, verticesPerRow) {
   function decodeType5Shading(mesh, reader, verticesPerRow) {
-    var coords = mesh.coords;
-    var colors = mesh.colors;
-    var ps = [];
+    const coords = mesh.coords;
+    const colors = mesh.colors;
+    const ps = [];
 
 
     while (reader.hasData) {
     while (reader.hasData) {
-      var coord = reader.readCoordinate();
-      var color = reader.readComponents();
+      const coord = reader.readCoordinate();
+      const color = reader.readComponents();
       ps.push(coords.length);
       ps.push(coords.length);
       coords.push(coord);
       coords.push(coord);
       colors.push(color);
       colors.push(color);
@@ -410,24 +405,24 @@ Shadings.Mesh = function MeshClosure() {
     });
     });
   }
   }
 
 
-  var MIN_SPLIT_PATCH_CHUNKS_AMOUNT = 3;
-  var MAX_SPLIT_PATCH_CHUNKS_AMOUNT = 20;
-  var TRIANGLE_DENSITY = 20;
+  const MIN_SPLIT_PATCH_CHUNKS_AMOUNT = 3;
+  const MAX_SPLIT_PATCH_CHUNKS_AMOUNT = 20;
+  const TRIANGLE_DENSITY = 20;
 
 
-  var getB = function getBClosure() {
+  const getB = function getBClosure() {
     function buildB(count) {
     function buildB(count) {
-      var lut = [];
+      const lut = [];
 
 
-      for (var i = 0; i <= count; i++) {
-        var t = i / count,
-            t_ = 1 - t;
+      for (let i = 0; i <= count; i++) {
+        const t = i / count,
+              t_ = 1 - t;
         lut.push(new Float32Array([t_ * t_ * t_, 3 * t * t_ * t_, 3 * t * t * t_, t * t * t]));
         lut.push(new Float32Array([t_ * t_ * t_, 3 * t * t_ * t_, 3 * t * t * t_, t * t * t]));
       }
       }
 
 
       return lut;
       return lut;
     }
     }
 
 
-    var cache = [];
+    const cache = [];
     return function getB(count) {
     return function getB(count) {
       if (!cache[count]) {
       if (!cache[count]) {
         cache[count] = buildB(count);
         cache[count] = buildB(count);
@@ -438,34 +433,34 @@ Shadings.Mesh = function MeshClosure() {
   }();
   }();
 
 
   function buildFigureFromPatch(mesh, index) {
   function buildFigureFromPatch(mesh, index) {
-    var figure = mesh.figures[index];
+    const figure = mesh.figures[index];
     (0, _util.assert)(figure.type === "patch", "Unexpected patch mesh figure");
     (0, _util.assert)(figure.type === "patch", "Unexpected patch mesh figure");
-    var coords = mesh.coords,
-        colors = mesh.colors;
-    var pi = figure.coords;
-    var ci = figure.colors;
-    var figureMinX = Math.min(coords[pi[0]][0], coords[pi[3]][0], coords[pi[12]][0], coords[pi[15]][0]);
-    var figureMinY = Math.min(coords[pi[0]][1], coords[pi[3]][1], coords[pi[12]][1], coords[pi[15]][1]);
-    var figureMaxX = Math.max(coords[pi[0]][0], coords[pi[3]][0], coords[pi[12]][0], coords[pi[15]][0]);
-    var figureMaxY = Math.max(coords[pi[0]][1], coords[pi[3]][1], coords[pi[12]][1], coords[pi[15]][1]);
-    var splitXBy = Math.ceil((figureMaxX - figureMinX) * TRIANGLE_DENSITY / (mesh.bounds[2] - mesh.bounds[0]));
+    const coords = mesh.coords,
+          colors = mesh.colors;
+    const pi = figure.coords;
+    const ci = figure.colors;
+    const figureMinX = Math.min(coords[pi[0]][0], coords[pi[3]][0], coords[pi[12]][0], coords[pi[15]][0]);
+    const figureMinY = Math.min(coords[pi[0]][1], coords[pi[3]][1], coords[pi[12]][1], coords[pi[15]][1]);
+    const figureMaxX = Math.max(coords[pi[0]][0], coords[pi[3]][0], coords[pi[12]][0], coords[pi[15]][0]);
+    const figureMaxY = Math.max(coords[pi[0]][1], coords[pi[3]][1], coords[pi[12]][1], coords[pi[15]][1]);
+    let splitXBy = Math.ceil((figureMaxX - figureMinX) * TRIANGLE_DENSITY / (mesh.bounds[2] - mesh.bounds[0]));
     splitXBy = Math.max(MIN_SPLIT_PATCH_CHUNKS_AMOUNT, Math.min(MAX_SPLIT_PATCH_CHUNKS_AMOUNT, splitXBy));
     splitXBy = Math.max(MIN_SPLIT_PATCH_CHUNKS_AMOUNT, Math.min(MAX_SPLIT_PATCH_CHUNKS_AMOUNT, splitXBy));
-    var splitYBy = Math.ceil((figureMaxY - figureMinY) * TRIANGLE_DENSITY / (mesh.bounds[3] - mesh.bounds[1]));
+    let splitYBy = Math.ceil((figureMaxY - figureMinY) * TRIANGLE_DENSITY / (mesh.bounds[3] - mesh.bounds[1]));
     splitYBy = Math.max(MIN_SPLIT_PATCH_CHUNKS_AMOUNT, Math.min(MAX_SPLIT_PATCH_CHUNKS_AMOUNT, splitYBy));
     splitYBy = Math.max(MIN_SPLIT_PATCH_CHUNKS_AMOUNT, Math.min(MAX_SPLIT_PATCH_CHUNKS_AMOUNT, splitYBy));
-    var verticesPerRow = splitXBy + 1;
-    var figureCoords = new Int32Array((splitYBy + 1) * verticesPerRow);
-    var figureColors = new Int32Array((splitYBy + 1) * verticesPerRow);
-    var k = 0;
-    var cl = new Uint8Array(3),
-        cr = new Uint8Array(3);
-    var c0 = colors[ci[0]],
-        c1 = colors[ci[1]],
-        c2 = colors[ci[2]],
-        c3 = colors[ci[3]];
-    var bRow = getB(splitYBy),
-        bCol = getB(splitXBy);
-
-    for (var row = 0; row <= splitYBy; row++) {
+    const verticesPerRow = splitXBy + 1;
+    const figureCoords = new Int32Array((splitYBy + 1) * verticesPerRow);
+    const figureColors = new Int32Array((splitYBy + 1) * verticesPerRow);
+    let k = 0;
+    const cl = new Uint8Array(3),
+          cr = new Uint8Array(3);
+    const c0 = colors[ci[0]],
+          c1 = colors[ci[1]],
+          c2 = colors[ci[2]],
+          c3 = colors[ci[3]];
+    const bRow = getB(splitYBy),
+          bCol = getB(splitXBy);
+
+    for (let row = 0; row <= splitYBy; row++) {
       cl[0] = (c0[0] * (splitYBy - row) + c2[0] * row) / splitYBy | 0;
       cl[0] = (c0[0] * (splitYBy - row) + c2[0] * row) / splitYBy | 0;
       cl[1] = (c0[1] * (splitYBy - row) + c2[1] * row) / splitYBy | 0;
       cl[1] = (c0[1] * (splitYBy - row) + c2[1] * row) / splitYBy | 0;
       cl[2] = (c0[2] * (splitYBy - row) + c2[2] * row) / splitYBy | 0;
       cl[2] = (c0[2] * (splitYBy - row) + c2[2] * row) / splitYBy | 0;
@@ -473,18 +468,18 @@ Shadings.Mesh = function MeshClosure() {
       cr[1] = (c1[1] * (splitYBy - row) + c3[1] * row) / splitYBy | 0;
       cr[1] = (c1[1] * (splitYBy - row) + c3[1] * row) / splitYBy | 0;
       cr[2] = (c1[2] * (splitYBy - row) + c3[2] * row) / splitYBy | 0;
       cr[2] = (c1[2] * (splitYBy - row) + c3[2] * row) / splitYBy | 0;
 
 
-      for (var col = 0; col <= splitXBy; col++, k++) {
+      for (let col = 0; col <= splitXBy; col++, k++) {
         if ((row === 0 || row === splitYBy) && (col === 0 || col === splitXBy)) {
         if ((row === 0 || row === splitYBy) && (col === 0 || col === splitXBy)) {
           continue;
           continue;
         }
         }
 
 
-        var x = 0,
+        let x = 0,
             y = 0;
             y = 0;
-        var q = 0;
+        let q = 0;
 
 
-        for (var i = 0; i <= 3; i++) {
-          for (var j = 0; j <= 3; j++, q++) {
-            var m = bRow[row][i] * bCol[col][j];
+        for (let i = 0; i <= 3; i++) {
+          for (let j = 0; j <= 3; j++, q++) {
+            const m = bRow[row][i] * bCol[col][j];
             x += coords[pi[q]][0] * m;
             x += coords[pi[q]][0] * m;
             y += coords[pi[q]][1] * m;
             y += coords[pi[q]][1] * m;
           }
           }
@@ -493,7 +488,7 @@ Shadings.Mesh = function MeshClosure() {
         figureCoords[k] = coords.length;
         figureCoords[k] = coords.length;
         coords.push([x, y]);
         coords.push([x, y]);
         figureColors[k] = colors.length;
         figureColors[k] = colors.length;
-        var newColor = new Uint8Array(3);
+        const newColor = new Uint8Array(3);
         newColor[0] = (cl[0] * (splitXBy - col) + cr[0] * col) / splitXBy | 0;
         newColor[0] = (cl[0] * (splitXBy - col) + cr[0] * col) / splitXBy | 0;
         newColor[1] = (cl[1] * (splitXBy - col) + cr[1] * col) / splitXBy | 0;
         newColor[1] = (cl[1] * (splitXBy - col) + cr[1] * col) / splitXBy | 0;
         newColor[2] = (cl[2] * (splitXBy - col) + cr[2] * col) / splitXBy | 0;
         newColor[2] = (cl[2] * (splitXBy - col) + cr[2] * col) / splitXBy | 0;
@@ -518,32 +513,31 @@ Shadings.Mesh = function MeshClosure() {
   }
   }
 
 
   function decodeType6Shading(mesh, reader) {
   function decodeType6Shading(mesh, reader) {
-    var coords = mesh.coords;
-    var colors = mesh.colors;
-    var ps = new Int32Array(16);
-    var cs = new Int32Array(4);
+    const coords = mesh.coords;
+    const colors = mesh.colors;
+    const ps = new Int32Array(16);
+    const cs = new Int32Array(4);
 
 
     while (reader.hasData) {
     while (reader.hasData) {
-      var f = reader.readFlag();
+      const f = reader.readFlag();
 
 
       if (!(0 <= f && f <= 3)) {
       if (!(0 <= f && f <= 3)) {
         throw new _util.FormatError("Unknown type6 flag");
         throw new _util.FormatError("Unknown type6 flag");
       }
       }
 
 
-      var i, ii;
-      var pi = coords.length;
+      const pi = coords.length;
 
 
-      for (i = 0, ii = f !== 0 ? 8 : 12; i < ii; i++) {
+      for (let i = 0, ii = f !== 0 ? 8 : 12; i < ii; i++) {
         coords.push(reader.readCoordinate());
         coords.push(reader.readCoordinate());
       }
       }
 
 
-      var ci = colors.length;
+      const ci = colors.length;
 
 
-      for (i = 0, ii = f !== 0 ? 2 : 4; i < ii; i++) {
+      for (let i = 0, ii = f !== 0 ? 2 : 4; i < ii; i++) {
         colors.push(reader.readComponents());
         colors.push(reader.readComponents());
       }
       }
 
 
-      var tmp1, tmp2, tmp3, tmp4;
+      let tmp1, tmp2, tmp3, tmp4;
 
 
       switch (f) {
       switch (f) {
         case 0:
         case 0:
@@ -649,32 +643,31 @@ Shadings.Mesh = function MeshClosure() {
   }
   }
 
 
   function decodeType7Shading(mesh, reader) {
   function decodeType7Shading(mesh, reader) {
-    var coords = mesh.coords;
-    var colors = mesh.colors;
-    var ps = new Int32Array(16);
-    var cs = new Int32Array(4);
+    const coords = mesh.coords;
+    const colors = mesh.colors;
+    const ps = new Int32Array(16);
+    const cs = new Int32Array(4);
 
 
     while (reader.hasData) {
     while (reader.hasData) {
-      var f = reader.readFlag();
+      const f = reader.readFlag();
 
 
       if (!(0 <= f && f <= 3)) {
       if (!(0 <= f && f <= 3)) {
         throw new _util.FormatError("Unknown type7 flag");
         throw new _util.FormatError("Unknown type7 flag");
       }
       }
 
 
-      var i, ii;
-      var pi = coords.length;
+      const pi = coords.length;
 
 
-      for (i = 0, ii = f !== 0 ? 12 : 16; i < ii; i++) {
+      for (let i = 0, ii = f !== 0 ? 12 : 16; i < ii; i++) {
         coords.push(reader.readCoordinate());
         coords.push(reader.readCoordinate());
       }
       }
 
 
-      var ci = colors.length;
+      const ci = colors.length;
 
 
-      for (i = 0, ii = f !== 0 ? 2 : 4; i < ii; i++) {
+      for (let i = 0, ii = f !== 0 ? 2 : 4; i < ii; i++) {
         colors.push(reader.readComponents());
         colors.push(reader.readComponents());
       }
       }
 
 
-      var tmp1, tmp2, tmp3, tmp4;
+      let tmp1, tmp2, tmp3, tmp4;
 
 
       switch (f) {
       switch (f) {
         case 0:
         case 0:
@@ -788,14 +781,14 @@ Shadings.Mesh = function MeshClosure() {
   }
   }
 
 
   function updateBounds(mesh) {
   function updateBounds(mesh) {
-    var minX = mesh.coords[0][0],
+    let minX = mesh.coords[0][0],
         minY = mesh.coords[0][1],
         minY = mesh.coords[0][1],
         maxX = minX,
         maxX = minX,
         maxY = minY;
         maxY = minY;
 
 
-    for (var i = 1, ii = mesh.coords.length; i < ii; i++) {
-      var x = mesh.coords[i][0],
-          y = mesh.coords[i][1];
+    for (let i = 1, ii = mesh.coords.length; i < ii; i++) {
+      const x = mesh.coords[i][0],
+            y = mesh.coords[i][1];
       minX = minX > x ? x : minX;
       minX = minX > x ? x : minX;
       minY = minY > y ? y : minY;
       minY = minY > y ? y : minY;
       maxX = maxX < x ? x : maxX;
       maxX = maxX < x ? x : maxX;
@@ -806,34 +799,34 @@ Shadings.Mesh = function MeshClosure() {
   }
   }
 
 
   function packData(mesh) {
   function packData(mesh) {
-    var i, ii, j, jj;
-    var coords = mesh.coords;
-    var coordsPacked = new Float32Array(coords.length * 2);
+    let i, ii, j, jj;
+    const coords = mesh.coords;
+    const coordsPacked = new Float32Array(coords.length * 2);
 
 
     for (i = 0, j = 0, ii = coords.length; i < ii; i++) {
     for (i = 0, j = 0, ii = coords.length; i < ii; i++) {
-      var xy = coords[i];
+      const xy = coords[i];
       coordsPacked[j++] = xy[0];
       coordsPacked[j++] = xy[0];
       coordsPacked[j++] = xy[1];
       coordsPacked[j++] = xy[1];
     }
     }
 
 
     mesh.coords = coordsPacked;
     mesh.coords = coordsPacked;
-    var colors = mesh.colors;
-    var colorsPacked = new Uint8Array(colors.length * 3);
+    const colors = mesh.colors;
+    const colorsPacked = new Uint8Array(colors.length * 3);
 
 
     for (i = 0, j = 0, ii = colors.length; i < ii; i++) {
     for (i = 0, j = 0, ii = colors.length; i < ii; i++) {
-      var c = colors[i];
+      const c = colors[i];
       colorsPacked[j++] = c[0];
       colorsPacked[j++] = c[0];
       colorsPacked[j++] = c[1];
       colorsPacked[j++] = c[1];
       colorsPacked[j++] = c[2];
       colorsPacked[j++] = c[2];
     }
     }
 
 
     mesh.colors = colorsPacked;
     mesh.colors = colorsPacked;
-    var figures = mesh.figures;
+    const figures = mesh.figures;
 
 
     for (i = 0, ii = figures.length; i < ii; i++) {
     for (i = 0, ii = figures.length; i < ii; i++) {
-      var figure = figures[i],
-          ps = figure.coords,
-          cs = figure.colors;
+      const figure = figures[i],
+            ps = figure.coords,
+            cs = figure.colors;
 
 
       for (j = 0, jj = ps.length; j < jj; j++) {
       for (j = 0, jj = ps.length; j < jj; j++) {
         ps[j] *= 2;
         ps[j] *= 2;
@@ -847,7 +840,7 @@ Shadings.Mesh = function MeshClosure() {
       throw new _util.FormatError("Mesh data is not a stream");
       throw new _util.FormatError("Mesh data is not a stream");
     }
     }
 
 
-    var dict = stream.dict;
+    const dict = stream.dict;
     this.matrix = matrix;
     this.matrix = matrix;
     this.shadingType = dict.get("ShadingType");
     this.shadingType = dict.get("ShadingType");
     this.type = "Pattern";
     this.type = "Pattern";
@@ -869,12 +862,12 @@ Shadings.Mesh = function MeshClosure() {
 
 
     this.cs = cs;
     this.cs = cs;
     this.background = dict.has("Background") ? cs.getRgb(dict.get("Background"), 0) : null;
     this.background = dict.has("Background") ? cs.getRgb(dict.get("Background"), 0) : null;
-    var fnObj = dict.getRaw("Function");
-    var fn = fnObj ? pdfFunctionFactory.createFromArray(fnObj) : null;
+    const fnObj = dict.getRaw("Function");
+    const fn = fnObj ? pdfFunctionFactory.createFromArray(fnObj) : null;
     this.coords = [];
     this.coords = [];
     this.colors = [];
     this.colors = [];
     this.figures = [];
     this.figures = [];
-    var decodeContext = {
+    const decodeContext = {
       bitsPerCoordinate: dict.get("BitsPerCoordinate"),
       bitsPerCoordinate: dict.get("BitsPerCoordinate"),
       bitsPerComponent: dict.get("BitsPerComponent"),
       bitsPerComponent: dict.get("BitsPerComponent"),
       bitsPerFlag: dict.get("BitsPerFlag"),
       bitsPerFlag: dict.get("BitsPerFlag"),
@@ -883,8 +876,8 @@ Shadings.Mesh = function MeshClosure() {
       colorSpace: cs,
       colorSpace: cs,
       numComps: fn ? 1 : cs.numComps
       numComps: fn ? 1 : cs.numComps
     };
     };
-    var reader = new MeshStreamReader(stream, decodeContext);
-    var patchMesh = false;
+    const reader = new MeshStreamReader(stream, decodeContext);
+    let patchMesh = false;
 
 
     switch (this.shadingType) {
     switch (this.shadingType) {
       case ShadingType.FREE_FORM_MESH:
       case ShadingType.FREE_FORM_MESH:
@@ -892,7 +885,7 @@ Shadings.Mesh = function MeshClosure() {
         break;
         break;
 
 
       case ShadingType.LATTICE_FORM_MESH:
       case ShadingType.LATTICE_FORM_MESH:
-        var verticesPerRow = dict.get("VerticesPerRow") | 0;
+        const verticesPerRow = dict.get("VerticesPerRow") | 0;
 
 
         if (verticesPerRow < 2) {
         if (verticesPerRow < 2) {
           throw new _util.FormatError("Invalid VerticesPerRow");
           throw new _util.FormatError("Invalid VerticesPerRow");
@@ -919,7 +912,7 @@ Shadings.Mesh = function MeshClosure() {
     if (patchMesh) {
     if (patchMesh) {
       updateBounds(this);
       updateBounds(this);
 
 
-      for (var i = 0, ii = this.figures.length; i < ii; i++) {
+      for (let i = 0, ii = this.figures.length; i < ii; i++) {
         buildFigureFromPatch(this, i);
         buildFigureFromPatch(this, i);
       }
       }
     }
     }

+ 22 - 18
lib/core/pdf_manager.js

@@ -2,7 +2,7 @@
  * @licstart The following is the entire license notice for the
  * @licstart The following is the entire license notice for the
  * Javascript code in this page
  * Javascript code in this page
  *
  *
- * Copyright 2020 Mozilla Foundation
+ * Copyright 2021 Mozilla Foundation
  *
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * you may not use this file except in compliance with the License.
@@ -36,6 +36,20 @@ var _document = require("./document.js");
 
 
 var _stream = require("./stream.js");
 var _stream = require("./stream.js");
 
 
+function parseDocBaseUrl(url) {
+  if (url) {
+    const absoluteUrl = (0, _util.createValidAbsoluteUrl)(url);
+
+    if (absoluteUrl) {
+      return absoluteUrl.href;
+    }
+
+    (0, _util.warn)(`Invalid absolute docBaseUrl: "${url}".`);
+  }
+
+  return null;
+}
+
 class BasePdfManager {
 class BasePdfManager {
   constructor() {
   constructor() {
     if (this.constructor === BasePdfManager) {
     if (this.constructor === BasePdfManager) {
@@ -52,19 +66,7 @@ class BasePdfManager {
   }
   }
 
 
   get docBaseUrl() {
   get docBaseUrl() {
-    let docBaseUrl = null;
-
-    if (this._docBaseUrl) {
-      const absoluteUrl = (0, _util.createValidAbsoluteUrl)(this._docBaseUrl);
-
-      if (absoluteUrl) {
-        docBaseUrl = absoluteUrl.href;
-      } else {
-        (0, _util.warn)(`Invalid absolute docBaseUrl: "${this._docBaseUrl}".`);
-      }
-    }
-
-    return (0, _util.shadow)(this, "docBaseUrl", docBaseUrl);
+    return this._docBaseUrl;
   }
   }
 
 
   onLoadedStream() {
   onLoadedStream() {
@@ -122,12 +124,13 @@ class BasePdfManager {
 }
 }
 
 
 class LocalPdfManager extends BasePdfManager {
 class LocalPdfManager extends BasePdfManager {
-  constructor(docId, data, password, evaluatorOptions, docBaseUrl) {
+  constructor(docId, data, password, evaluatorOptions, enableXfa, docBaseUrl) {
     super();
     super();
     this._docId = docId;
     this._docId = docId;
     this._password = password;
     this._password = password;
-    this._docBaseUrl = docBaseUrl;
+    this._docBaseUrl = parseDocBaseUrl(docBaseUrl);
     this.evaluatorOptions = evaluatorOptions;
     this.evaluatorOptions = evaluatorOptions;
+    this.enableXfa = enableXfa;
     const stream = new _stream.Stream(data);
     const stream = new _stream.Stream(data);
     this.pdfDocument = new _document.PDFDocument(this, stream);
     this.pdfDocument = new _document.PDFDocument(this, stream);
     this._loadedStreamPromise = Promise.resolve(stream);
     this._loadedStreamPromise = Promise.resolve(stream);
@@ -160,13 +163,14 @@ class LocalPdfManager extends BasePdfManager {
 exports.LocalPdfManager = LocalPdfManager;
 exports.LocalPdfManager = LocalPdfManager;
 
 
 class NetworkPdfManager extends BasePdfManager {
 class NetworkPdfManager extends BasePdfManager {
-  constructor(docId, pdfNetworkStream, args, evaluatorOptions, docBaseUrl) {
+  constructor(docId, pdfNetworkStream, args, evaluatorOptions, enableXfa, docBaseUrl) {
     super();
     super();
     this._docId = docId;
     this._docId = docId;
     this._password = args.password;
     this._password = args.password;
-    this._docBaseUrl = docBaseUrl;
+    this._docBaseUrl = parseDocBaseUrl(docBaseUrl);
     this.msgHandler = args.msgHandler;
     this.msgHandler = args.msgHandler;
     this.evaluatorOptions = evaluatorOptions;
     this.evaluatorOptions = evaluatorOptions;
+    this.enableXfa = enableXfa;
     this.streamManager = new _chunked_stream.ChunkedStreamManager(pdfNetworkStream, {
     this.streamManager = new _chunked_stream.ChunkedStreamManager(pdfNetworkStream, {
       msgHandler: args.msgHandler,
       msgHandler: args.msgHandler,
       length: args.length,
       length: args.length,

+ 10 - 10
lib/core/primitives.js

@@ -2,7 +2,7 @@
  * @licstart The following is the entire license notice for the
  * @licstart The following is the entire license notice for the
  * Javascript code in this page
  * Javascript code in this page
  *
  *
- * Copyright 2020 Mozilla Foundation
+ * Copyright 2021 Mozilla Foundation
  *
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * you may not use this file except in compliance with the License.
@@ -36,10 +36,10 @@ exports.RefSetCache = exports.RefSet = exports.Ref = exports.Name = exports.EOF
 
 
 var _util = require("../shared/util.js");
 var _util = require("../shared/util.js");
 
 
-var EOF = {};
+const EOF = {};
 exports.EOF = EOF;
 exports.EOF = EOF;
 
 
-var Name = function NameClosure() {
+const Name = function NameClosure() {
   let nameCache = Object.create(null);
   let nameCache = Object.create(null);
 
 
   function Name(name) {
   function Name(name) {
@@ -49,7 +49,7 @@ var Name = function NameClosure() {
   Name.prototype = {};
   Name.prototype = {};
 
 
   Name.get = function Name_get(name) {
   Name.get = function Name_get(name) {
-    var nameValue = nameCache[name];
+    const nameValue = nameCache[name];
     return nameValue ? nameValue : nameCache[name] = new Name(name);
     return nameValue ? nameValue : nameCache[name] = new Name(name);
   };
   };
 
 
@@ -62,7 +62,7 @@ var Name = function NameClosure() {
 
 
 exports.Name = Name;
 exports.Name = Name;
 
 
-var Cmd = function CmdClosure() {
+const Cmd = function CmdClosure() {
   let cmdCache = Object.create(null);
   let cmdCache = Object.create(null);
 
 
   function Cmd(cmd) {
   function Cmd(cmd) {
@@ -72,7 +72,7 @@ var Cmd = function CmdClosure() {
   Cmd.prototype = {};
   Cmd.prototype = {};
 
 
   Cmd.get = function Cmd_get(cmd) {
   Cmd.get = function Cmd_get(cmd) {
-    var cmdValue = cmdCache[cmd];
+    const cmdValue = cmdCache[cmd];
     return cmdValue ? cmdValue : cmdCache[cmd] = new Cmd(cmd);
     return cmdValue ? cmdValue : cmdCache[cmd] = new Cmd(cmd);
   };
   };
 
 
@@ -85,8 +85,8 @@ var Cmd = function CmdClosure() {
 
 
 exports.Cmd = Cmd;
 exports.Cmd = Cmd;
 
 
-var Dict = function DictClosure() {
-  var nonSerializable = function nonSerializableClosure() {
+const Dict = function DictClosure() {
+  const nonSerializable = function nonSerializableClosure() {
     return nonSerializable;
     return nonSerializable;
   };
   };
 
 
@@ -179,7 +179,7 @@ var Dict = function DictClosure() {
       return this._map[key] !== undefined;
       return this._map[key] !== undefined;
     },
     },
     forEach: function Dict_forEach(callback) {
     forEach: function Dict_forEach(callback) {
-      for (var key in this._map) {
+      for (const key in this._map) {
         callback(key, this.get(key));
         callback(key, this.get(key));
       }
       }
     }
     }
@@ -271,7 +271,7 @@ var Dict = function DictClosure() {
 
 
 exports.Dict = Dict;
 exports.Dict = Dict;
 
 
-var Ref = function RefClosure() {
+const Ref = function RefClosure() {
   let refCache = Object.create(null);
   let refCache = Object.create(null);
 
 
   function Ref(num, gen) {
   function Ref(num, gen) {

+ 1 - 1
lib/core/ps_parser.js

@@ -2,7 +2,7 @@
  * @licstart The following is the entire license notice for the
  * @licstart The following is the entire license notice for the
  * Javascript code in this page
  * Javascript code in this page
  *
  *
- * Copyright 2020 Mozilla Foundation
+ * Copyright 2021 Mozilla Foundation
  *
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * you may not use this file except in compliance with the License.

+ 1 - 1
lib/core/standard_fonts.js

@@ -2,7 +2,7 @@
  * @licstart The following is the entire license notice for the
  * @licstart The following is the entire license notice for the
  * Javascript code in this page
  * Javascript code in this page
  *
  *
- * Copyright 2020 Mozilla Foundation
+ * Copyright 2021 Mozilla Foundation
  *
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * you may not use this file except in compliance with the License.

+ 10 - 4
lib/core/stream.js

@@ -2,7 +2,7 @@
  * @licstart The following is the entire license notice for the
  * @licstart The following is the entire license notice for the
  * Javascript code in this page
  * Javascript code in this page
  *
  *
- * Copyright 2020 Mozilla Foundation
+ * Copyright 2021 Mozilla Foundation
  *
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * you may not use this file except in compliance with the License.
@@ -284,10 +284,16 @@ var DecodeStream = function DecodeStreamClosure() {
     },
     },
 
 
     makeSubStream: function DecodeStream_makeSubStream(start, length, dict) {
     makeSubStream: function DecodeStream_makeSubStream(start, length, dict) {
-      var end = start + length;
+      if (length === undefined) {
+        while (!this.eof) {
+          this.readBlock();
+        }
+      } else {
+        var end = start + length;
 
 
-      while (this.bufferLength <= end && !this.eof) {
-        this.readBlock();
+        while (this.bufferLength <= end && !this.eof) {
+          this.readBlock();
+        }
       }
       }
 
 
       return new Stream(this.buffer, start, length, dict);
       return new Stream(this.buffer, start, length, dict);

+ 119 - 108
lib/core/type1_parser.js

@@ -2,7 +2,7 @@
  * @licstart The following is the entire license notice for the
  * @licstart The following is the entire license notice for the
  * Javascript code in this page
  * Javascript code in this page
  *
  *
- * Copyright 2020 Mozilla Foundation
+ * Copyright 2021 Mozilla Foundation
  *
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * you may not use this file except in compliance with the License.
@@ -34,10 +34,10 @@ var _stream = require("./stream.js");
 
 
 var _util = require("../shared/util.js");
 var _util = require("../shared/util.js");
 
 
-var HINTING_ENABLED = false;
+const HINTING_ENABLED = false;
 
 
-var Type1CharString = function Type1CharStringClosure() {
-  var COMMAND_MAP = {
+const Type1CharString = function Type1CharStringClosure() {
+  const COMMAND_MAP = {
     hstem: [1],
     hstem: [1],
     vstem: [3],
     vstem: [3],
     vmoveto: [4],
     vmoveto: [4],
@@ -55,22 +55,22 @@ var Type1CharString = function Type1CharStringClosure() {
     hvcurveto: [31]
     hvcurveto: [31]
   };
   };
 
 
-  function Type1CharString() {
-    this.width = 0;
-    this.lsb = 0;
-    this.flexing = false;
-    this.output = [];
-    this.stack = [];
-  }
+  class Type1CharString {
+    constructor() {
+      this.width = 0;
+      this.lsb = 0;
+      this.flexing = false;
+      this.output = [];
+      this.stack = [];
+    }
 
 
-  Type1CharString.prototype = {
-    convert: function Type1CharString_convert(encoded, subrs, seacAnalysisEnabled) {
-      var count = encoded.length;
-      var error = false;
-      var wx, sbx, subrNumber;
+    convert(encoded, subrs, seacAnalysisEnabled) {
+      const count = encoded.length;
+      let error = false;
+      let wx, sbx, subrNumber;
 
 
-      for (var i = 0; i < count; i++) {
-        var value = encoded[i];
+      for (let i = 0; i < count; i++) {
+        let value = encoded[i];
 
 
         if (value < 32) {
         if (value < 32) {
           if (value === 12) {
           if (value === 12) {
@@ -103,7 +103,7 @@ var Type1CharString = function Type1CharStringClosure() {
                   break;
                   break;
                 }
                 }
 
 
-                var dy = this.stack.pop();
+                const dy = this.stack.pop();
                 this.stack.push(0, dy);
                 this.stack.push(0, dy);
                 break;
                 break;
               }
               }
@@ -235,7 +235,7 @@ var Type1CharString = function Type1CharStringClosure() {
 
 
               this.stack.pop();
               this.stack.pop();
               wx = this.stack.pop();
               wx = this.stack.pop();
-              var sby = this.stack.pop();
+              const sby = this.stack.pop();
               sbx = this.stack.pop();
               sbx = this.stack.pop();
               this.lsb = sbx;
               this.lsb = sbx;
               this.width = wx;
               this.width = wx;
@@ -249,8 +249,8 @@ var Type1CharString = function Type1CharStringClosure() {
                 break;
                 break;
               }
               }
 
 
-              var num2 = this.stack.pop();
-              var num1 = this.stack.pop();
+              const num2 = this.stack.pop();
+              const num1 = this.stack.pop();
               this.stack.push(num1 / num2);
               this.stack.push(num1 / num2);
               break;
               break;
 
 
@@ -261,10 +261,10 @@ var Type1CharString = function Type1CharStringClosure() {
               }
               }
 
 
               subrNumber = this.stack.pop();
               subrNumber = this.stack.pop();
-              var numArgs = this.stack.pop();
+              const numArgs = this.stack.pop();
 
 
               if (subrNumber === 0 && numArgs === 3) {
               if (subrNumber === 0 && numArgs === 3) {
-                var flexArgs = this.stack.splice(this.stack.length - 17, 17);
+                const flexArgs = this.stack.splice(this.stack.length - 17, 17);
                 this.stack.push(flexArgs[2] + flexArgs[0], flexArgs[3] + flexArgs[1], flexArgs[4], flexArgs[5], flexArgs[6], flexArgs[7], flexArgs[8], flexArgs[9], flexArgs[10], flexArgs[11], flexArgs[12], flexArgs[13], flexArgs[14]);
                 this.stack.push(flexArgs[2] + flexArgs[0], flexArgs[3] + flexArgs[1], flexArgs[4], flexArgs[5], flexArgs[6], flexArgs[7], flexArgs[8], flexArgs[9], flexArgs[10], flexArgs[11], flexArgs[12], flexArgs[13], flexArgs[14]);
                 error = this.executeCommand(13, COMMAND_MAP.flex, true);
                 error = this.executeCommand(13, COMMAND_MAP.flex, true);
                 this.flexing = false;
                 this.flexing = false;
@@ -306,19 +306,19 @@ var Type1CharString = function Type1CharStringClosure() {
       }
       }
 
 
       return error;
       return error;
-    },
+    }
 
 
     executeCommand(howManyArgs, command, keepStack) {
     executeCommand(howManyArgs, command, keepStack) {
-      var stackLength = this.stack.length;
+      const stackLength = this.stack.length;
 
 
       if (howManyArgs > stackLength) {
       if (howManyArgs > stackLength) {
         return true;
         return true;
       }
       }
 
 
-      var start = stackLength - howManyArgs;
+      const start = stackLength - howManyArgs;
 
 
-      for (var i = start; i < stackLength; i++) {
-        var value = this.stack[i];
+      for (let i = start; i < stackLength; i++) {
+        let value = this.stack[i];
 
 
         if (Number.isInteger(value)) {
         if (Number.isInteger(value)) {
           this.output.push(28, value >> 8 & 0xff, value & 0xff);
           this.output.push(28, value >> 8 & 0xff, value & 0xff);
@@ -339,13 +339,14 @@ var Type1CharString = function Type1CharStringClosure() {
       return false;
       return false;
     }
     }
 
 
-  };
+  }
+
   return Type1CharString;
   return Type1CharString;
 }();
 }();
 
 
-var Type1Parser = function Type1ParserClosure() {
-  var EEXEC_ENCRYPT_KEY = 55665;
-  var CHAR_STRS_ENCRYPT_KEY = 4330;
+const Type1Parser = function Type1ParserClosure() {
+  const EEXEC_ENCRYPT_KEY = 55665;
+  const CHAR_STRS_ENCRYPT_KEY = 4330;
 
 
   function isHexDigit(code) {
   function isHexDigit(code) {
     return code >= 48 && code <= 57 || code >= 65 && code <= 70 || code >= 97 && code <= 102;
     return code >= 48 && code <= 57 || code >= 65 && code <= 70 || code >= 97 && code <= 102;
@@ -356,9 +357,9 @@ var Type1Parser = function Type1ParserClosure() {
       return new Uint8Array(0);
       return new Uint8Array(0);
     }
     }
 
 
-    var r = key | 0,
-        c1 = 52845,
-        c2 = 22719,
+    const c1 = 52845,
+          c2 = 22719;
+    let r = key | 0,
         i,
         i,
         j;
         j;
 
 
@@ -366,11 +367,11 @@ var Type1Parser = function Type1ParserClosure() {
       r = (data[i] + r) * c1 + c2 & (1 << 16) - 1;
       r = (data[i] + r) * c1 + c2 & (1 << 16) - 1;
     }
     }
 
 
-    var count = data.length - discardNumber;
-    var decrypted = new Uint8Array(count);
+    const count = data.length - discardNumber;
+    const decrypted = new Uint8Array(count);
 
 
     for (i = discardNumber, j = 0; j < count; i++, j++) {
     for (i = discardNumber, j = 0; j < count; i++, j++) {
-      var value = data[i];
+      const value = data[i];
       decrypted[j] = value ^ r >> 8;
       decrypted[j] = value ^ r >> 8;
       r = (value + r) * c1 + c2 & (1 << 16) - 1;
       r = (value + r) * c1 + c2 & (1 << 16) - 1;
     }
     }
@@ -379,30 +380,30 @@ var Type1Parser = function Type1ParserClosure() {
   }
   }
 
 
   function decryptAscii(data, key, discardNumber) {
   function decryptAscii(data, key, discardNumber) {
-    var r = key | 0,
-        c1 = 52845,
-        c2 = 22719;
-    var count = data.length,
-        maybeLength = count >>> 1;
-    var decrypted = new Uint8Array(maybeLength);
-    var i, j;
+    const c1 = 52845,
+          c2 = 22719;
+    let r = key | 0;
+    const count = data.length,
+          maybeLength = count >>> 1;
+    const decrypted = new Uint8Array(maybeLength);
+    let i, j;
 
 
     for (i = 0, j = 0; i < count; i++) {
     for (i = 0, j = 0; i < count; i++) {
-      var digit1 = data[i];
+      const digit1 = data[i];
 
 
       if (!isHexDigit(digit1)) {
       if (!isHexDigit(digit1)) {
         continue;
         continue;
       }
       }
 
 
       i++;
       i++;
-      var digit2;
+      let digit2;
 
 
       while (i < count && !isHexDigit(digit2 = data[i])) {
       while (i < count && !isHexDigit(digit2 = data[i])) {
         i++;
         i++;
       }
       }
 
 
       if (i < count) {
       if (i < count) {
-        var value = parseInt(String.fromCharCode(digit1, digit2), 16);
+        const value = parseInt(String.fromCharCode(digit1, digit2), 16);
         decrypted[j++] = value ^ r >> 8;
         decrypted[j++] = value ^ r >> 8;
         r = (value + r) * c1 + c2 & (1 << 16) - 1;
         r = (value + r) * c1 + c2 & (1 << 16) - 1;
       }
       }
@@ -415,25 +416,25 @@ var Type1Parser = function Type1ParserClosure() {
     return c === 0x2f || c === 0x5b || c === 0x5d || c === 0x7b || c === 0x7d || c === 0x28 || c === 0x29;
     return c === 0x2f || c === 0x5b || c === 0x5d || c === 0x7b || c === 0x7d || c === 0x28 || c === 0x29;
   }
   }
 
 
-  function Type1Parser(stream, encrypted, seacAnalysisEnabled) {
-    if (encrypted) {
-      var data = stream.getBytes();
-      var isBinary = !((isHexDigit(data[0]) || (0, _core_utils.isWhiteSpace)(data[0])) && isHexDigit(data[1]) && isHexDigit(data[2]) && isHexDigit(data[3]) && isHexDigit(data[4]) && isHexDigit(data[5]) && isHexDigit(data[6]) && isHexDigit(data[7]));
-      stream = new _stream.Stream(isBinary ? decrypt(data, EEXEC_ENCRYPT_KEY, 4) : decryptAscii(data, EEXEC_ENCRYPT_KEY, 4));
-    }
+  class Type1Parser {
+    constructor(stream, encrypted, seacAnalysisEnabled) {
+      if (encrypted) {
+        const data = stream.getBytes();
+        const isBinary = !((isHexDigit(data[0]) || (0, _core_utils.isWhiteSpace)(data[0])) && isHexDigit(data[1]) && isHexDigit(data[2]) && isHexDigit(data[3]) && isHexDigit(data[4]) && isHexDigit(data[5]) && isHexDigit(data[6]) && isHexDigit(data[7]));
+        stream = new _stream.Stream(isBinary ? decrypt(data, EEXEC_ENCRYPT_KEY, 4) : decryptAscii(data, EEXEC_ENCRYPT_KEY, 4));
+      }
 
 
-    this.seacAnalysisEnabled = !!seacAnalysisEnabled;
-    this.stream = stream;
-    this.nextChar();
-  }
+      this.seacAnalysisEnabled = !!seacAnalysisEnabled;
+      this.stream = stream;
+      this.nextChar();
+    }
 
 
-  Type1Parser.prototype = {
-    readNumberArray: function Type1Parser_readNumberArray() {
+    readNumberArray() {
       this.getToken();
       this.getToken();
-      var array = [];
+      const array = [];
 
 
       while (true) {
       while (true) {
-        var token = this.getToken();
+        const token = this.getToken();
 
 
         if (token === null || token === "]" || token === "}") {
         if (token === null || token === "]" || token === "}") {
           break;
           break;
@@ -443,25 +444,30 @@ var Type1Parser = function Type1ParserClosure() {
       }
       }
 
 
       return array;
       return array;
-    },
-    readNumber: function Type1Parser_readNumber() {
-      var token = this.getToken();
+    }
+
+    readNumber() {
+      const token = this.getToken();
       return parseFloat(token || 0);
       return parseFloat(token || 0);
-    },
-    readInt: function Type1Parser_readInt() {
-      var token = this.getToken();
+    }
+
+    readInt() {
+      const token = this.getToken();
       return parseInt(token || 0, 10) | 0;
       return parseInt(token || 0, 10) | 0;
-    },
-    readBoolean: function Type1Parser_readBoolean() {
-      var token = this.getToken();
+    }
+
+    readBoolean() {
+      const token = this.getToken();
       return token === "true" ? 1 : 0;
       return token === "true" ? 1 : 0;
-    },
-    nextChar: function Type1_nextChar() {
+    }
+
+    nextChar() {
       return this.currentChar = this.stream.getByte();
       return this.currentChar = this.stream.getByte();
-    },
-    getToken: function Type1Parser_getToken() {
-      var comment = false;
-      var ch = this.currentChar;
+    }
+
+    getToken() {
+      let comment = false;
+      let ch = this.currentChar;
 
 
       while (true) {
       while (true) {
         if (ch === -1) {
         if (ch === -1) {
@@ -486,7 +492,7 @@ var Type1Parser = function Type1ParserClosure() {
         return String.fromCharCode(ch);
         return String.fromCharCode(ch);
       }
       }
 
 
-      var token = "";
+      let token = "";
 
 
       do {
       do {
         token += String.fromCharCode(ch);
         token += String.fromCharCode(ch);
@@ -494,28 +500,30 @@ var Type1Parser = function Type1ParserClosure() {
       } while (ch >= 0 && !(0, _core_utils.isWhiteSpace)(ch) && !isSpecial(ch));
       } while (ch >= 0 && !(0, _core_utils.isWhiteSpace)(ch) && !isSpecial(ch));
 
 
       return token;
       return token;
-    },
-    readCharStrings: function Type1Parser_readCharStrings(bytes, lenIV) {
+    }
+
+    readCharStrings(bytes, lenIV) {
       if (lenIV === -1) {
       if (lenIV === -1) {
         return bytes;
         return bytes;
       }
       }
 
 
       return decrypt(bytes, CHAR_STRS_ENCRYPT_KEY, lenIV);
       return decrypt(bytes, CHAR_STRS_ENCRYPT_KEY, lenIV);
-    },
-    extractFontProgram: function Type1Parser_extractFontProgram(properties) {
-      var stream = this.stream;
-      var subrs = [],
-          charstrings = [];
-      var privateData = Object.create(null);
+    }
+
+    extractFontProgram(properties) {
+      const stream = this.stream;
+      const subrs = [],
+            charstrings = [];
+      const privateData = Object.create(null);
       privateData.lenIV = 4;
       privateData.lenIV = 4;
-      var program = {
+      const program = {
         subrs: [],
         subrs: [],
         charstrings: [],
         charstrings: [],
         properties: {
         properties: {
           privateData
           privateData
         }
         }
       };
       };
-      var token, length, data, lenIV, encoded;
+      let token, length, data, lenIV, encoded;
 
 
       while ((token = this.getToken()) !== null) {
       while ((token = this.getToken()) !== null) {
         if (token !== "/") {
         if (token !== "/") {
@@ -542,7 +550,7 @@ var Type1Parser = function Type1ParserClosure() {
                 continue;
                 continue;
               }
               }
 
 
-              var glyph = this.getToken();
+              const glyph = this.getToken();
               length = this.readInt();
               length = this.readInt();
               this.getToken();
               this.getToken();
               data = length > 0 ? stream.getBytes(length) : new Uint8Array(0);
               data = length > 0 ? stream.getBytes(length) : new Uint8Array(0);
@@ -590,7 +598,7 @@ var Type1Parser = function Type1ParserClosure() {
           case "OtherBlues":
           case "OtherBlues":
           case "FamilyBlues":
           case "FamilyBlues":
           case "FamilyOtherBlues":
           case "FamilyOtherBlues":
-            var blueArray = this.readNumberArray();
+            const blueArray = this.readNumberArray();
 
 
             if (blueArray.length > 0 && blueArray.length % 2 === 0 && HINTING_ENABLED) {
             if (blueArray.length > 0 && blueArray.length % 2 === 0 && HINTING_ENABLED) {
               program.properties.privateData[token] = blueArray;
               program.properties.privateData[token] = blueArray;
@@ -623,12 +631,12 @@ var Type1Parser = function Type1ParserClosure() {
         }
         }
       }
       }
 
 
-      for (var i = 0; i < charstrings.length; i++) {
-        glyph = charstrings[i].glyph;
+      for (let i = 0; i < charstrings.length; i++) {
+        const glyph = charstrings[i].glyph;
         encoded = charstrings[i].encoded;
         encoded = charstrings[i].encoded;
-        var charString = new Type1CharString();
-        var error = charString.convert(encoded, subrs, this.seacAnalysisEnabled);
-        var output = charString.output;
+        const charString = new Type1CharString();
+        const error = charString.convert(encoded, subrs, this.seacAnalysisEnabled);
+        let output = charString.output;
 
 
         if (error) {
         if (error) {
           output = [14];
           output = [14];
@@ -658,9 +666,10 @@ var Type1Parser = function Type1ParserClosure() {
       }
       }
 
 
       return program;
       return program;
-    },
-    extractFontHeader: function Type1Parser_extractFontHeader(properties) {
-      var token;
+    }
+
+    extractFontHeader(properties) {
+      let token;
 
 
       while ((token = this.getToken()) !== null) {
       while ((token = this.getToken()) !== null) {
         if (token !== "/") {
         if (token !== "/") {
@@ -671,22 +680,22 @@ var Type1Parser = function Type1ParserClosure() {
 
 
         switch (token) {
         switch (token) {
           case "FontMatrix":
           case "FontMatrix":
-            var matrix = this.readNumberArray();
+            const matrix = this.readNumberArray();
             properties.fontMatrix = matrix;
             properties.fontMatrix = matrix;
             break;
             break;
 
 
           case "Encoding":
           case "Encoding":
-            var encodingArg = this.getToken();
-            var encoding;
+            const encodingArg = this.getToken();
+            let encoding;
 
 
             if (!/^\d+$/.test(encodingArg)) {
             if (!/^\d+$/.test(encodingArg)) {
               encoding = (0, _encodings.getEncoding)(encodingArg);
               encoding = (0, _encodings.getEncoding)(encodingArg);
             } else {
             } else {
               encoding = [];
               encoding = [];
-              var size = parseInt(encodingArg, 10) | 0;
+              const size = parseInt(encodingArg, 10) | 0;
               this.getToken();
               this.getToken();
 
 
-              for (var j = 0; j < size; j++) {
+              for (let j = 0; j < size; j++) {
                 token = this.getToken();
                 token = this.getToken();
 
 
                 while (token !== "dup" && token !== "def") {
                 while (token !== "dup" && token !== "def") {
@@ -701,9 +710,9 @@ var Type1Parser = function Type1ParserClosure() {
                   break;
                   break;
                 }
                 }
 
 
-                var index = this.readInt();
+                const index = this.readInt();
                 this.getToken();
                 this.getToken();
-                var glyph = this.getToken();
+                const glyph = this.getToken();
                 encoding[index] = glyph;
                 encoding[index] = glyph;
                 this.getToken();
                 this.getToken();
               }
               }
@@ -713,7 +722,7 @@ var Type1Parser = function Type1ParserClosure() {
             break;
             break;
 
 
           case "FontBBox":
           case "FontBBox":
-            var fontBBox = this.readNumberArray();
+            const fontBBox = this.readNumberArray();
             properties.ascent = Math.max(fontBBox[3], fontBBox[1]);
             properties.ascent = Math.max(fontBBox[3], fontBBox[1]);
             properties.descent = Math.min(fontBBox[1], fontBBox[3]);
             properties.descent = Math.min(fontBBox[1], fontBBox[3]);
             properties.ascentScaled = true;
             properties.ascentScaled = true;
@@ -721,7 +730,9 @@ var Type1Parser = function Type1ParserClosure() {
         }
         }
       }
       }
     }
     }
-  };
+
+  }
+
   return Type1Parser;
   return Type1Parser;
 }();
 }();
 
 

File diff suppressed because it is too large
+ 10 - 10
lib/core/unicode.js


+ 21 - 10
lib/core/worker.js

@@ -2,7 +2,7 @@
  * @licstart The following is the entire license notice for the
  * @licstart The following is the entire license notice for the
  * Javascript code in this page
  * Javascript code in this page
  *
  *
- * Copyright 2020 Mozilla Foundation
+ * Copyright 2021 Mozilla Foundation
  *
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * you may not use this file except in compliance with the License.
@@ -107,7 +107,7 @@ class WorkerMessageHandler {
     var WorkerTasks = [];
     var WorkerTasks = [];
     const verbosity = (0, _util.getVerbosityLevel)();
     const verbosity = (0, _util.getVerbosityLevel)();
     const apiVersion = docParams.apiVersion;
     const apiVersion = docParams.apiVersion;
-    const workerVersion = '2.7.570';
+    const workerVersion = '2.8.335';
 
 
     if (apiVersion !== workerVersion) {
     if (apiVersion !== workerVersion) {
       throw new Error(`The API version "${apiVersion}" does not match ` + `the Worker version "${workerVersion}".`);
       throw new Error(`The API version "${apiVersion}" does not match ` + `the Worker version "${workerVersion}".`);
@@ -124,7 +124,7 @@ class WorkerMessageHandler {
     }
     }
 
 
     if (typeof ReadableStream === "undefined") {
     if (typeof ReadableStream === "undefined") {
-      throw new Error("The browser/environment lacks native support for critical " + "functionality used by the PDF.js library (e.g. `ReadableStream`); " + "please use an `es5`-build instead.");
+      throw new Error("The browser/environment lacks native support for critical " + "functionality used by the PDF.js library (e.g. `ReadableStream`); " + "please use a `legacy`-build instead.");
     }
     }
 
 
     var docId = docParams.docId;
     var docId = docParams.docId;
@@ -158,21 +158,22 @@ class WorkerMessageHandler {
         await pdfManager.ensureDoc("checkFirstPage");
         await pdfManager.ensureDoc("checkFirstPage");
       }
       }
 
 
-      const [numPages, fingerprint] = await Promise.all([pdfManager.ensureDoc("numPages"), pdfManager.ensureDoc("fingerprint")]);
+      const [numPages, fingerprint, isPureXfa] = await Promise.all([pdfManager.ensureDoc("numPages"), pdfManager.ensureDoc("fingerprint"), pdfManager.ensureDoc("isPureXfa")]);
       return {
       return {
         numPages,
         numPages,
-        fingerprint
+        fingerprint,
+        isPureXfa
       };
       };
     }
     }
 
 
-    function getPdfManager(data, evaluatorOptions) {
+    function getPdfManager(data, evaluatorOptions, enableXfa) {
       var pdfManagerCapability = (0, _util.createPromiseCapability)();
       var pdfManagerCapability = (0, _util.createPromiseCapability)();
       let newPdfManager;
       let newPdfManager;
       var source = data.source;
       var source = data.source;
 
 
       if (source.data) {
       if (source.data) {
         try {
         try {
-          newPdfManager = new _pdf_manager.LocalPdfManager(docId, source.data, source.password, evaluatorOptions, docBaseUrl);
+          newPdfManager = new _pdf_manager.LocalPdfManager(docId, source.data, source.password, evaluatorOptions, enableXfa, docBaseUrl);
           pdfManagerCapability.resolve(newPdfManager);
           pdfManagerCapability.resolve(newPdfManager);
         } catch (ex) {
         } catch (ex) {
           pdfManagerCapability.reject(ex);
           pdfManagerCapability.reject(ex);
@@ -204,7 +205,7 @@ class WorkerMessageHandler {
           length: fullRequest.contentLength,
           length: fullRequest.contentLength,
           disableAutoFetch,
           disableAutoFetch,
           rangeChunkSize: source.rangeChunkSize
           rangeChunkSize: source.rangeChunkSize
-        }, evaluatorOptions, docBaseUrl);
+        }, evaluatorOptions, enableXfa, docBaseUrl);
 
 
         for (let i = 0; i < cachedChunks.length; i++) {
         for (let i = 0; i < cachedChunks.length; i++) {
           newPdfManager.sendProgressiveData(cachedChunks[i]);
           newPdfManager.sendProgressiveData(cachedChunks[i]);
@@ -227,7 +228,7 @@ class WorkerMessageHandler {
         }
         }
 
 
         try {
         try {
-          newPdfManager = new _pdf_manager.LocalPdfManager(docId, pdfFile, source.password, evaluatorOptions, docBaseUrl);
+          newPdfManager = new _pdf_manager.LocalPdfManager(docId, pdfFile, source.password, evaluatorOptions, enableXfa, docBaseUrl);
           pdfManagerCapability.resolve(newPdfManager);
           pdfManagerCapability.resolve(newPdfManager);
         } catch (ex) {
         } catch (ex) {
           pdfManagerCapability.reject(ex);
           pdfManagerCapability.reject(ex);
@@ -345,7 +346,7 @@ class WorkerMessageHandler {
         isEvalSupported: data.isEvalSupported,
         isEvalSupported: data.isEvalSupported,
         fontExtraProperties: data.fontExtraProperties
         fontExtraProperties: data.fontExtraProperties
       };
       };
-      getPdfManager(data, evaluatorOptions).then(function (newPdfManager) {
+      getPdfManager(data, evaluatorOptions, data.enableXfa).then(function (newPdfManager) {
         if (terminated) {
         if (terminated) {
           newPdfManager.terminate(new _util.AbortException("Worker was terminated."));
           newPdfManager.terminate(new _util.AbortException("Worker was terminated."));
           throw new Error("Worker was terminated");
           throw new Error("Worker was terminated");
@@ -416,6 +417,16 @@ class WorkerMessageHandler {
         return page.jsActions;
         return page.jsActions;
       });
       });
     });
     });
+    handler.on("GetPageXfa", function wphSetupGetXfa({
+      pageIndex
+    }) {
+      return pdfManager.getPage(pageIndex).then(function (page) {
+        return pdfManager.ensure(page, "xfaData");
+      });
+    });
+    handler.on("GetIsPureXfa", function wphSetupGetIsPureXfa(data) {
+      return pdfManager.ensureDoc("isPureXfa");
+    });
     handler.on("GetOutline", function wphSetupGetOutline(data) {
     handler.on("GetOutline", function wphSetupGetOutline(data) {
       return pdfManager.ensureCatalog("documentOutline");
       return pdfManager.ensureCatalog("documentOutline");
     });
     });

+ 1 - 1
lib/core/worker_stream.js

@@ -2,7 +2,7 @@
  * @licstart The following is the entire license notice for the
  * @licstart The following is the entire license notice for the
  * Javascript code in this page
  * Javascript code in this page
  *
  *
- * Copyright 2020 Mozilla Foundation
+ * Copyright 2021 Mozilla Foundation
  *
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * you may not use this file except in compliance with the License.

+ 2 - 2
lib/core/writer.js

@@ -2,7 +2,7 @@
  * @licstart The following is the entire license notice for the
  * @licstart The following is the entire license notice for the
  * Javascript code in this page
  * Javascript code in this page
  *
  *
- * Copyright 2020 Mozilla Foundation
+ * Copyright 2021 Mozilla Foundation
  *
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * you may not use this file except in compliance with the License.
@@ -33,7 +33,7 @@ var _primitives = require("./primitives.js");
 
 
 var _core_utils = require("./core_utils.js");
 var _core_utils = require("./core_utils.js");
 
 
-var _xml_parser = require("../shared/xml_parser.js");
+var _xml_parser = require("./xml_parser.js");
 
 
 var _crypto = require("./crypto.js");
 var _crypto = require("./crypto.js");
 
 

+ 535 - 0
lib/core/xfa/bind.js

@@ -0,0 +1,535 @@
+/**
+ * @licstart The following is the entire license notice for the
+ * Javascript code in this page
+ *
+ * Copyright 2021 Mozilla Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * @licend The above is the entire license notice for the
+ * Javascript code in this page
+ */
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.Binder = void 0;
+
+var _xfa_object = require("./xfa_object.js");
+
+var _template = require("./template.js");
+
+var _som = require("./som.js");
+
+var _namespaces = require("./namespaces.js");
+
+var _util = require("../../shared/util.js");
+
+function createText(content) {
+  const node = new _template.Text({});
+  node[_xfa_object.$content] = content;
+  return node;
+}
+
+class Binder {
+  constructor(root) {
+    this.root = root;
+    this.datasets = root.datasets;
+
+    if (root.datasets && root.datasets.data) {
+      this.emptyMerge = false;
+      this.data = root.datasets.data;
+    } else {
+      this.emptyMerge = true;
+      this.data = new _xfa_object.XmlObject(_namespaces.NamespaceIds.datasets.id, "data");
+    }
+
+    this.root.form = this.form = root.template[_xfa_object.$clone]();
+  }
+
+  _isConsumeData() {
+    return !this.emptyMerge && this._mergeMode;
+  }
+
+  _isMatchTemplate() {
+    return !this._isConsumeData();
+  }
+
+  bind() {
+    this._bindElement(this.form, this.data);
+
+    return this.form;
+  }
+
+  getData() {
+    return this.data;
+  }
+
+  _bindValue(formNode, data, picture) {
+    if (formNode[_xfa_object.$hasSettableValue]()) {
+      if (data[_xfa_object.$isDataValue]()) {
+        const value = data[_xfa_object.$content].trim();
+
+        formNode[_xfa_object.$setValue](createText(value));
+
+        formNode[_xfa_object.$data] = data;
+      } else if (formNode instanceof _template.Field && formNode.ui && formNode.ui.choiceList && formNode.ui.choiceList.open === "multiSelect") {
+        const value = data[_xfa_object.$getChildren]().map(child => child[_xfa_object.$content].trim()).join("\n");
+
+        formNode[_xfa_object.$setValue](createText(value));
+
+        formNode[_xfa_object.$data] = data;
+      } else if (this._isConsumeData()) {
+        (0, _util.warn)(`XFA - Nodes haven't the same type.`);
+      }
+    } else if (!data[_xfa_object.$isDataValue]() || this._isMatchTemplate()) {
+      this._bindElement(formNode, data);
+
+      formNode[_xfa_object.$data] = data;
+    } else {
+      (0, _util.warn)(`XFA - Nodes haven't the same type.`);
+    }
+  }
+
+  _findDataByNameToConsume(name, dataNode, global) {
+    if (!name) {
+      return null;
+    }
+
+    let generator, match;
+
+    for (let i = 0; i < 3; i++) {
+      generator = dataNode[_xfa_object.$getRealChildrenByNameIt](name, false, true);
+      match = generator.next().value;
+
+      if (match) {
+        return match;
+      }
+
+      if (dataNode[_xfa_object.$namespaceId] === _namespaces.NamespaceIds.datasets.id && dataNode[_xfa_object.$nodeName] === "data") {
+        break;
+      }
+
+      dataNode = dataNode[_xfa_object.$getParent]();
+    }
+
+    if (!global) {
+      return null;
+    }
+
+    generator = this.datasets[_xfa_object.$getRealChildrenByNameIt](name, false, false);
+
+    while (true) {
+      match = generator.next().value;
+
+      if (!match) {
+        break;
+      }
+
+      if (match[_xfa_object.$global]) {
+        return match;
+      }
+    }
+
+    generator = this.data[_xfa_object.$getAttributeIt](name, true);
+    match = generator.next().value;
+
+    if (match && match[_xfa_object.$isDataValue]()) {
+      return match;
+    }
+
+    return null;
+  }
+
+  _setProperties(formNode, dataNode) {
+    if (!formNode.hasOwnProperty("setProperty")) {
+      return;
+    }
+
+    for (const {
+      ref,
+      target,
+      connection
+    } of formNode.setProperty.children) {
+      if (connection) {
+        continue;
+      }
+
+      if (!ref) {
+        continue;
+      }
+
+      const [node] = (0, _som.searchNode)(this.root, dataNode, ref, false, false);
+
+      if (!node) {
+        (0, _util.warn)(`XFA - Invalid reference: ${ref}.`);
+        continue;
+      }
+
+      if (!node[_xfa_object.$isDescendent](this.data)) {
+        (0, _util.warn)(`XFA - Invalid node: must be a data node.`);
+        continue;
+      }
+
+      const [targetNode] = (0, _som.searchNode)(this.root, formNode, target, false, false);
+
+      if (!targetNode) {
+        (0, _util.warn)(`XFA - Invalid target: ${target}.`);
+        continue;
+      }
+
+      if (!targetNode[_xfa_object.$isDescendent](formNode)) {
+        (0, _util.warn)(`XFA - Invalid target: must be a property or subproperty.`);
+        continue;
+      }
+
+      const targetParent = targetNode[_xfa_object.$getParent]();
+
+      if (targetNode instanceof _template.SetProperty || targetParent instanceof _template.SetProperty) {
+        (0, _util.warn)(`XFA - Invalid target: cannot be a setProperty or one of its properties.`);
+        continue;
+      }
+
+      if (targetNode instanceof _template.BindItems || targetParent instanceof _template.BindItems) {
+        (0, _util.warn)(`XFA - Invalid target: cannot be a bindItems or one of its properties.`);
+        continue;
+      }
+
+      const content = node[_xfa_object.$text]();
+
+      const name = targetNode[_xfa_object.$nodeName];
+
+      if (targetNode instanceof _xfa_object.XFAAttribute) {
+        const attrs = Object.create(null);
+        attrs[name] = content;
+        const obj = Reflect.construct(Object.getPrototypeOf(targetParent).constructor, [attrs]);
+        targetParent[name] = obj[name];
+        continue;
+      }
+
+      if (!targetNode.hasOwnProperty(_xfa_object.$content)) {
+        (0, _util.warn)(`XFA - Invalid node to use in setProperty`);
+        continue;
+      }
+
+      targetNode[_xfa_object.$data] = node;
+      targetNode[_xfa_object.$content] = content;
+
+      targetNode[_xfa_object.$finalize]();
+    }
+  }
+
+  _bindItems(formNode, dataNode) {
+    if (!formNode.hasOwnProperty("items") || !formNode.hasOwnProperty("bindItems") || formNode.bindItems.isEmpty()) {
+      return;
+    }
+
+    for (const item of formNode.items.children) {
+      formNode[_xfa_object.$removeChild](item);
+    }
+
+    formNode.items.clear();
+    const labels = new _template.Items({});
+    const values = new _template.Items({});
+
+    formNode[_xfa_object.$appendChild](labels);
+
+    formNode.items.push(labels);
+
+    formNode[_xfa_object.$appendChild](values);
+
+    formNode.items.push(values);
+
+    for (const {
+      ref,
+      labelRef,
+      valueRef,
+      connection
+    } of formNode.bindItems.children) {
+      if (connection) {
+        continue;
+      }
+
+      if (!ref) {
+        continue;
+      }
+
+      const nodes = (0, _som.searchNode)(this.root, dataNode, ref, false, false);
+
+      if (!nodes) {
+        (0, _util.warn)(`XFA - Invalid reference: ${ref}.`);
+        continue;
+      }
+
+      for (const node of nodes) {
+        if (!node[_xfa_object.$isDescendent](this.datasets)) {
+          (0, _util.warn)(`XFA - Invalid ref (${ref}): must be a datasets child.`);
+          continue;
+        }
+
+        const [labelNode] = (0, _som.searchNode)(this.root, node, labelRef, true, false);
+
+        if (!labelNode) {
+          (0, _util.warn)(`XFA - Invalid label: ${labelRef}.`);
+          continue;
+        }
+
+        if (!labelNode[_xfa_object.$isDescendent](this.datasets)) {
+          (0, _util.warn)(`XFA - Invalid label: must be a datasets child.`);
+          continue;
+        }
+
+        const [valueNode] = (0, _som.searchNode)(this.root, node, valueRef, true, false);
+
+        if (!valueNode) {
+          (0, _util.warn)(`XFA - Invalid value: ${valueRef}.`);
+          continue;
+        }
+
+        if (!valueNode[_xfa_object.$isDescendent](this.datasets)) {
+          (0, _util.warn)(`XFA - Invalid value: must be a datasets child.`);
+          continue;
+        }
+
+        const label = createText(labelNode[_xfa_object.$text]());
+        const value = createText(valueNode[_xfa_object.$text]());
+
+        labels[_xfa_object.$appendChild](label);
+
+        labels.text.push(label);
+
+        values[_xfa_object.$appendChild](value);
+
+        values.text.push(value);
+      }
+    }
+  }
+
+  _bindOccurrences(formNode, matches, picture) {
+    let baseClone;
+
+    if (matches.length > 1) {
+      baseClone = formNode[_xfa_object.$clone]();
+    }
+
+    this._bindValue(formNode, matches[0], picture);
+
+    this._setProperties(formNode, matches[0]);
+
+    this._bindItems(formNode, matches[0]);
+
+    if (matches.length === 1) {
+      return;
+    }
+
+    const parent = formNode[_xfa_object.$getParent]();
+
+    const name = formNode[_xfa_object.$nodeName];
+
+    const pos = parent[_xfa_object.$indexOf](formNode);
+
+    for (let i = 1, ii = matches.length; i < ii; i++) {
+      const match = matches[i];
+
+      const clone = baseClone[_xfa_object.$clone]();
+
+      clone.occur.min = 1;
+      clone.occur.max = 1;
+      clone.occur.initial = 1;
+      parent[name].push(clone);
+
+      parent[_xfa_object.$insertAt](pos + i, clone);
+
+      this._bindValue(clone, match, picture);
+
+      this._setProperties(clone, match);
+
+      this._bindItems(clone, match);
+    }
+  }
+
+  _createOccurrences(formNode) {
+    if (!this.emptyMerge) {
+      return;
+    }
+
+    const {
+      occur
+    } = formNode;
+
+    if (!occur || occur.initial <= 1) {
+      return;
+    }
+
+    const parent = formNode[_xfa_object.$getParent]();
+
+    const name = formNode[_xfa_object.$nodeName];
+
+    for (let i = 0, ii = occur.initial; i < ii; i++) {
+      const clone = formNode[_xfa_object.$clone]();
+
+      clone.occur.min = 1;
+      clone.occur.max = 1;
+      clone.occur.initial = 1;
+      parent[name].push(clone);
+
+      parent[_xfa_object.$appendChild](clone);
+    }
+  }
+
+  _getOccurInfo(formNode) {
+    const {
+      occur
+    } = formNode;
+    const dataName = formNode.name;
+
+    if (!occur || !dataName) {
+      return [1, 1];
+    }
+
+    const max = occur.max === -1 ? Infinity : occur.max;
+    return [occur.min, max];
+  }
+
+  _bindElement(formNode, dataNode) {
+    const uselessNodes = [];
+
+    this._createOccurrences(formNode);
+
+    for (const child of formNode[_xfa_object.$getChildren]()) {
+      if (child[_xfa_object.$data]) {
+        continue;
+      }
+
+      if (this._mergeMode === undefined && child[_xfa_object.$nodeName] === "subform") {
+        this._mergeMode = child.mergeMode === "consumeData";
+      }
+
+      let global = false;
+      let picture = null;
+      let ref = null;
+      let match = null;
+
+      if (child.bind) {
+        switch (child.bind.match) {
+          case "none":
+            continue;
+
+          case "global":
+            global = true;
+            break;
+
+          case "dataRef":
+            if (!child.bind.ref) {
+              (0, _util.warn)(`XFA - ref is empty in node ${child[_xfa_object.$nodeName]}.`);
+              continue;
+            }
+
+            ref = child.bind.ref;
+            break;
+
+          default:
+            break;
+        }
+
+        if (child.bind.picture) {
+          picture = child.bind.picture[_xfa_object.$content];
+        }
+      }
+
+      const [min, max] = this._getOccurInfo(child);
+
+      if (ref) {
+        match = (0, _som.searchNode)(this.root, dataNode, ref, true, false);
+
+        if (match === null) {
+          match = (0, _som.createDataNode)(this.data, dataNode, ref);
+
+          if (this._isConsumeData()) {
+            match[_xfa_object.$consumed] = true;
+          }
+
+          match = [match];
+        } else {
+          if (this._isConsumeData()) {
+            match = match.filter(node => !node[_xfa_object.$consumed]);
+          }
+
+          if (match.length > max) {
+            match = match.slice(0, max);
+          } else if (match.length === 0) {
+            match = null;
+          }
+
+          if (match && this._isConsumeData()) {
+            match.forEach(node => {
+              node[_xfa_object.$consumed] = true;
+            });
+          }
+        }
+      } else {
+        if (!child.name) {
+          this._bindElement(child, dataNode);
+
+          continue;
+        }
+
+        if (this._isConsumeData()) {
+          const matches = [];
+
+          while (matches.length < max) {
+            const found = this._findDataByNameToConsume(child.name, dataNode, global);
+
+            if (!found) {
+              break;
+            }
+
+            found[_xfa_object.$consumed] = true;
+            matches.push(found);
+          }
+
+          match = matches.length > 0 ? matches : null;
+        } else {
+          match = dataNode[_xfa_object.$getRealChildrenByNameIt](child.name, false, false).next().value;
+
+          if (!match) {
+            match = new _xfa_object.XmlObject(dataNode[_xfa_object.$namespaceId], child.name);
+
+            dataNode[_xfa_object.$appendChild](match);
+          }
+
+          match = [match];
+        }
+      }
+
+      if (match) {
+        if (match.length < min) {
+          (0, _util.warn)(`XFA - Must have at least ${min} occurrences: ${formNode[_xfa_object.$nodeName]}.`);
+          continue;
+        }
+
+        this._bindOccurrences(child, match, picture);
+      } else if (min > 0) {
+        this._bindElement(child, dataNode);
+      } else {
+        uselessNodes.push(child);
+      }
+    }
+
+    uselessNodes.forEach(node => node[_xfa_object.$getParent]()[_xfa_object.$removeChild](node));
+  }
+
+}
+
+exports.Binder = Binder;

+ 232 - 0
lib/core/xfa/builder.js

@@ -0,0 +1,232 @@
+/**
+ * @licstart The following is the entire license notice for the
+ * Javascript code in this page
+ *
+ * Copyright 2021 Mozilla Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * @licend The above is the entire license notice for the
+ * Javascript code in this page
+ */
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.Builder = void 0;
+
+var _namespaces = require("./namespaces.js");
+
+var _xfa_object = require("./xfa_object.js");
+
+var _setup = require("./setup.js");
+
+var _template = require("./template.js");
+
+var _unknown = require("./unknown.js");
+
+var _util = require("../../shared/util.js");
+
+const _ids = Symbol();
+
+class Root extends _xfa_object.XFAObject {
+  constructor(ids) {
+    super(-1, "root", Object.create(null));
+    this.element = null;
+    this[_ids] = ids;
+  }
+
+  [_xfa_object.$onChild](child) {
+    this.element = child;
+    return true;
+  }
+
+  [_xfa_object.$finalize]() {
+    super[_xfa_object.$finalize]();
+
+    if (this.element.template instanceof _template.Template) {
+      this.element.template[_xfa_object.$resolvePrototypes](this[_ids]);
+    }
+  }
+
+}
+
+class Empty extends _xfa_object.XFAObject {
+  constructor() {
+    super(-1, "", Object.create(null));
+  }
+
+  [_xfa_object.$onChild](_) {
+    return false;
+  }
+
+}
+
+class Builder {
+  constructor() {
+    this._namespaceStack = [];
+    this._namespacePrefixes = new Map();
+    this._namespaces = new Map();
+    this._nextNsId = Math.max(...Object.values(_namespaces.NamespaceIds).map(({
+      id
+    }) => id));
+    this._currentNamespace = new _unknown.UnknownNamespace(++this._nextNsId);
+  }
+
+  buildRoot(ids) {
+    return new Root(ids);
+  }
+
+  build({
+    nsPrefix,
+    name,
+    attributes,
+    namespace,
+    prefixes
+  }) {
+    const hasNamespaceDef = namespace !== null;
+
+    if (hasNamespaceDef) {
+      this._namespaceStack.push(this._currentNamespace);
+
+      this._currentNamespace = this._searchNamespace(namespace);
+    }
+
+    if (prefixes) {
+      this._addNamespacePrefix(prefixes);
+    }
+
+    if (attributes.hasOwnProperty(_xfa_object.$nsAttributes)) {
+      const dataTemplate = _setup.NamespaceSetUp.datasets;
+      const nsAttrs = attributes[_xfa_object.$nsAttributes];
+      let xfaAttrs = null;
+
+      for (const [ns, attrs] of Object.entries(nsAttrs)) {
+        const nsToUse = this._getNamespaceToUse(ns);
+
+        if (nsToUse === dataTemplate) {
+          xfaAttrs = {
+            xfa: attrs
+          };
+          break;
+        }
+      }
+
+      if (xfaAttrs) {
+        attributes[_xfa_object.$nsAttributes] = xfaAttrs;
+      } else {
+        delete attributes[_xfa_object.$nsAttributes];
+      }
+    }
+
+    const namespaceToUse = this._getNamespaceToUse(nsPrefix);
+
+    const node = namespaceToUse && namespaceToUse[_namespaces.$buildXFAObject](name, attributes) || new Empty();
+
+    if (hasNamespaceDef || prefixes) {
+      node[_xfa_object.$cleanup] = {
+        hasNamespace: hasNamespaceDef,
+        prefixes
+      };
+    }
+
+    return node;
+  }
+
+  _searchNamespace(nsName) {
+    let ns = this._namespaces.get(nsName);
+
+    if (ns) {
+      return ns;
+    }
+
+    for (const [name, {
+      check
+    }] of Object.entries(_namespaces.NamespaceIds)) {
+      if (check(nsName)) {
+        ns = _setup.NamespaceSetUp[name];
+
+        if (ns) {
+          this._namespaces.set(nsName, ns);
+
+          return ns;
+        }
+
+        break;
+      }
+    }
+
+    ns = new _unknown.UnknownNamespace(++this._nextNsId);
+
+    this._namespaces.set(nsName, ns);
+
+    return ns;
+  }
+
+  _addNamespacePrefix(prefixes) {
+    for (const {
+      prefix,
+      value
+    } of prefixes) {
+      const namespace = this._searchNamespace(value);
+
+      let prefixStack = this._namespacePrefixes.get(prefix);
+
+      if (!prefixStack) {
+        prefixStack = [];
+
+        this._namespacePrefixes.set(prefix, prefixStack);
+      }
+
+      prefixStack.push(namespace);
+    }
+  }
+
+  _getNamespaceToUse(prefix) {
+    if (!prefix) {
+      return this._currentNamespace;
+    }
+
+    const prefixStack = this._namespacePrefixes.get(prefix);
+
+    if (prefixStack && prefixStack.length > 0) {
+      return prefixStack[prefixStack.length - 1];
+    }
+
+    (0, _util.warn)(`Unknown namespace prefix: ${prefix}.`);
+    return null;
+  }
+
+  clean(data) {
+    const {
+      hasNamespace,
+      prefixes
+    } = data;
+
+    if (hasNamespace) {
+      this._currentNamespace = this._namespaceStack.pop();
+    }
+
+    if (prefixes) {
+      prefixes.forEach(({
+        prefix
+      }) => {
+        this._namespacePrefixes.get(prefix).pop();
+      });
+    }
+  }
+
+}
+
+exports.Builder = Builder;

+ 1905 - 0
lib/core/xfa/config.js

@@ -0,0 +1,1905 @@
+/**
+ * @licstart The following is the entire license notice for the
+ * Javascript code in this page
+ *
+ * Copyright 2021 Mozilla Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * @licend The above is the entire license notice for the
+ * Javascript code in this page
+ */
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.ConfigNamespace = void 0;
+
+var _namespaces = require("./namespaces.js");
+
+var _xfa_object = require("./xfa_object.js");
+
+var _utils = require("./utils.js");
+
+var _util = require("../../shared/util.js");
+
+const CONFIG_NS_ID = _namespaces.NamespaceIds.config.id;
+
+class Acrobat extends _xfa_object.XFAObject {
+  constructor(attributes) {
+    super(CONFIG_NS_ID, "acrobat", true);
+    this.acrobat7 = null;
+    this.autoSave = null;
+    this.common = null;
+    this.validate = null;
+    this.validateApprovalSignatures = null;
+    this.submitUrl = new _xfa_object.XFAObjectArray();
+  }
+
+}
+
+class Acrobat7 extends _xfa_object.XFAObject {
+  constructor(attributes) {
+    super(CONFIG_NS_ID, "acrobat7", true);
+    this.dynamicRender = null;
+  }
+
+}
+
+class ADBE_JSConsole extends _xfa_object.OptionObject {
+  constructor(attributes) {
+    super(CONFIG_NS_ID, "ADBE_JSConsole", ["delegate", "Enable", "Disable"]);
+  }
+
+}
+
+class ADBE_JSDebugger extends _xfa_object.OptionObject {
+  constructor(attributes) {
+    super(CONFIG_NS_ID, "ADBE_JSDebugger", ["delegate", "Enable", "Disable"]);
+  }
+
+}
+
+class AddSilentPrint extends _xfa_object.Option01 {
+  constructor(attributes) {
+    super(CONFIG_NS_ID, "addSilentPrint");
+  }
+
+}
+
+class AddViewerPreferences extends _xfa_object.Option01 {
+  constructor(attributes) {
+    super(CONFIG_NS_ID, "addViewerPreferences");
+  }
+
+}
+
+class AdjustData extends _xfa_object.Option10 {
+  constructor(attributes) {
+    super(CONFIG_NS_ID, "adjustData");
+  }
+
+}
+
+class AdobeExtensionLevel extends _xfa_object.IntegerObject {
+  constructor(attributes) {
+    super(CONFIG_NS_ID, "adobeExtensionLevel", 0, n => n >= 1 && n <= 8);
+  }
+
+}
+
+class Agent extends _xfa_object.XFAObject {
+  constructor(attributes) {
+    super(CONFIG_NS_ID, "agent", true);
+    this.name = attributes.name ? attributes.name.trim() : "";
+    this.common = new _xfa_object.XFAObjectArray();
+  }
+
+}
+
+class AlwaysEmbed extends _xfa_object.ContentObject {
+  constructor(attributes) {
+    super(CONFIG_NS_ID, "alwaysEmbed");
+  }
+
+}
+
+class Amd extends _xfa_object.StringObject {
+  constructor(attributes) {
+    super(CONFIG_NS_ID, "amd");
+  }
+
+}
+
+class Area extends _xfa_object.XFAObject {
+  constructor(attributes) {
+    super(CONFIG_NS_ID, "area");
+    this.level = (0, _utils.getInteger)({
+      data: attributes.level,
+      defaultValue: 0,
+      validator: n => n >= 1 && n <= 3
+    });
+    this.name = (0, _utils.getStringOption)(attributes.name, ["", "barcode", "coreinit", "deviceDriver", "font", "general", "layout", "merge", "script", "signature", "sourceSet", "templateCache"]);
+  }
+
+}
+
+class Attributes extends _xfa_object.OptionObject {
+  constructor(attributes) {
+    super(CONFIG_NS_ID, "attributes", ["preserve", "delegate", "ignore"]);
+  }
+
+}
+
+class AutoSave extends _xfa_object.OptionObject {
+  constructor(attributes) {
+    super(CONFIG_NS_ID, "autoSave", ["disabled", "enabled"]);
+  }
+
+}
+
+class Base extends _xfa_object.StringObject {
+  constructor(attributes) {
+    super(CONFIG_NS_ID, "base");
+  }
+
+}
+
+class BatchOutput extends _xfa_object.XFAObject {
+  constructor(attributes) {
+    super(CONFIG_NS_ID, "batchOutput");
+    this.format = (0, _utils.getStringOption)(attributes.format, ["none", "concat", "zip", "zipCompress"]);
+  }
+
+}
+
+class BehaviorOverride extends _xfa_object.ContentObject {
+  constructor(attributes) {
+    super(CONFIG_NS_ID, "behaviorOverride");
+  }
+
+  [_xfa_object.$finalize]() {
+    this[_xfa_object.$content] = new Map(this[_xfa_object.$content].trim().split(/\s+/).filter(x => !!x && x.include(":")).map(x => x.split(":", 2)));
+  }
+
+}
+
+class Cache extends _xfa_object.XFAObject {
+  constructor(attributes) {
+    super(CONFIG_NS_ID, "cache", true);
+    this.templateCache = null;
+  }
+
+}
+
+class Change extends _xfa_object.Option01 {
+  constructor(attributes) {
+    super(CONFIG_NS_ID, "change");
+  }
+
+}
+
+class Common extends _xfa_object.XFAObject {
+  constructor(attributes) {
+    super(CONFIG_NS_ID, "common", true);
+    this.data = null;
+    this.locale = null;
+    this.localeSet = null;
+    this.messaging = null;
+    this.suppressBanner = null;
+    this.template = null;
+    this.validationMessaging = null;
+    this.versionControl = null;
+    this.log = new _xfa_object.XFAObjectArray();
+  }
+
+}
+
+class Compress extends _xfa_object.XFAObject {
+  constructor(attributes) {
+    super(CONFIG_NS_ID, "compress");
+    this.scope = (0, _utils.getStringOption)(attributes.scope, ["imageOnly", "document"]);
+  }
+
+}
+
+class CompressLogicalStructure extends _xfa_object.Option01 {
+  constructor(attributes) {
+    super(CONFIG_NS_ID, "compressLogicalStructure");
+  }
+
+}
+
+class CompressObjectStream extends _xfa_object.Option10 {
+  constructor(attributes) {
+    super(CONFIG_NS_ID, "compressObjectStream");
+  }
+
+}
+
+class Compression extends _xfa_object.XFAObject {
+  constructor(attributes) {
+    super(CONFIG_NS_ID, "compression", true);
+    this.compressLogicalStructure = null;
+    this.compressObjectStream = null;
+    this.level = null;
+    this.type = null;
+  }
+
+}
+
+class Config extends _xfa_object.XFAObject {
+  constructor(attributes) {
+    super(CONFIG_NS_ID, "config", true);
+    this.acrobat = null;
+    this.present = null;
+    this.trace = null;
+    this.agent = new _xfa_object.XFAObjectArray();
+  }
+
+}
+
+class Conformance extends _xfa_object.OptionObject {
+  constructor(attributes) {
+    super(CONFIG_NS_ID, "conformance", ["A", "B"]);
+  }
+
+}
+
+class ContentCopy extends _xfa_object.Option01 {
+  constructor(attributes) {
+    super(CONFIG_NS_ID, "contentCopy");
+  }
+
+}
+
+class Copies extends _xfa_object.IntegerObject {
+  constructor(attributes) {
+    super(CONFIG_NS_ID, "copies", 1, n => n >= 1);
+  }
+
+}
+
+class Creator extends _xfa_object.StringObject {
+  constructor(attributes) {
+    super(CONFIG_NS_ID, "creator");
+  }
+
+}
+
+class CurrentPage extends _xfa_object.IntegerObject {
+  constructor(attributes) {
+    super(CONFIG_NS_ID, "currentPage", 0, n => n >= 0);
+  }
+
+}
+
+class Data extends _xfa_object.XFAObject {
+  constructor(attributes) {
+    super(CONFIG_NS_ID, "data", true);
+    this.adjustData = null;
+    this.attributes = null;
+    this.incrementalLoad = null;
+    this.outputXSL = null;
+    this.range = null;
+    this.record = null;
+    this.startNode = null;
+    this.uri = null;
+    this.window = null;
+    this.xsl = null;
+    this.excludeNS = new _xfa_object.XFAObjectArray();
+    this.transform = new _xfa_object.XFAObjectArray();
+  }
+
+}
+
+class Debug extends _xfa_object.XFAObject {
+  constructor(attributes) {
+    super(CONFIG_NS_ID, "debug", true);
+    this.uri = null;
+  }
+
+}
+
+class DefaultTypeface extends _xfa_object.ContentObject {
+  constructor(attributes) {
+    super(CONFIG_NS_ID, "defaultTypeface");
+    this.writingScript = (0, _utils.getStringOption)(attributes.writingScript, ["*", "Arabic", "Cyrillic", "EastEuropeanRoman", "Greek", "Hebrew", "Japanese", "Korean", "Roman", "SimplifiedChinese", "Thai", "TraditionalChinese", "Vietnamese"]);
+  }
+
+}
+
+class Destination extends _xfa_object.OptionObject {
+  constructor(attributes) {
+    super(CONFIG_NS_ID, "destination", ["pdf", "pcl", "ps", "webClient", "zpl"]);
+  }
+
+}
+
+class DocumentAssembly extends _xfa_object.Option01 {
+  constructor(attributes) {
+    super(CONFIG_NS_ID, "documentAssembly");
+  }
+
+}
+
+class Driver extends _xfa_object.XFAObject {
+  constructor(attributes) {
+    super(CONFIG_NS_ID, "driver", true);
+    this.name = attributes.name ? attributes.name.trim() : "";
+    this.fontInfo = null;
+    this.xdc = null;
+  }
+
+}
+
+class DuplexOption extends _xfa_object.OptionObject {
+  constructor(attributes) {
+    super(CONFIG_NS_ID, "duplexOption", ["simplex", "duplexFlipLongEdge", "duplexFlipShortEdge"]);
+  }
+
+}
+
+class DynamicRender extends _xfa_object.OptionObject {
+  constructor(attributes) {
+    super(CONFIG_NS_ID, "dynamicRender", ["forbidden", "required"]);
+  }
+
+}
+
+class Embed extends _xfa_object.Option01 {
+  constructor(attributes) {
+    super(CONFIG_NS_ID, "embed");
+  }
+
+}
+
+class Encrypt extends _xfa_object.Option01 {
+  constructor(attributes) {
+    super(CONFIG_NS_ID, "encrypt");
+  }
+
+}
+
+class Encryption extends _xfa_object.XFAObject {
+  constructor(attributes) {
+    super(CONFIG_NS_ID, "encryption", true);
+    this.encrypt = null;
+    this.encryptionLevel = null;
+    this.permissions = null;
+  }
+
+}
+
+class EncryptionLevel extends _xfa_object.OptionObject {
+  constructor(attributes) {
+    super(CONFIG_NS_ID, "encryptionLevel", ["40bit", "128bit"]);
+  }
+
+}
+
+class Enforce extends _xfa_object.StringObject {
+  constructor(attributes) {
+    super(CONFIG_NS_ID, "enforce");
+  }
+
+}
+
+class Equate extends _xfa_object.XFAObject {
+  constructor(attributes) {
+    super(CONFIG_NS_ID, "equate");
+    this.force = (0, _utils.getInteger)({
+      data: attributes.force,
+      defaultValue: 1,
+      validator: n => n === 0
+    });
+    this.from = attributes.from || "";
+    this.to = attributes.to || "";
+  }
+
+}
+
+class EquateRange extends _xfa_object.XFAObject {
+  constructor(attributes) {
+    super(CONFIG_NS_ID, "equateRange");
+    this.from = attributes.from || "";
+    this.to = attributes.to || "";
+    this._unicodeRange = attributes.unicodeRange || "";
+  }
+
+  get unicodeRange() {
+    const ranges = [];
+    const unicodeRegex = /U\+([0-9a-fA-F]+)/;
+    const unicodeRange = this._unicodeRange;
+
+    for (let range of unicodeRange.split(",").map(x => x.trim()).filter(x => !!x)) {
+      range = range.split("-", 2).map(x => {
+        const found = x.match(unicodeRegex);
+
+        if (!found) {
+          return 0;
+        }
+
+        return parseInt(found[1], 16);
+      });
+
+      if (range.length === 1) {
+        range.push(range[0]);
+      }
+
+      ranges.push(range);
+    }
+
+    return (0, _util.shadow)(this, "unicodeRange", ranges);
+  }
+
+}
+
+class Exclude extends _xfa_object.ContentObject {
+  constructor(attributes) {
+    super(CONFIG_NS_ID, "exclude");
+  }
+
+  [_xfa_object.$finalize]() {
+    this[_xfa_object.$content] = this[_xfa_object.$content].trim().split(/\s+/).filter(x => x && ["calculate", "close", "enter", "exit", "initialize", "ready", "validate"].includes(x));
+  }
+
+}
+
+class ExcludeNS extends _xfa_object.StringObject {
+  constructor(attributes) {
+    super(CONFIG_NS_ID, "excludeNS");
+  }
+
+}
+
+class FlipLabel extends _xfa_object.OptionObject {
+  constructor(attributes) {
+    super(CONFIG_NS_ID, "flipLabel", ["usePrinterSetting", "on", "off"]);
+  }
+
+}
+
+class FontInfo extends _xfa_object.XFAObject {
+  constructor(attributes) {
+    super(CONFIG_NS_ID, "fontInfo", true);
+    this.embed = null;
+    this.map = null;
+    this.subsetBelow = null;
+    this.alwaysEmbed = new _xfa_object.XFAObjectArray();
+    this.defaultTypeface = new _xfa_object.XFAObjectArray();
+    this.neverEmbed = new _xfa_object.XFAObjectArray();
+  }
+
+}
+
+class FormFieldFilling extends _xfa_object.Option01 {
+  constructor(attributes) {
+    super(CONFIG_NS_ID, "formFieldFilling");
+  }
+
+}
+
+class GroupParent extends _xfa_object.StringObject {
+  constructor(attributes) {
+    super(CONFIG_NS_ID, "groupParent");
+  }
+
+}
+
+class IfEmpty extends _xfa_object.OptionObject {
+  constructor(attributes) {
+    super(CONFIG_NS_ID, "ifEmpty", ["dataValue", "dataGroup", "ignore", "remove"]);
+  }
+
+}
+
+class IncludeXDPContent extends _xfa_object.StringObject {
+  constructor(attributes) {
+    super(CONFIG_NS_ID, "includeXDPContent");
+  }
+
+}
+
+class IncrementalLoad extends _xfa_object.OptionObject {
+  constructor(attributes) {
+    super(CONFIG_NS_ID, "incrementalLoad", ["none", "forwardOnly"]);
+  }
+
+}
+
+class IncrementalMerge extends _xfa_object.Option01 {
+  constructor(attributes) {
+    super(CONFIG_NS_ID, "incrementalMerge");
+  }
+
+}
+
+class Interactive extends _xfa_object.Option01 {
+  constructor(attributes) {
+    super(CONFIG_NS_ID, "interactive");
+  }
+
+}
+
+class Jog extends _xfa_object.OptionObject {
+  constructor(attributes) {
+    super(CONFIG_NS_ID, "jog", ["usePrinterSetting", "none", "pageSet"]);
+  }
+
+}
+
+class LabelPrinter extends _xfa_object.XFAObject {
+  constructor(attributes) {
+    super(CONFIG_NS_ID, "labelPrinter", true);
+    this.name = (0, _utils.getStringOption)(attributes.name, ["zpl", "dpl", "ipl", "tcpl"]);
+    this.batchOutput = null;
+    this.flipLabel = null;
+    this.fontInfo = null;
+    this.xdc = null;
+  }
+
+}
+
+class Layout extends _xfa_object.OptionObject {
+  constructor(attributes) {
+    super(CONFIG_NS_ID, "layout", ["paginate", "panel"]);
+  }
+
+}
+
+class Level extends _xfa_object.IntegerObject {
+  constructor(attributes) {
+    super(CONFIG_NS_ID, "level", 0, n => n > 0);
+  }
+
+}
+
+class Linearized extends _xfa_object.Option01 {
+  constructor(attributes) {
+    super(CONFIG_NS_ID, "linearized");
+  }
+
+}
+
+class Locale extends _xfa_object.StringObject {
+  constructor(attributes) {
+    super(CONFIG_NS_ID, "locale");
+  }
+
+}
+
+class LocaleSet extends _xfa_object.StringObject {
+  constructor(attributes) {
+    super(CONFIG_NS_ID, "localeSet");
+  }
+
+}
+
+class Log extends _xfa_object.XFAObject {
+  constructor(attributes) {
+    super(CONFIG_NS_ID, "log", true);
+    this.mode = null;
+    this.threshold = null;
+    this.to = null;
+    this.uri = null;
+  }
+
+}
+
+class MapElement extends _xfa_object.XFAObject {
+  constructor(attributes) {
+    super(CONFIG_NS_ID, "map", true);
+    this.equate = new _xfa_object.XFAObjectArray();
+    this.equateRange = new _xfa_object.XFAObjectArray();
+  }
+
+}
+
+class MediumInfo extends _xfa_object.XFAObject {
+  constructor(attributes) {
+    super(CONFIG_NS_ID, "mediumInfo", true);
+    this.map = null;
+  }
+
+}
+
+class Message extends _xfa_object.XFAObject {
+  constructor(attributes) {
+    super(CONFIG_NS_ID, "message", true);
+    this.msgId = null;
+    this.severity = null;
+  }
+
+}
+
+class Messaging extends _xfa_object.XFAObject {
+  constructor(attributes) {
+    super(CONFIG_NS_ID, "messaging", true);
+    this.message = new _xfa_object.XFAObjectArray();
+  }
+
+}
+
+class Mode extends _xfa_object.OptionObject {
+  constructor(attributes) {
+    super(CONFIG_NS_ID, "mode", ["append", "overwrite"]);
+  }
+
+}
+
+class ModifyAnnots extends _xfa_object.Option01 {
+  constructor(attributes) {
+    super(CONFIG_NS_ID, "modifyAnnots");
+  }
+
+}
+
+class MsgId extends _xfa_object.IntegerObject {
+  constructor(attributes) {
+    super(CONFIG_NS_ID, "msgId", 1, n => n >= 1);
+  }
+
+}
+
+class NameAttr extends _xfa_object.StringObject {
+  constructor(attributes) {
+    super(CONFIG_NS_ID, "nameAttr");
+  }
+
+}
+
+class NeverEmbed extends _xfa_object.ContentObject {
+  constructor(attributes) {
+    super(CONFIG_NS_ID, "neverEmbed");
+  }
+
+}
+
+class NumberOfCopies extends _xfa_object.IntegerObject {
+  constructor(attributes) {
+    super(CONFIG_NS_ID, "numberOfCopies", null, n => n >= 2 && n <= 5);
+  }
+
+}
+
+class OpenAction extends _xfa_object.XFAObject {
+  constructor(attributes) {
+    super(CONFIG_NS_ID, "openAction", true);
+    this.destination = null;
+  }
+
+}
+
+class Output extends _xfa_object.XFAObject {
+  constructor(attributes) {
+    super(CONFIG_NS_ID, "output", true);
+    this.to = null;
+    this.type = null;
+    this.uri = null;
+  }
+
+}
+
+class OutputBin extends _xfa_object.StringObject {
+  constructor(attributes) {
+    super(CONFIG_NS_ID, "outputBin");
+  }
+
+}
+
+class OutputXSL extends _xfa_object.XFAObject {
+  constructor(attributes) {
+    super(CONFIG_NS_ID, "outputXSL", true);
+    this.uri = null;
+  }
+
+}
+
+class Overprint extends _xfa_object.OptionObject {
+  constructor(attributes) {
+    super(CONFIG_NS_ID, "overprint", ["none", "both", "draw", "field"]);
+  }
+
+}
+
+class Packets extends _xfa_object.StringObject {
+  constructor(attributes) {
+    super(CONFIG_NS_ID, "packets");
+  }
+
+  [_xfa_object.$finalize]() {
+    if (this[_xfa_object.$content] === "*") {
+      return;
+    }
+
+    this[_xfa_object.$content] = this[_xfa_object.$content].trim().split(/\s+/).filter(x => ["config", "datasets", "template", "xfdf", "xslt"].includes(x));
+  }
+
+}
+
+class PageOffset extends _xfa_object.XFAObject {
+  constructor(attributes) {
+    super(CONFIG_NS_ID, "pageOffset");
+    this.x = (0, _utils.getInteger)({
+      data: attributes.x,
+      defaultValue: "useXDCSetting",
+      validator: n => true
+    });
+    this.y = (0, _utils.getInteger)({
+      data: attributes.y,
+      defaultValue: "useXDCSetting",
+      validator: n => true
+    });
+  }
+
+}
+
+class PageRange extends _xfa_object.StringObject {
+  constructor(attributes) {
+    super(CONFIG_NS_ID, "pageRange");
+  }
+
+  [_xfa_object.$finalize]() {
+    const numbers = this[_xfa_object.$content].trim().split(/\s+/).map(x => parseInt(x, 10));
+
+    const ranges = [];
+
+    for (let i = 0, ii = numbers.length; i < ii; i += 2) {
+      ranges.push(numbers.slice(i, i + 2));
+    }
+
+    this[_xfa_object.$content] = ranges;
+  }
+
+}
+
+class Pagination extends _xfa_object.OptionObject {
+  constructor(attributes) {
+    super(CONFIG_NS_ID, "pagination", ["simplex", "duplexShortEdge", "duplexLongEdge"]);
+  }
+
+}
+
+class PaginationOverride extends _xfa_object.OptionObject {
+  constructor(attributes) {
+    super(CONFIG_NS_ID, "paginationOverride", ["none", "forceDuplex", "forceDuplexLongEdge", "forceDuplexShortEdge", "forceSimplex"]);
+  }
+
+}
+
+class Part extends _xfa_object.IntegerObject {
+  constructor(attributes) {
+    super(CONFIG_NS_ID, "part", 1, n => false);
+  }
+
+}
+
+class Pcl extends _xfa_object.XFAObject {
+  constructor(attributes) {
+    super(CONFIG_NS_ID, "pcl", true);
+    this.name = attributes.name || "";
+    this.batchOutput = null;
+    this.fontInfo = null;
+    this.jog = null;
+    this.mediumInfo = null;
+    this.outputBin = null;
+    this.pageOffset = null;
+    this.staple = null;
+    this.xdc = null;
+  }
+
+}
+
+class Pdf extends _xfa_object.XFAObject {
+  constructor(attributes) {
+    super(CONFIG_NS_ID, "pdf", true);
+    this.name = attributes.name || "";
+    this.adobeExtensionLevel = null;
+    this.batchOutput = null;
+    this.compression = null;
+    this.creator = null;
+    this.encryption = null;
+    this.fontInfo = null;
+    this.interactive = null;
+    this.linearized = null;
+    this.openAction = null;
+    this.pdfa = null;
+    this.producer = null;
+    this.renderPolicy = null;
+    this.scriptModel = null;
+    this.silentPrint = null;
+    this.submitFormat = null;
+    this.tagged = null;
+    this.version = null;
+    this.viewerPreferences = null;
+    this.xdc = null;
+  }
+
+}
+
+class Pdfa extends _xfa_object.XFAObject {
+  constructor(attributes) {
+    super(CONFIG_NS_ID, "pdfa", true);
+    this.amd = null;
+    this.conformance = null;
+    this.includeXDPContent = null;
+    this.part = null;
+  }
+
+}
+
+class Permissions extends _xfa_object.XFAObject {
+  constructor(attributes) {
+    super(CONFIG_NS_ID, "permissions", true);
+    this.accessibleContent = null;
+    this.change = null;
+    this.contentCopy = null;
+    this.documentAssembly = null;
+    this.formFieldFilling = null;
+    this.modifyAnnots = null;
+    this.plaintextMetadata = null;
+    this.print = null;
+    this.printHighQuality = null;
+  }
+
+}
+
+class PickTrayByPDFSize extends _xfa_object.Option01 {
+  constructor(attributes) {
+    super(CONFIG_NS_ID, "pickTrayByPDFSize");
+  }
+
+}
+
+class Picture extends _xfa_object.StringObject {
+  constructor(attributes) {
+    super(CONFIG_NS_ID, "picture");
+  }
+
+}
+
+class PlaintextMetadata extends _xfa_object.Option01 {
+  constructor(attributes) {
+    super(CONFIG_NS_ID, "plaintextMetadata");
+  }
+
+}
+
+class Presence extends _xfa_object.OptionObject {
+  constructor(attributes) {
+    super(CONFIG_NS_ID, "presence", ["preserve", "dissolve", "dissolveStructure", "ignore", "remove"]);
+  }
+
+}
+
+class Present extends _xfa_object.XFAObject {
+  constructor(attributes) {
+    super(CONFIG_NS_ID, "present", true);
+    this.behaviorOverride = null;
+    this.cache = null;
+    this.common = null;
+    this.copies = null;
+    this.destination = null;
+    this.incrementalMerge = null;
+    this.layout = null;
+    this.output = null;
+    this.overprint = null;
+    this.pagination = null;
+    this.paginationOverride = null;
+    this.script = null;
+    this.validate = null;
+    this.xdp = null;
+    this.driver = new _xfa_object.XFAObjectArray();
+    this.labelPrinter = new _xfa_object.XFAObjectArray();
+    this.pcl = new _xfa_object.XFAObjectArray();
+    this.pdf = new _xfa_object.XFAObjectArray();
+    this.ps = new _xfa_object.XFAObjectArray();
+    this.submitUrl = new _xfa_object.XFAObjectArray();
+    this.webClient = new _xfa_object.XFAObjectArray();
+    this.zpl = new _xfa_object.XFAObjectArray();
+  }
+
+}
+
+class Print extends _xfa_object.Option01 {
+  constructor(attributes) {
+    super(CONFIG_NS_ID, "print");
+  }
+
+}
+
+class PrintHighQuality extends _xfa_object.Option01 {
+  constructor(attributes) {
+    super(CONFIG_NS_ID, "printHighQuality");
+  }
+
+}
+
+class PrintScaling extends _xfa_object.OptionObject {
+  constructor(attributes) {
+    super(CONFIG_NS_ID, "printScaling", ["appdefault", "noScaling"]);
+  }
+
+}
+
+class PrinterName extends _xfa_object.StringObject {
+  constructor(attributes) {
+    super(CONFIG_NS_ID, "printerName");
+  }
+
+}
+
+class Producer extends _xfa_object.StringObject {
+  constructor(attributes) {
+    super(CONFIG_NS_ID, "producer");
+  }
+
+}
+
+class Ps extends _xfa_object.XFAObject {
+  constructor(attributes) {
+    super(CONFIG_NS_ID, "ps", true);
+    this.name = attributes.name || "";
+    this.batchOutput = null;
+    this.fontInfo = null;
+    this.jog = null;
+    this.mediumInfo = null;
+    this.outputBin = null;
+    this.staple = null;
+    this.xdc = null;
+  }
+
+}
+
+class Range extends _xfa_object.ContentObject {
+  constructor(attributes) {
+    super(CONFIG_NS_ID, "range");
+  }
+
+  [_xfa_object.$finalize]() {
+    this[_xfa_object.$content] = this[_xfa_object.$content].trim().split(/\s*,\s*/, 2).map(range => range.split("-").map(x => parseInt(x.trim(), 10))).filter(range => range.every(x => !isNaN(x))).map(range => {
+      if (range.length === 1) {
+        range.push(range[0]);
+      }
+
+      return range;
+    });
+  }
+
+}
+
+class Record extends _xfa_object.ContentObject {
+  constructor(attributes) {
+    super(CONFIG_NS_ID, "record");
+  }
+
+  [_xfa_object.$finalize]() {
+    this[_xfa_object.$content] = this[_xfa_object.$content].trim();
+    const n = parseInt(this[_xfa_object.$content], 10);
+
+    if (!isNaN(n) && n >= 0) {
+      this[_xfa_object.$content] = n;
+    }
+  }
+
+}
+
+class Relevant extends _xfa_object.ContentObject {
+  constructor(attributes) {
+    super(CONFIG_NS_ID, "relevant");
+  }
+
+  [_xfa_object.$finalize]() {
+    this[_xfa_object.$content] = this[_xfa_object.$content].trim().split(/\s+/);
+  }
+
+}
+
+class Rename extends _xfa_object.ContentObject {
+  constructor(attributes) {
+    super(CONFIG_NS_ID, "rename");
+  }
+
+  [_xfa_object.$finalize]() {
+    this[_xfa_object.$content] = this[_xfa_object.$content].trim();
+
+    if (this[_xfa_object.$content].toLowerCase().startsWith("xml") || this[_xfa_object.$content].match(new RegExp("[\\p{L}_][\\p{L}\\d._\\p{M}-]*", "u"))) {
+      (0, _util.warn)("XFA - Rename: invalid XFA name");
+    }
+  }
+
+}
+
+class RenderPolicy extends _xfa_object.OptionObject {
+  constructor(attributes) {
+    super(CONFIG_NS_ID, "renderPolicy", ["server", "client"]);
+  }
+
+}
+
+class RunScripts extends _xfa_object.OptionObject {
+  constructor(attributes) {
+    super(CONFIG_NS_ID, "runScripts", ["both", "client", "none", "server"]);
+  }
+
+}
+
+class Script extends _xfa_object.XFAObject {
+  constructor(attributes) {
+    super(CONFIG_NS_ID, "script", true);
+    this.currentPage = null;
+    this.exclude = null;
+    this.runScripts = null;
+  }
+
+}
+
+class ScriptModel extends _xfa_object.OptionObject {
+  constructor(attributes) {
+    super(CONFIG_NS_ID, "scriptModel", ["XFA", "none"]);
+  }
+
+}
+
+class Severity extends _xfa_object.OptionObject {
+  constructor(attributes) {
+    super(CONFIG_NS_ID, "severity", ["ignore", "error", "information", "trace", "warning"]);
+  }
+
+}
+
+class SilentPrint extends _xfa_object.XFAObject {
+  constructor(attributes) {
+    super(CONFIG_NS_ID, "silentPrint", true);
+    this.addSilentPrint = null;
+    this.printerName = null;
+  }
+
+}
+
+class Staple extends _xfa_object.XFAObject {
+  constructor(attributes) {
+    super(CONFIG_NS_ID, "staple");
+    this.mode = (0, _utils.getStringOption)(attributes.mode, ["usePrinterSetting", "on", "off"]);
+  }
+
+}
+
+class StartNode extends _xfa_object.StringObject {
+  constructor(attributes) {
+    super(CONFIG_NS_ID, "startNode");
+  }
+
+}
+
+class StartPage extends _xfa_object.IntegerObject {
+  constructor(attributes) {
+    super(CONFIG_NS_ID, "startPage", 0, n => true);
+  }
+
+}
+
+class SubmitFormat extends _xfa_object.OptionObject {
+  constructor(attributes) {
+    super(CONFIG_NS_ID, "submitFormat", ["html", "delegate", "fdf", "xml", "pdf"]);
+  }
+
+}
+
+class SubmitUrl extends _xfa_object.StringObject {
+  constructor(attributes) {
+    super(CONFIG_NS_ID, "submitUrl");
+  }
+
+}
+
+class SubsetBelow extends _xfa_object.IntegerObject {
+  constructor(attributes) {
+    super(CONFIG_NS_ID, "subsetBelow", 100, n => n >= 0 && n <= 100);
+  }
+
+}
+
+class SuppressBanner extends _xfa_object.Option01 {
+  constructor(attributes) {
+    super(CONFIG_NS_ID, "suppressBanner");
+  }
+
+}
+
+class Tagged extends _xfa_object.Option01 {
+  constructor(attributes) {
+    super(CONFIG_NS_ID, "tagged");
+  }
+
+}
+
+class Template extends _xfa_object.XFAObject {
+  constructor(attributes) {
+    super(CONFIG_NS_ID, "template", true);
+    this.base = null;
+    this.relevant = null;
+    this.startPage = null;
+    this.uri = null;
+    this.xsl = null;
+  }
+
+}
+
+class Threshold extends _xfa_object.OptionObject {
+  constructor(attributes) {
+    super(CONFIG_NS_ID, "threshold", ["trace", "error", "information", "warning"]);
+  }
+
+}
+
+class To extends _xfa_object.OptionObject {
+  constructor(attributes) {
+    super(CONFIG_NS_ID, "to", ["null", "memory", "stderr", "stdout", "system", "uri"]);
+  }
+
+}
+
+class TemplateCache extends _xfa_object.XFAObject {
+  constructor(attributes) {
+    super(CONFIG_NS_ID, "templateCache");
+    this.maxEntries = (0, _utils.getInteger)({
+      data: attributes.maxEntries,
+      defaultValue: 5,
+      validator: n => n >= 0
+    });
+  }
+
+}
+
+class Trace extends _xfa_object.XFAObject {
+  constructor(attributes) {
+    super(CONFIG_NS_ID, "trace", true);
+    this.area = new _xfa_object.XFAObjectArray();
+  }
+
+}
+
+class Transform extends _xfa_object.XFAObject {
+  constructor(attributes) {
+    super(CONFIG_NS_ID, "transform", true);
+    this.groupParent = null;
+    this.ifEmpty = null;
+    this.nameAttr = null;
+    this.picture = null;
+    this.presence = null;
+    this.rename = null;
+    this.whitespace = null;
+  }
+
+}
+
+class Type extends _xfa_object.OptionObject {
+  constructor(attributes) {
+    super(CONFIG_NS_ID, "type", ["none", "ascii85", "asciiHex", "ccittfax", "flate", "lzw", "runLength", "native", "xdp", "mergedXDP"]);
+  }
+
+}
+
+class Uri extends _xfa_object.StringObject {
+  constructor(attributes) {
+    super(CONFIG_NS_ID, "uri");
+  }
+
+}
+
+class Validate extends _xfa_object.OptionObject {
+  constructor(attributes) {
+    super(CONFIG_NS_ID, "validate", ["preSubmit", "prePrint", "preExecute", "preSave"]);
+  }
+
+}
+
+class ValidateApprovalSignatures extends _xfa_object.ContentObject {
+  constructor(attributes) {
+    super(CONFIG_NS_ID, "validateApprovalSignatures");
+  }
+
+  [_xfa_object.$finalize]() {
+    this[_xfa_object.$content] = this[_xfa_object.$content].trim().split(/\s+/).filter(x => ["docReady", "postSign"].includes(x));
+  }
+
+}
+
+class ValidationMessaging extends _xfa_object.OptionObject {
+  constructor(attributes) {
+    super(CONFIG_NS_ID, "validationMessaging", ["allMessagesIndividually", "allMessagesTogether", "firstMessageOnly", "noMessages"]);
+  }
+
+}
+
+class Version extends _xfa_object.OptionObject {
+  constructor(attributes) {
+    super(CONFIG_NS_ID, "version", ["1.7", "1.6", "1.5", "1.4", "1.3", "1.2"]);
+  }
+
+}
+
+class VersionControl extends _xfa_object.XFAObject {
+  constructor(attributes) {
+    super(CONFIG_NS_ID, "VersionControl");
+    this.outputBelow = (0, _utils.getStringOption)(attributes.outputBelow, ["warn", "error", "update"]);
+    this.sourceAbove = (0, _utils.getStringOption)(attributes.sourceAbove, ["warn", "error"]);
+    this.sourceBelow = (0, _utils.getStringOption)(attributes.sourceBelow, ["update", "maintain"]);
+  }
+
+}
+
+class ViewerPreferences extends _xfa_object.XFAObject {
+  constructor(attributes) {
+    super(CONFIG_NS_ID, "viewerPreferences", true);
+    this.ADBE_JSConsole = null;
+    this.ADBE_JSDebugger = null;
+    this.addViewerPreferences = null;
+    this.duplexOption = null;
+    this.enforce = null;
+    this.numberOfCopies = null;
+    this.pageRange = null;
+    this.pickTrayByPDFSize = null;
+    this.printScaling = null;
+  }
+
+}
+
+class WebClient extends _xfa_object.XFAObject {
+  constructor(attributes) {
+    super(CONFIG_NS_ID, "webClient", true);
+    this.name = attributes.name ? attributes.name.trim() : "";
+    this.fontInfo = null;
+    this.xdc = null;
+  }
+
+}
+
+class Whitespace extends _xfa_object.OptionObject {
+  constructor(attributes) {
+    super(CONFIG_NS_ID, "whitespace", ["preserve", "ltrim", "normalize", "rtrim", "trim"]);
+  }
+
+}
+
+class Window extends _xfa_object.ContentObject {
+  constructor(attributes) {
+    super(CONFIG_NS_ID, "window");
+  }
+
+  [_xfa_object.$finalize]() {
+    const pair = this[_xfa_object.$content].trim().split(/\s*,\s*/, 2).map(x => parseInt(x, 10));
+
+    if (pair.some(x => isNaN(x))) {
+      this[_xfa_object.$content] = [0, 0];
+      return;
+    }
+
+    if (pair.length === 1) {
+      pair.push(pair[0]);
+    }
+
+    this[_xfa_object.$content] = pair;
+  }
+
+}
+
+class Xdc extends _xfa_object.XFAObject {
+  constructor(attributes) {
+    super(CONFIG_NS_ID, "xdc", true);
+    this.uri = new _xfa_object.XFAObjectArray();
+    this.xsl = new _xfa_object.XFAObjectArray();
+  }
+
+}
+
+class Xdp extends _xfa_object.XFAObject {
+  constructor(attributes) {
+    super(CONFIG_NS_ID, "xdp", true);
+    this.packets = null;
+  }
+
+}
+
+class Xsl extends _xfa_object.XFAObject {
+  constructor(attributes) {
+    super(CONFIG_NS_ID, "xsl", true);
+    this.debug = null;
+    this.uri = null;
+  }
+
+}
+
+class Zpl extends _xfa_object.XFAObject {
+  constructor(attributes) {
+    super(CONFIG_NS_ID, "zpl", true);
+    this.name = attributes.name ? attributes.name.trim() : "";
+    this.batchOutput = null;
+    this.flipLabel = null;
+    this.fontInfo = null;
+    this.xdc = null;
+  }
+
+}
+
+class ConfigNamespace {
+  static [_namespaces.$buildXFAObject](name, attributes) {
+    if (ConfigNamespace.hasOwnProperty(name)) {
+      return ConfigNamespace[name](attributes);
+    }
+
+    return undefined;
+  }
+
+  static acrobat(attrs) {
+    return new Acrobat(attrs);
+  }
+
+  static acrobat7(attrs) {
+    return new Acrobat7(attrs);
+  }
+
+  static ADBE_JSConsole(attrs) {
+    return new ADBE_JSConsole(attrs);
+  }
+
+  static ADBE_JSDebugger(attrs) {
+    return new ADBE_JSDebugger(attrs);
+  }
+
+  static addSilentPrint(attrs) {
+    return new AddSilentPrint(attrs);
+  }
+
+  static addViewerPreferences(attrs) {
+    return new AddViewerPreferences(attrs);
+  }
+
+  static adjustData(attrs) {
+    return new AdjustData(attrs);
+  }
+
+  static adobeExtensionLevel(attrs) {
+    return new AdobeExtensionLevel(attrs);
+  }
+
+  static agent(attrs) {
+    return new Agent(attrs);
+  }
+
+  static alwaysEmbed(attrs) {
+    return new AlwaysEmbed(attrs);
+  }
+
+  static amd(attrs) {
+    return new Amd(attrs);
+  }
+
+  static area(attrs) {
+    return new Area(attrs);
+  }
+
+  static attributes(attrs) {
+    return new Attributes(attrs);
+  }
+
+  static autoSave(attrs) {
+    return new AutoSave(attrs);
+  }
+
+  static base(attrs) {
+    return new Base(attrs);
+  }
+
+  static batchOutput(attrs) {
+    return new BatchOutput(attrs);
+  }
+
+  static behaviorOverride(attrs) {
+    return new BehaviorOverride(attrs);
+  }
+
+  static cache(attrs) {
+    return new Cache(attrs);
+  }
+
+  static change(attrs) {
+    return new Change(attrs);
+  }
+
+  static common(attrs) {
+    return new Common(attrs);
+  }
+
+  static compress(attrs) {
+    return new Compress(attrs);
+  }
+
+  static compressLogicalStructure(attrs) {
+    return new CompressLogicalStructure(attrs);
+  }
+
+  static compressObjectStream(attrs) {
+    return new CompressObjectStream(attrs);
+  }
+
+  static compression(attrs) {
+    return new Compression(attrs);
+  }
+
+  static config(attrs) {
+    return new Config(attrs);
+  }
+
+  static conformance(attrs) {
+    return new Conformance(attrs);
+  }
+
+  static contentCopy(attrs) {
+    return new ContentCopy(attrs);
+  }
+
+  static copies(attrs) {
+    return new Copies(attrs);
+  }
+
+  static creator(attrs) {
+    return new Creator(attrs);
+  }
+
+  static currentPage(attrs) {
+    return new CurrentPage(attrs);
+  }
+
+  static data(attrs) {
+    return new Data(attrs);
+  }
+
+  static debug(attrs) {
+    return new Debug(attrs);
+  }
+
+  static defaultTypeface(attrs) {
+    return new DefaultTypeface(attrs);
+  }
+
+  static destination(attrs) {
+    return new Destination(attrs);
+  }
+
+  static documentAssembly(attrs) {
+    return new DocumentAssembly(attrs);
+  }
+
+  static driver(attrs) {
+    return new Driver(attrs);
+  }
+
+  static duplexOption(attrs) {
+    return new DuplexOption(attrs);
+  }
+
+  static dynamicRender(attrs) {
+    return new DynamicRender(attrs);
+  }
+
+  static embed(attrs) {
+    return new Embed(attrs);
+  }
+
+  static encrypt(attrs) {
+    return new Encrypt(attrs);
+  }
+
+  static encryption(attrs) {
+    return new Encryption(attrs);
+  }
+
+  static encryptionLevel(attrs) {
+    return new EncryptionLevel(attrs);
+  }
+
+  static enforce(attrs) {
+    return new Enforce(attrs);
+  }
+
+  static equate(attrs) {
+    return new Equate(attrs);
+  }
+
+  static equateRange(attrs) {
+    return new EquateRange(attrs);
+  }
+
+  static exclude(attrs) {
+    return new Exclude(attrs);
+  }
+
+  static excludeNS(attrs) {
+    return new ExcludeNS(attrs);
+  }
+
+  static flipLabel(attrs) {
+    return new FlipLabel(attrs);
+  }
+
+  static fontInfo(attrs) {
+    return new FontInfo(attrs);
+  }
+
+  static formFieldFilling(attrs) {
+    return new FormFieldFilling(attrs);
+  }
+
+  static groupParent(attrs) {
+    return new GroupParent(attrs);
+  }
+
+  static ifEmpty(attrs) {
+    return new IfEmpty(attrs);
+  }
+
+  static includeXDPContent(attrs) {
+    return new IncludeXDPContent(attrs);
+  }
+
+  static incrementalLoad(attrs) {
+    return new IncrementalLoad(attrs);
+  }
+
+  static incrementalMerge(attrs) {
+    return new IncrementalMerge(attrs);
+  }
+
+  static interactive(attrs) {
+    return new Interactive(attrs);
+  }
+
+  static jog(attrs) {
+    return new Jog(attrs);
+  }
+
+  static labelPrinter(attrs) {
+    return new LabelPrinter(attrs);
+  }
+
+  static layout(attrs) {
+    return new Layout(attrs);
+  }
+
+  static level(attrs) {
+    return new Level(attrs);
+  }
+
+  static linearized(attrs) {
+    return new Linearized(attrs);
+  }
+
+  static locale(attrs) {
+    return new Locale(attrs);
+  }
+
+  static localeSet(attrs) {
+    return new LocaleSet(attrs);
+  }
+
+  static log(attrs) {
+    return new Log(attrs);
+  }
+
+  static map(attrs) {
+    return new MapElement(attrs);
+  }
+
+  static mediumInfo(attrs) {
+    return new MediumInfo(attrs);
+  }
+
+  static message(attrs) {
+    return new Message(attrs);
+  }
+
+  static messaging(attrs) {
+    return new Messaging(attrs);
+  }
+
+  static mode(attrs) {
+    return new Mode(attrs);
+  }
+
+  static modifyAnnots(attrs) {
+    return new ModifyAnnots(attrs);
+  }
+
+  static msgId(attrs) {
+    return new MsgId(attrs);
+  }
+
+  static nameAttr(attrs) {
+    return new NameAttr(attrs);
+  }
+
+  static neverEmbed(attrs) {
+    return new NeverEmbed(attrs);
+  }
+
+  static numberOfCopies(attrs) {
+    return new NumberOfCopies(attrs);
+  }
+
+  static openAction(attrs) {
+    return new OpenAction(attrs);
+  }
+
+  static output(attrs) {
+    return new Output(attrs);
+  }
+
+  static outputBin(attrs) {
+    return new OutputBin(attrs);
+  }
+
+  static outputXSL(attrs) {
+    return new OutputXSL(attrs);
+  }
+
+  static overprint(attrs) {
+    return new Overprint(attrs);
+  }
+
+  static packets(attrs) {
+    return new Packets(attrs);
+  }
+
+  static pageOffset(attrs) {
+    return new PageOffset(attrs);
+  }
+
+  static pageRange(attrs) {
+    return new PageRange(attrs);
+  }
+
+  static pagination(attrs) {
+    return new Pagination(attrs);
+  }
+
+  static paginationOverride(attrs) {
+    return new PaginationOverride(attrs);
+  }
+
+  static part(attrs) {
+    return new Part(attrs);
+  }
+
+  static pcl(attrs) {
+    return new Pcl(attrs);
+  }
+
+  static pdf(attrs) {
+    return new Pdf(attrs);
+  }
+
+  static pdfa(attrs) {
+    return new Pdfa(attrs);
+  }
+
+  static permissions(attrs) {
+    return new Permissions(attrs);
+  }
+
+  static pickTrayByPDFSize(attrs) {
+    return new PickTrayByPDFSize(attrs);
+  }
+
+  static picture(attrs) {
+    return new Picture(attrs);
+  }
+
+  static plaintextMetadata(attrs) {
+    return new PlaintextMetadata(attrs);
+  }
+
+  static presence(attrs) {
+    return new Presence(attrs);
+  }
+
+  static present(attrs) {
+    return new Present(attrs);
+  }
+
+  static print(attrs) {
+    return new Print(attrs);
+  }
+
+  static printHighQuality(attrs) {
+    return new PrintHighQuality(attrs);
+  }
+
+  static printScaling(attrs) {
+    return new PrintScaling(attrs);
+  }
+
+  static printerName(attrs) {
+    return new PrinterName(attrs);
+  }
+
+  static producer(attrs) {
+    return new Producer(attrs);
+  }
+
+  static ps(attrs) {
+    return new Ps(attrs);
+  }
+
+  static range(attrs) {
+    return new Range(attrs);
+  }
+
+  static record(attrs) {
+    return new Record(attrs);
+  }
+
+  static relevant(attrs) {
+    return new Relevant(attrs);
+  }
+
+  static rename(attrs) {
+    return new Rename(attrs);
+  }
+
+  static renderPolicy(attrs) {
+    return new RenderPolicy(attrs);
+  }
+
+  static runScripts(attrs) {
+    return new RunScripts(attrs);
+  }
+
+  static script(attrs) {
+    return new Script(attrs);
+  }
+
+  static scriptModel(attrs) {
+    return new ScriptModel(attrs);
+  }
+
+  static severity(attrs) {
+    return new Severity(attrs);
+  }
+
+  static silentPrint(attrs) {
+    return new SilentPrint(attrs);
+  }
+
+  static staple(attrs) {
+    return new Staple(attrs);
+  }
+
+  static startNode(attrs) {
+    return new StartNode(attrs);
+  }
+
+  static startPage(attrs) {
+    return new StartPage(attrs);
+  }
+
+  static submitFormat(attrs) {
+    return new SubmitFormat(attrs);
+  }
+
+  static submitUrl(attrs) {
+    return new SubmitUrl(attrs);
+  }
+
+  static subsetBelow(attrs) {
+    return new SubsetBelow(attrs);
+  }
+
+  static suppressBanner(attrs) {
+    return new SuppressBanner(attrs);
+  }
+
+  static tagged(attrs) {
+    return new Tagged(attrs);
+  }
+
+  static template(attrs) {
+    return new Template(attrs);
+  }
+
+  static templateCache(attrs) {
+    return new TemplateCache(attrs);
+  }
+
+  static threshold(attrs) {
+    return new Threshold(attrs);
+  }
+
+  static to(attrs) {
+    return new To(attrs);
+  }
+
+  static trace(attrs) {
+    return new Trace(attrs);
+  }
+
+  static transform(attrs) {
+    return new Transform(attrs);
+  }
+
+  static type(attrs) {
+    return new Type(attrs);
+  }
+
+  static uri(attrs) {
+    return new Uri(attrs);
+  }
+
+  static validate(attrs) {
+    return new Validate(attrs);
+  }
+
+  static validateApprovalSignatures(attrs) {
+    return new ValidateApprovalSignatures(attrs);
+  }
+
+  static validationMessaging(attrs) {
+    return new ValidationMessaging(attrs);
+  }
+
+  static version(attrs) {
+    return new Version(attrs);
+  }
+
+  static versionControl(attrs) {
+    return new VersionControl(attrs);
+  }
+
+  static viewerPreferences(attrs) {
+    return new ViewerPreferences(attrs);
+  }
+
+  static webClient(attrs) {
+    return new WebClient(attrs);
+  }
+
+  static whitespace(attrs) {
+    return new Whitespace(attrs);
+  }
+
+  static window(attrs) {
+    return new Window(attrs);
+  }
+
+  static xdc(attrs) {
+    return new Xdc(attrs);
+  }
+
+  static xdp(attrs) {
+    return new Xdp(attrs);
+  }
+
+  static xsl(attrs) {
+    return new Xsl(attrs);
+  }
+
+  static zpl(attrs) {
+    return new Zpl(attrs);
+  }
+
+}
+
+exports.ConfigNamespace = ConfigNamespace;

+ 230 - 0
lib/core/xfa/connection_set.js

@@ -0,0 +1,230 @@
+/**
+ * @licstart The following is the entire license notice for the
+ * Javascript code in this page
+ *
+ * Copyright 2021 Mozilla Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * @licend The above is the entire license notice for the
+ * Javascript code in this page
+ */
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.ConnectionSetNamespace = void 0;
+
+var _namespaces = require("./namespaces.js");
+
+var _xfa_object = require("./xfa_object.js");
+
+const CONNECTION_SET_NS_ID = _namespaces.NamespaceIds.connectionSet.id;
+
+class ConnectionSet extends _xfa_object.XFAObject {
+  constructor(attributes) {
+    super(CONNECTION_SET_NS_ID, "connectionSet", true);
+    this.wsdlConnection = new _xfa_object.XFAObjectArray();
+    this.xmlConnection = new _xfa_object.XFAObjectArray();
+    this.xsdConnection = new _xfa_object.XFAObjectArray();
+  }
+
+}
+
+class EffectiveInputPolicy extends _xfa_object.XFAObject {
+  constructor(attributes) {
+    super(CONNECTION_SET_NS_ID, "effectiveInputPolicy");
+    this.id = attributes.id || "";
+    this.name = attributes.name || "";
+    this.use = attributes.use || "";
+    this.usehref = attributes.usehref || "";
+  }
+
+}
+
+class EffectiveOutputPolicy extends _xfa_object.XFAObject {
+  constructor(attributes) {
+    super(CONNECTION_SET_NS_ID, "effectiveOutputPolicy");
+    this.id = attributes.id || "";
+    this.name = attributes.name || "";
+    this.use = attributes.use || "";
+    this.usehref = attributes.usehref || "";
+  }
+
+}
+
+class Operation extends _xfa_object.StringObject {
+  constructor(attributes) {
+    super(CONNECTION_SET_NS_ID, "operation");
+    this.id = attributes.id || "";
+    this.input = attributes.input || "";
+    this.name = attributes.name || "";
+    this.output = attributes.output || "";
+    this.use = attributes.use || "";
+    this.usehref = attributes.usehref || "";
+  }
+
+}
+
+class RootElement extends _xfa_object.StringObject {
+  constructor(attributes) {
+    super(CONNECTION_SET_NS_ID, "rootElement");
+    this.id = attributes.id || "";
+    this.name = attributes.name || "";
+    this.use = attributes.use || "";
+    this.usehref = attributes.usehref || "";
+  }
+
+}
+
+class SoapAction extends _xfa_object.StringObject {
+  constructor(attributes) {
+    super(CONNECTION_SET_NS_ID, "soapAction");
+    this.id = attributes.id || "";
+    this.name = attributes.name || "";
+    this.use = attributes.use || "";
+    this.usehref = attributes.usehref || "";
+  }
+
+}
+
+class SoapAddress extends _xfa_object.StringObject {
+  constructor(attributes) {
+    super(CONNECTION_SET_NS_ID, "soapAddress");
+    this.id = attributes.id || "";
+    this.name = attributes.name || "";
+    this.use = attributes.use || "";
+    this.usehref = attributes.usehref || "";
+  }
+
+}
+
+class Uri extends _xfa_object.StringObject {
+  constructor(attributes) {
+    super(CONNECTION_SET_NS_ID, "uri");
+    this.id = attributes.id || "";
+    this.name = attributes.name || "";
+    this.use = attributes.use || "";
+    this.usehref = attributes.usehref || "";
+  }
+
+}
+
+class WsdlAddress extends _xfa_object.StringObject {
+  constructor(attributes) {
+    super(CONNECTION_SET_NS_ID, "wsdlAddress");
+    this.id = attributes.id || "";
+    this.name = attributes.name || "";
+    this.use = attributes.use || "";
+    this.usehref = attributes.usehref || "";
+  }
+
+}
+
+class WsdlConnection extends _xfa_object.XFAObject {
+  constructor(attributes) {
+    super(CONNECTION_SET_NS_ID, "wsdlConnection", true);
+    this.dataDescription = attributes.dataDescription || "";
+    this.name = attributes.name || "";
+    this.effectiveInputPolicy = null;
+    this.effectiveOutputPolicy = null;
+    this.operation = null;
+    this.soapAction = null;
+    this.soapAddress = null;
+    this.wsdlAddress = null;
+  }
+
+}
+
+class XmlConnection extends _xfa_object.XFAObject {
+  constructor(attributes) {
+    super(CONNECTION_SET_NS_ID, "xmlConnection", true);
+    this.dataDescription = attributes.dataDescription || "";
+    this.name = attributes.name || "";
+    this.uri = null;
+  }
+
+}
+
+class XsdConnection extends _xfa_object.XFAObject {
+  constructor(attributes) {
+    super(CONNECTION_SET_NS_ID, "xsdConnection", true);
+    this.dataDescription = attributes.dataDescription || "";
+    this.name = attributes.name || "";
+    this.rootElement = null;
+    this.uri = null;
+  }
+
+}
+
+class ConnectionSetNamespace {
+  static [_namespaces.$buildXFAObject](name, attributes) {
+    if (ConnectionSetNamespace.hasOwnProperty(name)) {
+      return ConnectionSetNamespace[name](attributes);
+    }
+
+    return undefined;
+  }
+
+  static connectionSet(attrs) {
+    return new ConnectionSet(attrs);
+  }
+
+  static effectiveInputPolicy(attrs) {
+    return new EffectiveInputPolicy(attrs);
+  }
+
+  static effectiveOutputPolicy(attrs) {
+    return new EffectiveOutputPolicy(attrs);
+  }
+
+  static operation(attrs) {
+    return new Operation(attrs);
+  }
+
+  static rootElement(attrs) {
+    return new RootElement(attrs);
+  }
+
+  static soapAction(attrs) {
+    return new SoapAction(attrs);
+  }
+
+  static soapAddress(attrs) {
+    return new SoapAddress(attrs);
+  }
+
+  static uri(attrs) {
+    return new Uri(attrs);
+  }
+
+  static wsdlAddress(attrs) {
+    return new WsdlAddress(attrs);
+  }
+
+  static wsdlConnection(attrs) {
+    return new WsdlConnection(attrs);
+  }
+
+  static xmlConnection(attrs) {
+    return new XmlConnection(attrs);
+  }
+
+  static xsdConnection(attrs) {
+    return new XsdConnection(attrs);
+  }
+
+}
+
+exports.ConnectionSetNamespace = ConnectionSetNamespace;

+ 82 - 0
lib/core/xfa/datasets.js

@@ -0,0 +1,82 @@
+/**
+ * @licstart The following is the entire license notice for the
+ * Javascript code in this page
+ *
+ * Copyright 2021 Mozilla Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * @licend The above is the entire license notice for the
+ * Javascript code in this page
+ */
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.DatasetsNamespace = void 0;
+
+var _xfa_object = require("./xfa_object.js");
+
+var _namespaces = require("./namespaces.js");
+
+const DATASETS_NS_ID = _namespaces.NamespaceIds.datasets.id;
+
+class Data extends _xfa_object.XmlObject {
+  constructor(attributes) {
+    super(DATASETS_NS_ID, "data", attributes);
+  }
+
+}
+
+class Datasets extends _xfa_object.XFAObject {
+  constructor(attributes) {
+    super(DATASETS_NS_ID, "datasets", true);
+    this.data = null;
+    this.Signature = null;
+  }
+
+  [_xfa_object.$onChild](child) {
+    const name = child[_xfa_object.$nodeName];
+
+    if (name === "data" && child[_xfa_object.$namespaceId] === DATASETS_NS_ID || name === "Signature" && child[_xfa_object.$namespaceId] === _namespaces.NamespaceIds.signature.id) {
+      this[name] = child;
+    } else {
+      child[_xfa_object.$global] = true;
+    }
+
+    this[_xfa_object.$appendChild](child);
+  }
+
+}
+
+class DatasetsNamespace {
+  static [_namespaces.$buildXFAObject](name, attributes) {
+    if (DatasetsNamespace.hasOwnProperty(name)) {
+      return DatasetsNamespace[name](attributes);
+    }
+
+    return undefined;
+  }
+
+  static datasets(attributes) {
+    return new Datasets(attributes);
+  }
+
+  static data(attributes) {
+    return new Data(attributes);
+  }
+
+}
+
+exports.DatasetsNamespace = DatasetsNamespace;

Some files were not shown because too many files changed in this diff