api_spec.js 66 KB

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