Bug 1411345 - HTMLEditRules::GetHighestInlineParent() shouldn't return editing host even when it's the highest inline parent of aNode r=m_kato

HTMLEditRules::BustUpInlinesAtRangeEndpoints() tries to split all inline nodes
at range start and range end.  It uses EditorBase::SplitNodeDeep() to split
the nodes and HTMLEditRules::GetHighestInlineParent() to retrieve the highest
inline parent of them.

Currently, HTMLEditRules::GetHighestInlineParent() may return editing host or
ancestor of it if active editing host is not block.  Then, it may cause
splitting editing host or its parents and following methods of HTMLEditRules
will fail to modify the nodes created outside the editing host.

So, HTMLEditRules::GetHighestInlineParent() should return only one of the
descendants of active editing host.

Unfortunately, even if just adding the test case as a crash test, I cannot
reproduce the crash with automated tests.  Therefore, this patch doesn't
include any automated tests.

And this patch changes a crash test, 1402196.html, which expects that an inline
editing host is split by execCommand("insertOrderedList").  However, this patch
fixes this wrong behavior.  Therefore, this patch changes the event target of
event listener from <p> inside the editing host to the editing host itself.

MozReview-Commit-ID: 8i5ci1fcrDd

--HG--
extra : rebase_source : 572a7b22550a38ca71c954f62eefa695addd53c2
This commit is contained in:
Masayuki Nakano 2017-10-31 01:14:58 +09:00
Родитель 7dcccb8252
Коммит b327dea259
3 изменённых файлов: 35 добавлений и 5 удалений

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

@ -6361,12 +6361,37 @@ HTMLEditRules::GetHighestInlineParent(nsINode& aNode)
if (!aNode.IsContent() || IsBlockNode(aNode)) {
return nullptr;
}
OwningNonNull<nsIContent> node = *aNode.AsContent();
while (node->GetParent() && IsInlineNode(*node->GetParent())) {
node = *node->GetParent();
if (NS_WARN_IF(!mHTMLEditor)) {
return nullptr;
}
return node;
Element* host = mHTMLEditor->GetActiveEditingHost();
if (NS_WARN_IF(!host)) {
return nullptr;
}
// If aNode is the editing host itself, there is no modifiable inline parent.
if (&aNode == host) {
return nullptr;
}
// If aNode is outside of the <body> element, we don't support to edit
// such elements for now.
// XXX This should be MOZ_ASSERT after fixing bug 1413131 for avoiding
// calling this expensive method.
if (NS_WARN_IF(!EditorUtils::IsDescendantOf(&aNode, host))) {
return nullptr;
}
// Looks for the highest inline parent in the editing host.
nsIContent* content = aNode.AsContent();
for (nsIContent* parent = content->GetParent();
parent && parent != host && IsInlineNode(*parent);
parent = parent->GetParent()) {
content = parent;
}
return content;
}
/**

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

@ -378,6 +378,11 @@ protected:
nsresult BustUpInlinesAtBRs(
nsIContent& aNode,
nsTArray<OwningNonNull<nsINode>>& aOutArrayOfNodes);
/**
* GetHiestInlineParent() returns the highest inline node parent between
* aNode and the editing host. Even if the editing host is an inline
* element, this method never returns the editing host as the result.
*/
nsIContent* GetHighestInlineParent(nsINode& aNode);
void MakeTransitionList(nsTArray<OwningNonNull<nsINode>>& aNodeArray,
nsTArray<bool>& aTransitionArray);

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

@ -3,7 +3,7 @@
<head>
<script>
function load() {
document.getElementById("p").addEventListener("DOMNodeInserted", () => {
document.getElementById("spacer").addEventListener("DOMNodeInserted", () => {
document.getElementById("style").appendChild(
document.getElementById("table"));
document.documentElement.classList.remove("reftest-wait");