/**
 * @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";

var _util = require("../../shared/util.js");

var _test_utils = require("./test_utils.js");

var _api = require("../../display/api.js");

var _display_utils = require("../../display/display_utils.js");

var _ui_utils = require("../../web/ui_utils.js");

var _image_utils = require("../../core/image_utils.js");

var _worker_options = require("../../display/worker_options.js");

var _is_node = require("../../shared/is_node.js");

var _metadata = require("../../display/metadata.js");

describe("api", function () {
  const basicApiFileName = "basicapi.pdf";
  const basicApiFileLength = 105779;
  const basicApiGetDocumentParams = (0, _test_utils.buildGetDocumentParams)(basicApiFileName);
  let CanvasFactory;
  beforeAll(function () {
    CanvasFactory = new _api.DefaultCanvasFactory();
  });
  afterAll(function () {
    CanvasFactory = null;
  });

  function waitSome(callback) {
    const WAIT_TIMEOUT = 10;
    setTimeout(function () {
      callback();
    }, WAIT_TIMEOUT);
  }

  function mergeText(items) {
    return items.map(chunk => chunk.str + (chunk.hasEOL ? "\n" : "")).join("");
  }

  describe("getDocument", function () {
    it("creates pdf doc from URL-string", async function () {
      const urlStr = _test_utils.TEST_PDFS_PATH + basicApiFileName;
      const loadingTask = (0, _api.getDocument)(urlStr);
      expect(loadingTask instanceof _api.PDFDocumentLoadingTask).toEqual(true);
      const pdfDocument = await loadingTask.promise;
      expect(typeof urlStr).toEqual("string");
      expect(pdfDocument instanceof _api.PDFDocumentProxy).toEqual(true);
      expect(pdfDocument.numPages).toEqual(3);
      await loadingTask.destroy();
    });
    it("creates pdf doc from URL-object", async function () {
      if (_is_node.isNodeJS) {
        pending("window.location is not supported in Node.js.");
      }

      const urlObj = new URL(_test_utils.TEST_PDFS_PATH + basicApiFileName, window.location);
      const loadingTask = (0, _api.getDocument)(urlObj);
      expect(loadingTask instanceof _api.PDFDocumentLoadingTask).toEqual(true);
      const pdfDocument = await loadingTask.promise;
      expect(urlObj instanceof URL).toEqual(true);
      expect(pdfDocument instanceof _api.PDFDocumentProxy).toEqual(true);
      expect(pdfDocument.numPages).toEqual(3);
      await loadingTask.destroy();
    });
    it("creates pdf doc from URL", async function () {
      const loadingTask = (0, _api.getDocument)(basicApiGetDocumentParams);
      expect(loadingTask instanceof _api.PDFDocumentLoadingTask).toEqual(true);
      const progressReportedCapability = (0, _util.createPromiseCapability)();

      loadingTask.onProgress = function (progressData) {
        if (!progressReportedCapability.settled) {
          progressReportedCapability.resolve(progressData);
        }
      };

      const data = await Promise.all([progressReportedCapability.promise, loadingTask.promise]);
      expect(data[0].loaded / data[0].total >= 0).toEqual(true);
      expect(data[1] instanceof _api.PDFDocumentProxy).toEqual(true);
      expect(loadingTask).toEqual(data[1].loadingTask);
      await loadingTask.destroy();
    });
    it("creates pdf doc from URL and aborts before worker initialized", async function () {
      const loadingTask = (0, _api.getDocument)(basicApiGetDocumentParams);
      expect(loadingTask instanceof _api.PDFDocumentLoadingTask).toEqual(true);
      const destroyed = loadingTask.destroy();

      try {
        await loadingTask.promise;
        expect(false).toEqual(true);
      } catch (reason) {
        expect(true).toEqual(true);
        await destroyed;
      }
    });
    it("creates pdf doc from URL and aborts loading after worker initialized", async function () {
      const loadingTask = (0, _api.getDocument)(basicApiGetDocumentParams);
      expect(loadingTask instanceof _api.PDFDocumentLoadingTask).toEqual(true);

      const destroyed = loadingTask._worker.promise.then(function () {
        return loadingTask.destroy();
      });

      await destroyed;
      expect(true).toEqual(true);
    });
    it("creates pdf doc from typed array", async function () {
      const typedArrayPdf = await _test_utils.DefaultFileReaderFactory.fetch({
        path: _test_utils.TEST_PDFS_PATH + basicApiFileName
      });
      expect(typedArrayPdf.length).toEqual(basicApiFileLength);
      const loadingTask = (0, _api.getDocument)(typedArrayPdf);
      expect(loadingTask instanceof _api.PDFDocumentLoadingTask).toEqual(true);
      const progressReportedCapability = (0, _util.createPromiseCapability)();

      loadingTask.onProgress = function (data) {
        progressReportedCapability.resolve(data);
      };

      const data = await Promise.all([loadingTask.promise, progressReportedCapability.promise]);
      expect(data[0] instanceof _api.PDFDocumentProxy).toEqual(true);
      expect(data[1].loaded / data[1].total).toEqual(1);
      await loadingTask.destroy();
    });
    it("creates pdf doc from invalid PDF file", async function () {
      const loadingTask = (0, _api.getDocument)((0, _test_utils.buildGetDocumentParams)("bug1020226.pdf"));
      expect(loadingTask instanceof _api.PDFDocumentLoadingTask).toEqual(true);

      try {
        await loadingTask.promise;
        expect(false).toEqual(true);
      } catch (reason) {
        expect(reason instanceof _util.InvalidPDFException).toEqual(true);
        expect(reason.message).toEqual("Invalid PDF structure.");
      }

      await loadingTask.destroy();
    });
    it("creates pdf doc from non-existent URL", async function () {
      if (!_is_node.isNodeJS) {
        pending("Fails intermittently on Linux in browsers.");
      }

      const loadingTask = (0, _api.getDocument)((0, _test_utils.buildGetDocumentParams)("non-existent.pdf"));
      expect(loadingTask instanceof _api.PDFDocumentLoadingTask).toEqual(true);

      try {
        await loadingTask.promise;
        expect(false).toEqual(true);
      } catch (reason) {
        expect(reason instanceof _util.MissingPDFException).toEqual(true);
      }

      await loadingTask.destroy();
    });
    it("creates pdf doc from PDF file protected with user and owner password", async function () {
      const loadingTask = (0, _api.getDocument)((0, _test_utils.buildGetDocumentParams)("pr6531_1.pdf"));
      expect(loadingTask instanceof _api.PDFDocumentLoadingTask).toEqual(true);
      const passwordNeededCapability = (0, _util.createPromiseCapability)();
      const passwordIncorrectCapability = (0, _util.createPromiseCapability)();

      loadingTask.onPassword = function (updatePassword, reason) {
        if (reason === _util.PasswordResponses.NEED_PASSWORD && !passwordNeededCapability.settled) {
          passwordNeededCapability.resolve();
          updatePassword("qwerty");
          return;
        }

        if (reason === _util.PasswordResponses.INCORRECT_PASSWORD && !passwordIncorrectCapability.settled) {
          passwordIncorrectCapability.resolve();
          updatePassword("asdfasdf");
          return;
        }

        expect(false).toEqual(true);
      };

      const data = await Promise.all([passwordNeededCapability.promise, passwordIncorrectCapability.promise, loadingTask.promise]);
      expect(data[2] instanceof _api.PDFDocumentProxy).toEqual(true);
      await loadingTask.destroy();
    });
    it("creates pdf doc from PDF file protected with only a user password", async function () {
      const filename = "pr6531_2.pdf";
      const passwordNeededLoadingTask = (0, _api.getDocument)((0, _test_utils.buildGetDocumentParams)(filename, {
        password: ""
      }));
      expect(passwordNeededLoadingTask instanceof _api.PDFDocumentLoadingTask).toEqual(true);
      const result1 = passwordNeededLoadingTask.promise.then(function () {
        expect(false).toEqual(true);
        return Promise.reject(new Error("loadingTask should be rejected"));
      }, function (data) {
        expect(data instanceof _util.PasswordException).toEqual(true);
        expect(data.code).toEqual(_util.PasswordResponses.NEED_PASSWORD);
        return passwordNeededLoadingTask.destroy();
      });
      const passwordIncorrectLoadingTask = (0, _api.getDocument)((0, _test_utils.buildGetDocumentParams)(filename, {
        password: "qwerty"
      }));
      expect(passwordIncorrectLoadingTask instanceof _api.PDFDocumentLoadingTask).toEqual(true);
      const result2 = passwordIncorrectLoadingTask.promise.then(function () {
        expect(false).toEqual(true);
        return Promise.reject(new Error("loadingTask should be rejected"));
      }, function (data) {
        expect(data instanceof _util.PasswordException).toEqual(true);
        expect(data.code).toEqual(_util.PasswordResponses.INCORRECT_PASSWORD);
        return passwordIncorrectLoadingTask.destroy();
      });
      const passwordAcceptedLoadingTask = (0, _api.getDocument)((0, _test_utils.buildGetDocumentParams)(filename, {
        password: "asdfasdf"
      }));
      expect(passwordAcceptedLoadingTask instanceof _api.PDFDocumentLoadingTask).toEqual(true);
      const result3 = passwordAcceptedLoadingTask.promise.then(function (data) {
        expect(data instanceof _api.PDFDocumentProxy).toEqual(true);
        return passwordAcceptedLoadingTask.destroy();
      });
      await Promise.all([result1, result2, result3]);
    });
    it("creates pdf doc from password protected PDF file and aborts/throws " + "in the onPassword callback (issue 7806)", async function () {
      const filename = "issue3371.pdf";
      const passwordNeededLoadingTask = (0, _api.getDocument)((0, _test_utils.buildGetDocumentParams)(filename));
      expect(passwordNeededLoadingTask instanceof _api.PDFDocumentLoadingTask).toEqual(true);
      const passwordIncorrectLoadingTask = (0, _api.getDocument)((0, _test_utils.buildGetDocumentParams)(filename, {
        password: "qwerty"
      }));
      expect(passwordIncorrectLoadingTask instanceof _api.PDFDocumentLoadingTask).toEqual(true);
      let passwordNeededDestroyed;

      passwordNeededLoadingTask.onPassword = function (callback, reason) {
        if (reason === _util.PasswordResponses.NEED_PASSWORD) {
          passwordNeededDestroyed = passwordNeededLoadingTask.destroy();
          return;
        }

        expect(false).toEqual(true);
      };

      const result1 = passwordNeededLoadingTask.promise.then(function () {
        expect(false).toEqual(true);
        return Promise.reject(new Error("loadingTask should be rejected"));
      }, function (reason) {
        expect(reason instanceof _util.PasswordException).toEqual(true);
        expect(reason.code).toEqual(_util.PasswordResponses.NEED_PASSWORD);
        return passwordNeededDestroyed;
      });

      passwordIncorrectLoadingTask.onPassword = function (callback, reason) {
        if (reason === _util.PasswordResponses.INCORRECT_PASSWORD) {
          throw new Error("Incorrect password");
        }

        expect(false).toEqual(true);
      };

      const result2 = passwordIncorrectLoadingTask.promise.then(function () {
        expect(false).toEqual(true);
        return Promise.reject(new Error("loadingTask should be rejected"));
      }, function (reason) {
        expect(reason instanceof _util.PasswordException).toEqual(true);
        expect(reason.code).toEqual(_util.PasswordResponses.INCORRECT_PASSWORD);
        return passwordIncorrectLoadingTask.destroy();
      });
      await Promise.all([result1, result2]);
    });
    it("creates pdf doc from empty typed array", async function () {
      const loadingTask = (0, _api.getDocument)(new Uint8Array(0));
      expect(loadingTask instanceof _api.PDFDocumentLoadingTask).toEqual(true);

      try {
        await loadingTask.promise;
        expect(false).toEqual(true);
      } catch (reason) {
        expect(reason instanceof _util.InvalidPDFException).toEqual(true);
        expect(reason.message).toEqual("The PDF file is empty, i.e. its size is zero bytes.");
      }

      await loadingTask.destroy();
    });
    it("checks that `docId`s are unique and increasing", async function () {
      const loadingTask1 = (0, _api.getDocument)(basicApiGetDocumentParams);
      expect(loadingTask1 instanceof _api.PDFDocumentLoadingTask).toEqual(true);
      await loadingTask1.promise;
      const docId1 = loadingTask1.docId;
      const loadingTask2 = (0, _api.getDocument)(basicApiGetDocumentParams);
      expect(loadingTask2 instanceof _api.PDFDocumentLoadingTask).toEqual(true);
      await loadingTask2.promise;
      const docId2 = loadingTask2.docId;
      expect(docId1).not.toEqual(docId2);
      const docIdRegExp = /^d(\d+)$/,
            docNum1 = docIdRegExp.exec(docId1)?.[1],
            docNum2 = docIdRegExp.exec(docId2)?.[1];
      expect(+docNum1).toBeLessThan(+docNum2);
      await Promise.all([loadingTask1.destroy(), loadingTask2.destroy()]);
    });
    it("creates pdf doc from PDF file with bad XRef entry", async function () {
      const loadingTask = (0, _api.getDocument)((0, _test_utils.buildGetDocumentParams)("PDFBOX-4352-0.pdf", {
        rangeChunkSize: 100
      }));
      expect(loadingTask instanceof _api.PDFDocumentLoadingTask).toEqual(true);
      const pdfDocument = await loadingTask.promise;
      expect(pdfDocument.numPages).toEqual(1);
      const page = await pdfDocument.getPage(1);
      expect(page instanceof _api.PDFPageProxy).toEqual(true);
      const opList = await page.getOperatorList();
      expect(opList.fnArray.length).toEqual(0);
      expect(opList.argsArray.length).toEqual(0);
      expect(opList.lastChunk).toEqual(true);
      await loadingTask.destroy();
    });
    it("creates pdf doc from PDF file with bad XRef header", async function () {
      const loadingTask = (0, _api.getDocument)((0, _test_utils.buildGetDocumentParams)("GHOSTSCRIPT-698804-1-fuzzed.pdf"));
      expect(loadingTask instanceof _api.PDFDocumentLoadingTask).toEqual(true);
      const pdfDocument = await loadingTask.promise;
      expect(pdfDocument.numPages).toEqual(1);
      const page = await pdfDocument.getPage(1);
      expect(page instanceof _api.PDFPageProxy).toEqual(true);
      const opList = await page.getOperatorList();
      expect(opList.fnArray.length).toEqual(0);
      expect(opList.argsArray.length).toEqual(0);
      expect(opList.lastChunk).toEqual(true);
      await loadingTask.destroy();
    });
    it("creates pdf doc from PDF file with bad XRef byteWidths", async function () {
      const loadingTask = (0, _api.getDocument)((0, _test_utils.buildGetDocumentParams)("REDHAT-1531897-0.pdf"));
      expect(loadingTask instanceof _api.PDFDocumentLoadingTask).toEqual(true);

      try {
        await loadingTask.promise;
        expect(false).toEqual(true);
      } catch (reason) {
        expect(reason instanceof _util.InvalidPDFException).toEqual(true);
        expect(reason.message).toEqual("Invalid PDF structure.");
      }

      await loadingTask.destroy();
    });
    it("creates pdf doc from PDF file with inaccessible /Pages tree", async function () {
      const loadingTask = (0, _api.getDocument)((0, _test_utils.buildGetDocumentParams)("poppler-395-0-fuzzed.pdf"));
      expect(loadingTask instanceof _api.PDFDocumentLoadingTask).toEqual(true);

      try {
        await loadingTask.promise;
        expect(false).toEqual(true);
      } catch (reason) {
        expect(reason instanceof _util.InvalidPDFException).toEqual(true);
        expect(reason.message).toEqual("Invalid Root reference.");
      }

      await loadingTask.destroy();
    });
    it("creates pdf doc from PDF files, with bad /Pages tree /Count", async function () {
      const loadingTask1 = (0, _api.getDocument)((0, _test_utils.buildGetDocumentParams)("poppler-67295-0.pdf"));
      const loadingTask2 = (0, _api.getDocument)((0, _test_utils.buildGetDocumentParams)("poppler-85140-0.pdf"));
      expect(loadingTask1 instanceof _api.PDFDocumentLoadingTask).toEqual(true);
      expect(loadingTask2 instanceof _api.PDFDocumentLoadingTask).toEqual(true);
      const pdfDocument1 = await loadingTask1.promise;
      const pdfDocument2 = await loadingTask2.promise;
      expect(pdfDocument1.numPages).toEqual(1);
      expect(pdfDocument2.numPages).toEqual(1);
      const page = await pdfDocument1.getPage(1);
      expect(page instanceof _api.PDFPageProxy).toEqual(true);
      const opList = await page.getOperatorList();
      expect(opList.fnArray.length).toBeGreaterThan(5);
      expect(opList.argsArray.length).toBeGreaterThan(5);
      expect(opList.lastChunk).toEqual(true);

      try {
        await pdfDocument2.getPage(1);
        expect(false).toEqual(true);
      } catch (reason) {
        expect(reason instanceof _util.UnknownErrorException).toEqual(true);
        expect(reason.message).toEqual("Bad (uncompressed) XRef entry: 3R");
      }

      await Promise.all([loadingTask1.destroy(), loadingTask2.destroy()]);
    });
    it("creates pdf doc from PDF files, with circular references", async function () {
      const loadingTask1 = (0, _api.getDocument)((0, _test_utils.buildGetDocumentParams)("poppler-91414-0-53.pdf"));
      const loadingTask2 = (0, _api.getDocument)((0, _test_utils.buildGetDocumentParams)("poppler-91414-0-54.pdf"));
      expect(loadingTask1 instanceof _api.PDFDocumentLoadingTask).toEqual(true);
      expect(loadingTask2 instanceof _api.PDFDocumentLoadingTask).toEqual(true);
      const pdfDocument1 = await loadingTask1.promise;
      const pdfDocument2 = await loadingTask2.promise;
      expect(pdfDocument1.numPages).toEqual(1);
      expect(pdfDocument2.numPages).toEqual(1);
      const pageA = await pdfDocument1.getPage(1);
      const pageB = await pdfDocument2.getPage(1);
      expect(pageA instanceof _api.PDFPageProxy).toEqual(true);
      expect(pageB instanceof _api.PDFPageProxy).toEqual(true);

      for (const opList of [await pageA.getOperatorList(), await pageB.getOperatorList()]) {
        expect(opList.fnArray.length).toBeGreaterThan(5);
        expect(opList.argsArray.length).toBeGreaterThan(5);
        expect(opList.lastChunk).toEqual(true);
      }

      await Promise.all([loadingTask1.destroy(), loadingTask2.destroy()]);
    });
    it("creates pdf doc from PDF files, with bad /Pages tree /Kids entries", async function () {
      const loadingTask1 = (0, _api.getDocument)((0, _test_utils.buildGetDocumentParams)("poppler-742-0-fuzzed.pdf"));
      const loadingTask2 = (0, _api.getDocument)((0, _test_utils.buildGetDocumentParams)("poppler-937-0-fuzzed.pdf"));
      expect(loadingTask1 instanceof _api.PDFDocumentLoadingTask).toEqual(true);
      expect(loadingTask2 instanceof _api.PDFDocumentLoadingTask).toEqual(true);
      const pdfDocument1 = await loadingTask1.promise;
      const pdfDocument2 = await loadingTask2.promise;
      expect(pdfDocument1.numPages).toEqual(1);
      expect(pdfDocument2.numPages).toEqual(1);

      try {
        await pdfDocument1.getPage(1);
        expect(false).toEqual(true);
      } catch (reason) {
        expect(reason instanceof _util.UnknownErrorException).toEqual(true);
        expect(reason.message).toEqual("Page dictionary kids object is not an array.");
      }

      try {
        await pdfDocument2.getPage(1);
        expect(false).toEqual(true);
      } catch (reason) {
        expect(reason instanceof _util.UnknownErrorException).toEqual(true);
        expect(reason.message).toEqual("Page dictionary kids object is not an array.");
      }

      await Promise.all([loadingTask1.destroy(), loadingTask2.destroy()]);
    });
  });
  describe("PDFWorker", function () {
    it("worker created or destroyed", async function () {
      if (_is_node.isNodeJS) {
        pending("Worker is not supported in Node.js.");
      }

      const worker = new _api.PDFWorker({
        name: "test1"
      });
      await worker.promise;
      expect(worker.name).toEqual("test1");
      expect(!!worker.port).toEqual(true);
      expect(worker.destroyed).toEqual(false);
      expect(!!worker._webWorker).toEqual(true);
      expect(worker.port === worker._webWorker).toEqual(true);
      worker.destroy();
      expect(!!worker.port).toEqual(false);
      expect(worker.destroyed).toEqual(true);
    });
    it("worker created or destroyed by getDocument", async function () {
      if (_is_node.isNodeJS) {
        pending("Worker is not supported in Node.js.");
      }

      const loadingTask = (0, _api.getDocument)(basicApiGetDocumentParams);
      let worker;
      loadingTask.promise.then(function () {
        worker = loadingTask._worker;
        expect(!!worker).toEqual(true);
      });
      const destroyPromise = loadingTask.promise.then(function () {
        return loadingTask.destroy();
      });
      await destroyPromise;
      const destroyedWorker = loadingTask._worker;
      expect(!!destroyedWorker).toEqual(false);
      expect(worker.destroyed).toEqual(true);
    });
    it("worker created and can be used in getDocument", async function () {
      if (_is_node.isNodeJS) {
        pending("Worker is not supported in Node.js.");
      }

      const worker = new _api.PDFWorker({
        name: "test1"
      });
      const loadingTask = (0, _api.getDocument)((0, _test_utils.buildGetDocumentParams)(basicApiFileName, {
        worker
      }));
      loadingTask.promise.then(function () {
        const docWorker = loadingTask._worker;
        expect(!!docWorker).toEqual(false);
        const messageHandlerPort = loadingTask._transport.messageHandler.comObj;
        expect(messageHandlerPort === worker.port).toEqual(true);
      });
      const destroyPromise = loadingTask.promise.then(function () {
        return loadingTask.destroy();
      });
      await destroyPromise;
      expect(worker.destroyed).toEqual(false);
      worker.destroy();
    });
    it("creates more than one worker", async function () {
      if (_is_node.isNodeJS) {
        pending("Worker is not supported in Node.js.");
      }

      const worker1 = new _api.PDFWorker({
        name: "test1"
      });
      const worker2 = new _api.PDFWorker({
        name: "test2"
      });
      const worker3 = new _api.PDFWorker({
        name: "test3"
      });
      await Promise.all([worker1.promise, worker2.promise, worker3.promise]);
      expect(worker1.port !== worker2.port && worker1.port !== worker3.port && worker2.port !== worker3.port).toEqual(true);
      worker1.destroy();
      worker2.destroy();
      worker3.destroy();
    });
    it("gets current workerSrc", function () {
      if (_is_node.isNodeJS) {
        pending("Worker is not supported in Node.js.");
      }

      const workerSrc = _api.PDFWorker.workerSrc;
      expect(typeof workerSrc).toEqual("string");
      expect(workerSrc).toEqual(_worker_options.GlobalWorkerOptions.workerSrc);
    });
  });
  describe("PDFDocument", function () {
    let pdfLoadingTask, pdfDocument;
    beforeAll(async function () {
      pdfLoadingTask = (0, _api.getDocument)(basicApiGetDocumentParams);
      pdfDocument = await pdfLoadingTask.promise;
    });
    afterAll(async function () {
      await pdfLoadingTask.destroy();
    });
    it("gets number of pages", function () {
      expect(pdfDocument.numPages).toEqual(3);
    });
    it("gets fingerprints", function () {
      expect(pdfDocument.fingerprints).toEqual(["ea8b35919d6279a369e835bde778611b", null]);
    });
    it("gets fingerprints, from modified document", async function () {
      const loadingTask = (0, _api.getDocument)((0, _test_utils.buildGetDocumentParams)("annotation-tx.pdf"));
      const pdfDoc = await loadingTask.promise;
      expect(pdfDoc.fingerprints).toEqual(["3ebd77c320274649a68f10dbf3b9f882", "e7087346aa4b4ae0911c1f1643b57345"]);
      await loadingTask.destroy();
    });
    it("gets page", async function () {
      const data = await pdfDocument.getPage(1);
      expect(data instanceof _api.PDFPageProxy).toEqual(true);
      expect(data.pageNumber).toEqual(1);
    });
    it("gets non-existent page", async function () {
      let outOfRangePromise = pdfDocument.getPage(100);
      let nonIntegerPromise = pdfDocument.getPage(2.5);
      let nonNumberPromise = pdfDocument.getPage("1");
      outOfRangePromise = outOfRangePromise.then(function () {
        throw new Error("shall fail for out-of-range pageNumber parameter");
      }, function (reason) {
        expect(reason instanceof Error).toEqual(true);
      });
      nonIntegerPromise = nonIntegerPromise.then(function () {
        throw new Error("shall fail for non-integer pageNumber parameter");
      }, function (reason) {
        expect(reason instanceof Error).toEqual(true);
      });
      nonNumberPromise = nonNumberPromise.then(function () {
        throw new Error("shall fail for non-number pageNumber parameter");
      }, function (reason) {
        expect(reason instanceof Error).toEqual(true);
      });
      await Promise.all([outOfRangePromise, nonIntegerPromise, nonNumberPromise]);
    });
    it("gets page, from /Pages tree with circular reference", async function () {
      const loadingTask = (0, _api.getDocument)((0, _test_utils.buildGetDocumentParams)("Pages-tree-refs.pdf"));
      const page1 = loadingTask.promise.then(function (pdfDoc) {
        return pdfDoc.getPage(1).then(function (pdfPage) {
          expect(pdfPage instanceof _api.PDFPageProxy).toEqual(true);
          expect(pdfPage.ref).toEqual({
            num: 6,
            gen: 0
          });
        }, function (reason) {
          throw new Error("shall not fail for valid page");
        });
      });
      const page2 = loadingTask.promise.then(function (pdfDoc) {
        return pdfDoc.getPage(2).then(function (pdfPage) {
          throw new Error("shall fail for invalid page");
        }, function (reason) {
          expect(reason instanceof _util.UnknownErrorException).toEqual(true);
          expect(reason.message).toEqual("Pages tree contains circular reference.");
        });
      });
      await Promise.all([page1, page2]);
      await loadingTask.destroy();
    });
    it("gets page multiple time, with working caches", async function () {
      const promiseA = pdfDocument.getPage(1);
      const promiseB = pdfDocument.getPage(1);
      expect(promiseA instanceof Promise).toEqual(true);
      expect(promiseA).toBe(promiseB);
      const pageA = await promiseA;
      const pageB = await promiseB;
      expect(pageA instanceof _api.PDFPageProxy).toEqual(true);
      expect(pageA).toBe(pageB);
    });
    it("gets page index", async function () {
      const ref = {
        num: 17,
        gen: 0
      };
      const pageIndex = await pdfDocument.getPageIndex(ref);
      expect(pageIndex).toEqual(1);
    });
    it("gets invalid page index", async function () {
      const ref = {
        num: 3,
        gen: 0
      };

      try {
        await pdfDocument.getPageIndex(ref);
        expect(false).toEqual(true);
      } catch (reason) {
        expect(reason instanceof _util.UnknownErrorException).toEqual(true);
        expect(reason.message).toEqual("The reference does not point to a /Page dictionary.");
      }
    });
    it("gets destinations, from /Dests dictionary", async function () {
      const destinations = await pdfDocument.getDestinations();
      expect(destinations).toEqual({
        chapter1: [{
          gen: 0,
          num: 17
        }, {
          name: "XYZ"
        }, 0, 841.89, null]
      });
    });
    it("gets a destination, from /Dests dictionary", async function () {
      const destination = await pdfDocument.getDestination("chapter1");
      expect(destination).toEqual([{
        gen: 0,
        num: 17
      }, {
        name: "XYZ"
      }, 0, 841.89, null]);
    });
    it("gets a non-existent destination, from /Dests dictionary", async function () {
      const destination = await pdfDocument.getDestination("non-existent-named-destination");
      expect(destination).toEqual(null);
    });
    it("gets destinations, from /Names (NameTree) dictionary", async function () {
      const loadingTask = (0, _api.getDocument)((0, _test_utils.buildGetDocumentParams)("issue6204.pdf"));
      const pdfDoc = await loadingTask.promise;
      const destinations = await pdfDoc.getDestinations();
      expect(destinations).toEqual({
        "Page.1": [{
          num: 1,
          gen: 0
        }, {
          name: "XYZ"
        }, 0, 375, null],
        "Page.2": [{
          num: 6,
          gen: 0
        }, {
          name: "XYZ"
        }, 0, 375, null]
      });
      await loadingTask.destroy();
    });
    it("gets a destination, from /Names (NameTree) dictionary", async function () {
      const loadingTask = (0, _api.getDocument)((0, _test_utils.buildGetDocumentParams)("issue6204.pdf"));
      const pdfDoc = await loadingTask.promise;
      const destination = await pdfDoc.getDestination("Page.1");
      expect(destination).toEqual([{
        num: 1,
        gen: 0
      }, {
        name: "XYZ"
      }, 0, 375, null]);
      await loadingTask.destroy();
    });
    it("gets a non-existent destination, from /Names (NameTree) dictionary", async function () {
      const loadingTask = (0, _api.getDocument)((0, _test_utils.buildGetDocumentParams)("issue6204.pdf"));
      const pdfDoc = await loadingTask.promise;
      const destination = await pdfDoc.getDestination("non-existent-named-destination");
      expect(destination).toEqual(null);
      await loadingTask.destroy();
    });
    it("gets a destination, from out-of-order /Names (NameTree) dictionary (issue 10272)", async function () {
      if (_is_node.isNodeJS) {
        pending("Linked test-cases are not supported in Node.js.");
      }

      const loadingTask = (0, _api.getDocument)((0, _test_utils.buildGetDocumentParams)("issue10272.pdf"));
      const pdfDoc = await loadingTask.promise;
      const destination = await pdfDoc.getDestination("link_1");
      expect(destination).toEqual([{
        num: 17,
        gen: 0
      }, {
        name: "XYZ"
      }, 69, 125, 0]);
      await loadingTask.destroy();
    });
    it("gets non-string destination", async function () {
      let numberPromise = pdfDocument.getDestination(4.3);
      let booleanPromise = pdfDocument.getDestination(true);
      let arrayPromise = pdfDocument.getDestination([{
        num: 17,
        gen: 0
      }, {
        name: "XYZ"
      }, 0, 841.89, null]);
      numberPromise = numberPromise.then(function () {
        throw new Error("shall fail for non-string destination.");
      }, function (reason) {
        expect(reason instanceof Error).toEqual(true);
      });
      booleanPromise = booleanPromise.then(function () {
        throw new Error("shall fail for non-string destination.");
      }, function (reason) {
        expect(reason instanceof Error).toEqual(true);
      });
      arrayPromise = arrayPromise.then(function () {
        throw new Error("shall fail for non-string destination.");
      }, function (reason) {
        expect(reason instanceof Error).toEqual(true);
      });
      await Promise.all([numberPromise, booleanPromise, arrayPromise]);
    });
    it("gets non-existent page labels", async function () {
      const pageLabels = await pdfDocument.getPageLabels();
      expect(pageLabels).toEqual(null);
    });
    it("gets page labels", async function () {
      const loadingTask0 = (0, _api.getDocument)((0, _test_utils.buildGetDocumentParams)("bug793632.pdf"));
      const promise0 = loadingTask0.promise.then(function (pdfDoc) {
        return pdfDoc.getPageLabels();
      });
      const loadingTask1 = (0, _api.getDocument)((0, _test_utils.buildGetDocumentParams)("issue1453.pdf"));
      const promise1 = loadingTask1.promise.then(function (pdfDoc) {
        return pdfDoc.getPageLabels();
      });
      const loadingTask2 = (0, _api.getDocument)((0, _test_utils.buildGetDocumentParams)("rotation.pdf"));
      const promise2 = loadingTask2.promise.then(function (pdfDoc) {
        return pdfDoc.getPageLabels();
      });
      const loadingTask3 = (0, _api.getDocument)((0, _test_utils.buildGetDocumentParams)("bad-PageLabels.pdf"));
      const promise3 = loadingTask3.promise.then(function (pdfDoc) {
        return pdfDoc.getPageLabels();
      });
      const pageLabels = await Promise.all([promise0, promise1, promise2, promise3]);
      expect(pageLabels[0]).toEqual(["i", "ii", "iii", "1"]);
      expect(pageLabels[1]).toEqual(["Front Page1"]);
      expect(pageLabels[2]).toEqual(["1", "2"]);
      expect(pageLabels[3]).toEqual(["X3"]);
      await Promise.all([loadingTask0.destroy(), loadingTask1.destroy(), loadingTask2.destroy(), loadingTask3.destroy()]);
    });
    it("gets default page layout", async function () {
      const loadingTask = (0, _api.getDocument)((0, _test_utils.buildGetDocumentParams)("tracemonkey.pdf"));
      const pdfDoc = await loadingTask.promise;
      const pageLayout = await pdfDoc.getPageLayout();
      expect(pageLayout).toEqual("");
      await loadingTask.destroy();
    });
    it("gets non-default page layout", async function () {
      const pageLayout = await pdfDocument.getPageLayout();
      expect(pageLayout).toEqual("SinglePage");
    });
    it("gets default page mode", async function () {
      const loadingTask = (0, _api.getDocument)((0, _test_utils.buildGetDocumentParams)("tracemonkey.pdf"));
      const pdfDoc = await loadingTask.promise;
      const pageMode = await pdfDoc.getPageMode();
      expect(pageMode).toEqual("UseNone");
      await loadingTask.destroy();
    });
    it("gets non-default page mode", async function () {
      const pageMode = await pdfDocument.getPageMode();
      expect(pageMode).toEqual("UseOutlines");
    });
    it("gets default viewer preferences", async function () {
      const loadingTask = (0, _api.getDocument)((0, _test_utils.buildGetDocumentParams)("tracemonkey.pdf"));
      const pdfDoc = await loadingTask.promise;
      const prefs = await pdfDoc.getViewerPreferences();
      expect(prefs).toEqual(null);
      await loadingTask.destroy();
    });
    it("gets non-default viewer preferences", async function () {
      const prefs = await pdfDocument.getViewerPreferences();
      expect(prefs).toEqual({
        Direction: "L2R"
      });
    });
    it("gets default open action", async function () {
      const loadingTask = (0, _api.getDocument)((0, _test_utils.buildGetDocumentParams)("tracemonkey.pdf"));
      const pdfDoc = await loadingTask.promise;
      const openAction = await pdfDoc.getOpenAction();
      expect(openAction).toEqual(null);
      await loadingTask.destroy();
    });
    it("gets non-default open action (with destination)", async function () {
      const openAction = await pdfDocument.getOpenAction();
      expect(openAction.dest).toEqual([{
        num: 15,
        gen: 0
      }, {
        name: "FitH"
      }, null]);
      expect(openAction.action).toBeUndefined();
    });
    it("gets non-default open action (with Print action)", async function () {
      const loadingTask1 = (0, _api.getDocument)((0, _test_utils.buildGetDocumentParams)("bug1001080.pdf"));
      const loadingTask2 = (0, _api.getDocument)((0, _test_utils.buildGetDocumentParams)("issue11442_reduced.pdf"));
      const promise1 = loadingTask1.promise.then(function (pdfDoc) {
        return pdfDoc.getOpenAction();
      }).then(function (openAction) {
        expect(openAction.dest).toBeUndefined();
        expect(openAction.action).toEqual("Print");
        return loadingTask1.destroy();
      });
      const promise2 = loadingTask2.promise.then(function (pdfDoc) {
        return pdfDoc.getOpenAction();
      }).then(function (openAction) {
        expect(openAction.dest).toBeUndefined();
        expect(openAction.action).toEqual("Print");
        return loadingTask2.destroy();
      });
      await Promise.all([promise1, promise2]);
    });
    it("gets non-existent attachments", async function () {
      const attachments = await pdfDocument.getAttachments();
      expect(attachments).toEqual(null);
    });
    it("gets attachments", async function () {
      const loadingTask = (0, _api.getDocument)((0, _test_utils.buildGetDocumentParams)("attachment.pdf"));
      const pdfDoc = await loadingTask.promise;
      const attachments = await pdfDoc.getAttachments();
      const attachment = attachments["foo.txt"];
      expect(attachment.filename).toEqual("foo.txt");
      expect(attachment.content).toEqual(new Uint8Array([98, 97, 114, 32, 98, 97, 122, 32, 10]));
      await loadingTask.destroy();
    });
    it("gets javascript", async function () {
      const javascript = await pdfDocument.getJavaScript();
      expect(javascript).toEqual(null);
    });
    it("gets javascript with printing instructions (JS action)", async function () {
      const loadingTask = (0, _api.getDocument)((0, _test_utils.buildGetDocumentParams)("issue6106.pdf"));
      const pdfDoc = await loadingTask.promise;
      const javascript = await pdfDoc.getJavaScript();
      expect(javascript).toEqual(["this.print({bUI:true,bSilent:false,bShrinkToFit:true});"]);
      expect(javascript[0]).toMatch(_ui_utils.AutoPrintRegExp);
      await loadingTask.destroy();
    });
    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 = (0, _api.getDocument)((0, _test_utils.buildGetDocumentParams)("doc_actions.pdf"));
      const pdfDoc = await loadingTask.promise;
      const hasJSActions = await pdfDoc.hasJSActions();
      expect(hasJSActions).toEqual(true);
      await loadingTask.destroy();
    });
    it("gets non-existent JSActions", async function () {
      const jsActions = await pdfDocument.getJSActions();
      expect(jsActions).toEqual(null);
    });
    it("gets JSActions", async function () {
      const loadingTask = (0, _api.getDocument)((0, _test_utils.buildGetDocumentParams)("doc_actions.pdf"));
      const pdfDoc = await loadingTask.promise;
      const docActions = await pdfDoc.getJSActions();
      const page1 = await pdfDoc.getPage(1);
      const page1Actions = await page1.getJSActions();
      const page3 = await pdfDoc.getPage(3);
      const page3Actions = await page3.getJSActions();
      expect(docActions).toEqual({
        DidPrint: [`this.getField("Text2").value = "DidPrint";`],
        DidSave: [`this.getField("Text2").value = "DidSave";`],
        WillClose: [`this.getField("Text1").value = "WillClose";`],
        WillPrint: [`this.getField("Text1").value = "WillPrint";`],
        WillSave: [`this.getField("Text1").value = "WillSave";`]
      });
      expect(page1Actions).toEqual({
        PageOpen: [`this.getField("Text1").value = "PageOpen 1";`],
        PageClose: [`this.getField("Text2").value = "PageClose 1";`]
      });
      expect(page3Actions).toEqual({
        PageOpen: [`this.getField("Text5").value = "PageOpen 3";`],
        PageClose: [`this.getField("Text6").value = "PageClose 3";`]
      });
      await loadingTask.destroy();
    });
    it("gets non-existent outline", async function () {
      const loadingTask = (0, _api.getDocument)((0, _test_utils.buildGetDocumentParams)("tracemonkey.pdf"));
      const pdfDoc = await loadingTask.promise;
      const outline = await pdfDoc.getOutline();
      expect(outline).toEqual(null);
      await loadingTask.destroy();
    });
    it("gets outline", async function () {
      const outline = await pdfDocument.getOutline();
      expect(Array.isArray(outline)).toEqual(true);
      expect(outline.length).toEqual(2);
      const outlineItem = outline[1];
      expect(outlineItem.title).toEqual("Chapter 1");
      expect(Array.isArray(outlineItem.dest)).toEqual(true);
      expect(outlineItem.url).toEqual(null);
      expect(outlineItem.unsafeUrl).toBeUndefined();
      expect(outlineItem.newWindow).toBeUndefined();
      expect(outlineItem.bold).toEqual(true);
      expect(outlineItem.italic).toEqual(false);
      expect(outlineItem.color).toEqual(new Uint8ClampedArray([0, 64, 128]));
      expect(outlineItem.items.length).toEqual(1);
      expect(outlineItem.items[0].title).toEqual("Paragraph 1.1");
    });
    it("gets outline containing a URL", async function () {
      const loadingTask = (0, _api.getDocument)((0, _test_utils.buildGetDocumentParams)("issue3214.pdf"));
      const pdfDoc = await loadingTask.promise;
      const outline = await pdfDoc.getOutline();
      expect(Array.isArray(outline)).toEqual(true);
      expect(outline.length).toEqual(5);
      const outlineItemTwo = outline[2];
      expect(typeof outlineItemTwo.title).toEqual("string");
      expect(outlineItemTwo.dest).toEqual(null);
      expect(outlineItemTwo.url).toEqual("http://google.com/");
      expect(outlineItemTwo.unsafeUrl).toEqual("http://google.com");
      expect(outlineItemTwo.newWindow).toBeUndefined();
      const outlineItemOne = outline[1];
      expect(outlineItemOne.bold).toEqual(false);
      expect(outlineItemOne.italic).toEqual(true);
      expect(outlineItemOne.color).toEqual(new Uint8ClampedArray([0, 0, 0]));
      await loadingTask.destroy();
    });
    it("gets outline with non-displayable chars", async function () {
      const loadingTask = (0, _api.getDocument)((0, _test_utils.buildGetDocumentParams)("issue14267.pdf"));
      const pdfDoc = await loadingTask.promise;
      const outline = await pdfDoc.getOutline();
      expect(Array.isArray(outline)).toEqual(true);
      expect(outline.length).toEqual(1);
      const outlineItem = outline[0];
      expect(outlineItem.title).toEqual("hello\x11world");
      await loadingTask.destroy();
    });
    it("gets non-existent permissions", async function () {
      const permissions = await pdfDocument.getPermissions();
      expect(permissions).toEqual(null);
    });
    it("gets permissions", async function () {
      const loadingTask0 = (0, _api.getDocument)((0, _test_utils.buildGetDocumentParams)("issue9972-1.pdf"));
      const promise0 = loadingTask0.promise.then(function (pdfDoc) {
        return pdfDoc.getPermissions();
      });
      const loadingTask1 = (0, _api.getDocument)((0, _test_utils.buildGetDocumentParams)("issue9972-2.pdf"));
      const promise1 = loadingTask1.promise.then(function (pdfDoc) {
        return pdfDoc.getPermissions();
      });
      const loadingTask2 = (0, _api.getDocument)((0, _test_utils.buildGetDocumentParams)("issue9972-3.pdf"));
      const promise2 = loadingTask2.promise.then(function (pdfDoc) {
        return pdfDoc.getPermissions();
      });
      const totalPermissionCount = Object.keys(_util.PermissionFlag).length;
      const permissions = await Promise.all([promise0, promise1, promise2]);
      expect(permissions[0].length).toEqual(totalPermissionCount - 1);
      expect(permissions[0].includes(_util.PermissionFlag.MODIFY_CONTENTS)).toBeFalsy();
      expect(permissions[1].length).toEqual(totalPermissionCount - 2);
      expect(permissions[1].includes(_util.PermissionFlag.PRINT)).toBeFalsy();
      expect(permissions[1].includes(_util.PermissionFlag.PRINT_HIGH_QUALITY)).toBeFalsy();
      expect(permissions[2].length).toEqual(totalPermissionCount - 1);
      expect(permissions[2].includes(_util.PermissionFlag.COPY)).toBeFalsy();
      await Promise.all([loadingTask0.destroy(), loadingTask1.destroy(), loadingTask2.destroy()]);
    });
    it("gets metadata", async function () {
      const {
        info,
        metadata,
        contentDispositionFilename,
        contentLength
      } = await pdfDocument.getMetadata();
      expect(info.Title).toEqual("Basic API Test");
      expect(info.Custom).toEqual(undefined);
      expect(info.PDFFormatVersion).toEqual("1.7");
      expect(info.Language).toEqual("en");
      expect(info.EncryptFilterName).toEqual(null);
      expect(info.IsLinearized).toEqual(false);
      expect(info.IsAcroFormPresent).toEqual(false);
      expect(info.IsXFAPresent).toEqual(false);
      expect(info.IsCollectionPresent).toEqual(false);
      expect(info.IsSignaturesPresent).toEqual(false);
      expect(metadata instanceof _metadata.Metadata).toEqual(true);
      expect(metadata.get("dc:title")).toEqual("Basic API Test");
      expect(contentDispositionFilename).toEqual(null);
      expect(contentLength).toEqual(basicApiFileLength);
    });
    it("gets metadata, with custom info dict entries", async function () {
      const loadingTask = (0, _api.getDocument)((0, _test_utils.buildGetDocumentParams)("tracemonkey.pdf"));
      const pdfDoc = await loadingTask.promise;
      const {
        info,
        metadata,
        contentDispositionFilename,
        contentLength
      } = await pdfDoc.getMetadata();
      expect(info.Creator).toEqual("TeX");
      expect(info.Producer).toEqual("pdfeTeX-1.21a");
      expect(info.CreationDate).toEqual("D:20090401163925-07'00'");
      const custom = info.Custom;
      expect(typeof custom === "object" && custom !== null).toEqual(true);
      expect(custom["PTEX.Fullbanner"]).toEqual("This is pdfeTeX, " + "Version 3.141592-1.21a-2.2 (Web2C 7.5.4) kpathsea version 3.5.6");
      expect(info.PDFFormatVersion).toEqual("1.4");
      expect(info.Language).toEqual(null);
      expect(info.EncryptFilterName).toEqual(null);
      expect(info.IsLinearized).toEqual(false);
      expect(info.IsAcroFormPresent).toEqual(false);
      expect(info.IsXFAPresent).toEqual(false);
      expect(info.IsCollectionPresent).toEqual(false);
      expect(info.IsSignaturesPresent).toEqual(false);
      expect(metadata).toEqual(null);
      expect(contentDispositionFilename).toEqual(null);
      expect(contentLength).toEqual(1016315);
      await loadingTask.destroy();
    });
    it("gets metadata, with missing PDF header (bug 1606566)", async function () {
      const loadingTask = (0, _api.getDocument)((0, _test_utils.buildGetDocumentParams)("bug1606566.pdf"));
      const pdfDoc = await loadingTask.promise;
      const {
        info,
        metadata,
        contentDispositionFilename,
        contentLength
      } = await pdfDoc.getMetadata();
      expect(info.Custom).toEqual(undefined);
      expect(info.PDFFormatVersion).toEqual(null);
      expect(info.Language).toEqual(null);
      expect(info.EncryptFilterName).toEqual(null);
      expect(info.IsLinearized).toEqual(false);
      expect(info.IsAcroFormPresent).toEqual(false);
      expect(info.IsXFAPresent).toEqual(false);
      expect(info.IsCollectionPresent).toEqual(false);
      expect(info.IsSignaturesPresent).toEqual(false);
      expect(metadata).toEqual(null);
      expect(contentDispositionFilename).toEqual(null);
      expect(contentLength).toEqual(624);
      await loadingTask.destroy();
    });
    it("gets metadata, with corrupt /Metadata XRef entry", async function () {
      const loadingTask = (0, _api.getDocument)((0, _test_utils.buildGetDocumentParams)("PDFBOX-3148-2-fuzzed.pdf"));
      const pdfDoc = await loadingTask.promise;
      const {
        info,
        metadata,
        contentDispositionFilename,
        contentLength
      } = await pdfDoc.getMetadata();
      expect(info.Custom).toEqual(undefined);
      expect(info.PDFFormatVersion).toEqual("1.6");
      expect(info.Language).toEqual(null);
      expect(info.EncryptFilterName).toEqual(null);
      expect(info.IsLinearized).toEqual(false);
      expect(info.IsAcroFormPresent).toEqual(true);
      expect(info.IsXFAPresent).toEqual(false);
      expect(info.IsCollectionPresent).toEqual(false);
      expect(info.IsSignaturesPresent).toEqual(false);
      expect(metadata).toEqual(null);
      expect(contentDispositionFilename).toEqual(null);
      expect(contentLength).toEqual(244351);
      await loadingTask.destroy();
    });
    it("gets markInfo", async function () {
      const loadingTask = (0, _api.getDocument)((0, _test_utils.buildGetDocumentParams)("annotation-line.pdf"));
      const pdfDoc = await loadingTask.promise;
      const markInfo = await pdfDoc.getMarkInfo();
      expect(markInfo.Marked).toEqual(true);
      expect(markInfo.UserProperties).toEqual(false);
      expect(markInfo.Suspects).toEqual(false);
    });
    it("gets data", async function () {
      const data = await pdfDocument.getData();
      expect(data instanceof Uint8Array).toEqual(true);
      expect(data.length).toEqual(basicApiFileLength);
    });
    it("gets download info", async function () {
      const downloadInfo = await pdfDocument.getDownloadInfo();
      expect(downloadInfo).toEqual({
        length: basicApiFileLength
      });
    });
    it("gets document stats", async function () {
      const stats = pdfDocument.stats;
      expect(stats).toEqual(null);
    });
    it("cleans up document resources", async function () {
      await pdfDocument.cleanup();
      expect(true).toEqual(true);
    });
    it("checks that fingerprints are unique", async function () {
      const loadingTask1 = (0, _api.getDocument)((0, _test_utils.buildGetDocumentParams)("issue4436r.pdf"));
      const loadingTask2 = (0, _api.getDocument)((0, _test_utils.buildGetDocumentParams)("issue4575.pdf"));
      const data = await Promise.all([loadingTask1.promise, loadingTask2.promise]);
      const fingerprints1 = data[0].fingerprints;
      const fingerprints2 = data[1].fingerprints;
      expect(fingerprints1).not.toEqual(fingerprints2);
      expect(fingerprints1).toEqual(["2f695a83d6e7553c24fc08b7ac69712d", null]);
      expect(fingerprints2).toEqual(["04c7126b34a46b6d4d6e7a1eff7edcb6", null]);
      await Promise.all([loadingTask1.destroy(), loadingTask2.destroy()]);
    });
    it("write a value in an annotation, save the pdf and load it", async function () {
      let loadingTask = (0, _api.getDocument)((0, _test_utils.buildGetDocumentParams)("evaljs.pdf"));
      let pdfDoc = await loadingTask.promise;
      const value = "Hello World";
      pdfDoc.annotationStorage.setValue("55R", {
        value
      });
      const data = await pdfDoc.saveDocument();
      await loadingTask.destroy();
      loadingTask = (0, _api.getDocument)(data);
      pdfDoc = await loadingTask.promise;
      const pdfPage = await pdfDoc.getPage(1);
      const annotations = await pdfPage.getAnnotations();
      const field = annotations.find(annotation => annotation.id === "55R");
      expect(!!field).toEqual(true);
      expect(field.fieldValue).toEqual(value);
      await loadingTask.destroy();
    });
    describe("Cross-origin", function () {
      let loadingTask;

      function _checkCanLoad(expectSuccess, filename, options) {
        if (_is_node.isNodeJS) {
          pending("Cannot simulate cross-origin requests in Node.js");
        }

        const params = (0, _test_utils.buildGetDocumentParams)(filename, options);
        const url = new URL(params.url);

        if (url.hostname === "localhost") {
          url.hostname = "127.0.0.1";
        } else if (params.url.hostname === "127.0.0.1") {
          url.hostname = "localhost";
        } else {
          pending("Can only run cross-origin test on localhost!");
        }

        params.url = url.href;
        loadingTask = (0, _api.getDocument)(params);
        return loadingTask.promise.then(function (pdf) {
          return pdf.destroy();
        }).then(function () {
          expect(expectSuccess).toEqual(true);
        }, function (error) {
          if (expectSuccess) {
            expect(error).toEqual("There should not be any error");
          }

          expect(expectSuccess).toEqual(false);
        });
      }

      function testCanLoad(filename, options) {
        return _checkCanLoad(true, filename, options);
      }

      function testCannotLoad(filename, options) {
        return _checkCanLoad(false, filename, options);
      }

      afterEach(async function () {
        if (loadingTask && !loadingTask.destroyed) {
          await loadingTask.destroy();
        }
      });
      it("server disallows cors", async function () {
        await testCannotLoad("basicapi.pdf");
      });
      it("server allows cors without credentials, default withCredentials", async function () {
        await testCanLoad("basicapi.pdf?cors=withoutCredentials");
      });
      it("server allows cors without credentials, and withCredentials=false", async function () {
        await testCanLoad("basicapi.pdf?cors=withoutCredentials", {
          withCredentials: false
        });
      });
      it("server allows cors without credentials, but withCredentials=true", async function () {
        await testCannotLoad("basicapi.pdf?cors=withoutCredentials", {
          withCredentials: true
        });
      });
      it("server allows cors with credentials, and withCredentials=true", async function () {
        await testCanLoad("basicapi.pdf?cors=withCredentials", {
          withCredentials: true
        });
      });
      it("server allows cors with credentials, and withCredentials=false", async function () {
        await testCanLoad("basicapi.pdf?cors=withCredentials", {
          withCredentials: false
        });
      });
    });
  });
  describe("Page", function () {
    let pdfLoadingTask, pdfDocument, page;
    beforeAll(async function () {
      pdfLoadingTask = (0, _api.getDocument)(basicApiGetDocumentParams);
      pdfDocument = await pdfLoadingTask.promise;
      page = await pdfDocument.getPage(1);
    });
    afterAll(async function () {
      await pdfLoadingTask.destroy();
    });
    it("gets page number", function () {
      expect(page.pageNumber).toEqual(1);
    });
    it("gets rotate", function () {
      expect(page.rotate).toEqual(0);
    });
    it("gets ref", function () {
      expect(page.ref).toEqual({
        num: 15,
        gen: 0
      });
    });
    it("gets userUnit", function () {
      expect(page.userUnit).toEqual(1.0);
    });
    it("gets view", function () {
      expect(page.view).toEqual([0, 0, 595.28, 841.89]);
    });
    it("gets view, with empty/invalid bounding boxes", async function () {
      const viewLoadingTask = (0, _api.getDocument)((0, _test_utils.buildGetDocumentParams)("boundingBox_invalid.pdf"));
      const pdfDoc = await viewLoadingTask.promise;
      const numPages = pdfDoc.numPages;
      expect(numPages).toEqual(3);
      const viewPromises = [];

      for (let i = 0; i < numPages; i++) {
        viewPromises[i] = pdfDoc.getPage(i + 1).then(pdfPage => {
          return pdfPage.view;
        });
      }

      const [page1, page2, page3] = await Promise.all(viewPromises);
      expect(page1).toEqual([0, 0, 612, 792]);
      expect(page2).toEqual([0, 0, 800, 600]);
      expect(page3).toEqual([0, 0, 600, 800]);
      await viewLoadingTask.destroy();
    });
    it("gets viewport", function () {
      const viewport = page.getViewport({
        scale: 1.5,
        rotation: 90
      });
      expect(viewport.viewBox).toEqual(page.view);
      expect(viewport.scale).toEqual(1.5);
      expect(viewport.rotation).toEqual(90);
      expect(viewport.transform).toEqual([0, 1.5, 1.5, 0, 0, 0]);
      expect(viewport.width).toEqual(1262.835);
      expect(viewport.height).toEqual(892.92);
    });
    it('gets viewport with "offsetX/offsetY" arguments', function () {
      const viewport = page.getViewport({
        scale: 1,
        rotation: 0,
        offsetX: 100,
        offsetY: -100
      });
      expect(viewport.transform).toEqual([1, 0, 0, -1, 100, 741.89]);
    });
    it('gets viewport respecting "dontFlip" argument', function () {
      const scale = 1,
            rotation = 0;
      const viewport = page.getViewport({
        scale,
        rotation
      });
      const dontFlipViewport = page.getViewport({
        scale,
        rotation,
        dontFlip: true
      });
      expect(dontFlipViewport).not.toEqual(viewport);
      expect(dontFlipViewport).toEqual(viewport.clone({
        dontFlip: true
      }));
      expect(viewport.transform).toEqual([1, 0, 0, -1, 0, 841.89]);
      expect(dontFlipViewport.transform).toEqual([1, 0, -0, 1, 0, 0]);
    });
    it("gets viewport with invalid rotation", function () {
      expect(function () {
        page.getViewport({
          scale: 1,
          rotation: 45
        });
      }).toThrow(new Error("PageViewport: Invalid rotation, must be a multiple of 90 degrees."));
    });
    it("gets annotations", async function () {
      const defaultPromise = page.getAnnotations().then(function (data) {
        expect(data.length).toEqual(4);
      });
      const anyPromise = page.getAnnotations({
        intent: "any"
      }).then(function (data) {
        expect(data.length).toEqual(4);
      });
      const displayPromise = page.getAnnotations({
        intent: "display"
      }).then(function (data) {
        expect(data.length).toEqual(4);
      });
      const printPromise = page.getAnnotations({
        intent: "print"
      }).then(function (data) {
        expect(data.length).toEqual(4);
      });
      await Promise.all([defaultPromise, anyPromise, displayPromise, printPromise]);
    });
    it("gets annotations containing relative URLs (bug 766086)", async function () {
      const filename = "bug766086.pdf";
      const defaultLoadingTask = (0, _api.getDocument)((0, _test_utils.buildGetDocumentParams)(filename));
      const defaultPromise = defaultLoadingTask.promise.then(function (pdfDoc) {
        return pdfDoc.getPage(1).then(function (pdfPage) {
          return pdfPage.getAnnotations();
        });
      });
      const docBaseUrlLoadingTask = (0, _api.getDocument)((0, _test_utils.buildGetDocumentParams)(filename, {
        docBaseUrl: "http://www.example.com/test/pdfs/qwerty.pdf"
      }));
      const docBaseUrlPromise = docBaseUrlLoadingTask.promise.then(function (pdfDoc) {
        return pdfDoc.getPage(1).then(function (pdfPage) {
          return pdfPage.getAnnotations();
        });
      });
      const invalidDocBaseUrlLoadingTask = (0, _api.getDocument)((0, _test_utils.buildGetDocumentParams)(filename, {
        docBaseUrl: "qwerty.pdf"
      }));
      const invalidDocBaseUrlPromise = invalidDocBaseUrlLoadingTask.promise.then(function (pdfDoc) {
        return pdfDoc.getPage(1).then(function (pdfPage) {
          return pdfPage.getAnnotations();
        });
      });
      const [defaultAnnotations, docBaseUrlAnnotations, invalidDocBaseUrlAnnotations] = await Promise.all([defaultPromise, docBaseUrlPromise, invalidDocBaseUrlPromise]);
      expect(defaultAnnotations[0].url).toBeUndefined();
      expect(defaultAnnotations[0].unsafeUrl).toEqual("../../0021/002156/215675E.pdf#15");
      expect(docBaseUrlAnnotations[0].url).toEqual("http://www.example.com/0021/002156/215675E.pdf#15");
      expect(docBaseUrlAnnotations[0].unsafeUrl).toEqual("../../0021/002156/215675E.pdf#15");
      expect(invalidDocBaseUrlAnnotations[0].url).toBeUndefined();
      expect(invalidDocBaseUrlAnnotations[0].unsafeUrl).toEqual("../../0021/002156/215675E.pdf#15");
      await Promise.all([defaultLoadingTask.destroy(), docBaseUrlLoadingTask.destroy(), invalidDocBaseUrlLoadingTask.destroy()]);
    });
    it("gets text content", async function () {
      const defaultPromise = page.getTextContent();
      const parametersPromise = page.getTextContent({
        normalizeWhitespace: true,
        disableCombineTextItems: true
      });
      const data = await Promise.all([defaultPromise, parametersPromise]);
      expect(!!data[0].items).toEqual(true);
      expect(data[0].items.length).toEqual(11);
      expect(!!data[0].styles).toEqual(true);
      const page1 = mergeText(data[0].items);
      expect(page1).toEqual(`Table Of Content
Chapter 1 .......................................................... 2
Paragraph 1.1 ...................................................... 3
page 1 / 3`);
      expect(!!data[1].items).toEqual(true);
      expect(data[1].items.length).toEqual(6);
      expect(!!data[1].styles).toEqual(true);
    });
    it("gets text content, with correct properties (issue 8276)", async function () {
      const loadingTask = (0, _api.getDocument)((0, _test_utils.buildGetDocumentParams)("issue8276_reduced.pdf"));
      const pdfDoc = await loadingTask.promise;
      const pdfPage = await pdfDoc.getPage(1);
      const {
        items,
        styles
      } = await pdfPage.getTextContent();
      expect(items.length).toEqual(1);
      const fontName = items[0].fontName;
      expect(Object.keys(styles)).toEqual([fontName]);
      expect(items[0]).toEqual({
        dir: "ltr",
        fontName,
        height: 18,
        str: "Issue 8276",
        transform: [18, 0, 0, 18, 441.81, 708.4499999999999],
        width: 77.49,
        hasEOL: false
      });
      expect(styles[fontName]).toEqual({
        fontFamily: "serif",
        ascent: NaN,
        descent: NaN,
        vertical: false
      });
      await loadingTask.destroy();
    });
    it("gets text content, with no extra spaces (issue 13226)", async function () {
      const loadingTask = (0, _api.getDocument)((0, _test_utils.buildGetDocumentParams)("issue13226.pdf"));
      const pdfDoc = await loadingTask.promise;
      const pdfPage = await pdfDoc.getPage(1);
      const {
        items
      } = await pdfPage.getTextContent();
      const text = mergeText(items);
      expect(text).toEqual("Mitarbeiterinnen und Mitarbeiter arbeiten in über 100 Ländern engagiert im Dienste");
      await loadingTask.destroy();
    });
    it("gets text content, with merged spaces (issue 13201)", async function () {
      const loadingTask = (0, _api.getDocument)((0, _test_utils.buildGetDocumentParams)("issue13201.pdf"));
      const pdfDoc = await loadingTask.promise;
      const pdfPage = await pdfDoc.getPage(1);
      const {
        items
      } = await pdfPage.getTextContent();
      const text = mergeText(items);
      expect(text.includes("Abstract. A purely peer-to-peer version of electronic cash would allow online")).toEqual(true);
      expect(text.includes("avoid mediating disputes. The cost of mediation increases transaction costs, limiting the")).toEqual(true);
      expect(text.includes("system is secure as long as honest nodes collectively control more CPU power than any")).toEqual(true);
      await loadingTask.destroy();
    });
    it("gets text content, with no spaces between letters of words (issue 11913)", async function () {
      const loadingTask = (0, _api.getDocument)((0, _test_utils.buildGetDocumentParams)("issue11913.pdf"));
      const pdfDoc = await loadingTask.promise;
      const pdfPage = await pdfDoc.getPage(1);
      const {
        items
      } = await pdfPage.getTextContent();
      const text = mergeText(items);
      expect(text.includes("1. The first of these cases arises from the tragic handicap which has blighted the life of the Plaintiff, and from the response of the")).toEqual(true);
      expect(text.includes("argued in this Court the appeal raises narrower, but important, issues which may be summarised as follows:-")).toEqual(true);
      await loadingTask.destroy();
    });
    it("gets text content, with merged spaces (issue 10900)", async function () {
      const loadingTask = (0, _api.getDocument)((0, _test_utils.buildGetDocumentParams)("issue10900.pdf"));
      const pdfDoc = await loadingTask.promise;
      const pdfPage = await pdfDoc.getPage(1);
      const {
        items
      } = await pdfPage.getTextContent();
      const text = mergeText(items);
      expect(text.includes(`3 3 3 3
851.5 854.9 839.3 837.5
633.6 727.8 789.9 796.2
1,485.1 1,582.7 1,629.2 1,633.7
114.2 121.7 125.3 130.7
13.0x 13.0x 13.0x 12.5x`)).toEqual(true);
      await loadingTask.destroy();
    });
    it("gets text content, with spaces (issue 10640)", async function () {
      const loadingTask = (0, _api.getDocument)((0, _test_utils.buildGetDocumentParams)("issue10640.pdf"));
      const pdfDoc = await loadingTask.promise;
      const pdfPage = await pdfDoc.getPage(1);
      const {
        items
      } = await pdfPage.getTextContent();
      const text = mergeText(items);
      expect(text.includes(`Open Sans is a humanist sans serif typeface designed by Steve Matteson.
Open Sans was designed with an upright stress, open forms and a neu-
tral, yet friendly appearance. It was optimized for print, web, and mobile
interfaces, and has excellent legibility characteristics in its letterforms (see
figure \x81 on the following page). This font is available from the Google Font
Directory [\x81] as TrueType files licensed under the Apache License version \x82.\x80.
This package provides support for this font in LATEX. It includes Type \x81
versions of the fonts, converted for this package using FontForge from its
sources, for full support with Dvips.`)).toEqual(true);
      await loadingTask.destroy();
    });
    it("gets text content, with negative spaces (bug 931481)", async function () {
      if (_is_node.isNodeJS) {
        pending("Linked test-cases are not supported in Node.js.");
      }

      const loadingTask = (0, _api.getDocument)((0, _test_utils.buildGetDocumentParams)("bug931481.pdf"));
      const pdfDoc = await loadingTask.promise;
      const pdfPage = await pdfDoc.getPage(1);
      const {
        items
      } = await pdfPage.getTextContent();
      const text = mergeText(items);
      expect(text.includes(`Kathrin Nachbaur
Die promovierte Juristin ist 1979 in Graz geboren und aufgewachsen. Nach
erfolgreichem Studienabschluss mit Fokus auf Europarecht absolvierte sie ein
Praktikum bei Magna International in Kanada in der Human Resources Abteilung.
Anschliessend wurde sie geschult in Human Resources, Arbeitsrecht und
Kommunikation, währenddessen sie auch an ihrem Doktorat im Wirtschaftsrecht
arbeitete. Seither arbeitete sie bei Magna International als Projekt Manager in der
Innovationsabteilung. Seit 2009 ist sie Frank Stronachs Büroleiterin in Österreich und
Kanada. Zusätzlich ist sie seit 2012 Vice President, Business Development der
Stronach Group und Vizepräsidentin und Institutsleiterin des Stronach Institut für
sozialökonomische Gerechtigkeit.`)).toEqual(true);
      await loadingTask.destroy();
    });
    it("gets text content, with beginbfrange operator handled correctly (bug 1627427)", async function () {
      const loadingTask = (0, _api.getDocument)((0, _test_utils.buildGetDocumentParams)("bug1627427_reduced.pdf"));
      const pdfDoc = await loadingTask.promise;
      const pdfPage = await pdfDoc.getPage(1);
      const {
        items
      } = await pdfPage.getTextContent();
      const text = mergeText(items);
      expect(text).toEqual("침하게 흐린 품이 눈이 올 듯하더니 눈은 아니 오고 얼다가 만 비가 추");
      await loadingTask.destroy();
    });
    it("gets empty structure tree", async function () {
      const tree = await page.getStructTree();
      expect(tree).toEqual(null);
    });
    it("gets simple structure tree", async function () {
      const loadingTask = (0, _api.getDocument)((0, _test_utils.buildGetDocumentParams)("structure_simple.pdf"));
      const pdfDoc = await loadingTask.promise;
      const pdfPage = await pdfDoc.getPage(1);
      const tree = await pdfPage.getStructTree();
      expect(tree).toEqual({
        role: "Root",
        children: [{
          role: "Document",
          lang: "en-US",
          children: [{
            role: "H1",
            children: [{
              role: "NonStruct",
              children: [{
                type: "content",
                id: "page2R_mcid0"
              }]
            }]
          }, {
            role: "P",
            children: [{
              role: "NonStruct",
              children: [{
                type: "content",
                id: "page2R_mcid1"
              }]
            }]
          }, {
            role: "H2",
            children: [{
              role: "NonStruct",
              children: [{
                type: "content",
                id: "page2R_mcid2"
              }]
            }]
          }, {
            role: "P",
            children: [{
              role: "NonStruct",
              children: [{
                type: "content",
                id: "page2R_mcid3"
              }]
            }]
          }]
        }]
      });
      await loadingTask.destroy();
    });
    it("gets operator list", async function () {
      const operatorList = await page.getOperatorList();
      expect(operatorList.fnArray.length).toBeGreaterThan(100);
      expect(operatorList.argsArray.length).toBeGreaterThan(100);
      expect(operatorList.lastChunk).toEqual(true);
    });
    it("gets operatorList with JPEG image (issue 4888)", async function () {
      const loadingTask = (0, _api.getDocument)((0, _test_utils.buildGetDocumentParams)("cmykjpeg.pdf"));
      const pdfDoc = await loadingTask.promise;
      const pdfPage = await pdfDoc.getPage(1);
      const operatorList = await pdfPage.getOperatorList();
      const imgIndex = operatorList.fnArray.indexOf(_util.OPS.paintImageXObject);
      const imgArgs = operatorList.argsArray[imgIndex];
      const {
        data
      } = pdfPage.objs.get(imgArgs[0]);
      expect(data instanceof Uint8ClampedArray).toEqual(true);
      expect(data.length).toEqual(90000);
      await loadingTask.destroy();
    });
    it("gets operatorList, from corrupt PDF file (issue 8702), " + "with/without `stopAtErrors` set", async function () {
      const loadingTask1 = (0, _api.getDocument)((0, _test_utils.buildGetDocumentParams)("issue8702.pdf", {
        stopAtErrors: false
      }));
      const loadingTask2 = (0, _api.getDocument)((0, _test_utils.buildGetDocumentParams)("issue8702.pdf", {
        stopAtErrors: true
      }));
      const result1 = loadingTask1.promise.then(pdfDoc => {
        return pdfDoc.getPage(1).then(pdfPage => {
          return pdfPage.getOperatorList().then(opList => {
            expect(opList.fnArray.length).toBeGreaterThan(100);
            expect(opList.argsArray.length).toBeGreaterThan(100);
            expect(opList.lastChunk).toEqual(true);
            return loadingTask1.destroy();
          });
        });
      });
      const result2 = loadingTask2.promise.then(pdfDoc => {
        return pdfDoc.getPage(1).then(pdfPage => {
          return pdfPage.getOperatorList().then(opList => {
            expect(opList.fnArray.length).toEqual(0);
            expect(opList.argsArray.length).toEqual(0);
            expect(opList.lastChunk).toEqual(true);
            return loadingTask2.destroy();
          });
        });
      });
      await Promise.all([result1, result2]);
    });
    it("gets operator list, containing Annotation-operatorLists", async function () {
      const loadingTask = (0, _api.getDocument)((0, _test_utils.buildGetDocumentParams)("annotation-line.pdf"));
      const pdfDoc = await loadingTask.promise;
      const pdfPage = await pdfDoc.getPage(1);
      const operatorList = await pdfPage.getOperatorList();
      expect(operatorList.fnArray.length).toBeGreaterThan(20);
      expect(operatorList.argsArray.length).toBeGreaterThan(20);
      expect(operatorList.lastChunk).toEqual(true);
      expect(operatorList.fnArray.includes(_util.OPS.beginAnnotation)).toEqual(true);
      expect(operatorList.fnArray.includes(_util.OPS.endAnnotation)).toEqual(true);
      await loadingTask.destroy();
    });
    it("gets operator list, with `annotationMode`-option", async function () {
      const loadingTask = (0, _api.getDocument)((0, _test_utils.buildGetDocumentParams)("evaljs.pdf"));
      const pdfDoc = await loadingTask.promise;
      const pdfPage = await pdfDoc.getPage(2);
      pdfDoc.annotationStorage.setValue("30R", {
        value: "test"
      });
      pdfDoc.annotationStorage.setValue("31R", {
        value: true
      });
      const opListAnnotDisable = await pdfPage.getOperatorList({
        annotationMode: _util.AnnotationMode.DISABLE
      });
      expect(opListAnnotDisable.fnArray.length).toEqual(0);
      expect(opListAnnotDisable.argsArray.length).toEqual(0);
      expect(opListAnnotDisable.lastChunk).toEqual(true);
      const opListAnnotEnable = await pdfPage.getOperatorList({
        annotationMode: _util.AnnotationMode.ENABLE
      });
      expect(opListAnnotEnable.fnArray.length).toBeGreaterThan(150);
      expect(opListAnnotEnable.argsArray.length).toBeGreaterThan(150);
      expect(opListAnnotEnable.lastChunk).toEqual(true);
      const opListAnnotEnableForms = await pdfPage.getOperatorList({
        annotationMode: _util.AnnotationMode.ENABLE_FORMS
      });
      expect(opListAnnotEnableForms.fnArray.length).toBeGreaterThan(40);
      expect(opListAnnotEnableForms.argsArray.length).toBeGreaterThan(40);
      expect(opListAnnotEnableForms.lastChunk).toEqual(true);
      const opListAnnotEnableStorage = await pdfPage.getOperatorList({
        annotationMode: _util.AnnotationMode.ENABLE_STORAGE
      });
      expect(opListAnnotEnableStorage.fnArray.length).toBeGreaterThan(170);
      expect(opListAnnotEnableStorage.argsArray.length).toBeGreaterThan(170);
      expect(opListAnnotEnableStorage.lastChunk).toEqual(true);
      expect(opListAnnotDisable.fnArray.length).toBeLessThan(opListAnnotEnableForms.fnArray.length);
      expect(opListAnnotEnableForms.fnArray.length).toBeLessThan(opListAnnotEnable.fnArray.length);
      expect(opListAnnotEnable.fnArray.length).toBeLessThan(opListAnnotEnableStorage.fnArray.length);
      await loadingTask.destroy();
    });
    it("gets operatorList, with page resources containing corrupt /CCITTFaxDecode data", async function () {
      const loadingTask = (0, _api.getDocument)((0, _test_utils.buildGetDocumentParams)("poppler-90-0-fuzzed.pdf"));
      expect(loadingTask instanceof _api.PDFDocumentLoadingTask).toEqual(true);
      const pdfDoc = await loadingTask.promise;
      expect(pdfDoc.numPages).toEqual(16);
      const pdfPage = await pdfDoc.getPage(6);
      expect(pdfPage instanceof _api.PDFPageProxy).toEqual(true);
      const opList = await pdfPage.getOperatorList();
      expect(opList.fnArray.length).toBeGreaterThan(25);
      expect(opList.argsArray.length).toBeGreaterThan(25);
      expect(opList.lastChunk).toEqual(true);
      await loadingTask.destroy();
    });
    it("gets document stats after parsing page", async function () {
      await page.getOperatorList();
      const stats = pdfDocument.stats;
      const expectedStreamTypes = {
        [_util.StreamType.FLATE]: true
      };
      const expectedFontTypes = {
        [_util.FontType.TYPE1STANDARD]: true,
        [_util.FontType.CIDFONTTYPE2]: true
      };
      expect(stats).toEqual({
        streamTypes: expectedStreamTypes,
        fontTypes: expectedFontTypes
      });
    });
    it("gets page stats after parsing page, without `pdfBug` set", async function () {
      await page.getOperatorList();
      expect(page.stats).toEqual(null);
    });
    it("gets page stats after parsing page, with `pdfBug` set", async function () {
      const loadingTask = (0, _api.getDocument)((0, _test_utils.buildGetDocumentParams)(basicApiFileName, {
        pdfBug: true
      }));
      const pdfDoc = await loadingTask.promise;
      const pdfPage = await pdfDoc.getPage(1);
      await pdfPage.getOperatorList();
      const stats = pdfPage.stats;
      expect(stats instanceof _display_utils.StatTimer).toEqual(true);
      expect(stats.times.length).toEqual(1);
      const [statEntry] = stats.times;
      expect(statEntry.name).toEqual("Page Request");
      expect(statEntry.end - statEntry.start).toBeGreaterThanOrEqual(0);
      await loadingTask.destroy();
    });
    it("gets page stats after rendering page, with `pdfBug` set", async function () {
      const loadingTask = (0, _api.getDocument)((0, _test_utils.buildGetDocumentParams)(basicApiFileName, {
        pdfBug: true
      }));
      const pdfDoc = await loadingTask.promise;
      const pdfPage = await pdfDoc.getPage(1);
      const viewport = pdfPage.getViewport({
        scale: 1
      });
      const canvasAndCtx = CanvasFactory.create(viewport.width, viewport.height);
      const renderTask = pdfPage.render({
        canvasContext: canvasAndCtx.context,
        canvasFactory: CanvasFactory,
        viewport
      });
      expect(renderTask instanceof _api.RenderTask).toEqual(true);
      await renderTask.promise;
      const stats = pdfPage.stats;
      expect(stats instanceof _display_utils.StatTimer).toEqual(true);
      expect(stats.times.length).toEqual(3);
      const [statEntryOne, statEntryTwo, statEntryThree] = stats.times;
      expect(statEntryOne.name).toEqual("Page Request");
      expect(statEntryOne.end - statEntryOne.start).toBeGreaterThanOrEqual(0);
      expect(statEntryTwo.name).toEqual("Rendering");
      expect(statEntryTwo.end - statEntryTwo.start).toBeGreaterThan(0);
      expect(statEntryThree.name).toEqual("Overall");
      expect(statEntryThree.end - statEntryThree.start).toBeGreaterThan(0);
      CanvasFactory.destroy(canvasAndCtx);
      await loadingTask.destroy();
    });
    it("cancels rendering of page", async function () {
      const viewport = page.getViewport({
        scale: 1
      });
      const canvasAndCtx = CanvasFactory.create(viewport.width, viewport.height);
      const renderTask = page.render({
        canvasContext: canvasAndCtx.context,
        canvasFactory: CanvasFactory,
        viewport
      });
      expect(renderTask instanceof _api.RenderTask).toEqual(true);
      renderTask.cancel();

      try {
        await renderTask.promise;
        expect(false).toEqual(true);
      } catch (reason) {
        expect(reason instanceof _display_utils.RenderingCancelledException).toEqual(true);
        expect(reason.message).toEqual("Rendering cancelled, page 1");
        expect(reason.type).toEqual("canvas");
      }

      CanvasFactory.destroy(canvasAndCtx);
    });
    it("re-render page, using the same canvas, after cancelling rendering", async function () {
      const viewport = page.getViewport({
        scale: 1
      });
      const canvasAndCtx = CanvasFactory.create(viewport.width, viewport.height);
      const renderTask = page.render({
        canvasContext: canvasAndCtx.context,
        canvasFactory: CanvasFactory,
        viewport
      });
      expect(renderTask instanceof _api.RenderTask).toEqual(true);
      renderTask.cancel();

      try {
        await renderTask.promise;
        expect(false).toEqual(true);
      } catch (reason) {
        expect(reason instanceof _display_utils.RenderingCancelledException).toEqual(true);
      }

      const reRenderTask = page.render({
        canvasContext: canvasAndCtx.context,
        canvasFactory: CanvasFactory,
        viewport
      });
      expect(reRenderTask instanceof _api.RenderTask).toEqual(true);
      await reRenderTask.promise;
      CanvasFactory.destroy(canvasAndCtx);
    });
    it("multiple render() on the same canvas", async function () {
      const optionalContentConfigPromise = pdfDocument.getOptionalContentConfig();
      const viewport = page.getViewport({
        scale: 1
      });
      const canvasAndCtx = CanvasFactory.create(viewport.width, viewport.height);
      const renderTask1 = page.render({
        canvasContext: canvasAndCtx.context,
        canvasFactory: CanvasFactory,
        viewport,
        optionalContentConfigPromise
      });
      expect(renderTask1 instanceof _api.RenderTask).toEqual(true);
      const renderTask2 = page.render({
        canvasContext: canvasAndCtx.context,
        canvasFactory: CanvasFactory,
        viewport,
        optionalContentConfigPromise
      });
      expect(renderTask2 instanceof _api.RenderTask).toEqual(true);
      await Promise.all([renderTask1.promise, renderTask2.promise.then(() => {
        expect(false).toEqual(true);
      }, reason => {
        expect(/multiple render\(\)/.test(reason.message)).toEqual(true);
      })]);
    });
    it("cleans up document resources after rendering of page", async function () {
      const loadingTask = (0, _api.getDocument)((0, _test_utils.buildGetDocumentParams)(basicApiFileName));
      const pdfDoc = await loadingTask.promise;
      const pdfPage = await pdfDoc.getPage(1);
      const viewport = pdfPage.getViewport({
        scale: 1
      });
      const canvasAndCtx = CanvasFactory.create(viewport.width, viewport.height);
      const renderTask = pdfPage.render({
        canvasContext: canvasAndCtx.context,
        canvasFactory: CanvasFactory,
        viewport
      });
      expect(renderTask instanceof _api.RenderTask).toEqual(true);
      await renderTask.promise;
      await pdfDoc.cleanup();
      expect(true).toEqual(true);
      CanvasFactory.destroy(canvasAndCtx);
      await loadingTask.destroy();
    });
    it("cleans up document resources during rendering of page", async function () {
      const loadingTask = (0, _api.getDocument)((0, _test_utils.buildGetDocumentParams)("tracemonkey.pdf"));
      const pdfDoc = await loadingTask.promise;
      const pdfPage = await pdfDoc.getPage(1);
      const viewport = pdfPage.getViewport({
        scale: 1
      });
      const canvasAndCtx = CanvasFactory.create(viewport.width, viewport.height);
      const renderTask = pdfPage.render({
        canvasContext: canvasAndCtx.context,
        canvasFactory: CanvasFactory,
        viewport
      });
      expect(renderTask instanceof _api.RenderTask).toEqual(true);

      renderTask.onContinue = function (cont) {
        waitSome(cont);
      };

      try {
        await pdfDoc.cleanup();
        expect(false).toEqual(true);
      } catch (reason) {
        expect(reason instanceof Error).toEqual(true);
        expect(reason.message).toEqual("startCleanup: Page 1 is currently rendering.");
      }

      await renderTask.promise;
      CanvasFactory.destroy(canvasAndCtx);
      await loadingTask.destroy();
    });
    it("caches image resources at the document/page level as expected (issue 11878)", async function () {
      const {
        NUM_PAGES_THRESHOLD
      } = _image_utils.GlobalImageCache,
            EXPECTED_WIDTH = 2550,
            EXPECTED_HEIGHT = 3300;
      const loadingTask = (0, _api.getDocument)((0, _test_utils.buildGetDocumentParams)("issue11878.pdf"));
      const pdfDoc = await loadingTask.promise;
      let firstImgData = null;

      for (let i = 1; i <= pdfDoc.numPages; i++) {
        const pdfPage = await pdfDoc.getPage(i);
        const opList = await pdfPage.getOperatorList();
        const {
          commonObjs,
          objs
        } = pdfPage;
        const imgIndex = opList.fnArray.indexOf(_util.OPS.paintImageXObject);
        const [objId, width, height] = opList.argsArray[imgIndex];

        if (i < NUM_PAGES_THRESHOLD) {
          expect(objId).toEqual(`img_p${i - 1}_1`);
          expect(objs.has(objId)).toEqual(true);
          expect(commonObjs.has(objId)).toEqual(false);
        } else {
          expect(objId).toEqual(`g_${loadingTask.docId}_img_p${NUM_PAGES_THRESHOLD - 1}_1`);
          expect(objs.has(objId)).toEqual(false);
          expect(commonObjs.has(objId)).toEqual(true);
        }

        expect(width).toEqual(EXPECTED_WIDTH);
        expect(height).toEqual(EXPECTED_HEIGHT);

        if (i === 1) {
          firstImgData = objs.get(objId);
          expect(firstImgData.width).toEqual(EXPECTED_WIDTH);
          expect(firstImgData.height).toEqual(EXPECTED_HEIGHT);
          expect(firstImgData.kind).toEqual(_util.ImageKind.RGB_24BPP);
          expect(firstImgData.data instanceof Uint8ClampedArray).toEqual(true);
          expect(firstImgData.data.length).toEqual(25245000);
        } else {
          const objsPool = i >= NUM_PAGES_THRESHOLD ? commonObjs : objs;
          const currentImgData = objsPool.get(objId);
          expect(currentImgData.width).toEqual(firstImgData.width);
          expect(currentImgData.height).toEqual(firstImgData.height);
          expect(currentImgData.kind).toEqual(firstImgData.kind);
          expect(currentImgData.data instanceof Uint8ClampedArray).toEqual(true);
          expect(currentImgData.data.every((value, index) => {
            return value === firstImgData.data[index];
          })).toEqual(true);
        }
      }

      await loadingTask.destroy();
      firstImgData = null;
    });
  });
  describe("Multiple `getDocument` instances", function () {
    const pdf1 = (0, _test_utils.buildGetDocumentParams)("tracemonkey.pdf");
    const pdf2 = (0, _test_utils.buildGetDocumentParams)("TAMReview.pdf");
    const pdf3 = (0, _test_utils.buildGetDocumentParams)("issue6068.pdf");
    const loadingTasks = [];

    async function renderPDF(filename) {
      const loadingTask = (0, _api.getDocument)(filename);
      loadingTasks.push(loadingTask);
      const pdf = await loadingTask.promise;
      const page = await pdf.getPage(1);
      const viewport = page.getViewport({
        scale: 1.2
      });
      const canvasAndCtx = CanvasFactory.create(viewport.width, viewport.height);
      const renderTask = page.render({
        canvasContext: canvasAndCtx.context,
        canvasFactory: CanvasFactory,
        viewport
      });
      await renderTask.promise;
      const data = canvasAndCtx.canvas.toDataURL();
      CanvasFactory.destroy(canvasAndCtx);
      return data;
    }

    afterEach(async function () {
      const destroyPromises = loadingTasks.map(function (loadingTask) {
        return loadingTask.destroy();
      });
      await Promise.all(destroyPromises);
    });
    it("should correctly render PDFs in parallel", async function () {
      let baseline1, baseline2, baseline3;
      const promiseDone = renderPDF(pdf1).then(function (data1) {
        baseline1 = data1;
        return renderPDF(pdf2);
      }).then(function (data2) {
        baseline2 = data2;
        return renderPDF(pdf3);
      }).then(function (data3) {
        baseline3 = data3;
        return Promise.all([renderPDF(pdf1), renderPDF(pdf2), renderPDF(pdf3)]);
      }).then(function (dataUrls) {
        expect(dataUrls[0]).toEqual(baseline1);
        expect(dataUrls[1]).toEqual(baseline2);
        expect(dataUrls[2]).toEqual(baseline3);
        return true;
      });
      await promiseDone;
    });
  });
  describe("PDFDataRangeTransport", function () {
    let dataPromise;
    beforeAll(function () {
      const fileName = "tracemonkey.pdf";
      dataPromise = _test_utils.DefaultFileReaderFactory.fetch({
        path: _test_utils.TEST_PDFS_PATH + fileName
      });
    });
    afterAll(function () {
      dataPromise = null;
    });
    it("should fetch document info and page using ranges", async function () {
      const initialDataLength = 4000;
      let fetches = 0;
      const data = await dataPromise;
      const initialData = data.subarray(0, initialDataLength);
      const transport = new _api.PDFDataRangeTransport(data.length, initialData);

      transport.requestDataRange = function (begin, end) {
        fetches++;
        waitSome(function () {
          transport.onDataProgress(4000);
          transport.onDataRange(begin, data.subarray(begin, end));
        });
      };

      const loadingTask = (0, _api.getDocument)(transport);
      const pdfDocument = await loadingTask.promise;
      expect(pdfDocument.numPages).toEqual(14);
      const pdfPage = await pdfDocument.getPage(10);
      expect(pdfPage.rotate).toEqual(0);
      expect(fetches).toBeGreaterThan(2);
      await loadingTask.destroy();
    });
    it("should fetch document info and page using range and streaming", async function () {
      const initialDataLength = 4000;
      let fetches = 0;
      const data = await dataPromise;
      const initialData = data.subarray(0, initialDataLength);
      const transport = new _api.PDFDataRangeTransport(data.length, initialData);

      transport.requestDataRange = function (begin, end) {
        fetches++;

        if (fetches === 1) {
          transport.onDataProgressiveRead(data.subarray(initialDataLength));
        }

        waitSome(function () {
          transport.onDataRange(begin, data.subarray(begin, end));
        });
      };

      const loadingTask = (0, _api.getDocument)(transport);
      const pdfDocument = await loadingTask.promise;
      expect(pdfDocument.numPages).toEqual(14);
      const pdfPage = await pdfDocument.getPage(10);
      expect(pdfPage.rotate).toEqual(0);
      expect(fetches).toEqual(1);
      await new Promise(resolve => {
        waitSome(resolve);
      });
      await loadingTask.destroy();
    });
    it("should fetch document info and page, without range, " + "using complete initialData", async function () {
      let fetches = 0;
      const data = await dataPromise;
      const transport = new _api.PDFDataRangeTransport(data.length, data, true);

      transport.requestDataRange = function (begin, end) {
        fetches++;
      };

      const loadingTask = (0, _api.getDocument)({
        disableRange: true,
        range: transport
      });
      const pdfDocument = await loadingTask.promise;
      expect(pdfDocument.numPages).toEqual(14);
      const pdfPage = await pdfDocument.getPage(10);
      expect(pdfPage.rotate).toEqual(0);
      expect(fetches).toEqual(0);
      await loadingTask.destroy();
    });
  });
});