mirror of
https://github.com/mozilla/pdf.js.git
synced 2026-08-01 03:47:20 +02:00
Merge pull request #21666 from calixteman/bug2054348
Fix the selection rendering when a page has been destroyed and rendered again (bug 2054348)
This commit is contained in:
commit
a80897dc9a
@ -641,7 +641,8 @@ class DrawLayer {
|
||||
textLayerData.selectionDiv = div;
|
||||
}
|
||||
|
||||
if (!div.parentNode && drawLayer.#parent) {
|
||||
if (drawLayer.#parent && div.parentNode !== drawLayer.#parent) {
|
||||
// The div can still be in a canvas wrapper which has been removed.
|
||||
drawLayer.#parent.append(div);
|
||||
this.#selections.add(div);
|
||||
}
|
||||
|
||||
@ -20,9 +20,11 @@
|
||||
import {
|
||||
closePages,
|
||||
closeSinglePage,
|
||||
firstPageOnTop,
|
||||
getSpanRectFromText,
|
||||
kbSelectAll,
|
||||
loadAndWait,
|
||||
scrollIntoView,
|
||||
waitForEvent,
|
||||
} from "./test_utils.mjs";
|
||||
import { MathClamp } from "../../src/shared/math_clamp.js";
|
||||
@ -1148,6 +1150,94 @@ describe("Text layer", () => {
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe("when the page has been destroyed and rendered again", () => {
|
||||
const selectionSelector = ".canvasWrapper .selection svg path[d]";
|
||||
const timeout = 5000;
|
||||
|
||||
let pages;
|
||||
|
||||
beforeEach(async () => {
|
||||
pages = await loadAndWait(
|
||||
"tracemonkey.pdf",
|
||||
`.page[data-page-number = "1"] .endOfContent`,
|
||||
undefined,
|
||||
undefined,
|
||||
{ annotationEditorMode: -1 }
|
||||
);
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
await closePages(pages);
|
||||
});
|
||||
|
||||
async function selectSomeText(page) {
|
||||
const [positionStart, positionEnd] = await Promise.all([
|
||||
getSpanRectFromText(
|
||||
page,
|
||||
1,
|
||||
"(frequently executed) bytecode sequences, records"
|
||||
).then(middlePosition),
|
||||
getSpanRectFromText(
|
||||
page,
|
||||
1,
|
||||
"them, and compiles them to fast native code. We call such a se-"
|
||||
).then(belowEndPosition),
|
||||
]);
|
||||
|
||||
await page.mouse.move(positionStart.x, positionStart.y);
|
||||
await page.mouse.down();
|
||||
await moveInSteps(page, positionStart, positionEnd, 20);
|
||||
await page.mouse.up();
|
||||
}
|
||||
|
||||
it("must draw the selection", async () => {
|
||||
await Promise.all(
|
||||
pages.map(async ([browserName, page]) => {
|
||||
await selectSomeText(page);
|
||||
await page.waitForSelector(selectionSelector, { timeout });
|
||||
|
||||
await page.evaluate(() => {
|
||||
document.getSelection().removeAllRanges();
|
||||
});
|
||||
await page.waitForSelector(selectionSelector, {
|
||||
hidden: true,
|
||||
timeout,
|
||||
});
|
||||
|
||||
// Scroll down, page by page, until the first page view is
|
||||
// evicted from the buffer: its canvas wrapper is then removed.
|
||||
const pagesCount = await page.evaluate(
|
||||
() => window.PDFViewerApplication.pagesCount
|
||||
);
|
||||
let isDestroyed = false;
|
||||
for (let i = 2; i <= pagesCount && !isDestroyed; i++) {
|
||||
const selector = `.page[data-page-number = "${i}"]`;
|
||||
await scrollIntoView(page, selector);
|
||||
await page.waitForSelector(
|
||||
`${selector} .canvasWrapper canvas`,
|
||||
{ timeout: 0 }
|
||||
);
|
||||
isDestroyed = !(await page.$(
|
||||
`.page[data-page-number = "1"] .canvasWrapper`
|
||||
));
|
||||
}
|
||||
|
||||
expect(isDestroyed)
|
||||
.withContext(`In ${browserName}, first page destroyed`)
|
||||
.toBeTrue();
|
||||
|
||||
await firstPageOnTop(page);
|
||||
await page.waitForSelector(
|
||||
`.page[data-page-number = "1"] .canvasWrapper canvas`,
|
||||
{ timeout: 0 }
|
||||
);
|
||||
await selectSomeText(page);
|
||||
await page.waitForSelector(selectionSelector, { timeout });
|
||||
})
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("using selection carets", () => {
|
||||
|
||||
@ -370,6 +370,7 @@ const PDFViewerApplication = {
|
||||
// Set some specific preferences for tests.
|
||||
if (typeof PDFJSDev !== "undefined" && PDFJSDev.test("TESTING")) {
|
||||
Object.assign(opts, {
|
||||
annotationEditorMode: x => parseInt(x, 10),
|
||||
capCanvasAreaFactor: x => parseInt(x, 10),
|
||||
docBaseUrl: x => x,
|
||||
enableAltText: x => x === "true",
|
||||
|
||||
@ -936,9 +936,14 @@ class PDFPageView extends BasePDFPageView {
|
||||
if (this.structTreeLayer && !this.textLayer) {
|
||||
this.structTreeLayer = null;
|
||||
}
|
||||
// The annotation editor layer and the draw layer keep references on the
|
||||
// text layer (the latter uses its div in order to render the selection),
|
||||
// hence they must be recreated too.
|
||||
if (
|
||||
this.annotationEditorLayer &&
|
||||
(!keepAnnotationEditorLayer || !this.annotationEditorLayer.div)
|
||||
(!keepAnnotationEditorLayer ||
|
||||
!this.annotationEditorLayer.div ||
|
||||
!this.textLayer)
|
||||
) {
|
||||
if (this.drawLayer) {
|
||||
this.drawLayer.cancel();
|
||||
@ -947,6 +952,10 @@ class PDFPageView extends BasePDFPageView {
|
||||
this.annotationEditorLayer.cancel();
|
||||
this.annotationEditorLayer = null;
|
||||
}
|
||||
if (this.drawLayer && !this.textLayer) {
|
||||
this.drawLayer.cancel();
|
||||
this.drawLayer = null;
|
||||
}
|
||||
if (this.xfaLayer && (!keepXfaLayer || !this.xfaLayer.div)) {
|
||||
this.xfaLayer.cancel();
|
||||
this.xfaLayer = null;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user