Add the possibility to collect Javascript actions
This commit is contained in:
		
							parent
							
								
									fd1d9cc85f
								
							
						
					
					
						commit
						71ecc3129b
					
				| @ -14,12 +14,14 @@ | ||||
|  */ | ||||
| 
 | ||||
| import { | ||||
|   AnnotationActionEventType, | ||||
|   AnnotationBorderStyleType, | ||||
|   AnnotationFieldFlag, | ||||
|   AnnotationFlag, | ||||
|   AnnotationReplyType, | ||||
|   AnnotationType, | ||||
|   assert, | ||||
|   bytesToString, | ||||
|   escapeString, | ||||
|   getModificationDate, | ||||
|   isString, | ||||
| @ -30,7 +32,15 @@ import { | ||||
|   warn, | ||||
| } from "../shared/util.js"; | ||||
| import { Catalog, FileSpec, ObjectLoader } from "./obj.js"; | ||||
| import { Dict, isDict, isName, isRef, isStream, Name } from "./primitives.js"; | ||||
| import { | ||||
|   Dict, | ||||
|   isDict, | ||||
|   isName, | ||||
|   isRef, | ||||
|   isStream, | ||||
|   Name, | ||||
|   RefSet, | ||||
| } from "./primitives.js"; | ||||
| import { ColorSpace } from "./colorspace.js"; | ||||
| import { getInheritableProperty } from "./core_utils.js"; | ||||
| import { OperatorList } from "./operator_list.js"; | ||||
| @ -569,6 +579,20 @@ class Annotation { | ||||
|     return null; | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|    * Get field data for usage in JS sandbox. | ||||
|    * | ||||
|    * Field object is defined here: | ||||
|    * https://www.adobe.com/content/dam/acom/en/devnet/acrobat/pdfs/js_api_reference.pdf#page=16
 | ||||
|    * | ||||
|    * @public | ||||
|    * @memberof Annotation | ||||
|    * @returns {Object | null} | ||||
|    */ | ||||
|   getFieldObject() { | ||||
|     return null; | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|    * Reset the annotation. | ||||
|    * | ||||
| @ -903,6 +927,7 @@ class WidgetAnnotation extends Annotation { | ||||
| 
 | ||||
|     data.annotationType = AnnotationType.WIDGET; | ||||
|     data.fieldName = this._constructFieldName(dict); | ||||
|     data.actions = this._collectActions(params.xref, dict); | ||||
| 
 | ||||
|     const fieldValue = getInheritableProperty({ | ||||
|       dict, | ||||
| @ -937,6 +962,7 @@ class WidgetAnnotation extends Annotation { | ||||
|     } | ||||
| 
 | ||||
|     data.readOnly = this.hasFieldFlag(AnnotationFieldFlag.READONLY); | ||||
|     data.hidden = this.hasFieldFlag(AnnotationFieldFlag.HIDDEN); | ||||
| 
 | ||||
|     // Hide signatures because we cannot validate them, and unset the fieldValue
 | ||||
|     // since it's (most likely) a `Dict` which is non-serializable and will thus
 | ||||
| @ -944,6 +970,7 @@ class WidgetAnnotation extends Annotation { | ||||
|     if (data.fieldType === "Sig") { | ||||
|       data.fieldValue = null; | ||||
|       this.setFlags(AnnotationFlag.HIDDEN); | ||||
|       data.hidden = true; | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
| @ -1366,6 +1393,87 @@ class WidgetAnnotation extends Annotation { | ||||
|     } | ||||
|     return localResources || Dict.empty; | ||||
|   } | ||||
| 
 | ||||
|   _collectJS(entry, xref, list, parents) { | ||||
|     if (!entry) { | ||||
|       return; | ||||
|     } | ||||
| 
 | ||||
|     let parent = null; | ||||
|     if (isRef(entry)) { | ||||
|       if (parents.has(entry)) { | ||||
|         // If we've already found entry then we've a cycle.
 | ||||
|         return; | ||||
|       } | ||||
|       parent = entry; | ||||
|       parents.put(parent); | ||||
|       entry = xref.fetch(entry); | ||||
|     } | ||||
|     if (Array.isArray(entry)) { | ||||
|       for (const element of entry) { | ||||
|         this._collectJS(element, xref, list, parents); | ||||
|       } | ||||
|     } else if (entry instanceof Dict) { | ||||
|       if (isName(entry.get("S"), "JavaScript") && entry.has("JS")) { | ||||
|         const js = entry.get("JS"); | ||||
|         let code; | ||||
|         if (isStream(js)) { | ||||
|           code = bytesToString(js.getBytes()); | ||||
|         } else { | ||||
|           code = js; | ||||
|         } | ||||
|         code = stringToPDFString(code); | ||||
|         if (code) { | ||||
|           list.push(code); | ||||
|         } | ||||
|       } | ||||
|       this._collectJS(entry.getRaw("Next"), xref, list, parents); | ||||
|     } | ||||
| 
 | ||||
|     if (parent) { | ||||
|       parents.remove(parent); | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   _collectActions(xref, dict) { | ||||
|     const actions = Object.create(null); | ||||
|     if (dict.has("AA")) { | ||||
|       const additionalActions = dict.get("AA"); | ||||
|       for (const key of additionalActions.getKeys()) { | ||||
|         if (key in AnnotationActionEventType) { | ||||
|           const actionDict = additionalActions.getRaw(key); | ||||
|           const parents = new RefSet(); | ||||
|           const list = []; | ||||
|           this._collectJS(actionDict, xref, list, parents); | ||||
|           if (list.length > 0) { | ||||
|             actions[AnnotationActionEventType[key]] = list; | ||||
|           } | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|     // Collect the Action if any (we may have one on pushbutton)
 | ||||
|     if (dict.has("A")) { | ||||
|       const actionDict = dict.get("A"); | ||||
|       const parents = new RefSet(); | ||||
|       const list = []; | ||||
|       this._collectJS(actionDict, xref, list, parents); | ||||
|       if (list.length > 0) { | ||||
|         actions.Action = list; | ||||
|       } | ||||
|     } | ||||
|     return actions; | ||||
|   } | ||||
| 
 | ||||
|   getFieldObject() { | ||||
|     if (this.data.fieldType === "Sig") { | ||||
|       return { | ||||
|         id: this.data.id, | ||||
|         value: null, | ||||
|         type: "signature", | ||||
|       }; | ||||
|     } | ||||
|     return null; | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| class TextWidgetAnnotation extends WidgetAnnotation { | ||||
| @ -1516,6 +1624,23 @@ class TextWidgetAnnotation extends WidgetAnnotation { | ||||
| 
 | ||||
|     return chunks; | ||||
|   } | ||||
| 
 | ||||
|   getFieldObject() { | ||||
|     return { | ||||
|       id: this.data.id, | ||||
|       value: this.data.fieldValue, | ||||
|       multiline: this.data.multiLine, | ||||
|       password: this.hasFieldFlag(AnnotationFieldFlag.PASSWORD), | ||||
|       charLimit: this.data.maxLen, | ||||
|       comb: this.data.comb, | ||||
|       editable: !this.data.readOnly, | ||||
|       hidden: this.data.hidden, | ||||
|       name: this.data.fieldName, | ||||
|       rect: this.data.rect, | ||||
|       actions: this.data.actions, | ||||
|       type: "text", | ||||
|     }; | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| class ButtonWidgetAnnotation extends WidgetAnnotation { | ||||
| @ -1793,6 +1918,28 @@ class ButtonWidgetAnnotation extends WidgetAnnotation { | ||||
|       docBaseUrl: params.pdfManager.docBaseUrl, | ||||
|     }); | ||||
|   } | ||||
| 
 | ||||
|   getFieldObject() { | ||||
|     let type = "button"; | ||||
|     let value = null; | ||||
|     if (this.data.checkBox) { | ||||
|       type = "checkbox"; | ||||
|       value = this.data.fieldValue && this.data.fieldValue !== "Off"; | ||||
|     } else if (this.data.radioButton) { | ||||
|       type = "radiobutton"; | ||||
|       value = this.data.fieldValue === this.data.buttonValue; | ||||
|     } | ||||
|     return { | ||||
|       id: this.data.id, | ||||
|       value, | ||||
|       editable: !this.data.readOnly, | ||||
|       name: this.data.fieldName, | ||||
|       rect: this.data.rect, | ||||
|       hidden: this.data.hidden, | ||||
|       actions: this.data.actions, | ||||
|       type, | ||||
|     }; | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| class ChoiceWidgetAnnotation extends WidgetAnnotation { | ||||
| @ -1843,6 +1990,23 @@ class ChoiceWidgetAnnotation extends WidgetAnnotation { | ||||
|     this.data.multiSelect = this.hasFieldFlag(AnnotationFieldFlag.MULTISELECT); | ||||
|     this._hasText = true; | ||||
|   } | ||||
| 
 | ||||
|   getFieldObject() { | ||||
|     const type = this.data.combo ? "combobox" : "listbox"; | ||||
|     const value = | ||||
|       this.data.fieldValue.length > 0 ? this.data.fieldValue[0] : null; | ||||
|     return { | ||||
|       id: this.data.id, | ||||
|       value, | ||||
|       editable: !this.data.readOnly, | ||||
|       name: this.data.fieldName, | ||||
|       rect: this.data.rect, | ||||
|       multipleSelection: this.data.multiSelect, | ||||
|       hidden: this.data.hidden, | ||||
|       actions: this.data.actions, | ||||
|       type, | ||||
|     }; | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| class TextAnnotation extends MarkupAnnotation { | ||||
|  | ||||
| @ -708,7 +708,7 @@ class PDFDocument { | ||||
|   } | ||||
| 
 | ||||
|   get formInfo() { | ||||
|     const formInfo = { hasAcroForm: false, hasXfa: false }; | ||||
|     const formInfo = { hasAcroForm: false, hasXfa: false, fields: null }; | ||||
|     const acroForm = this.catalog.acroForm; | ||||
|     if (!acroForm) { | ||||
|       return shadow(this, "formInfo", formInfo); | ||||
| @ -736,6 +736,9 @@ class PDFDocument { | ||||
|       const hasOnlyDocumentSignatures = | ||||
|         !!(sigFlags & 0x1) && this._hasOnlyDocumentSignatures(fields); | ||||
|       formInfo.hasAcroForm = hasFields && !hasOnlyDocumentSignatures; | ||||
|       if (hasFields) { | ||||
|         formInfo.fields = fields; | ||||
|       } | ||||
|     } catch (ex) { | ||||
|       if (ex instanceof MissingDataException) { | ||||
|         throw ex; | ||||
| @ -935,6 +938,73 @@ class PDFDocument { | ||||
|       ? this.catalog.cleanup(manuallyTriggered) | ||||
|       : clearPrimitiveCaches(); | ||||
|   } | ||||
| 
 | ||||
|   _collectFieldObjects(name, fieldRef, promises) { | ||||
|     const field = this.xref.fetchIfRef(fieldRef); | ||||
|     if (field.has("T")) { | ||||
|       const partName = stringToPDFString(field.get("T")); | ||||
|       if (name === "") { | ||||
|         name = partName; | ||||
|       } else { | ||||
|         name = `${name}.${partName}`; | ||||
|       } | ||||
|     } | ||||
| 
 | ||||
|     if (!(name in promises)) { | ||||
|       promises.set(name, []); | ||||
|     } | ||||
|     promises.get(name).push( | ||||
|       AnnotationFactory.create( | ||||
|         this.xref, | ||||
|         fieldRef, | ||||
|         this.pdfManager, | ||||
|         this._localIdFactory | ||||
|       ) | ||||
|         .then(annotation => annotation.getFieldObject()) | ||||
|         .catch(function (reason) { | ||||
|           warn(`_collectFieldObjects: "${reason}".`); | ||||
|           return null; | ||||
|         }) | ||||
|     ); | ||||
| 
 | ||||
|     if (field.has("Kids")) { | ||||
|       const kids = field.get("Kids"); | ||||
|       for (const kid of kids) { | ||||
|         this._collectFieldObjects(name, kid, promises); | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   get fieldObjects() { | ||||
|     const formInfo = this.formInfo; | ||||
|     if (!formInfo.fields) { | ||||
|       return shadow(this, "fieldObjects", Promise.resolve(null)); | ||||
|     } | ||||
| 
 | ||||
|     const allFields = Object.create(null); | ||||
|     const fieldPromises = new Map(); | ||||
|     for (const fieldRef of formInfo.fields) { | ||||
|       this._collectFieldObjects("", fieldRef, fieldPromises); | ||||
|     } | ||||
| 
 | ||||
|     const allPromises = []; | ||||
|     for (const [name, promises] of fieldPromises.entries()) { | ||||
|       allPromises.push( | ||||
|         Promise.all(promises).then(fields => { | ||||
|           fields = fields.filter(field => field !== null); | ||||
|           if (fields.length > 0) { | ||||
|             allFields[name] = fields; | ||||
|           } | ||||
|         }) | ||||
|       ); | ||||
|     } | ||||
| 
 | ||||
|     return shadow( | ||||
|       this, | ||||
|       "fieldObjects", | ||||
|       Promise.all(allPromises).then(() => allFields) | ||||
|     ); | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| export { Page, PDFDocument }; | ||||
|  | ||||
| @ -516,6 +516,10 @@ class WorkerMessageHandler { | ||||
|       }); | ||||
|     }); | ||||
| 
 | ||||
|     handler.on("GetFieldObjects", function (data) { | ||||
|       return pdfManager.ensureDoc("fieldObjects"); | ||||
|     }); | ||||
| 
 | ||||
|     handler.on("SaveDocument", function ({ | ||||
|       numPages, | ||||
|       annotationStorage, | ||||
|  | ||||
| @ -876,6 +876,14 @@ class PDFDocumentProxy { | ||||
|   saveDocument(annotationStorage) { | ||||
|     return this._transport.saveDocument(annotationStorage); | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|    * @returns {Promise<Array<Object>>} A promise that is resolved with an | ||||
|    *   {Array<Object>} containing field data for the JS sandbox. | ||||
|    */ | ||||
|   getFieldObjects() { | ||||
|     return this._transport.getFieldObjects(); | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| /** | ||||
| @ -2549,6 +2557,10 @@ class WorkerTransport { | ||||
|       }); | ||||
|   } | ||||
| 
 | ||||
|   getFieldObjects() { | ||||
|     return this.messageHandler.sendWithPromise("GetFieldObjects", null); | ||||
|   } | ||||
| 
 | ||||
|   getDestinations() { | ||||
|     return this.messageHandler.sendWithPromise("GetDestinations", null); | ||||
|   } | ||||
|  | ||||
| @ -144,6 +144,28 @@ const AnnotationBorderStyleType = { | ||||
|   UNDERLINE: 5, | ||||
| }; | ||||
| 
 | ||||
| const AnnotationActionEventType = { | ||||
|   E: "MouseEnter", | ||||
|   X: "MouseExit", | ||||
|   D: "MouseDown", | ||||
|   U: "MouseUp", | ||||
|   Fo: "Focus", | ||||
|   Bl: "Blur", | ||||
|   PO: "PageOpen", | ||||
|   PC: "PageClose", | ||||
|   PV: "PageVisible", | ||||
|   PI: "PageInvisible", | ||||
|   K: "Keystroke", | ||||
|   F: "Format", | ||||
|   V: "Validate", | ||||
|   C: "Calculate", | ||||
|   WC: "WillClose", | ||||
|   WS: "WillSave", | ||||
|   DS: "DidSave", | ||||
|   WP: "WillPrint", | ||||
|   DP: "DidPrint", | ||||
| }; | ||||
| 
 | ||||
| const StreamType = { | ||||
|   UNKNOWN: "UNKNOWN", | ||||
|   FLATE: "FLATE", | ||||
| @ -971,6 +993,7 @@ export { | ||||
|   OPS, | ||||
|   VerbosityLevel, | ||||
|   UNSUPPORTED_FEATURES, | ||||
|   AnnotationActionEventType, | ||||
|   AnnotationBorderStyleType, | ||||
|   AnnotationFieldFlag, | ||||
|   AnnotationFlag, | ||||
|  | ||||
| @ -298,6 +298,7 @@ describe("annotation", function () { | ||||
|       expect(annotation.hasFlag(AnnotationFlag.NOZOOM)).toEqual(true); | ||||
|       expect(annotation.hasFlag(AnnotationFlag.PRINT)).toEqual(true); | ||||
|       expect(annotation.hasFlag(AnnotationFlag.READONLY)).toEqual(false); | ||||
|       expect(annotation.hasFlag(AnnotationFlag.HIDDEN)).toEqual(false); | ||||
|     }); | ||||
| 
 | ||||
|     it("should be viewable and not printable by default", function () { | ||||
| @ -1433,6 +1434,7 @@ describe("annotation", function () { | ||||
|         expect(data.textAlignment).toEqual(null); | ||||
|         expect(data.maxLen).toEqual(null); | ||||
|         expect(data.readOnly).toEqual(false); | ||||
|         expect(data.hidden).toEqual(false); | ||||
|         expect(data.multiLine).toEqual(false); | ||||
|         expect(data.comb).toEqual(false); | ||||
|         done(); | ||||
| @ -1457,6 +1459,7 @@ describe("annotation", function () { | ||||
|         expect(data.textAlignment).toEqual(null); | ||||
|         expect(data.maxLen).toEqual(null); | ||||
|         expect(data.readOnly).toEqual(false); | ||||
|         expect(data.hidden).toEqual(false); | ||||
|         expect(data.multiLine).toEqual(false); | ||||
|         expect(data.comb).toEqual(false); | ||||
|         done(); | ||||
| @ -1484,6 +1487,7 @@ describe("annotation", function () { | ||||
|         expect(data.textAlignment).toEqual(1); | ||||
|         expect(data.maxLen).toEqual(20); | ||||
|         expect(data.readOnly).toEqual(true); | ||||
|         expect(data.hidden).toEqual(false); | ||||
|         expect(data.multiLine).toEqual(true); | ||||
|         done(); | ||||
|       }, done.fail); | ||||
| @ -1863,6 +1867,92 @@ describe("annotation", function () { | ||||
|           done(); | ||||
|         }, done.fail); | ||||
|     }); | ||||
| 
 | ||||
|     it("should get field object for usage in JS sandbox", function (done) { | ||||
|       const textWidgetRef = Ref.get(123, 0); | ||||
|       const xDictRef = Ref.get(141, 0); | ||||
|       const dDictRef = Ref.get(262, 0); | ||||
|       const next0Ref = Ref.get(314, 0); | ||||
|       const next1Ref = Ref.get(271, 0); | ||||
|       const next2Ref = Ref.get(577, 0); | ||||
|       const next00Ref = Ref.get(413, 0); | ||||
|       const xDict = new Dict(); | ||||
|       const dDict = new Dict(); | ||||
|       const next0Dict = new Dict(); | ||||
|       const next1Dict = new Dict(); | ||||
|       const next2Dict = new Dict(); | ||||
|       const next00Dict = new Dict(); | ||||
| 
 | ||||
|       const xref = new XRefMock([ | ||||
|         { ref: textWidgetRef, data: textWidgetDict }, | ||||
|         { ref: xDictRef, data: xDict }, | ||||
|         { ref: dDictRef, data: dDict }, | ||||
|         { ref: next0Ref, data: next0Dict }, | ||||
|         { ref: next00Ref, data: next00Dict }, | ||||
|         { ref: next1Ref, data: next1Dict }, | ||||
|         { ref: next2Ref, data: next2Dict }, | ||||
|       ]); | ||||
| 
 | ||||
|       const JS = Name.get("JavaScript"); | ||||
|       const additionalActionsDict = new Dict(); | ||||
|       const eDict = new Dict(); | ||||
|       eDict.set("JS", "hello()"); | ||||
|       eDict.set("S", JS); | ||||
|       additionalActionsDict.set("E", eDict); | ||||
| 
 | ||||
|       // Test the cycle detection here
 | ||||
|       xDict.set("JS", "world()"); | ||||
|       xDict.set("S", JS); | ||||
|       xDict.set("Next", [next0Ref, next1Ref, next2Ref, xDictRef]); | ||||
| 
 | ||||
|       next0Dict.set("JS", "olleh()"); | ||||
|       next0Dict.set("S", JS); | ||||
|       next0Dict.set("Next", next00Ref); | ||||
| 
 | ||||
|       next00Dict.set("JS", "foo()"); | ||||
|       next00Dict.set("S", JS); | ||||
|       next00Dict.set("Next", next0Ref); | ||||
| 
 | ||||
|       next1Dict.set("JS", "dlrow()"); | ||||
|       next1Dict.set("S", JS); | ||||
|       next1Dict.set("Next", xDictRef); | ||||
| 
 | ||||
|       next2Dict.set("JS", "oof()"); | ||||
|       next2Dict.set("S", JS); | ||||
| 
 | ||||
|       dDict.set("JS", "bar()"); | ||||
|       dDict.set("S", JS); | ||||
|       dDict.set("Next", dDictRef); | ||||
|       additionalActionsDict.set("D", dDictRef); | ||||
| 
 | ||||
|       additionalActionsDict.set("X", xDictRef); | ||||
|       textWidgetDict.set("AA", additionalActionsDict); | ||||
| 
 | ||||
|       partialEvaluator.xref = xref; | ||||
| 
 | ||||
|       AnnotationFactory.create( | ||||
|         xref, | ||||
|         textWidgetRef, | ||||
|         pdfManagerMock, | ||||
|         idFactoryMock | ||||
|       ) | ||||
|         .then(annotation => { | ||||
|           return annotation.getFieldObject(); | ||||
|         }) | ||||
|         .then(object => { | ||||
|           const actions = object.actions; | ||||
|           expect(actions.MouseEnter).toEqual(["hello()"]); | ||||
|           expect(actions.MouseExit).toEqual([ | ||||
|             "world()", | ||||
|             "olleh()", | ||||
|             "foo()", | ||||
|             "dlrow()", | ||||
|             "oof()", | ||||
|           ]); | ||||
|           expect(actions.MouseDown).toEqual(["bar()"]); | ||||
|           done(); | ||||
|         }, done.fail); | ||||
|     }); | ||||
|   }); | ||||
| 
 | ||||
|   describe("ButtonWidgetAnnotation", function () { | ||||
| @ -2524,7 +2614,11 @@ describe("annotation", function () { | ||||
|     it("should handle push buttons", function (done) { | ||||
|       const buttonWidgetRef = Ref.get(124, 0); | ||||
|       buttonWidgetDict.set("Ff", AnnotationFieldFlag.PUSHBUTTON); | ||||
|       buttonWidgetDict.set("A", "whatever"); | ||||
| 
 | ||||
|       const actionDict = new Dict(); | ||||
|       actionDict.set("S", Name.get("JavaScript")); | ||||
|       actionDict.set("JS", "do_something();"); | ||||
|       buttonWidgetDict.set("A", actionDict); | ||||
| 
 | ||||
|       const xref = new XRefMock([ | ||||
|         { ref: buttonWidgetRef, data: buttonWidgetDict }, | ||||
| @ -2538,6 +2632,7 @@ describe("annotation", function () { | ||||
|       ).then(({ data }) => { | ||||
|         expect(data.annotationType).toEqual(AnnotationType.WIDGET); | ||||
|         expect(data.pushButton).toEqual(true); | ||||
|         expect(data.actions.Action).toEqual(["do_something();"]); | ||||
|         done(); | ||||
|       }, done.fail); | ||||
|     }); | ||||
| @ -2779,6 +2874,7 @@ describe("annotation", function () { | ||||
|       ).then(({ data }) => { | ||||
|         expect(data.annotationType).toEqual(AnnotationType.WIDGET); | ||||
|         expect(data.readOnly).toEqual(false); | ||||
|         expect(data.hidden).toEqual(false); | ||||
|         expect(data.combo).toEqual(false); | ||||
|         expect(data.multiSelect).toEqual(false); | ||||
|         done(); | ||||
| @ -2801,6 +2897,7 @@ describe("annotation", function () { | ||||
|       ).then(({ data }) => { | ||||
|         expect(data.annotationType).toEqual(AnnotationType.WIDGET); | ||||
|         expect(data.readOnly).toEqual(false); | ||||
|         expect(data.hidden).toEqual(false); | ||||
|         expect(data.combo).toEqual(false); | ||||
|         expect(data.multiSelect).toEqual(false); | ||||
|         done(); | ||||
| @ -2828,6 +2925,7 @@ describe("annotation", function () { | ||||
|       ).then(({ data }) => { | ||||
|         expect(data.annotationType).toEqual(AnnotationType.WIDGET); | ||||
|         expect(data.readOnly).toEqual(true); | ||||
|         expect(data.hidden).toEqual(false); | ||||
|         expect(data.combo).toEqual(true); | ||||
|         expect(data.multiSelect).toEqual(true); | ||||
|         done(); | ||||
|  | ||||
| @ -63,6 +63,7 @@ describe("document", function () { | ||||
|       expect(pdfDocument.formInfo).toEqual({ | ||||
|         hasAcroForm: false, | ||||
|         hasXfa: false, | ||||
|         fields: null, | ||||
|       }); | ||||
|     }); | ||||
| 
 | ||||
| @ -75,6 +76,7 @@ describe("document", function () { | ||||
|       expect(pdfDocument.formInfo).toEqual({ | ||||
|         hasAcroForm: false, | ||||
|         hasXfa: false, | ||||
|         fields: null, | ||||
|       }); | ||||
| 
 | ||||
|       acroForm.set("XFA", ["foo", "bar"]); | ||||
| @ -82,6 +84,7 @@ describe("document", function () { | ||||
|       expect(pdfDocument.formInfo).toEqual({ | ||||
|         hasAcroForm: false, | ||||
|         hasXfa: true, | ||||
|         fields: null, | ||||
|       }); | ||||
| 
 | ||||
|       acroForm.set("XFA", new StringStream("")); | ||||
| @ -89,6 +92,7 @@ describe("document", function () { | ||||
|       expect(pdfDocument.formInfo).toEqual({ | ||||
|         hasAcroForm: false, | ||||
|         hasXfa: false, | ||||
|         fields: null, | ||||
|       }); | ||||
| 
 | ||||
|       acroForm.set("XFA", new StringStream("non-empty")); | ||||
| @ -96,6 +100,7 @@ describe("document", function () { | ||||
|       expect(pdfDocument.formInfo).toEqual({ | ||||
|         hasAcroForm: false, | ||||
|         hasXfa: true, | ||||
|         fields: null, | ||||
|       }); | ||||
|     }); | ||||
| 
 | ||||
| @ -108,6 +113,7 @@ describe("document", function () { | ||||
|       expect(pdfDocument.formInfo).toEqual({ | ||||
|         hasAcroForm: false, | ||||
|         hasXfa: false, | ||||
|         fields: null, | ||||
|       }); | ||||
| 
 | ||||
|       acroForm.set("Fields", ["foo", "bar"]); | ||||
| @ -115,6 +121,7 @@ describe("document", function () { | ||||
|       expect(pdfDocument.formInfo).toEqual({ | ||||
|         hasAcroForm: true, | ||||
|         hasXfa: false, | ||||
|         fields: ["foo", "bar"], | ||||
|       }); | ||||
| 
 | ||||
|       // If the first bit of the `SigFlags` entry is set and the `Fields` array
 | ||||
| @ -125,6 +132,7 @@ describe("document", function () { | ||||
|       expect(pdfDocument.formInfo).toEqual({ | ||||
|         hasAcroForm: true, | ||||
|         hasXfa: false, | ||||
|         fields: ["foo", "bar"], | ||||
|       }); | ||||
| 
 | ||||
|       const annotationDict = new Dict(); | ||||
| @ -147,6 +155,7 @@ describe("document", function () { | ||||
|       expect(pdfDocument.formInfo).toEqual({ | ||||
|         hasAcroForm: false, | ||||
|         hasXfa: false, | ||||
|         fields: null, | ||||
|       }); | ||||
|     }); | ||||
|   }); | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user