Bug 1810406 - Make `IMEContentObserver` initialize its root element with the anonymous `<div>` if the editor is a `TextEditor` r=smaug

Although I cannot reproduce the bug in mochitest with
`nsIDOMWindowUtils.sendQueryContentEvent`, one of the problem in the web site
is, the frame of `<textarea>` is reframed at typing something.  Then, retrieving
computed style causes a flush **before** new `TextEditor` is recreated and
re-initialize `IMEContentObserver` with new anonymous contents.  At this time,
`IMEContentObserver` gets shadow root or document element from start container
of the first selection range which is in the text node in the anonymous `<div>`
instead of the anonymous `<div>` here:
https://searchfox.org/mozilla-central/rev/01d7150d99c3c175300560d33dcdeea3f6b7eb29/dom/events/IMEContentObserver.cpp#272,277-279

The reason is, `nsFrameSelection` has not been set to the independent selection
for the text control because `EditorBase::InitializeSelection` has not been
called via a call of `PostCreate` and of course, the selection ancestor limiter
has not been reset yet.
https://searchfox.org/mozilla-central/rev/01d7150d99c3c175300560d33dcdeea3f6b7eb29/editor/libeditor/EditorBase.cpp#5204,5212

Therefore, `nsINode::GetSelectionRootContent` crosses the native anonymous
subtree boundary and return a parent node of the text control because here
does not work as expected.
https://searchfox.org/mozilla-central/rev/01d7150d99c3c175300560d33dcdeea3f6b7eb29/dom/base/nsINode.cpp#583-593

`IMEContentObserver` should use `EditorBase::GetRoot()` instead of referring
`Selection` because it's stabler in any situation at that time.

Differential Revision: https://phabricator.services.mozilla.com/D170032
This commit is contained in:
Masayuki Nakano 2023-02-21 22:51:42 +00:00
Родитель 7e1172fe66
Коммит 0df404cf45
2 изменённых файлов: 13 добавлений и 7 удалений

Просмотреть файл

@ -436,8 +436,6 @@ Element* nsINode::GetAnonymousRootElementOfTextEditor(
return nullptr;
}
MOZ_ASSERT(!textEditor->IsHTMLEditor(),
"If it were an HTML editor, needs to use GetRootElement()");
Element* rootElement = textEditor->GetRoot();
if (aTextEditor) {
textEditor.forget(aTextEditor);
@ -558,10 +556,16 @@ nsIContent* nsINode::GetSelectionRootContent(PresShell* aPresShell) {
return nullptr;
}
if (AsContent()->HasIndependentSelection()) {
// This node should be a descendant of input/textarea editor.
Element* anonymousDivElement = GetAnonymousRootElementOfTextEditor();
if (anonymousDivElement) {
if (AsContent()->HasIndependentSelection() || IsInNativeAnonymousSubtree()) {
// This node should be an inclusive descendant of input/textarea editor.
// In that case, the anonymous <div> for TextEditor should be always the
// selection root.
// FIXME: If Selection for the document is collapsed in <input> or
// <textarea>, returning anonymous <div> may make the callers confused.
// Perhaps, we should do this only when this is in the native anonymous
// subtree unless the callers explicitly want to retrieve the anonymous
// <div> from a text control element.
if (Element* anonymousDivElement = GetAnonymousRootElementOfTextEditor()) {
return anonymousDivElement;
}
}

Просмотреть файл

@ -269,7 +269,9 @@ bool IMEContentObserver::InitWithEditor(nsPresContext& aPresContext,
return false;
}
if (const nsRange* selRange = mSelection->GetRangeAt(0)) {
if (mEditorBase->IsTextEditor()) {
mRootElement = mEditorBase->GetRoot(); // The anonymous <div>
} else if (const nsRange* selRange = mSelection->GetRangeAt(0)) {
if (NS_WARN_IF(!selRange->GetStartContainer())) {
return false;
}