mirror of
https://github.com/mozilla/pdf.js.git
synced 2026-08-04 05:17:24 +02:00
Merge pull request #21687 from calixteman/fix/quad-regex-delete-word
Scan backwards to delete a word in a text field
This commit is contained in:
commit
d0779c411e
@ -1811,11 +1811,21 @@ class TextWidgetAnnotationElement extends WidgetAnnotationElement {
|
||||
switch (event.inputType) {
|
||||
// https://rawgit.com/w3c/input-events/v1/index.html#interface-InputEvent-Attributes
|
||||
case "deleteWordBackward": {
|
||||
const match = value
|
||||
.substring(0, selectionStart)
|
||||
.match(/\w*\W*$/);
|
||||
if (match) {
|
||||
selStart -= match[0].length;
|
||||
// The previous unanchored regex could take quadratic time, so
|
||||
// scan backwards over the trailing non-word characters and
|
||||
// then the word.
|
||||
const wordCharPattern = /\w/;
|
||||
while (
|
||||
selStart > 0 &&
|
||||
!wordCharPattern.test(value[selStart - 1])
|
||||
) {
|
||||
selStart--;
|
||||
}
|
||||
while (
|
||||
selStart > 0 &&
|
||||
wordCharPattern.test(value[selStart - 1])
|
||||
) {
|
||||
selStart--;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@ -1204,6 +1204,69 @@ describe("Interaction", () => {
|
||||
);
|
||||
});
|
||||
|
||||
it("must efficiently delete a word from a large field", async () => {
|
||||
const nonWordLength = 200000;
|
||||
|
||||
await Promise.all(
|
||||
pages.map(async ([browserName, page]) => {
|
||||
await waitForScripting(page);
|
||||
|
||||
const result = await page.$eval(
|
||||
getSelector("27R"),
|
||||
(element, length) => {
|
||||
element.value = `${"!".repeat(length)}a`;
|
||||
element.setSelectionRange(
|
||||
element.value.length,
|
||||
element.value.length
|
||||
);
|
||||
|
||||
const eventBus = window.PDFViewerApplication.eventBus;
|
||||
const eventBusPrototype = Object.getPrototypeOf(eventBus);
|
||||
const originalDispatch = eventBusPrototype.dispatch;
|
||||
let selection;
|
||||
eventBusPrototype.dispatch = function (eventName, data) {
|
||||
if (
|
||||
this === eventBus &&
|
||||
eventName === "dispatcheventinsandbox"
|
||||
) {
|
||||
const { selEnd, selStart } = data.detail;
|
||||
selection = { selEnd, selStart };
|
||||
return;
|
||||
}
|
||||
originalDispatch.call(this, eventName, data);
|
||||
};
|
||||
|
||||
const event = new InputEvent("beforeinput", {
|
||||
bubbles: true,
|
||||
cancelable: true,
|
||||
inputType: "deleteWordBackward",
|
||||
});
|
||||
try {
|
||||
const startTime = performance.now();
|
||||
element.dispatchEvent(event);
|
||||
return {
|
||||
duration: performance.now() - startTime,
|
||||
selection,
|
||||
};
|
||||
} finally {
|
||||
eventBusPrototype.dispatch = originalDispatch;
|
||||
}
|
||||
},
|
||||
nonWordLength
|
||||
);
|
||||
expect(result.selection)
|
||||
.withContext(`In ${browserName}`)
|
||||
.toEqual({
|
||||
selEnd: nonWordLength + 1,
|
||||
selStart: nonWordLength,
|
||||
});
|
||||
expect(result.duration)
|
||||
.withContext(`In ${browserName}`)
|
||||
.toBeLessThan(1000);
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
it("must check that an infinite loop is not triggered", async () => {
|
||||
await Promise.all(
|
||||
pages.map(async ([browserName, page]) => {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user