api_spec.js 68 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732
  1. /**
  2. * @licstart The following is the entire license notice for the
  3. * Javascript code in this page
  4. *
  5. * Copyright 2021 Mozilla Foundation
  6. *
  7. * Licensed under the Apache License, Version 2.0 (the "License");
  8. * you may not use this file except in compliance with the License.
  9. * You may obtain a copy of the License at
  10. *
  11. * http://www.apache.org/licenses/LICENSE-2.0
  12. *
  13. * Unless required by applicable law or agreed to in writing, software
  14. * distributed under the License is distributed on an "AS IS" BASIS,
  15. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  16. * See the License for the specific language governing permissions and
  17. * limitations under the License.
  18. *
  19. * @licend The above is the entire license notice for the
  20. * Javascript code in this page
  21. */
  22. "use strict";
  23. var _test_utils = require("./test_utils.js");
  24. var _util = require("../../shared/util.js");
  25. var _api = require("../../display/api.js");
  26. var _display_utils = require("../../display/display_utils.js");
  27. var _ui_utils = require("../../web/ui_utils.js");
  28. var _image_utils = require("../../core/image_utils.js");
  29. var _worker_options = require("../../display/worker_options.js");
  30. var _is_node = require("../../shared/is_node.js");
  31. var _metadata = require("../../display/metadata.js");
  32. describe("api", function () {
  33. const basicApiFileName = "basicapi.pdf";
  34. const basicApiFileLength = 105779;
  35. const basicApiGetDocumentParams = (0, _test_utils.buildGetDocumentParams)(basicApiFileName);
  36. let CanvasFactory;
  37. beforeAll(function (done) {
  38. CanvasFactory = new _api.DefaultCanvasFactory();
  39. done();
  40. });
  41. afterAll(function (done) {
  42. CanvasFactory = null;
  43. done();
  44. });
  45. function waitSome(callback) {
  46. const WAIT_TIMEOUT = 10;
  47. setTimeout(function () {
  48. callback();
  49. }, WAIT_TIMEOUT);
  50. }
  51. describe("getDocument", function () {
  52. it("creates pdf doc from URL-string", async function () {
  53. const urlStr = _test_utils.TEST_PDFS_PATH + basicApiFileName;
  54. const loadingTask = (0, _api.getDocument)(urlStr);
  55. const pdfDocument = await loadingTask.promise;
  56. expect(typeof urlStr).toEqual("string");
  57. expect(pdfDocument instanceof _api.PDFDocumentProxy).toEqual(true);
  58. expect(pdfDocument.numPages).toEqual(3);
  59. await loadingTask.destroy();
  60. });
  61. it("creates pdf doc from URL-object", async function () {
  62. if (_is_node.isNodeJS) {
  63. pending("window.location is not supported in Node.js.");
  64. }
  65. const urlObj = new URL(_test_utils.TEST_PDFS_PATH + basicApiFileName, window.location);
  66. const loadingTask = (0, _api.getDocument)(urlObj);
  67. const pdfDocument = await loadingTask.promise;
  68. expect(urlObj instanceof URL).toEqual(true);
  69. expect(pdfDocument instanceof _api.PDFDocumentProxy).toEqual(true);
  70. expect(pdfDocument.numPages).toEqual(3);
  71. await loadingTask.destroy();
  72. });
  73. it("creates pdf doc from URL", function (done) {
  74. const loadingTask = (0, _api.getDocument)(basicApiGetDocumentParams);
  75. const progressReportedCapability = (0, _util.createPromiseCapability)();
  76. loadingTask.onProgress = function (progressData) {
  77. if (!progressReportedCapability.settled) {
  78. progressReportedCapability.resolve(progressData);
  79. }
  80. };
  81. const promises = [progressReportedCapability.promise, loadingTask.promise];
  82. Promise.all(promises).then(function (data) {
  83. expect(data[0].loaded / data[0].total >= 0).toEqual(true);
  84. expect(data[1] instanceof _api.PDFDocumentProxy).toEqual(true);
  85. expect(loadingTask).toEqual(data[1].loadingTask);
  86. loadingTask.destroy().then(done);
  87. }).catch(done.fail);
  88. });
  89. it("creates pdf doc from URL and aborts before worker initialized", function (done) {
  90. const loadingTask = (0, _api.getDocument)(basicApiGetDocumentParams);
  91. const destroyed = loadingTask.destroy();
  92. loadingTask.promise.then(function (reason) {
  93. done.fail("shall fail loading");
  94. }).catch(function (reason) {
  95. expect(true).toEqual(true);
  96. destroyed.then(done);
  97. });
  98. });
  99. it("creates pdf doc from URL and aborts loading after worker initialized", function (done) {
  100. const loadingTask = (0, _api.getDocument)(basicApiGetDocumentParams);
  101. const destroyed = loadingTask._worker.promise.then(function () {
  102. return loadingTask.destroy();
  103. });
  104. destroyed.then(function (data) {
  105. expect(true).toEqual(true);
  106. done();
  107. }).catch(done.fail);
  108. });
  109. it("creates pdf doc from typed array", function (done) {
  110. const typedArrayPdfPromise = _test_utils.DefaultFileReaderFactory.fetch({
  111. path: _test_utils.TEST_PDFS_PATH + basicApiFileName
  112. });
  113. typedArrayPdfPromise.then(typedArrayPdf => {
  114. expect(typedArrayPdf.length).toEqual(basicApiFileLength);
  115. const loadingTask = (0, _api.getDocument)(typedArrayPdf);
  116. const progressReportedCapability = (0, _util.createPromiseCapability)();
  117. loadingTask.onProgress = function (data) {
  118. progressReportedCapability.resolve(data);
  119. };
  120. return Promise.all([loadingTask.promise, progressReportedCapability.promise]).then(function (data) {
  121. expect(data[0] instanceof _api.PDFDocumentProxy).toEqual(true);
  122. expect(data[1].loaded / data[1].total).toEqual(1);
  123. loadingTask.destroy().then(done);
  124. });
  125. }).catch(done.fail);
  126. });
  127. it("creates pdf doc from invalid PDF file", function (done) {
  128. const loadingTask = (0, _api.getDocument)((0, _test_utils.buildGetDocumentParams)("bug1020226.pdf"));
  129. loadingTask.promise.then(function () {
  130. done.fail("shall fail loading");
  131. }).catch(function (reason) {
  132. expect(reason instanceof _util.InvalidPDFException).toEqual(true);
  133. expect(reason.message).toEqual("Invalid PDF structure.");
  134. loadingTask.destroy().then(done);
  135. });
  136. });
  137. it("creates pdf doc from non-existent URL", function (done) {
  138. if (!_is_node.isNodeJS) {
  139. pending("Fails intermittently on linux in browsers.");
  140. }
  141. const loadingTask = (0, _api.getDocument)((0, _test_utils.buildGetDocumentParams)("non-existent.pdf"));
  142. loadingTask.promise.then(function (error) {
  143. done.fail("shall fail loading");
  144. }).catch(function (error) {
  145. expect(error instanceof _util.MissingPDFException).toEqual(true);
  146. loadingTask.destroy().then(done);
  147. });
  148. });
  149. it("creates pdf doc from PDF file protected with user and owner password", function (done) {
  150. const loadingTask = (0, _api.getDocument)((0, _test_utils.buildGetDocumentParams)("pr6531_1.pdf"));
  151. const passwordNeededCapability = (0, _util.createPromiseCapability)();
  152. const passwordIncorrectCapability = (0, _util.createPromiseCapability)();
  153. loadingTask.onPassword = function (updatePassword, reason) {
  154. if (reason === _util.PasswordResponses.NEED_PASSWORD && !passwordNeededCapability.settled) {
  155. passwordNeededCapability.resolve();
  156. updatePassword("qwerty");
  157. return;
  158. }
  159. if (reason === _util.PasswordResponses.INCORRECT_PASSWORD && !passwordIncorrectCapability.settled) {
  160. passwordIncorrectCapability.resolve();
  161. updatePassword("asdfasdf");
  162. return;
  163. }
  164. expect(false).toEqual(true);
  165. };
  166. const promises = [passwordNeededCapability.promise, passwordIncorrectCapability.promise, loadingTask.promise];
  167. Promise.all(promises).then(function (data) {
  168. expect(data[2] instanceof _api.PDFDocumentProxy).toEqual(true);
  169. loadingTask.destroy().then(done);
  170. }).catch(done.fail);
  171. });
  172. it("creates pdf doc from PDF file protected with only a user password", function (done) {
  173. const filename = "pr6531_2.pdf";
  174. const passwordNeededLoadingTask = (0, _api.getDocument)((0, _test_utils.buildGetDocumentParams)(filename, {
  175. password: ""
  176. }));
  177. const result1 = passwordNeededLoadingTask.promise.then(function () {
  178. done.fail("shall fail with no password");
  179. return Promise.reject(new Error("loadingTask should be rejected"));
  180. }, function (data) {
  181. expect(data instanceof _util.PasswordException).toEqual(true);
  182. expect(data.code).toEqual(_util.PasswordResponses.NEED_PASSWORD);
  183. return passwordNeededLoadingTask.destroy();
  184. });
  185. const passwordIncorrectLoadingTask = (0, _api.getDocument)((0, _test_utils.buildGetDocumentParams)(filename, {
  186. password: "qwerty"
  187. }));
  188. const result2 = passwordIncorrectLoadingTask.promise.then(function () {
  189. done.fail("shall fail with wrong password");
  190. return Promise.reject(new Error("loadingTask should be rejected"));
  191. }, function (data) {
  192. expect(data instanceof _util.PasswordException).toEqual(true);
  193. expect(data.code).toEqual(_util.PasswordResponses.INCORRECT_PASSWORD);
  194. return passwordIncorrectLoadingTask.destroy();
  195. });
  196. const passwordAcceptedLoadingTask = (0, _api.getDocument)((0, _test_utils.buildGetDocumentParams)(filename, {
  197. password: "asdfasdf"
  198. }));
  199. const result3 = passwordAcceptedLoadingTask.promise.then(function (data) {
  200. expect(data instanceof _api.PDFDocumentProxy).toEqual(true);
  201. return passwordAcceptedLoadingTask.destroy();
  202. });
  203. Promise.all([result1, result2, result3]).then(function () {
  204. done();
  205. }).catch(done.fail);
  206. });
  207. it("creates pdf doc from password protected PDF file and aborts/throws " + "in the onPassword callback (issue 7806)", function (done) {
  208. const filename = "issue3371.pdf";
  209. const passwordNeededLoadingTask = (0, _api.getDocument)((0, _test_utils.buildGetDocumentParams)(filename));
  210. const passwordIncorrectLoadingTask = (0, _api.getDocument)((0, _test_utils.buildGetDocumentParams)(filename, {
  211. password: "qwerty"
  212. }));
  213. let passwordNeededDestroyed;
  214. passwordNeededLoadingTask.onPassword = function (callback, reason) {
  215. if (reason === _util.PasswordResponses.NEED_PASSWORD) {
  216. passwordNeededDestroyed = passwordNeededLoadingTask.destroy();
  217. return;
  218. }
  219. expect(false).toEqual(true);
  220. };
  221. const result1 = passwordNeededLoadingTask.promise.then(function () {
  222. done.fail("shall fail since the loadingTask should be destroyed");
  223. return Promise.reject(new Error("loadingTask should be rejected"));
  224. }, function (reason) {
  225. expect(reason instanceof _util.PasswordException).toEqual(true);
  226. expect(reason.code).toEqual(_util.PasswordResponses.NEED_PASSWORD);
  227. return passwordNeededDestroyed;
  228. });
  229. passwordIncorrectLoadingTask.onPassword = function (callback, reason) {
  230. if (reason === _util.PasswordResponses.INCORRECT_PASSWORD) {
  231. throw new Error("Incorrect password");
  232. }
  233. expect(false).toEqual(true);
  234. };
  235. const result2 = passwordIncorrectLoadingTask.promise.then(function () {
  236. done.fail("shall fail since the onPassword callback should throw");
  237. return Promise.reject(new Error("loadingTask should be rejected"));
  238. }, function (reason) {
  239. expect(reason instanceof _util.PasswordException).toEqual(true);
  240. expect(reason.code).toEqual(_util.PasswordResponses.INCORRECT_PASSWORD);
  241. return passwordIncorrectLoadingTask.destroy();
  242. });
  243. Promise.all([result1, result2]).then(function () {
  244. done();
  245. }).catch(done.fail);
  246. });
  247. it("creates pdf doc from empty typed array", function (done) {
  248. const loadingTask = (0, _api.getDocument)(new Uint8Array(0));
  249. loadingTask.promise.then(function () {
  250. done.fail("shall not open empty file");
  251. }, function (reason) {
  252. expect(reason instanceof _util.InvalidPDFException);
  253. expect(reason.message).toEqual("The PDF file is empty, i.e. its size is zero bytes.");
  254. loadingTask.destroy().then(done);
  255. });
  256. });
  257. });
  258. describe("PDFWorker", function () {
  259. it("worker created or destroyed", function (done) {
  260. if (_is_node.isNodeJS) {
  261. pending("Worker is not supported in Node.js.");
  262. }
  263. const worker = new _api.PDFWorker({
  264. name: "test1"
  265. });
  266. worker.promise.then(function () {
  267. expect(worker.name).toEqual("test1");
  268. expect(!!worker.port).toEqual(true);
  269. expect(worker.destroyed).toEqual(false);
  270. expect(!!worker._webWorker).toEqual(true);
  271. expect(worker.port === worker._webWorker).toEqual(true);
  272. worker.destroy();
  273. expect(!!worker.port).toEqual(false);
  274. expect(worker.destroyed).toEqual(true);
  275. done();
  276. }).catch(done.fail);
  277. });
  278. it("worker created or destroyed by getDocument", function (done) {
  279. if (_is_node.isNodeJS) {
  280. pending("Worker is not supported in Node.js.");
  281. }
  282. const loadingTask = (0, _api.getDocument)(basicApiGetDocumentParams);
  283. let worker;
  284. loadingTask.promise.then(function () {
  285. worker = loadingTask._worker;
  286. expect(!!worker).toEqual(true);
  287. });
  288. const destroyPromise = loadingTask.promise.then(function () {
  289. return loadingTask.destroy();
  290. });
  291. destroyPromise.then(function () {
  292. const destroyedWorker = loadingTask._worker;
  293. expect(!!destroyedWorker).toEqual(false);
  294. expect(worker.destroyed).toEqual(true);
  295. done();
  296. }).catch(done.fail);
  297. });
  298. it("worker created and can be used in getDocument", function (done) {
  299. if (_is_node.isNodeJS) {
  300. pending("Worker is not supported in Node.js.");
  301. }
  302. const worker = new _api.PDFWorker({
  303. name: "test1"
  304. });
  305. const loadingTask = (0, _api.getDocument)((0, _test_utils.buildGetDocumentParams)(basicApiFileName, {
  306. worker
  307. }));
  308. loadingTask.promise.then(function () {
  309. const docWorker = loadingTask._worker;
  310. expect(!!docWorker).toEqual(false);
  311. const messageHandlerPort = loadingTask._transport.messageHandler.comObj;
  312. expect(messageHandlerPort === worker.port).toEqual(true);
  313. });
  314. const destroyPromise = loadingTask.promise.then(function () {
  315. return loadingTask.destroy();
  316. });
  317. destroyPromise.then(function () {
  318. expect(worker.destroyed).toEqual(false);
  319. worker.destroy();
  320. done();
  321. }).catch(done.fail);
  322. });
  323. it("creates more than one worker", function (done) {
  324. if (_is_node.isNodeJS) {
  325. pending("Worker is not supported in Node.js.");
  326. }
  327. const worker1 = new _api.PDFWorker({
  328. name: "test1"
  329. });
  330. const worker2 = new _api.PDFWorker({
  331. name: "test2"
  332. });
  333. const worker3 = new _api.PDFWorker({
  334. name: "test3"
  335. });
  336. const ready = Promise.all([worker1.promise, worker2.promise, worker3.promise]);
  337. ready.then(function () {
  338. expect(worker1.port !== worker2.port && worker1.port !== worker3.port && worker2.port !== worker3.port).toEqual(true);
  339. worker1.destroy();
  340. worker2.destroy();
  341. worker3.destroy();
  342. done();
  343. }).catch(done.fail);
  344. });
  345. it("gets current workerSrc", function () {
  346. if (_is_node.isNodeJS) {
  347. pending("Worker is not supported in Node.js.");
  348. }
  349. const workerSrc = _api.PDFWorker.getWorkerSrc();
  350. expect(typeof workerSrc).toEqual("string");
  351. expect(workerSrc).toEqual(_worker_options.GlobalWorkerOptions.workerSrc);
  352. });
  353. });
  354. describe("PDFDocument", function () {
  355. let pdfLoadingTask, pdfDocument;
  356. beforeAll(function (done) {
  357. pdfLoadingTask = (0, _api.getDocument)(basicApiGetDocumentParams);
  358. pdfLoadingTask.promise.then(function (data) {
  359. pdfDocument = data;
  360. done();
  361. });
  362. });
  363. afterAll(function (done) {
  364. pdfLoadingTask.destroy().then(done);
  365. });
  366. it("gets number of pages", function () {
  367. expect(pdfDocument.numPages).toEqual(3);
  368. });
  369. it("gets fingerprint", function () {
  370. expect(pdfDocument.fingerprint).toEqual("ea8b35919d6279a369e835bde778611b");
  371. });
  372. it("gets page", function (done) {
  373. const promise = pdfDocument.getPage(1);
  374. promise.then(function (data) {
  375. expect(data instanceof _api.PDFPageProxy).toEqual(true);
  376. expect(data.pageNumber).toEqual(1);
  377. done();
  378. }).catch(done.fail);
  379. });
  380. it("gets non-existent page", function (done) {
  381. let outOfRangePromise = pdfDocument.getPage(100);
  382. let nonIntegerPromise = pdfDocument.getPage(2.5);
  383. let nonNumberPromise = pdfDocument.getPage("1");
  384. outOfRangePromise = outOfRangePromise.then(function () {
  385. throw new Error("shall fail for out-of-range pageNumber parameter");
  386. }, function (reason) {
  387. expect(reason instanceof Error).toEqual(true);
  388. });
  389. nonIntegerPromise = nonIntegerPromise.then(function () {
  390. throw new Error("shall fail for non-integer pageNumber parameter");
  391. }, function (reason) {
  392. expect(reason instanceof Error).toEqual(true);
  393. });
  394. nonNumberPromise = nonNumberPromise.then(function () {
  395. throw new Error("shall fail for non-number pageNumber parameter");
  396. }, function (reason) {
  397. expect(reason instanceof Error).toEqual(true);
  398. });
  399. Promise.all([outOfRangePromise, nonIntegerPromise, nonNumberPromise]).then(function () {
  400. done();
  401. }).catch(done.fail);
  402. });
  403. it("gets page, from /Pages tree with circular reference", function (done) {
  404. const loadingTask = (0, _api.getDocument)((0, _test_utils.buildGetDocumentParams)("Pages-tree-refs.pdf"));
  405. const page1 = loadingTask.promise.then(function (pdfDoc) {
  406. return pdfDoc.getPage(1).then(function (pdfPage) {
  407. expect(pdfPage instanceof _api.PDFPageProxy).toEqual(true);
  408. expect(pdfPage.ref).toEqual({
  409. num: 6,
  410. gen: 0
  411. });
  412. }, function (reason) {
  413. throw new Error("shall not fail for valid page");
  414. });
  415. });
  416. const page2 = loadingTask.promise.then(function (pdfDoc) {
  417. return pdfDoc.getPage(2).then(function (pdfPage) {
  418. throw new Error("shall fail for invalid page");
  419. }, function (reason) {
  420. expect(reason instanceof Error).toEqual(true);
  421. expect(reason.message).toEqual("Pages tree contains circular reference.");
  422. });
  423. });
  424. Promise.all([page1, page2]).then(function () {
  425. loadingTask.destroy().then(done);
  426. }, done.fail);
  427. });
  428. it("gets page index", function (done) {
  429. const ref = {
  430. num: 17,
  431. gen: 0
  432. };
  433. const promise = pdfDocument.getPageIndex(ref);
  434. promise.then(function (pageIndex) {
  435. expect(pageIndex).toEqual(1);
  436. done();
  437. }).catch(done.fail);
  438. });
  439. it("gets invalid page index", function (done) {
  440. const ref = {
  441. num: 3,
  442. gen: 0
  443. };
  444. const promise = pdfDocument.getPageIndex(ref);
  445. promise.then(function () {
  446. done.fail("shall fail for invalid page reference.");
  447. }).catch(function (reason) {
  448. expect(reason instanceof Error).toEqual(true);
  449. done();
  450. });
  451. });
  452. it("gets destinations, from /Dests dictionary", function (done) {
  453. const promise = pdfDocument.getDestinations();
  454. promise.then(function (data) {
  455. expect(data).toEqual({
  456. chapter1: [{
  457. gen: 0,
  458. num: 17
  459. }, {
  460. name: "XYZ"
  461. }, 0, 841.89, null]
  462. });
  463. done();
  464. }).catch(done.fail);
  465. });
  466. it("gets a destination, from /Dests dictionary", function (done) {
  467. const promise = pdfDocument.getDestination("chapter1");
  468. promise.then(function (data) {
  469. expect(data).toEqual([{
  470. gen: 0,
  471. num: 17
  472. }, {
  473. name: "XYZ"
  474. }, 0, 841.89, null]);
  475. done();
  476. }).catch(done.fail);
  477. });
  478. it("gets a non-existent destination, from /Dests dictionary", function (done) {
  479. const promise = pdfDocument.getDestination("non-existent-named-destination");
  480. promise.then(function (data) {
  481. expect(data).toEqual(null);
  482. done();
  483. }).catch(done.fail);
  484. });
  485. it("gets destinations, from /Names (NameTree) dictionary", function (done) {
  486. const loadingTask = (0, _api.getDocument)((0, _test_utils.buildGetDocumentParams)("issue6204.pdf"));
  487. const promise = loadingTask.promise.then(function (pdfDoc) {
  488. return pdfDoc.getDestinations();
  489. });
  490. promise.then(function (destinations) {
  491. expect(destinations).toEqual({
  492. "Page.1": [{
  493. num: 1,
  494. gen: 0
  495. }, {
  496. name: "XYZ"
  497. }, 0, 375, null],
  498. "Page.2": [{
  499. num: 6,
  500. gen: 0
  501. }, {
  502. name: "XYZ"
  503. }, 0, 375, null]
  504. });
  505. loadingTask.destroy().then(done);
  506. }).catch(done.fail);
  507. });
  508. it("gets a destination, from /Names (NameTree) dictionary", function (done) {
  509. const loadingTask = (0, _api.getDocument)((0, _test_utils.buildGetDocumentParams)("issue6204.pdf"));
  510. const promise = loadingTask.promise.then(function (pdfDoc) {
  511. return pdfDoc.getDestination("Page.1");
  512. });
  513. promise.then(function (destination) {
  514. expect(destination).toEqual([{
  515. num: 1,
  516. gen: 0
  517. }, {
  518. name: "XYZ"
  519. }, 0, 375, null]);
  520. loadingTask.destroy().then(done);
  521. }).catch(done.fail);
  522. });
  523. it("gets a non-existent destination, from /Names (NameTree) dictionary", function (done) {
  524. const loadingTask = (0, _api.getDocument)((0, _test_utils.buildGetDocumentParams)("issue6204.pdf"));
  525. const promise = loadingTask.promise.then(function (pdfDoc) {
  526. return pdfDoc.getDestination("non-existent-named-destination");
  527. });
  528. promise.then(function (destination) {
  529. expect(destination).toEqual(null);
  530. loadingTask.destroy().then(done);
  531. }).catch(done.fail);
  532. });
  533. it("gets non-string destination", function (done) {
  534. let numberPromise = pdfDocument.getDestination(4.3);
  535. let booleanPromise = pdfDocument.getDestination(true);
  536. let arrayPromise = pdfDocument.getDestination([{
  537. num: 17,
  538. gen: 0
  539. }, {
  540. name: "XYZ"
  541. }, 0, 841.89, null]);
  542. numberPromise = numberPromise.then(function () {
  543. throw new Error("shall fail for non-string destination.");
  544. }, function (reason) {
  545. expect(reason instanceof Error).toEqual(true);
  546. });
  547. booleanPromise = booleanPromise.then(function () {
  548. throw new Error("shall fail for non-string destination.");
  549. }, function (reason) {
  550. expect(reason instanceof Error).toEqual(true);
  551. });
  552. arrayPromise = arrayPromise.then(function () {
  553. throw new Error("shall fail for non-string destination.");
  554. }, function (reason) {
  555. expect(reason instanceof Error).toEqual(true);
  556. });
  557. Promise.all([numberPromise, booleanPromise, arrayPromise]).then(done, done.fail);
  558. });
  559. it("gets non-existent page labels", function (done) {
  560. const promise = pdfDocument.getPageLabels();
  561. promise.then(function (data) {
  562. expect(data).toEqual(null);
  563. done();
  564. }).catch(done.fail);
  565. });
  566. it("gets page labels", function (done) {
  567. const loadingTask0 = (0, _api.getDocument)((0, _test_utils.buildGetDocumentParams)("bug793632.pdf"));
  568. const promise0 = loadingTask0.promise.then(function (pdfDoc) {
  569. return pdfDoc.getPageLabels();
  570. });
  571. const loadingTask1 = (0, _api.getDocument)((0, _test_utils.buildGetDocumentParams)("issue1453.pdf"));
  572. const promise1 = loadingTask1.promise.then(function (pdfDoc) {
  573. return pdfDoc.getPageLabels();
  574. });
  575. const loadingTask2 = (0, _api.getDocument)((0, _test_utils.buildGetDocumentParams)("rotation.pdf"));
  576. const promise2 = loadingTask2.promise.then(function (pdfDoc) {
  577. return pdfDoc.getPageLabels();
  578. });
  579. const loadingTask3 = (0, _api.getDocument)((0, _test_utils.buildGetDocumentParams)("bad-PageLabels.pdf"));
  580. const promise3 = loadingTask3.promise.then(function (pdfDoc) {
  581. return pdfDoc.getPageLabels();
  582. });
  583. Promise.all([promise0, promise1, promise2, promise3]).then(function (pageLabels) {
  584. expect(pageLabels[0]).toEqual(["i", "ii", "iii", "1"]);
  585. expect(pageLabels[1]).toEqual(["Front Page1"]);
  586. expect(pageLabels[2]).toEqual(["1", "2"]);
  587. expect(pageLabels[3]).toEqual(["X3"]);
  588. Promise.all([loadingTask0.destroy(), loadingTask1.destroy(), loadingTask2.destroy(), loadingTask3.destroy()]).then(done);
  589. }).catch(done.fail);
  590. });
  591. it("gets default page layout", function (done) {
  592. const loadingTask = (0, _api.getDocument)((0, _test_utils.buildGetDocumentParams)("tracemonkey.pdf"));
  593. loadingTask.promise.then(function (pdfDoc) {
  594. return pdfDoc.getPageLayout();
  595. }).then(function (mode) {
  596. expect(mode).toEqual("");
  597. loadingTask.destroy().then(done);
  598. }).catch(done.fail);
  599. });
  600. it("gets non-default page layout", function (done) {
  601. pdfDocument.getPageLayout().then(function (mode) {
  602. expect(mode).toEqual("SinglePage");
  603. done();
  604. }).catch(done.fail);
  605. });
  606. it("gets default page mode", function (done) {
  607. const loadingTask = (0, _api.getDocument)((0, _test_utils.buildGetDocumentParams)("tracemonkey.pdf"));
  608. loadingTask.promise.then(function (pdfDoc) {
  609. return pdfDoc.getPageMode();
  610. }).then(function (mode) {
  611. expect(mode).toEqual("UseNone");
  612. loadingTask.destroy().then(done);
  613. }).catch(done.fail);
  614. });
  615. it("gets non-default page mode", function (done) {
  616. pdfDocument.getPageMode().then(function (mode) {
  617. expect(mode).toEqual("UseOutlines");
  618. done();
  619. }).catch(done.fail);
  620. });
  621. it("gets default viewer preferences", function (done) {
  622. const loadingTask = (0, _api.getDocument)((0, _test_utils.buildGetDocumentParams)("tracemonkey.pdf"));
  623. loadingTask.promise.then(function (pdfDoc) {
  624. return pdfDoc.getViewerPreferences();
  625. }).then(function (prefs) {
  626. expect(prefs).toEqual(null);
  627. loadingTask.destroy().then(done);
  628. }).catch(done.fail);
  629. });
  630. it("gets non-default viewer preferences", function (done) {
  631. pdfDocument.getViewerPreferences().then(function (prefs) {
  632. expect(prefs).toEqual({
  633. Direction: "L2R"
  634. });
  635. done();
  636. }).catch(done.fail);
  637. });
  638. it("gets default open action", function (done) {
  639. const loadingTask = (0, _api.getDocument)((0, _test_utils.buildGetDocumentParams)("tracemonkey.pdf"));
  640. loadingTask.promise.then(function (pdfDoc) {
  641. return pdfDoc.getOpenAction();
  642. }).then(function (openAction) {
  643. expect(openAction).toEqual(null);
  644. loadingTask.destroy().then(done);
  645. }).catch(done.fail);
  646. });
  647. it("gets non-default open action (with destination)", function (done) {
  648. pdfDocument.getOpenAction().then(function (openAction) {
  649. expect(openAction.dest).toEqual([{
  650. num: 15,
  651. gen: 0
  652. }, {
  653. name: "FitH"
  654. }, null]);
  655. expect(openAction.action).toBeUndefined();
  656. done();
  657. }).catch(done.fail);
  658. });
  659. it("gets non-default open action (with Print action)", function (done) {
  660. const loadingTask1 = (0, _api.getDocument)((0, _test_utils.buildGetDocumentParams)("bug1001080.pdf"));
  661. const loadingTask2 = (0, _api.getDocument)((0, _test_utils.buildGetDocumentParams)("issue11442_reduced.pdf"));
  662. const promise1 = loadingTask1.promise.then(function (pdfDoc) {
  663. return pdfDoc.getOpenAction();
  664. }).then(function (openAction) {
  665. expect(openAction.dest).toBeUndefined();
  666. expect(openAction.action).toEqual("Print");
  667. return loadingTask1.destroy();
  668. });
  669. const promise2 = loadingTask2.promise.then(function (pdfDoc) {
  670. return pdfDoc.getOpenAction();
  671. }).then(function (openAction) {
  672. expect(openAction.dest).toBeUndefined();
  673. expect(openAction.action).toEqual("Print");
  674. return loadingTask2.destroy();
  675. });
  676. Promise.all([promise1, promise2]).then(done, done.fail);
  677. });
  678. it("gets non-existent attachments", function (done) {
  679. const promise = pdfDocument.getAttachments();
  680. promise.then(function (data) {
  681. expect(data).toEqual(null);
  682. done();
  683. }).catch(done.fail);
  684. });
  685. it("gets attachments", function (done) {
  686. const loadingTask = (0, _api.getDocument)((0, _test_utils.buildGetDocumentParams)("attachment.pdf"));
  687. const promise = loadingTask.promise.then(function (pdfDoc) {
  688. return pdfDoc.getAttachments();
  689. });
  690. promise.then(function (data) {
  691. const attachment = data["foo.txt"];
  692. expect(attachment.filename).toEqual("foo.txt");
  693. expect(attachment.content).toEqual(new Uint8Array([98, 97, 114, 32, 98, 97, 122, 32, 10]));
  694. loadingTask.destroy().then(done);
  695. }).catch(done.fail);
  696. });
  697. it("gets javascript", function (done) {
  698. const promise = pdfDocument.getJavaScript();
  699. promise.then(function (data) {
  700. expect(data).toEqual(null);
  701. done();
  702. }).catch(done.fail);
  703. });
  704. it("gets javascript with printing instructions (JS action)", function (done) {
  705. const loadingTask = (0, _api.getDocument)((0, _test_utils.buildGetDocumentParams)("issue6106.pdf"));
  706. const promise = loadingTask.promise.then(function (pdfDoc) {
  707. return pdfDoc.getJavaScript();
  708. });
  709. promise.then(function (data) {
  710. expect(data).toEqual(["this.print({bUI:true,bSilent:false,bShrinkToFit:true});"]);
  711. expect(data[0]).toMatch(_ui_utils.AutoPrintRegExp);
  712. loadingTask.destroy().then(done);
  713. }).catch(done.fail);
  714. });
  715. it("gets JSActions (none)", function (done) {
  716. const promise = pdfDocument.getJSActions();
  717. promise.then(function (data) {
  718. expect(data).toEqual(null);
  719. done();
  720. }).catch(done.fail);
  721. });
  722. it("gets JSActions", function (done) {
  723. const loadingTask = (0, _api.getDocument)((0, _test_utils.buildGetDocumentParams)("doc_actions.pdf"));
  724. const promise = loadingTask.promise.then(async pdfDoc => {
  725. const docActions = await pdfDoc.getJSActions();
  726. const page1 = await pdfDoc.getPage(1);
  727. const page3 = await pdfDoc.getPage(3);
  728. const page1Actions = await page1.getJSActions();
  729. const page3Actions = await page3.getJSActions();
  730. return [docActions, page1Actions, page3Actions];
  731. });
  732. promise.then(async ([docActions, page1Actions, page3Actions]) => {
  733. expect(docActions).toEqual({
  734. DidPrint: [`this.getField("Text2").value = "DidPrint";`],
  735. DidSave: [`this.getField("Text2").value = "DidSave";`],
  736. WillClose: [`this.getField("Text1").value = "WillClose";`],
  737. WillPrint: [`this.getField("Text1").value = "WillPrint";`],
  738. WillSave: [`this.getField("Text1").value = "WillSave";`]
  739. });
  740. expect(page1Actions).toEqual({
  741. PageOpen: [`this.getField("Text1").value = "PageOpen 1";`],
  742. PageClose: [`this.getField("Text2").value = "PageClose 1";`]
  743. });
  744. expect(page3Actions).toEqual({
  745. PageOpen: [`this.getField("Text5").value = "PageOpen 3";`],
  746. PageClose: [`this.getField("Text6").value = "PageClose 3";`]
  747. });
  748. loadingTask.destroy().then(done);
  749. }).catch(done.fail);
  750. });
  751. it("gets non-existent outline", function (done) {
  752. const loadingTask = (0, _api.getDocument)((0, _test_utils.buildGetDocumentParams)("tracemonkey.pdf"));
  753. const promise = loadingTask.promise.then(function (pdfDoc) {
  754. return pdfDoc.getOutline();
  755. });
  756. promise.then(function (outline) {
  757. expect(outline).toEqual(null);
  758. loadingTask.destroy().then(done);
  759. }).catch(done.fail);
  760. });
  761. it("gets outline", function (done) {
  762. const promise = pdfDocument.getOutline();
  763. promise.then(function (outline) {
  764. expect(Array.isArray(outline)).toEqual(true);
  765. expect(outline.length).toEqual(2);
  766. const outlineItem = outline[1];
  767. expect(outlineItem.title).toEqual("Chapter 1");
  768. expect(Array.isArray(outlineItem.dest)).toEqual(true);
  769. expect(outlineItem.url).toEqual(null);
  770. expect(outlineItem.unsafeUrl).toBeUndefined();
  771. expect(outlineItem.newWindow).toBeUndefined();
  772. expect(outlineItem.bold).toEqual(true);
  773. expect(outlineItem.italic).toEqual(false);
  774. expect(outlineItem.color).toEqual(new Uint8ClampedArray([0, 64, 128]));
  775. expect(outlineItem.items.length).toEqual(1);
  776. expect(outlineItem.items[0].title).toEqual("Paragraph 1.1");
  777. done();
  778. }).catch(done.fail);
  779. });
  780. it("gets outline containing a url", function (done) {
  781. const loadingTask = (0, _api.getDocument)((0, _test_utils.buildGetDocumentParams)("issue3214.pdf"));
  782. loadingTask.promise.then(function (pdfDoc) {
  783. pdfDoc.getOutline().then(function (outline) {
  784. expect(Array.isArray(outline)).toEqual(true);
  785. expect(outline.length).toEqual(5);
  786. const outlineItemTwo = outline[2];
  787. expect(typeof outlineItemTwo.title).toEqual("string");
  788. expect(outlineItemTwo.dest).toEqual(null);
  789. expect(outlineItemTwo.url).toEqual("http://google.com/");
  790. expect(outlineItemTwo.unsafeUrl).toEqual("http://google.com");
  791. expect(outlineItemTwo.newWindow).toBeUndefined();
  792. const outlineItemOne = outline[1];
  793. expect(outlineItemOne.bold).toEqual(false);
  794. expect(outlineItemOne.italic).toEqual(true);
  795. expect(outlineItemOne.color).toEqual(new Uint8ClampedArray([0, 0, 0]));
  796. loadingTask.destroy().then(done);
  797. });
  798. }).catch(done.fail);
  799. });
  800. it("gets non-existent permissions", function (done) {
  801. pdfDocument.getPermissions().then(function (permissions) {
  802. expect(permissions).toEqual(null);
  803. done();
  804. }).catch(done.fail);
  805. });
  806. it("gets permissions", function (done) {
  807. const loadingTask0 = (0, _api.getDocument)((0, _test_utils.buildGetDocumentParams)("issue9972-1.pdf"));
  808. const promise0 = loadingTask0.promise.then(function (pdfDoc) {
  809. return pdfDoc.getPermissions();
  810. });
  811. const loadingTask1 = (0, _api.getDocument)((0, _test_utils.buildGetDocumentParams)("issue9972-2.pdf"));
  812. const promise1 = loadingTask1.promise.then(function (pdfDoc) {
  813. return pdfDoc.getPermissions();
  814. });
  815. const loadingTask2 = (0, _api.getDocument)((0, _test_utils.buildGetDocumentParams)("issue9972-3.pdf"));
  816. const promise2 = loadingTask2.promise.then(function (pdfDoc) {
  817. return pdfDoc.getPermissions();
  818. });
  819. const totalPermissionCount = Object.keys(_util.PermissionFlag).length;
  820. Promise.all([promise0, promise1, promise2]).then(function (permissions) {
  821. expect(permissions[0].length).toEqual(totalPermissionCount - 1);
  822. expect(permissions[0].includes(_util.PermissionFlag.MODIFY_CONTENTS)).toBeFalsy();
  823. expect(permissions[1].length).toEqual(totalPermissionCount - 2);
  824. expect(permissions[1].includes(_util.PermissionFlag.PRINT)).toBeFalsy();
  825. expect(permissions[1].includes(_util.PermissionFlag.PRINT_HIGH_QUALITY)).toBeFalsy();
  826. expect(permissions[2].length).toEqual(totalPermissionCount - 1);
  827. expect(permissions[2].includes(_util.PermissionFlag.COPY)).toBeFalsy();
  828. Promise.all([loadingTask0.destroy(), loadingTask1.destroy(), loadingTask2.destroy()]).then(done);
  829. }).catch(done.fail);
  830. });
  831. it("gets metadata", function (done) {
  832. const promise = pdfDocument.getMetadata();
  833. promise.then(function ({
  834. info,
  835. metadata,
  836. contentDispositionFilename,
  837. contentLength
  838. }) {
  839. expect(info.Title).toEqual("Basic API Test");
  840. expect(info.Custom).toEqual(undefined);
  841. expect(info.PDFFormatVersion).toEqual("1.7");
  842. expect(info.IsLinearized).toEqual(false);
  843. expect(info.IsAcroFormPresent).toEqual(false);
  844. expect(info.IsXFAPresent).toEqual(false);
  845. expect(info.IsCollectionPresent).toEqual(false);
  846. expect(metadata instanceof _metadata.Metadata).toEqual(true);
  847. expect(metadata.get("dc:title")).toEqual("Basic API Test");
  848. expect(contentDispositionFilename).toEqual(null);
  849. expect(contentLength).toEqual(basicApiFileLength);
  850. done();
  851. }).catch(done.fail);
  852. });
  853. it("gets metadata, with custom info dict entries", function (done) {
  854. const loadingTask = (0, _api.getDocument)((0, _test_utils.buildGetDocumentParams)("tracemonkey.pdf"));
  855. loadingTask.promise.then(function (pdfDoc) {
  856. return pdfDoc.getMetadata();
  857. }).then(function ({
  858. info,
  859. metadata,
  860. contentDispositionFilename,
  861. contentLength
  862. }) {
  863. expect(info.Creator).toEqual("TeX");
  864. expect(info.Producer).toEqual("pdfeTeX-1.21a");
  865. expect(info.CreationDate).toEqual("D:20090401163925-07'00'");
  866. const custom = info.Custom;
  867. expect(typeof custom === "object" && custom !== null).toEqual(true);
  868. expect(custom["PTEX.Fullbanner"]).toEqual("This is pdfeTeX, " + "Version 3.141592-1.21a-2.2 (Web2C 7.5.4) kpathsea version 3.5.6");
  869. expect(info.PDFFormatVersion).toEqual("1.4");
  870. expect(info.IsLinearized).toEqual(false);
  871. expect(info.IsAcroFormPresent).toEqual(false);
  872. expect(info.IsXFAPresent).toEqual(false);
  873. expect(info.IsCollectionPresent).toEqual(false);
  874. expect(metadata).toEqual(null);
  875. expect(contentDispositionFilename).toEqual(null);
  876. expect(contentLength).toEqual(1016315);
  877. loadingTask.destroy().then(done);
  878. }).catch(done.fail);
  879. });
  880. it("gets metadata, with missing PDF header (bug 1606566)", function (done) {
  881. const loadingTask = (0, _api.getDocument)((0, _test_utils.buildGetDocumentParams)("bug1606566.pdf"));
  882. loadingTask.promise.then(function (pdfDoc) {
  883. return pdfDoc.getMetadata();
  884. }).then(function ({
  885. info,
  886. metadata,
  887. contentDispositionFilename,
  888. contentLength
  889. }) {
  890. expect(info.PDFFormatVersion).toEqual(null);
  891. expect(info.IsLinearized).toEqual(false);
  892. expect(info.IsAcroFormPresent).toEqual(false);
  893. expect(info.IsXFAPresent).toEqual(false);
  894. expect(info.IsCollectionPresent).toEqual(false);
  895. expect(metadata).toEqual(null);
  896. expect(contentDispositionFilename).toEqual(null);
  897. expect(contentLength).toEqual(624);
  898. loadingTask.destroy().then(done);
  899. }).catch(done.fail);
  900. });
  901. it("gets markInfo", function (done) {
  902. const loadingTask = (0, _api.getDocument)((0, _test_utils.buildGetDocumentParams)("annotation-line.pdf"));
  903. loadingTask.promise.then(function (pdfDoc) {
  904. return pdfDoc.getMarkInfo();
  905. }).then(function (info) {
  906. expect(info.Marked).toEqual(true);
  907. expect(info.UserProperties).toEqual(false);
  908. expect(info.Suspects).toEqual(false);
  909. done();
  910. }).catch(done.fail);
  911. });
  912. it("gets data", function (done) {
  913. const promise = pdfDocument.getData();
  914. promise.then(function (data) {
  915. expect(data instanceof Uint8Array).toEqual(true);
  916. expect(data.length).toEqual(basicApiFileLength);
  917. done();
  918. }).catch(done.fail);
  919. });
  920. it("gets download info", function (done) {
  921. const promise = pdfDocument.getDownloadInfo();
  922. promise.then(function (data) {
  923. expect(data).toEqual({
  924. length: basicApiFileLength
  925. });
  926. done();
  927. }).catch(done.fail);
  928. });
  929. it("gets document stats", function (done) {
  930. const promise = pdfDocument.getStats();
  931. promise.then(function (stats) {
  932. expect(stats).toEqual({
  933. streamTypes: {},
  934. fontTypes: {}
  935. });
  936. done();
  937. }).catch(done.fail);
  938. });
  939. it("cleans up document resources", async function () {
  940. await pdfDocument.cleanup();
  941. expect(true).toEqual(true);
  942. });
  943. it("checks that fingerprints are unique", function (done) {
  944. const loadingTask1 = (0, _api.getDocument)((0, _test_utils.buildGetDocumentParams)("issue4436r.pdf"));
  945. const loadingTask2 = (0, _api.getDocument)((0, _test_utils.buildGetDocumentParams)("issue4575.pdf"));
  946. Promise.all([loadingTask1.promise, loadingTask2.promise]).then(function (data) {
  947. const fingerprint1 = data[0].fingerprint;
  948. const fingerprint2 = data[1].fingerprint;
  949. expect(fingerprint1).not.toEqual(fingerprint2);
  950. expect(fingerprint1).toEqual("2f695a83d6e7553c24fc08b7ac69712d");
  951. expect(fingerprint2).toEqual("04c7126b34a46b6d4d6e7a1eff7edcb6");
  952. Promise.all([loadingTask1.destroy(), loadingTask2.destroy()]).then(done);
  953. }).catch(done.fail);
  954. });
  955. describe("Cross-origin", function () {
  956. let loadingTask;
  957. function _checkCanLoad(expectSuccess, filename, options) {
  958. if (_is_node.isNodeJS) {
  959. pending("Cannot simulate cross-origin requests in Node.js");
  960. }
  961. const params = (0, _test_utils.buildGetDocumentParams)(filename, options);
  962. const url = new URL(params.url);
  963. if (url.hostname === "localhost") {
  964. url.hostname = "127.0.0.1";
  965. } else if (params.url.hostname === "127.0.0.1") {
  966. url.hostname = "localhost";
  967. } else {
  968. pending("Can only run cross-origin test on localhost!");
  969. }
  970. params.url = url.href;
  971. loadingTask = (0, _api.getDocument)(params);
  972. return loadingTask.promise.then(function (pdf) {
  973. return pdf.destroy();
  974. }).then(function () {
  975. expect(expectSuccess).toEqual(true);
  976. }, function (error) {
  977. if (expectSuccess) {
  978. expect(error).toEqual("There should not be any error");
  979. }
  980. expect(expectSuccess).toEqual(false);
  981. });
  982. }
  983. function testCanLoad(filename, options) {
  984. return _checkCanLoad(true, filename, options);
  985. }
  986. function testCannotLoad(filename, options) {
  987. return _checkCanLoad(false, filename, options);
  988. }
  989. afterEach(function (done) {
  990. if (loadingTask && !loadingTask.destroyed) {
  991. loadingTask.destroy().then(done);
  992. } else {
  993. done();
  994. }
  995. });
  996. it("server disallows cors", function (done) {
  997. testCannotLoad("basicapi.pdf").then(done);
  998. });
  999. it("server allows cors without credentials, default withCredentials", function (done) {
  1000. testCanLoad("basicapi.pdf?cors=withoutCredentials").then(done);
  1001. });
  1002. it("server allows cors without credentials, and withCredentials=false", function (done) {
  1003. testCanLoad("basicapi.pdf?cors=withoutCredentials", {
  1004. withCredentials: false
  1005. }).then(done);
  1006. });
  1007. it("server allows cors without credentials, but withCredentials=true", function (done) {
  1008. testCannotLoad("basicapi.pdf?cors=withoutCredentials", {
  1009. withCredentials: true
  1010. }).then(done);
  1011. });
  1012. it("server allows cors with credentials, and withCredentials=true", function (done) {
  1013. testCanLoad("basicapi.pdf?cors=withCredentials", {
  1014. withCredentials: true
  1015. }).then(done);
  1016. });
  1017. it("server allows cors with credentials, and withCredentials=false", function (done) {
  1018. testCanLoad("basicapi.pdf?cors=withCredentials", {
  1019. withCredentials: false
  1020. }).then(done);
  1021. });
  1022. });
  1023. });
  1024. describe("Page", function () {
  1025. let pdfLoadingTask, pdfDocument, page;
  1026. beforeAll(function (done) {
  1027. pdfLoadingTask = (0, _api.getDocument)(basicApiGetDocumentParams);
  1028. pdfLoadingTask.promise.then(function (doc) {
  1029. pdfDocument = doc;
  1030. pdfDocument.getPage(1).then(function (data) {
  1031. page = data;
  1032. done();
  1033. });
  1034. }).catch(done.fail);
  1035. });
  1036. afterAll(function (done) {
  1037. pdfLoadingTask.destroy().then(done);
  1038. });
  1039. it("gets page number", function () {
  1040. expect(page.pageNumber).toEqual(1);
  1041. });
  1042. it("gets rotate", function () {
  1043. expect(page.rotate).toEqual(0);
  1044. });
  1045. it("gets ref", function () {
  1046. expect(page.ref).toEqual({
  1047. num: 15,
  1048. gen: 0
  1049. });
  1050. });
  1051. it("gets userUnit", function () {
  1052. expect(page.userUnit).toEqual(1.0);
  1053. });
  1054. it("gets view", function () {
  1055. expect(page.view).toEqual([0, 0, 595.28, 841.89]);
  1056. });
  1057. it("gets view, with empty/invalid bounding boxes", function (done) {
  1058. const viewLoadingTask = (0, _api.getDocument)((0, _test_utils.buildGetDocumentParams)("boundingBox_invalid.pdf"));
  1059. viewLoadingTask.promise.then(pdfDoc => {
  1060. const numPages = pdfDoc.numPages;
  1061. expect(numPages).toEqual(3);
  1062. const viewPromises = [];
  1063. for (let i = 0; i < numPages; i++) {
  1064. viewPromises[i] = pdfDoc.getPage(i + 1).then(pdfPage => {
  1065. return pdfPage.view;
  1066. });
  1067. }
  1068. Promise.all(viewPromises).then(([page1, page2, page3]) => {
  1069. expect(page1).toEqual([0, 0, 612, 792]);
  1070. expect(page2).toEqual([0, 0, 800, 600]);
  1071. expect(page3).toEqual([0, 0, 600, 800]);
  1072. viewLoadingTask.destroy().then(done);
  1073. });
  1074. }).catch(done.fail);
  1075. });
  1076. it("gets viewport", function () {
  1077. const viewport = page.getViewport({
  1078. scale: 1.5,
  1079. rotation: 90
  1080. });
  1081. expect(viewport.viewBox).toEqual(page.view);
  1082. expect(viewport.scale).toEqual(1.5);
  1083. expect(viewport.rotation).toEqual(90);
  1084. expect(viewport.transform).toEqual([0, 1.5, 1.5, 0, 0, 0]);
  1085. expect(viewport.width).toEqual(1262.835);
  1086. expect(viewport.height).toEqual(892.92);
  1087. });
  1088. it('gets viewport with "offsetX/offsetY" arguments', function () {
  1089. const viewport = page.getViewport({
  1090. scale: 1,
  1091. rotation: 0,
  1092. offsetX: 100,
  1093. offsetY: -100
  1094. });
  1095. expect(viewport.transform).toEqual([1, 0, 0, -1, 100, 741.89]);
  1096. });
  1097. it('gets viewport respecting "dontFlip" argument', function () {
  1098. const scale = 1,
  1099. rotation = 0;
  1100. const viewport = page.getViewport({
  1101. scale,
  1102. rotation
  1103. });
  1104. const dontFlipViewport = page.getViewport({
  1105. scale,
  1106. rotation,
  1107. dontFlip: true
  1108. });
  1109. expect(dontFlipViewport).not.toEqual(viewport);
  1110. expect(dontFlipViewport).toEqual(viewport.clone({
  1111. dontFlip: true
  1112. }));
  1113. expect(viewport.transform).toEqual([1, 0, 0, -1, 0, 841.89]);
  1114. expect(dontFlipViewport.transform).toEqual([1, 0, -0, 1, 0, 0]);
  1115. });
  1116. it("gets viewport with invalid rotation", function () {
  1117. expect(function () {
  1118. page.getViewport({
  1119. scale: 1,
  1120. rotation: 45
  1121. });
  1122. }).toThrow(new Error("PageViewport: Invalid rotation, must be a multiple of 90 degrees."));
  1123. });
  1124. it("gets annotations", function (done) {
  1125. const defaultPromise = page.getAnnotations().then(function (data) {
  1126. expect(data.length).toEqual(4);
  1127. });
  1128. const displayPromise = page.getAnnotations({
  1129. intent: "display"
  1130. }).then(function (data) {
  1131. expect(data.length).toEqual(4);
  1132. });
  1133. const printPromise = page.getAnnotations({
  1134. intent: "print"
  1135. }).then(function (data) {
  1136. expect(data.length).toEqual(4);
  1137. });
  1138. Promise.all([defaultPromise, displayPromise, printPromise]).then(function () {
  1139. done();
  1140. }).catch(done.fail);
  1141. });
  1142. it("gets annotations containing relative URLs (bug 766086)", function (done) {
  1143. const filename = "bug766086.pdf";
  1144. const defaultLoadingTask = (0, _api.getDocument)((0, _test_utils.buildGetDocumentParams)(filename));
  1145. const defaultPromise = defaultLoadingTask.promise.then(function (pdfDoc) {
  1146. return pdfDoc.getPage(1).then(function (pdfPage) {
  1147. return pdfPage.getAnnotations();
  1148. });
  1149. });
  1150. const docBaseUrlLoadingTask = (0, _api.getDocument)((0, _test_utils.buildGetDocumentParams)(filename, {
  1151. docBaseUrl: "http://www.example.com/test/pdfs/qwerty.pdf"
  1152. }));
  1153. const docBaseUrlPromise = docBaseUrlLoadingTask.promise.then(function (pdfDoc) {
  1154. return pdfDoc.getPage(1).then(function (pdfPage) {
  1155. return pdfPage.getAnnotations();
  1156. });
  1157. });
  1158. const invalidDocBaseUrlLoadingTask = (0, _api.getDocument)((0, _test_utils.buildGetDocumentParams)(filename, {
  1159. docBaseUrl: "qwerty.pdf"
  1160. }));
  1161. const invalidDocBaseUrlPromise = invalidDocBaseUrlLoadingTask.promise.then(function (pdfDoc) {
  1162. return pdfDoc.getPage(1).then(function (pdfPage) {
  1163. return pdfPage.getAnnotations();
  1164. });
  1165. });
  1166. Promise.all([defaultPromise, docBaseUrlPromise, invalidDocBaseUrlPromise]).then(function (data) {
  1167. const defaultAnnotations = data[0];
  1168. const docBaseUrlAnnotations = data[1];
  1169. const invalidDocBaseUrlAnnotations = data[2];
  1170. expect(defaultAnnotations[0].url).toBeUndefined();
  1171. expect(defaultAnnotations[0].unsafeUrl).toEqual("../../0021/002156/215675E.pdf#15");
  1172. expect(docBaseUrlAnnotations[0].url).toEqual("http://www.example.com/0021/002156/215675E.pdf#15");
  1173. expect(docBaseUrlAnnotations[0].unsafeUrl).toEqual("../../0021/002156/215675E.pdf#15");
  1174. expect(invalidDocBaseUrlAnnotations[0].url).toBeUndefined();
  1175. expect(invalidDocBaseUrlAnnotations[0].unsafeUrl).toEqual("../../0021/002156/215675E.pdf#15");
  1176. Promise.all([defaultLoadingTask.destroy(), docBaseUrlLoadingTask.destroy(), invalidDocBaseUrlLoadingTask.destroy()]).then(done);
  1177. }).catch(done.fail);
  1178. });
  1179. it("gets text content", function (done) {
  1180. const defaultPromise = page.getTextContent();
  1181. const parametersPromise = page.getTextContent({
  1182. normalizeWhitespace: true,
  1183. disableCombineTextItems: true
  1184. });
  1185. const promises = [defaultPromise, parametersPromise];
  1186. Promise.all(promises).then(function (data) {
  1187. expect(!!data[0].items).toEqual(true);
  1188. expect(data[0].items.length).toEqual(7);
  1189. expect(!!data[0].styles).toEqual(true);
  1190. expect(JSON.stringify(data[0])).toEqual(JSON.stringify(data[1]));
  1191. done();
  1192. }).catch(done.fail);
  1193. });
  1194. it("gets text content, with correct properties (issue 8276)", function (done) {
  1195. const loadingTask = (0, _api.getDocument)((0, _test_utils.buildGetDocumentParams)("issue8276_reduced.pdf"));
  1196. loadingTask.promise.then(pdfDoc => {
  1197. pdfDoc.getPage(1).then(pdfPage => {
  1198. pdfPage.getTextContent().then(({
  1199. items,
  1200. styles
  1201. }) => {
  1202. expect(items.length).toEqual(1);
  1203. expect(Object.keys(styles)).toEqual(["Times"]);
  1204. expect(items[0]).toEqual({
  1205. dir: "ltr",
  1206. fontName: "Times",
  1207. height: 18,
  1208. str: "Issue 8276",
  1209. transform: [18, 0, 0, 18, 441.81, 708.4499999999999],
  1210. width: 77.49
  1211. });
  1212. expect(styles.Times).toEqual({
  1213. fontFamily: "serif",
  1214. ascent: NaN,
  1215. descent: NaN,
  1216. vertical: false
  1217. });
  1218. loadingTask.destroy().then(done);
  1219. });
  1220. });
  1221. }).catch(done.fail);
  1222. });
  1223. it("gets operator list", function (done) {
  1224. const promise = page.getOperatorList();
  1225. promise.then(function (oplist) {
  1226. expect(!!oplist.fnArray).toEqual(true);
  1227. expect(!!oplist.argsArray).toEqual(true);
  1228. expect(oplist.lastChunk).toEqual(true);
  1229. done();
  1230. }).catch(done.fail);
  1231. });
  1232. it("gets operatorList with JPEG image (issue 4888)", function (done) {
  1233. const loadingTask = (0, _api.getDocument)((0, _test_utils.buildGetDocumentParams)("cmykjpeg.pdf"));
  1234. loadingTask.promise.then(pdfDoc => {
  1235. pdfDoc.getPage(1).then(pdfPage => {
  1236. pdfPage.getOperatorList().then(opList => {
  1237. const imgIndex = opList.fnArray.indexOf(_util.OPS.paintImageXObject);
  1238. const imgArgs = opList.argsArray[imgIndex];
  1239. const {
  1240. data
  1241. } = pdfPage.objs.get(imgArgs[0]);
  1242. expect(data instanceof Uint8ClampedArray).toEqual(true);
  1243. expect(data.length).toEqual(90000);
  1244. loadingTask.destroy().then(done);
  1245. });
  1246. });
  1247. }).catch(done.fail);
  1248. });
  1249. it("gets operatorList, from corrupt PDF file (issue 8702), " + "with/without `stopAtErrors` set", function (done) {
  1250. const loadingTask1 = (0, _api.getDocument)((0, _test_utils.buildGetDocumentParams)("issue8702.pdf", {
  1251. stopAtErrors: false
  1252. }));
  1253. const loadingTask2 = (0, _api.getDocument)((0, _test_utils.buildGetDocumentParams)("issue8702.pdf", {
  1254. stopAtErrors: true
  1255. }));
  1256. const result1 = loadingTask1.promise.then(pdfDoc => {
  1257. return pdfDoc.getPage(1).then(pdfPage => {
  1258. return pdfPage.getOperatorList().then(opList => {
  1259. expect(opList.fnArray.length).toBeGreaterThan(100);
  1260. expect(opList.argsArray.length).toBeGreaterThan(100);
  1261. expect(opList.lastChunk).toEqual(true);
  1262. return loadingTask1.destroy();
  1263. });
  1264. });
  1265. });
  1266. const result2 = loadingTask2.promise.then(pdfDoc => {
  1267. return pdfDoc.getPage(1).then(pdfPage => {
  1268. return pdfPage.getOperatorList().then(opList => {
  1269. expect(opList.fnArray.length).toEqual(0);
  1270. expect(opList.argsArray.length).toEqual(0);
  1271. expect(opList.lastChunk).toEqual(true);
  1272. return loadingTask2.destroy();
  1273. });
  1274. });
  1275. });
  1276. Promise.all([result1, result2]).then(done, done.fail);
  1277. });
  1278. it("gets document stats after parsing page", function (done) {
  1279. const promise = page.getOperatorList().then(function () {
  1280. return pdfDocument.getStats();
  1281. });
  1282. const expectedStreamTypes = {};
  1283. expectedStreamTypes[_util.StreamType.FLATE] = true;
  1284. const expectedFontTypes = {};
  1285. expectedFontTypes[_util.FontType.TYPE1] = true;
  1286. expectedFontTypes[_util.FontType.CIDFONTTYPE2] = true;
  1287. promise.then(function (stats) {
  1288. expect(stats).toEqual({
  1289. streamTypes: expectedStreamTypes,
  1290. fontTypes: expectedFontTypes
  1291. });
  1292. done();
  1293. }).catch(done.fail);
  1294. });
  1295. it("gets page stats after parsing page, without `pdfBug` set", function (done) {
  1296. page.getOperatorList().then(opList => {
  1297. return page.stats;
  1298. }).then(stats => {
  1299. expect(stats).toEqual(null);
  1300. done();
  1301. }, done.fail);
  1302. });
  1303. it("gets page stats after parsing page, with `pdfBug` set", function (done) {
  1304. const loadingTask = (0, _api.getDocument)((0, _test_utils.buildGetDocumentParams)(basicApiFileName, {
  1305. pdfBug: true
  1306. }));
  1307. loadingTask.promise.then(pdfDoc => {
  1308. return pdfDoc.getPage(1).then(pdfPage => {
  1309. return pdfPage.getOperatorList().then(opList => {
  1310. return pdfPage.stats;
  1311. });
  1312. });
  1313. }).then(stats => {
  1314. expect(stats instanceof _display_utils.StatTimer).toEqual(true);
  1315. expect(stats.times.length).toEqual(1);
  1316. const [statEntry] = stats.times;
  1317. expect(statEntry.name).toEqual("Page Request");
  1318. expect(statEntry.end - statEntry.start).toBeGreaterThanOrEqual(0);
  1319. loadingTask.destroy().then(done);
  1320. }, done.fail);
  1321. });
  1322. it("gets page stats after rendering page, with `pdfBug` set", function (done) {
  1323. const loadingTask = (0, _api.getDocument)((0, _test_utils.buildGetDocumentParams)(basicApiFileName, {
  1324. pdfBug: true
  1325. }));
  1326. let canvasAndCtx;
  1327. loadingTask.promise.then(pdfDoc => {
  1328. return pdfDoc.getPage(1).then(pdfPage => {
  1329. const viewport = pdfPage.getViewport({
  1330. scale: 1
  1331. });
  1332. canvasAndCtx = CanvasFactory.create(viewport.width, viewport.height);
  1333. const renderTask = pdfPage.render({
  1334. canvasContext: canvasAndCtx.context,
  1335. canvasFactory: CanvasFactory,
  1336. viewport
  1337. });
  1338. return renderTask.promise.then(() => {
  1339. return pdfPage.stats;
  1340. });
  1341. });
  1342. }).then(stats => {
  1343. expect(stats instanceof _display_utils.StatTimer).toEqual(true);
  1344. expect(stats.times.length).toEqual(3);
  1345. const [statEntryOne, statEntryTwo, statEntryThree] = stats.times;
  1346. expect(statEntryOne.name).toEqual("Page Request");
  1347. expect(statEntryOne.end - statEntryOne.start).toBeGreaterThanOrEqual(0);
  1348. expect(statEntryTwo.name).toEqual("Rendering");
  1349. expect(statEntryTwo.end - statEntryTwo.start).toBeGreaterThan(0);
  1350. expect(statEntryThree.name).toEqual("Overall");
  1351. expect(statEntryThree.end - statEntryThree.start).toBeGreaterThan(0);
  1352. CanvasFactory.destroy(canvasAndCtx);
  1353. loadingTask.destroy().then(done);
  1354. }, done.fail);
  1355. });
  1356. it("cancels rendering of page", function (done) {
  1357. const viewport = page.getViewport({
  1358. scale: 1
  1359. });
  1360. const canvasAndCtx = CanvasFactory.create(viewport.width, viewport.height);
  1361. const renderTask = page.render({
  1362. canvasContext: canvasAndCtx.context,
  1363. canvasFactory: CanvasFactory,
  1364. viewport
  1365. });
  1366. renderTask.cancel();
  1367. renderTask.promise.then(function () {
  1368. done.fail("shall cancel rendering");
  1369. }).catch(function (error) {
  1370. expect(error instanceof _display_utils.RenderingCancelledException).toEqual(true);
  1371. expect(error.message).toEqual("Rendering cancelled, page 1");
  1372. expect(error.type).toEqual("canvas");
  1373. CanvasFactory.destroy(canvasAndCtx);
  1374. done();
  1375. });
  1376. });
  1377. it("re-render page, using the same canvas, after cancelling rendering", function (done) {
  1378. const viewport = page.getViewport({
  1379. scale: 1
  1380. });
  1381. const canvasAndCtx = CanvasFactory.create(viewport.width, viewport.height);
  1382. const renderTask = page.render({
  1383. canvasContext: canvasAndCtx.context,
  1384. canvasFactory: CanvasFactory,
  1385. viewport
  1386. });
  1387. renderTask.cancel();
  1388. renderTask.promise.then(() => {
  1389. throw new Error("shall cancel rendering");
  1390. }, reason => {
  1391. expect(reason instanceof _display_utils.RenderingCancelledException).toEqual(true);
  1392. }).then(() => {
  1393. const reRenderTask = page.render({
  1394. canvasContext: canvasAndCtx.context,
  1395. canvasFactory: CanvasFactory,
  1396. viewport
  1397. });
  1398. return reRenderTask.promise;
  1399. }).then(() => {
  1400. CanvasFactory.destroy(canvasAndCtx);
  1401. done();
  1402. }, done.fail);
  1403. });
  1404. it("multiple render() on the same canvas", function (done) {
  1405. const optionalContentConfigPromise = pdfDocument.getOptionalContentConfig();
  1406. const viewport = page.getViewport({
  1407. scale: 1
  1408. });
  1409. const canvasAndCtx = CanvasFactory.create(viewport.width, viewport.height);
  1410. const renderTask1 = page.render({
  1411. canvasContext: canvasAndCtx.context,
  1412. canvasFactory: CanvasFactory,
  1413. viewport,
  1414. optionalContentConfigPromise
  1415. });
  1416. const renderTask2 = page.render({
  1417. canvasContext: canvasAndCtx.context,
  1418. canvasFactory: CanvasFactory,
  1419. viewport,
  1420. optionalContentConfigPromise
  1421. });
  1422. Promise.all([renderTask1.promise, renderTask2.promise.then(() => {
  1423. done.fail("shall fail rendering");
  1424. }, reason => {
  1425. expect(/multiple render\(\)/.test(reason.message)).toEqual(true);
  1426. })]).then(done);
  1427. });
  1428. it("cleans up document resources after rendering of page", async function () {
  1429. const loadingTask = (0, _api.getDocument)((0, _test_utils.buildGetDocumentParams)(basicApiFileName));
  1430. const pdfDoc = await loadingTask.promise;
  1431. const pdfPage = await pdfDoc.getPage(1);
  1432. const viewport = pdfPage.getViewport({
  1433. scale: 1
  1434. });
  1435. const canvasAndCtx = CanvasFactory.create(viewport.width, viewport.height);
  1436. const renderTask = pdfPage.render({
  1437. canvasContext: canvasAndCtx.context,
  1438. canvasFactory: CanvasFactory,
  1439. viewport
  1440. });
  1441. await renderTask.promise;
  1442. await pdfDoc.cleanup();
  1443. expect(true).toEqual(true);
  1444. CanvasFactory.destroy(canvasAndCtx);
  1445. await loadingTask.destroy();
  1446. });
  1447. it("cleans up document resources during rendering of page", async function () {
  1448. const loadingTask = (0, _api.getDocument)((0, _test_utils.buildGetDocumentParams)("tracemonkey.pdf"));
  1449. const pdfDoc = await loadingTask.promise;
  1450. const pdfPage = await pdfDoc.getPage(1);
  1451. const viewport = pdfPage.getViewport({
  1452. scale: 1
  1453. });
  1454. const canvasAndCtx = CanvasFactory.create(viewport.width, viewport.height);
  1455. const renderTask = pdfPage.render({
  1456. canvasContext: canvasAndCtx.context,
  1457. canvasFactory: CanvasFactory,
  1458. viewport
  1459. });
  1460. renderTask.onContinue = function (cont) {
  1461. waitSome(cont);
  1462. };
  1463. try {
  1464. await pdfDoc.cleanup();
  1465. throw new Error("shall fail cleanup");
  1466. } catch (reason) {
  1467. expect(reason instanceof Error).toEqual(true);
  1468. expect(reason.message).toEqual("startCleanup: Page 1 is currently rendering.");
  1469. }
  1470. await renderTask.promise;
  1471. CanvasFactory.destroy(canvasAndCtx);
  1472. await loadingTask.destroy();
  1473. });
  1474. it("caches image resources at the document/page level as expected (issue 11878)", async function () {
  1475. const {
  1476. NUM_PAGES_THRESHOLD
  1477. } = _image_utils.GlobalImageCache,
  1478. EXPECTED_WIDTH = 2550,
  1479. EXPECTED_HEIGHT = 3300;
  1480. const loadingTask = (0, _api.getDocument)((0, _test_utils.buildGetDocumentParams)("issue11878.pdf"));
  1481. const pdfDoc = await loadingTask.promise;
  1482. let firstImgData = null;
  1483. for (let i = 1; i <= pdfDoc.numPages; i++) {
  1484. const pdfPage = await pdfDoc.getPage(i);
  1485. const opList = await pdfPage.getOperatorList();
  1486. const {
  1487. commonObjs,
  1488. objs
  1489. } = pdfPage;
  1490. const imgIndex = opList.fnArray.indexOf(_util.OPS.paintImageXObject);
  1491. const [objId, width, height] = opList.argsArray[imgIndex];
  1492. if (i < NUM_PAGES_THRESHOLD) {
  1493. expect(objId).toEqual(`img_p${i - 1}_1`);
  1494. expect(objs.has(objId)).toEqual(true);
  1495. expect(commonObjs.has(objId)).toEqual(false);
  1496. } else {
  1497. expect(objId).toEqual(`g_${loadingTask.docId}_img_p${NUM_PAGES_THRESHOLD - 1}_1`);
  1498. expect(objs.has(objId)).toEqual(false);
  1499. expect(commonObjs.has(objId)).toEqual(true);
  1500. }
  1501. expect(width).toEqual(EXPECTED_WIDTH);
  1502. expect(height).toEqual(EXPECTED_HEIGHT);
  1503. if (i === 1) {
  1504. firstImgData = objs.get(objId);
  1505. expect(firstImgData.width).toEqual(EXPECTED_WIDTH);
  1506. expect(firstImgData.height).toEqual(EXPECTED_HEIGHT);
  1507. expect(firstImgData.kind).toEqual(_util.ImageKind.RGB_24BPP);
  1508. expect(firstImgData.data instanceof Uint8ClampedArray).toEqual(true);
  1509. expect(firstImgData.data.length).toEqual(25245000);
  1510. } else {
  1511. const objsPool = i >= NUM_PAGES_THRESHOLD ? commonObjs : objs;
  1512. const currentImgData = objsPool.get(objId);
  1513. expect(currentImgData.width).toEqual(firstImgData.width);
  1514. expect(currentImgData.height).toEqual(firstImgData.height);
  1515. expect(currentImgData.kind).toEqual(firstImgData.kind);
  1516. expect(currentImgData.data instanceof Uint8ClampedArray).toEqual(true);
  1517. expect(currentImgData.data.every((value, index) => {
  1518. return value === firstImgData.data[index];
  1519. })).toEqual(true);
  1520. }
  1521. }
  1522. await loadingTask.destroy();
  1523. firstImgData = null;
  1524. });
  1525. });
  1526. describe("Multiple `getDocument` instances", function () {
  1527. const pdf1 = (0, _test_utils.buildGetDocumentParams)("tracemonkey.pdf");
  1528. const pdf2 = (0, _test_utils.buildGetDocumentParams)("TAMReview.pdf");
  1529. const pdf3 = (0, _test_utils.buildGetDocumentParams)("issue6068.pdf");
  1530. const loadingTasks = [];
  1531. async function renderPDF(filename) {
  1532. const loadingTask = (0, _api.getDocument)(filename);
  1533. loadingTasks.push(loadingTask);
  1534. const pdf = await loadingTask.promise;
  1535. const page = await pdf.getPage(1);
  1536. const viewport = page.getViewport({
  1537. scale: 1.2
  1538. });
  1539. const canvasAndCtx = CanvasFactory.create(viewport.width, viewport.height);
  1540. const renderTask = page.render({
  1541. canvasContext: canvasAndCtx.context,
  1542. canvasFactory: CanvasFactory,
  1543. viewport
  1544. });
  1545. await renderTask.promise;
  1546. const data = canvasAndCtx.canvas.toDataURL();
  1547. CanvasFactory.destroy(canvasAndCtx);
  1548. return data;
  1549. }
  1550. afterEach(function (done) {
  1551. const destroyPromises = loadingTasks.map(function (loadingTask) {
  1552. return loadingTask.destroy();
  1553. });
  1554. Promise.all(destroyPromises).then(done);
  1555. });
  1556. it("should correctly render PDFs in parallel", function (done) {
  1557. let baseline1, baseline2, baseline3;
  1558. const promiseDone = renderPDF(pdf1).then(function (data1) {
  1559. baseline1 = data1;
  1560. return renderPDF(pdf2);
  1561. }).then(function (data2) {
  1562. baseline2 = data2;
  1563. return renderPDF(pdf3);
  1564. }).then(function (data3) {
  1565. baseline3 = data3;
  1566. return Promise.all([renderPDF(pdf1), renderPDF(pdf2), renderPDF(pdf3)]);
  1567. }).then(function (dataUrls) {
  1568. expect(dataUrls[0]).toEqual(baseline1);
  1569. expect(dataUrls[1]).toEqual(baseline2);
  1570. expect(dataUrls[2]).toEqual(baseline3);
  1571. return true;
  1572. });
  1573. promiseDone.then(function () {
  1574. done();
  1575. }).catch(done.fail);
  1576. });
  1577. });
  1578. describe("PDFDataRangeTransport", function () {
  1579. let dataPromise;
  1580. beforeAll(function (done) {
  1581. const fileName = "tracemonkey.pdf";
  1582. dataPromise = _test_utils.DefaultFileReaderFactory.fetch({
  1583. path: _test_utils.TEST_PDFS_PATH + fileName
  1584. });
  1585. done();
  1586. });
  1587. afterAll(function () {
  1588. dataPromise = null;
  1589. });
  1590. it("should fetch document info and page using ranges", function (done) {
  1591. const initialDataLength = 4000;
  1592. let fetches = 0,
  1593. loadingTask;
  1594. dataPromise.then(function (data) {
  1595. const initialData = data.subarray(0, initialDataLength);
  1596. const transport = new _api.PDFDataRangeTransport(data.length, initialData);
  1597. transport.requestDataRange = function (begin, end) {
  1598. fetches++;
  1599. waitSome(function () {
  1600. transport.onDataProgress(4000);
  1601. transport.onDataRange(begin, data.subarray(begin, end));
  1602. });
  1603. };
  1604. loadingTask = (0, _api.getDocument)(transport);
  1605. return loadingTask.promise;
  1606. }).then(function (pdfDocument) {
  1607. expect(pdfDocument.numPages).toEqual(14);
  1608. return pdfDocument.getPage(10);
  1609. }).then(function (pdfPage) {
  1610. expect(pdfPage.rotate).toEqual(0);
  1611. expect(fetches).toBeGreaterThan(2);
  1612. loadingTask.destroy().then(done);
  1613. }).catch(done.fail);
  1614. });
  1615. it("should fetch document info and page using range and streaming", function (done) {
  1616. const initialDataLength = 4000;
  1617. let fetches = 0,
  1618. loadingTask;
  1619. dataPromise.then(function (data) {
  1620. const initialData = data.subarray(0, initialDataLength);
  1621. const transport = new _api.PDFDataRangeTransport(data.length, initialData);
  1622. transport.requestDataRange = function (begin, end) {
  1623. fetches++;
  1624. if (fetches === 1) {
  1625. transport.onDataProgressiveRead(data.subarray(initialDataLength));
  1626. }
  1627. waitSome(function () {
  1628. transport.onDataRange(begin, data.subarray(begin, end));
  1629. });
  1630. };
  1631. loadingTask = (0, _api.getDocument)(transport);
  1632. return loadingTask.promise;
  1633. }).then(function (pdfDocument) {
  1634. expect(pdfDocument.numPages).toEqual(14);
  1635. return pdfDocument.getPage(10);
  1636. }).then(function (pdfPage) {
  1637. expect(pdfPage.rotate).toEqual(0);
  1638. expect(fetches).toEqual(1);
  1639. waitSome(function () {
  1640. loadingTask.destroy().then(done);
  1641. });
  1642. }).catch(done.fail);
  1643. });
  1644. it("should fetch document info and page, without range, " + "using complete initialData", function (done) {
  1645. let fetches = 0,
  1646. loadingTask;
  1647. dataPromise.then(function (data) {
  1648. const transport = new _api.PDFDataRangeTransport(data.length, data, true);
  1649. transport.requestDataRange = function (begin, end) {
  1650. fetches++;
  1651. };
  1652. loadingTask = (0, _api.getDocument)({
  1653. disableRange: true,
  1654. range: transport
  1655. });
  1656. return loadingTask.promise;
  1657. }).then(function (pdfDocument) {
  1658. expect(pdfDocument.numPages).toEqual(14);
  1659. return pdfDocument.getPage(10);
  1660. }).then(function (pdfPage) {
  1661. expect(pdfPage.rotate).toEqual(0);
  1662. expect(fetches).toEqual(0);
  1663. loadingTask.destroy().then(done);
  1664. }).catch(done.fail);
  1665. });
  1666. });
  1667. });