commit c207c4aa7c74becb16954380ecef8edf9e26c174
parent 6854f37d493b5b073a8d72b685684538eb35051c
Author: Masayuki Nakano <masayuki@d-toybox.com>
Date: Fri, 14 Nov 2025 22:22:14 +0000
Bug 1998523 - Make `HTMLEditUtils` stop treating ruby related boxes as block r=m_kato
Previously, we did treat them as `block` to preserve the ruby structure
when deleting something from inside a `<rb>` or `<rt>` as same as
Chrome. On the other hand, we need to treat them as inline too since
they appear as inline content and should be removable from the
surrounding position. Therefore, both `IsBlockElement` and
`IsInlineContent` returned `true`. Then, this inconsistency causes
`WhiteSpaceVisibilityKeeper` is confused at deleting invisible `<ruby>`,
`<rb>` and `<rt>`. The delete handler tries to join `<rb>` and
following line of it in the `<body>` in the testcase and the `<rb>` is
invisible and white-spaces around it are invisible due to immediately
before/after the `<body>`. Therefore, `WhiteSpaceVisibilityKeeper`
deletes the `<rb>` too even though the delete handler tries to use the
`<rb>` is the destination (left block). Therefore, middle of handling
the white-spaces, the target becomes disconnected and that is asserted.
Fortunately, Chromium already stopped the special handling [1].
Therefore, we can stop the special handling in `HTMLEditUtils`.
Although this may cause odd result at deleting `<rb>` or `<rt>` content,
Chromium is broken in this situation too and `<ruby>` must not be used
in `contenteditable` in the wild. So, we can just stop the special
handling for now.
Differential Revision: https://phabricator.services.mozilla.com/D271739
Diffstat:
2 files changed, 22 insertions(+), 7 deletions(-)
diff --git a/editor/libeditor/HTMLEditUtils.cpp b/editor/libeditor/HTMLEditUtils.cpp
@@ -309,11 +309,6 @@ bool HTMLEditUtils::IsBlockElement(const nsIContent& aContent,
// structure as far as possible.
return IsHTMLBlockElementByDefault(aContent);
}
- // Both Blink and WebKit treat ruby style as a block, see IsEnclosingBlock()
- // in Chromium or isBlock() in WebKit.
- if (styleDisplay->IsRubyDisplayType()) {
- return true;
- }
// If the outside is not inline, treat it as block.
if (!styleDisplay->IsInlineOutsideStyle()) {
return true;
@@ -364,8 +359,7 @@ bool HTMLEditUtils::IsInlineContent(const nsIContent& aContent,
}
// Different block IsBlockElement, when the display-outside is inline, it's
// simply an inline element.
- return styleDisplay->IsInlineOutsideStyle() ||
- styleDisplay->IsRubyDisplayType();
+ return styleDisplay->IsInlineOutsideStyle();
}
bool HTMLEditUtils::IsFlexOrGridItem(const Element& aElement) {
diff --git a/testing/web-platform/tests/editing/crashtests/delete-around-orphan-rb.html b/testing/web-platform/tests/editing/crashtests/delete-around-orphan-rb.html
@@ -0,0 +1,21 @@
+<!doctype html>
+<html>
+<head>
+<meta charset="utf-8">
+<script>
+"use strict";
+
+document.addEventListener("DOMContentLoaded", async () => {
+ document.documentElement.contentEditable = "plaintext-only";
+ getSelection().collapse(document.body.lastChild, 0);
+ document.execCommand("delete");
+}, {once: true});
+
+// FYI: The white-space only text node in <rb> is important.
+</script>
+</head>
+<body>
+ <rb>
+ </rb>
+</body>
+</html>