From b01eeaf8e138e3541bda2f424b95170a6f88395c Mon Sep 17 00:00:00 2001 From: Jonas Jenwald Date: Tue, 21 Apr 2026 11:36:56 +0200 Subject: [PATCH] Improve the "CopyLocalImage" unit-tests Rather than relying on the time it takes to parse/render the pages, which leads to intermittent failures, add a test-only property and use it to check if the "CopyLocalImage" code-path was exercised. --- src/display/api.js | 6 +++++- test/unit/api_spec.js | 24 +++++++++--------------- 2 files changed, 14 insertions(+), 16 deletions(-) diff --git a/src/display/api.js b/src/display/api.js index 6de590441..3cf541917 100644 --- a/src/display/api.js +++ b/src/display/api.js @@ -2794,7 +2794,11 @@ class WorkerTransport { if (!data.dataLen) { return null; } - this.commonObjs.resolve(id, structuredClone(data)); + const copy = structuredClone(data); + if (typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) { + copy.CopyLocalImage = true; + } + this.commonObjs.resolve(id, copy); return data.dataLen; } } diff --git a/test/unit/api_spec.js b/test/unit/api_spec.js index d9c29732b..1be2c3037 100644 --- a/test/unit/api_spec.js +++ b/test/unit/api_spec.js @@ -4883,8 +4883,7 @@ have written that much by now. So, here’s to squashing bugs.`); const pdfDoc = await loadingTask.promise; const { canvasFactory } = pdfDoc; let checkedCopyLocalImage = false, - firstImgData = null, - firstStatsOverall = null; + firstImgData = null; for (let i = 1; i <= pdfDoc.numPages; i++) { const pdfPage = await pdfDoc.getPage(i); @@ -4905,10 +4904,6 @@ have written that much by now. So, here’s to squashing bugs.`); // the image-data below. canvasFactory.destroy(canvasAndCtx); - const [statsOverall] = pdfPage.stats.times - .filter(time => time.name === "Overall") - .map(time => time.end - time.start); - const { commonObjs, objs } = pdfPage; const imgIndex = opList.fnArray.indexOf(OPS.paintImageXObject); const [objId, width, height] = opList.argsArray[imgIndex]; @@ -4932,7 +4927,6 @@ have written that much by now. So, here’s to squashing bugs.`); // Ensure that the actual image data is identical for all pages. if (i === 1) { firstImgData = objs.get(objId); - firstStatsOverall = statsOverall; expect(firstImgData.width).toEqual(EXPECTED_WIDTH); expect(firstImgData.height).toEqual(EXPECTED_HEIGHT); @@ -4958,10 +4952,9 @@ have written that much by now. So, here’s to squashing bugs.`); ).toEqual(true); if (i === NUM_PAGES_THRESHOLD) { - checkedCopyLocalImage = true; - // Ensure that the image was copied in the main-thread, rather - // than being re-parsed in the worker-thread (which is slower). - expect(statsOverall).toBeLessThan(firstStatsOverall / 2); + // Ensure that the image was copied in the main-thread (into + // commonObjs), rather than being re-parsed in the worker-thread. + checkedCopyLocalImage = currentImgData.CopyLocalImage; } } } @@ -4969,7 +4962,6 @@ have written that much by now. So, here’s to squashing bugs.`); await loadingTask.destroy(); firstImgData = null; - firstStatsOverall = null; }); it("caches image resources at the document/page level, with main-thread copying of complex images (issue 11518)", async function () { @@ -5011,11 +5003,13 @@ have written that much by now. So, here’s to squashing bugs.`); expect(objs.has(objId)).toEqual(true); expect(commonObjs.has(objId)).toEqual(false); } else if (i === NUM_PAGES_THRESHOLD) { - checkedCopyLocalImage = true; - // Ensure that the image was copied in the main-thread (into - // commonObjs), rather than being re-parsed in the worker-thread. expect(objs.has(objId)).toEqual(false); expect(commonObjs.has(objId)).toEqual(true); + + // Ensure that the image was copied in the main-thread (into + // commonObjs), rather than being re-parsed in the worker-thread. + const imgData = commonObjs.get(objId); + checkedCopyLocalImage = imgData.CopyLocalImage; } else { break; }