[FIX] web_editor: prevent traceback on arrow keypress at editor edge
Steps to reproduce:
1. Type a backtick
2. Type "A"
3. Type a backtick
4. Hit Left Arrow key
5. Hit Right Arrow key 2x
This led to a traceback ("Cannot read properties of null (reading
'isContentEditable') at OdooEditor._onKeyDown") because using `nextLeaf`
without specifying the editable bounds returned a node that was not
within these bounds, and a subsequent call to `closestElement` on this
node returned `null` as a result.
task-3749506
closes odoo/odoo#154484
X-original-commit: ec1fe7b05e0d91605f78dd1844c7d2222671eab3
Signed-off-by: Geelen Sébastien (sge) <sge@odoo.com>
Signed-off-by: Antoine Guenet (age) <age@odoo.com>
This commit is contained in:
@@ -4070,20 +4070,22 @@ export class OdooEditor extends EventTarget {
|
||||
// Find previous character.
|
||||
let previousCharacter = focusOffset > 0 && focusNode.textContent[focusOffset - 1];
|
||||
if (!previousCharacter) {
|
||||
focusNode = previousLeaf(focusNode);
|
||||
focusOffset = nodeSize(focusNode);
|
||||
previousCharacter = focusNode.textContent[focusOffset - 1];
|
||||
focusNode = previousLeaf(focusNode, this.editable);
|
||||
focusOffset = focusNode && nodeSize(focusNode);
|
||||
previousCharacter = focusNode && focusNode.textContent[focusOffset - 1];
|
||||
}
|
||||
// Move selection if previous character is zero-width space
|
||||
if (previousCharacter === '\u200B' && !focusNode.parentElement.hasAttribute('data-o-link-zws')) {
|
||||
if (focusNode && previousCharacter === '\u200B' && !focusNode.parentElement.hasAttribute('data-o-link-zws')) {
|
||||
focusOffset -= 1;
|
||||
while (focusNode && (focusOffset < 0 || !focusNode.textContent[focusOffset])) {
|
||||
focusNode = nextLeaf(focusNode);
|
||||
focusNode = nextLeaf(focusNode, this.editable);
|
||||
focusOffset = focusNode && nodeSize(focusNode);
|
||||
}
|
||||
const startContainer = ev.shiftKey ? anchorNode : focusNode;
|
||||
const startOffset = ev.shiftKey ? anchorOffset : focusOffset;
|
||||
setSelection(startContainer, startOffset, focusNode, focusOffset);
|
||||
if (focusNode) {
|
||||
const startContainer = ev.shiftKey ? anchorNode : focusNode;
|
||||
const startOffset = ev.shiftKey ? anchorOffset : focusOffset;
|
||||
setSelection(startContainer, startOffset, focusNode, focusOffset);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (IS_KEYBOARD_EVENT_RIGHT_ARROW(ev)) {
|
||||
@@ -4111,25 +4113,27 @@ export class OdooEditor extends EventTarget {
|
||||
// Find next character.
|
||||
let nextCharacter = focusNode.textContent[focusOffset];
|
||||
if (!nextCharacter) {
|
||||
focusNode = nextLeaf(focusNode);
|
||||
focusNode = nextLeaf(focusNode, this.editable);
|
||||
focusOffset = 0;
|
||||
nextCharacter = focusNode.textContent[focusOffset];
|
||||
nextCharacter = focusNode && focusNode.textContent[focusOffset];
|
||||
}
|
||||
// Move selection if next character is zero-width space
|
||||
if (nextCharacter === '\u200B' && !focusNode.parentElement.hasAttribute('data-o-link-zws')) {
|
||||
focusOffset += 1;
|
||||
let newFocusNode = focusNode;
|
||||
while (newFocusNode && (!newFocusNode.textContent[focusOffset] || !closestElement(newFocusNode).isContentEditable)) {
|
||||
newFocusNode = nextLeaf(newFocusNode);
|
||||
newFocusNode = nextLeaf(newFocusNode, this.editable);
|
||||
focusOffset = 0;
|
||||
}
|
||||
if (!focusOffset && closestBlock(focusNode) !== closestBlock(newFocusNode)) {
|
||||
if (newFocusNode && !focusOffset && closestBlock(focusNode) !== closestBlock(newFocusNode)) {
|
||||
newFocusNode = focusNode; // Do not move selection to next block.
|
||||
focusOffset = nodeSize(focusNode);
|
||||
focusOffset = focusNode && nodeSize(focusNode);
|
||||
}
|
||||
if (newFocusNode) {
|
||||
const startContainer = ev.shiftKey ? anchorNode : newFocusNode;
|
||||
const startOffset = ev.shiftKey ? anchorOffset : focusOffset;
|
||||
setSelection(startContainer, startOffset, newFocusNode, focusOffset);
|
||||
}
|
||||
const startContainer = ev.shiftKey ? anchorNode : newFocusNode;
|
||||
const startOffset = ev.shiftKey ? anchorOffset : focusOffset;
|
||||
setSelection(startContainer, startOffset, newFocusNode, focusOffset);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user