[api-minor] Ensure that PDFDocumentProxy.hasJSActions won't fail if MissingDataExceptions are thrown during the associated worker-thread parsing
				
					
				
			With the current implementation of `PDFDocument.hasJSActions`, in the worker-thread, we're not actually handling not-yet-loaded data correctly. This can thus fail in *two* different ways: - The `PDFDocument.fieldObjects` getter (and its helper method), while it may *return* a Promise, still fetches all of its data synchronously and it can thus throw a `MissingDataException` during parsing. - The `Catalog.jsActions` getter, which is completely synchronous, can obviously throw a `MissingDataException` during parsing. If either of these cases occur currently, the `PDFDocumentProxy.hasJSActions` method in the API can either return a *rejected* Promise (which it never should) or possibly "hang" and never resolve. *Please note:* While I've not *yet* seen this error in an actual PDF document, it can happen during loading if you're unlucky enough with e.g. the structure of the PDF document and/or the download speed offered by the server. This patch is thus based on code-inspection *and* on manually throwing a `MissingDataException` on the first access of `Catalog.jsActions` to simulate this situation. Finally, this patch adds a couple of *API* unit-tests for this (since none existed).
This commit is contained in:
		
							parent
							
								
									4aa27cc645
								
							
						
					
					
						commit
						2b2234fd5a
					
				@ -1182,19 +1182,28 @@ class PDFDocument {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  get hasJSActions() {
 | 
			
		||||
    return shadow(
 | 
			
		||||
      this,
 | 
			
		||||
      "hasJSActions",
 | 
			
		||||
      this.fieldObjects.then(fieldObjects => {
 | 
			
		||||
        return (
 | 
			
		||||
          (fieldObjects !== null &&
 | 
			
		||||
            Object.values(fieldObjects).some(fieldObject =>
 | 
			
		||||
              fieldObject.some(object => object.actions !== null)
 | 
			
		||||
            )) ||
 | 
			
		||||
          !!this.catalog.jsActions
 | 
			
		||||
        );
 | 
			
		||||
      })
 | 
			
		||||
    );
 | 
			
		||||
    const promise = this.pdfManager.ensure(this, "_parseHasJSActions");
 | 
			
		||||
    return shadow(this, "hasJSActions", promise);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * @private
 | 
			
		||||
   */
 | 
			
		||||
  async _parseHasJSActions() {
 | 
			
		||||
    const [catalogJsActions, fieldObjects] = await Promise.all([
 | 
			
		||||
      this.pdfManager.ensureCatalog("jsActions"),
 | 
			
		||||
      this.pdfManager.ensure(this, "fieldObjects"),
 | 
			
		||||
    ]);
 | 
			
		||||
 | 
			
		||||
    if (catalogJsActions) {
 | 
			
		||||
      return true;
 | 
			
		||||
    }
 | 
			
		||||
    if (fieldObjects) {
 | 
			
		||||
      return Object.values(fieldObjects).some(fieldObject =>
 | 
			
		||||
        fieldObject.some(object => object.actions !== null)
 | 
			
		||||
      );
 | 
			
		||||
    }
 | 
			
		||||
    return false;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  get calculationOrderIds() {
 | 
			
		||||
 | 
			
		||||
@ -1014,6 +1014,23 @@ describe("api", function () {
 | 
			
		||||
        .catch(done.fail);
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    it("gets hasJSActions, in document without javaScript", async function () {
 | 
			
		||||
      const hasJSActions = await pdfDocument.hasJSActions();
 | 
			
		||||
 | 
			
		||||
      expect(hasJSActions).toEqual(false);
 | 
			
		||||
    });
 | 
			
		||||
    it("gets hasJSActions, in document with javaScript", async function () {
 | 
			
		||||
      const loadingTask = getDocument(
 | 
			
		||||
        buildGetDocumentParams("doc_actions.pdf")
 | 
			
		||||
      );
 | 
			
		||||
      const pdfDoc = await loadingTask.promise;
 | 
			
		||||
      const hasJSActions = await pdfDoc.hasJSActions();
 | 
			
		||||
 | 
			
		||||
      expect(hasJSActions).toEqual(true);
 | 
			
		||||
 | 
			
		||||
      await loadingTask.destroy();
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    it("gets JSActions (none)", function (done) {
 | 
			
		||||
      const promise = pdfDocument.getJSActions();
 | 
			
		||||
      promise
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user