зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1384606 - part 1: Make `nsIFrame::GetFrameFromDirection` treat frames in different native anonymous subtree not selectable r=emilio
It's called by `PeekOffsetFor*` and `GetPrevNextBidiLevels`, so it's used for considering whether to put caret or move a selection range boundary. Therefore, it should treat nodes which can be managed by `Selection` as selectable. In theory, even if a native anonymous subtree does not have an independent selection, its content nodes should not be the container of the selection range boundaries of selection outside the subtree since Selection API shouldn't expose nodes in native anonymous subtrees. Therefore, it can simply treat content nodes in different anonymous subtrees are not selectable. Note that it's not standardized that how `Selection.modify` works with various content nodes. https://w3c.github.io/selection-api/#dom-selection-modify And also Chrome cannot cross generated content like form controls with this API. This could cause web-compat issues, but it does not make sense for caret navigation, and anyway out of scope of this bug. Therefore, this patch just adds the crash test. Differential Revision: https://phabricator.services.mozilla.com/D172204
This commit is contained in:
Родитель
f150350f35
Коммит
c5e00ff09c
|
@ -9536,6 +9536,8 @@ nsIFrame::SelectablePeekReport nsIFrame::GetFrameFromDirection(
|
|||
bool selectable = false;
|
||||
nsIFrame* traversedFrame = this;
|
||||
AutoAssertNoDomMutations guard;
|
||||
const nsIContent* const nativeAnonymousSubtreeContent =
|
||||
GetClosestNativeAnonymousSubtreeRoot();
|
||||
while (!selectable) {
|
||||
auto [blockFrame, lineFrame] =
|
||||
traversedFrame->GetContainingBlockForLine(aScrollViewStop);
|
||||
|
@ -9573,10 +9575,17 @@ nsIFrame::SelectablePeekReport nsIFrame::GetFrameFromDirection(
|
|||
return result;
|
||||
}
|
||||
|
||||
auto IsSelectable = [aForceEditableRegion](const nsIFrame* aFrame) {
|
||||
auto IsSelectable = [aForceEditableRegion, nativeAnonymousSubtreeContent](
|
||||
const nsIFrame* aFrame) {
|
||||
if (!aFrame->IsSelectable(nullptr)) {
|
||||
return false;
|
||||
}
|
||||
// If the new frame is in a native anonymous subtree, we should treat it
|
||||
// as not selectable unless the frame and found frame are in same subtree.
|
||||
if (aFrame->GetClosestNativeAnonymousSubtreeRoot() !=
|
||||
nativeAnonymousSubtreeContent) {
|
||||
return false;
|
||||
}
|
||||
return !aForceEditableRegion || aFrame->GetContent()->IsEditable();
|
||||
};
|
||||
|
||||
|
|
|
@ -747,6 +747,18 @@ class nsIFrame : public nsQueryFrame {
|
|||
*/
|
||||
nsIContent* GetContent() const { return mContent; }
|
||||
|
||||
/**
|
||||
* @brief Get the closest native anonymous subtree root if the content is in a
|
||||
* native anonymous subtree.
|
||||
*
|
||||
* @return The root of native anonymous subtree which the content belongs to.
|
||||
* Otherwise, nullptr.
|
||||
*/
|
||||
nsIContent* GetClosestNativeAnonymousSubtreeRoot() const {
|
||||
return mContent ? mContent->GetClosestNativeAnonymousSubtreeRoot()
|
||||
: nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the frame that should be the parent for the frames of child elements
|
||||
* May return nullptr during reflow
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<style>
|
||||
div {
|
||||
border: medium solid red;
|
||||
border-width: 32em;
|
||||
}
|
||||
</style>
|
||||
<script>
|
||||
document.addEventListener("DOMContentLoaded", () => {
|
||||
document.execCommand("selectAll");
|
||||
getSelection().modify("move", "backward", "character");
|
||||
getSelection().collapseToStart();
|
||||
}, {once: true});
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<button contenteditable></button>
|
||||
<input value="a">
|
||||
<div></div>
|
||||
</body>
|
||||
</html>
|
Загрузка…
Ссылка в новой задаче