Bug 1816312, try to avoid creating Range objects in some common cases when spellchecker is disabled for contentEditable, r=masayuki

This is not very optimimal, but tracking spellchecking state in DOM tree is tricky because of multiple contentEditables and possibility to set spellcheck true/false anywhere etc.
At least this helps with the testcase quite a bit.

Differential Revision: https://phabricator.services.mozilla.com/D169870
This commit is contained in:
Olli Pettay 2023-02-16 11:48:13 +00:00
Родитель 54d824cb31
Коммит 21d3624930
5 изменённых файлов: 43 добавлений и 12 удалений

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

@ -6217,22 +6217,23 @@ void Document::DeferredContentEditableCountChange(Element* aElement) {
RefPtr<HTMLEditor> htmlEditor = docshell->GetHTMLEditor();
if (htmlEditor) {
RefPtr<nsRange> range = nsRange::Create(aElement);
IgnoredErrorResult res;
range->SelectNode(*aElement, res);
if (res.Failed()) {
// The node might be detached from the document at this point,
// which would cause this call to fail. In this case, we can
// safely ignore the contenteditable count change.
return;
}
nsCOMPtr<nsIInlineSpellChecker> spellChecker;
rv = htmlEditor->GetInlineSpellChecker(false,
getter_AddRefs(spellChecker));
NS_ENSURE_SUCCESS_VOID(rv);
if (spellChecker) {
if (spellChecker &&
aElement->InclusiveDescendantMayNeedSpellchecking(htmlEditor)) {
RefPtr<nsRange> range = nsRange::Create(aElement);
IgnoredErrorResult res;
range->SelectNode(*aElement, res);
if (res.Failed()) {
// The node might be detached from the document at this point,
// which would cause this call to fail. In this case, we can
// safely ignore the contenteditable count change.
return;
}
rv = spellChecker->SpellCheckRange(range);
NS_ENSURE_SUCCESS_VOID(rv);
}

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

@ -22,6 +22,7 @@
#include "mozilla/EventListenerManager.h"
#include "mozilla/ElementAnimationData.h"
#include "mozilla/HTMLEditor.h"
#include "mozilla/mozInlineSpellChecker.h"
#include "mozilla/PresShell.h"
#include "mozilla/RestyleManager.h"
#include "mozilla/TextEditor.h"
@ -356,6 +357,13 @@ void nsIContent::ConstructUbiNode(void* storage) {
JS::ubi::Concrete<nsIContent>::construct(storage, this);
}
bool nsIContent::InclusiveDescendantMayNeedSpellchecking(HTMLEditor* aEditor) {
// Return true if the node may have elements as children, since those or their
// descendants may have spellcheck attributes.
return HasFlag(NODE_MAY_HAVE_ELEMENT_CHILDREN) ||
mozInlineSpellChecker::ShouldSpellCheckNode(aEditor, this);
}
//----------------------------------------------------------------------
static inline JSObject* GetJSObjectChild(nsWrapperCache* aCache) {

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

@ -565,6 +565,7 @@ LOCAL_INCLUDES += [
"/dom/xml",
"/dom/xslt/xpath",
"/dom/xul",
"/extensions/spellcheck/src",
"/gfx/2d",
"/image",
"/js/xpconnect/loader",

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

@ -17,6 +17,7 @@ class nsIFrame;
namespace mozilla {
class EventChainPreVisitor;
class HTMLEditor;
struct URLExtraData;
namespace dom {
struct BindContext;
@ -624,6 +625,12 @@ class nsIContent : public nsINode {
return rc == 0;
}
/**
* Use this method with designMode and contentEditable to check if the
* node may need spellchecking.
*/
bool InclusiveDescendantMayNeedSpellchecking(mozilla::HTMLEditor* aEditor);
protected:
/**
* Lazily allocated extended slots to avoid

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

@ -4423,12 +4423,26 @@ void HTMLEditor::DoContentInserted(nsIContent* aChild,
// Update spellcheck for only the newly-inserted node (bug 743819)
if (mInlineSpellChecker) {
RefPtr<nsRange> range = nsRange::Create(aChild);
nsIContent* endContent = aChild;
if (aInsertedOrAppended == eAppended) {
nsIContent* child = nullptr;
for (child = aChild; child; child = child->GetNextSibling()) {
if (child->InclusiveDescendantMayNeedSpellchecking(this)) {
break;
}
}
if (!child) {
// No child needed spellchecking, return.
return;
}
// Maybe more than 1 child was appended.
endContent = container->GetLastChild();
} else if (!aChild->InclusiveDescendantMayNeedSpellchecking(this)) {
return;
}
RefPtr<nsRange> range = nsRange::Create(aChild);
range->SelectNodesInContainer(container, aChild, endContent);
DebugOnly<nsresult> rvIgnored =
mInlineSpellChecker->SpellCheckRange(range);