UNPKG

pdfjs-dist

Version:

Generic build of Mozilla's PDF.js library.

1,080 lines (1,079 loc) • 109 kB
/** * @licstart The following is the entire license notice for the * JavaScript code in this page * * Copyright 2022 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 _annotation_storage = require("../../display/annotation_storage.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 TypedArray", async function () { const typedArrayPdf = await _test_utils.DefaultFileReaderFactory.fetch({ path: _test_utils.TEST_PDFS_PATH + basicApiFileName }); expect(typedArrayPdf instanceof Uint8Array).toEqual(true); 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 ArrayBuffer", async function () { const { buffer: arrayBufferPdf } = await _test_utils.DefaultFileReaderFactory.fetch({ path: _test_utils.TEST_PDFS_PATH + basicApiFileName }); expect(arrayBufferPdf instanceof ArrayBuffer).toEqual(true); expect(arrayBufferPdf.byteLength).toEqual(basicApiFileLength); const loadingTask = (0, _api.getDocument)(arrayBufferPdf); 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 password protected PDF file and passes an Error " + "(asynchronously) to the onPassword callback (bug 1754421)", async function () { const loadingTask = (0, _api.getDocument)((0, _test_utils.buildGetDocumentParams)("issue3371.pdf")); expect(loadingTask instanceof _api.PDFDocumentLoadingTask).toEqual(true); loadingTask.onPassword = function (updatePassword, reason) { waitSome(() => { updatePassword(new Error("Should reject the loadingTask.")); }); }; await loadingTask.promise.then(function () { expect(false).toEqual(true); }, function (reason) { expect(reason instanceof _util.PasswordException).toEqual(true); expect(reason.code).toEqual(_util.PasswordResponses.NEED_PASSWORD); }); await loadingTask.destroy(); }); it("creates pdf doc from empty TypedArray", 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); expect(opList.separateAnnots).toEqual(null); 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); expect(opList.separateAnnots).toEqual(null); 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")); const loadingTask3 = (0, _api.getDocument)((0, _test_utils.buildGetDocumentParams)("poppler-85140-0.pdf", { stopAtErrors: true })); expect(loadingTask1 instanceof _api.PDFDocumentLoadingTask).toEqual(true); expect(loadingTask2 instanceof _api.PDFDocumentLoadingTask).toEqual(true); expect(loadingTask3 instanceof _api.PDFDocumentLoadingTask).toEqual(true); const pdfDocument1 = await loadingTask1.promise; const pdfDocument2 = await loadingTask2.promise; const pdfDocument3 = await loadingTask3.promise; expect(pdfDocument1.numPages).toEqual(1); expect(pdfDocument2.numPages).toEqual(1); expect(pdfDocument3.numPages).toEqual(1); const pageA = await pdfDocument1.getPage(1); expect(pageA instanceof _api.PDFPageProxy).toEqual(true); const opListA = await pageA.getOperatorList(); expect(opListA.fnArray.length).toBeGreaterThan(5); expect(opListA.argsArray.length).toBeGreaterThan(5); expect(opListA.lastChunk).toEqual(true); expect(opListA.separateAnnots).toEqual(null); const pageB = await pdfDocument2.getPage(1); expect(pageB instanceof _api.PDFPageProxy).toEqual(true); const opListB = await pageB.getOperatorList(); expect(opListB.fnArray.length).toBe(0); expect(opListB.argsArray.length).toBe(0); expect(opListB.lastChunk).toEqual(true); expect(opListB.separateAnnots).toEqual(null); try { await pdfDocument3.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(), loadingTask3.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); expect(opList.separateAnnots).toEqual(null); } 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("Illegal character: 41"); } try { await pdfDocument2.getPage(1); expect(false).toEqual(true); } catch (reason) { expect(reason instanceof _util.UnknownErrorException).toEqual(true); expect(reason.message).toEqual("End of file inside array."); } await Promise.all([loadingTask1.destroy(), loadingTask2.destroy()]); }); it("creates pdf doc from PDF file with bad /Resources entry", async function () { const loadingTask = (0, _api.getDocument)((0, _test_utils.buildGetDocumentParams)("issue15150.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).toEqual([_util.OPS.setLineWidth, _util.OPS.setStrokeRGBColor, _util.OPS.constructPath, _util.OPS.closeStroke]); expect(opList.argsArray).toEqual([[0.5], new Uint8ClampedArray([255, 0, 0]), [[_util.OPS.moveTo, _util.OPS.lineTo], [0, 9.75, 0.5, 9.75], [0, 0.5, 9.75, 9.75]], null]); expect(opList.lastChunk).toEqual(true); await loadingTask.destroy(); }); it("creates pdf doc from PDF file, with incomplete trailer", async function () { const loadingTask = (0, _api.getDocument)((0, _test_utils.buildGetDocumentParams)("issue15590.pdf")); expect(loadingTask instanceof _api.PDFDocumentLoadingTask).toEqual(true); const pdfDocument = await loadingTask.promise; expect(pdfDocument.numPages).toEqual(1); const jsActions = await pdfDocument.getJSActions(); expect(jsActions).toEqual({ OpenAction: ["func=function(){app.alert(1)};func();"] }); const page = await pdfDocument.getPage(1); expect(page instanceof _api.PDFPageProxy).toEqual(true); await loadingTask.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 () { const pageNumbers = [100, 2.5, "1"]; for (const pageNumber of pageNumbers) { try { await pdfDocument.getPage(pageNumber); expect(false).toEqual(true); } catch (reason) { expect(reason instanceof Error).toEqual(true); expect(reason.message).toEqual("Invalid page request."); } } }); 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 pageRefs = [{ num: 3, gen: 0 }, { num: -1, gen: 0 }, "qwerty", null]; const expectedErrors = [{ exception: _util.UnknownErrorException, message: "The reference does not point to a /Page dictionary." }, { exception: Error, message: "Invalid pageIndex request." }, { exception: Error, message: "Invalid pageIndex request." }, { exception: Error, message: "Invalid pageIndex request." }]; for (let i = 0, ii = pageRefs.length; i < ii; i++) { try { await pdfDocument.getPageIndex(pageRefs[i]); expect(false).toEqual(true); } catch (reason) { const { exception, message } = expectedErrors[i]; expect(reason instanceof exception).toEqual(true); expect(reason.message).toEqual(message); } } }); 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 a destination, from /Names (NameTree) dictionary with keys using PDFDocEncoding (issue 14847)", async function () { const loadingTask = (0, _api.getDocument)((0, _test_utils.buildGetDocumentParams)("issue14847.pdf")); const pdfDoc = await loadingTask.promise; const destination = await pdfDoc.getDestination("index"); expect(destination).toEqual([{ num: 10, gen: 0 }, { name: "XYZ" }, 85.039, 728.504, null]); 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 fieldObjects", async function () { const fieldObjects = await pdfDocument.getFieldObjects(); expect(fieldObjects).toEqual(null); }); it("gets fieldObjects", async function () { const loadingTask = (0, _api.getDocument)((0, _test_utils.buildGetDocumentParams)("js-authors.pdf")); const pdfDoc = await loadingTask.promise; const fieldObjects = await pdfDoc.getFieldObjects(); expect(fieldObjects).toEqual({ Text1: [{ id: "25R", value: "", defaultValue: "", multiline: false, password: false, charLimit: 0, comb: false, editable: true, hidden: false, name: "Text1", rect: [24.1789, 719.66, 432.22, 741.66], actions: null, page: 0, strokeColor: null, fillColor: null, rotation: 0, type: "text" }], Button1: [{ id: "26R", value: "Off", defaultValue: null, exportValues: undefined, editable: true, name: "Button1", rect: [455.436, 719.678, 527.436, 739.678], hidden: false, actions: { Action: [`this.getField("Text1").value = this.info.authors.join("::");`] }, page: 0, strokeColor: null, fillColor: new Uint8ClampedArray([192, 192, 192]), rotation: 0, type: "button" }] }); await loadingTask.destroy(); }); it("gets non-existent calculationOrder", async function () { const calculationOrder = await pdfDocument.getCalculationOrderIds(); expect(calculationOrder).toEqual(null); }); it("gets calculationOrder", 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)("issue13132.pdf")); const pdfDoc = await loadingTask.promise; const calculationOrder = await pdfDoc.getCalculationOrderIds(); expect(calculationOrder).toEqual(["319R", "320R", "321R", "322R", "323R", "324R", "325R", "326R", "327R", "328R", "329R", "330R", "331R", "332R", "333R", "334R", "335R"]); 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 dest-strings using PDFDocEncoding (issue 14864)", 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)("issue14864.pdf")); const pdfDoc = await loadingTask.promise; const outline = await pdfDoc.getOutline(); expect(Array.isArray(outline)).toEqual(true); expect(outline.length).toEqual(6); expect(outline[4]).toEqual({ action: null, attach