зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1396980 - Spending too much time making ranges for spellchecker on Facebook page, r=smaug
This commit is contained in:
Родитель
042dcb26b0
Коммит
5a9bc69d68
|
@ -1491,23 +1491,17 @@ nsresult mozInlineSpellChecker::DoSpellCheck(mozInlineSpellWordUtil& aWordUtil,
|
|||
PRTime beginTime = PR_Now();
|
||||
|
||||
nsAutoString wordText;
|
||||
RefPtr<nsRange> wordRange;
|
||||
NodeOffsetRange wordNodeOffsetRange;
|
||||
bool dontCheckWord;
|
||||
while (NS_SUCCEEDED(aWordUtil.GetNextWord(wordText,
|
||||
getter_AddRefs(wordRange),
|
||||
while (NS_SUCCEEDED(aWordUtil.GetNextWord(wordText, &wordNodeOffsetRange,
|
||||
&dontCheckWord)) &&
|
||||
wordRange) {
|
||||
!wordNodeOffsetRange.Empty()) {
|
||||
|
||||
// get the range for the current word.
|
||||
nsINode *beginNode;
|
||||
nsINode *endNode;
|
||||
int32_t beginOffset, endOffset;
|
||||
|
||||
ErrorResult erv;
|
||||
beginNode = wordRange->GetStartContainer(erv);
|
||||
endNode = wordRange->GetEndContainer(erv);
|
||||
beginOffset = wordRange->GetStartOffset(erv);
|
||||
endOffset = wordRange->GetEndOffset(erv);
|
||||
nsINode* beginNode = wordNodeOffsetRange.Begin().mNode;
|
||||
nsINode* endNode = wordNodeOffsetRange.End().mNode;
|
||||
int32_t beginOffset = wordNodeOffsetRange.Begin().mOffset;
|
||||
int32_t endOffset = wordNodeOffsetRange.End().mOffset;
|
||||
|
||||
// see if we've done enough words in this round and run out of time.
|
||||
if (wordsChecked >= INLINESPELL_MINIMUM_WORDS_BEFORE_TIMEOUT &&
|
||||
|
@ -1535,6 +1529,7 @@ nsresult mozInlineSpellChecker::DoSpellCheck(mozInlineSpellWordUtil& aWordUtil,
|
|||
printf("\n");
|
||||
#endif
|
||||
|
||||
ErrorResult erv;
|
||||
// see if there is a spellcheck range that already intersects the word
|
||||
// and remove it. We only need to remove old ranges, so don't bother if
|
||||
// there were no ranges when we started out.
|
||||
|
@ -1582,15 +1577,19 @@ nsresult mozInlineSpellChecker::DoSpellCheck(mozInlineSpellWordUtil& aWordUtil,
|
|||
continue;
|
||||
|
||||
wordsChecked++;
|
||||
|
||||
if (isMisspelled) {
|
||||
// misspelled words count extra toward the max
|
||||
AddRange(aSpellCheckSelection, wordRange);
|
||||
|
||||
aStatus->mWordCount ++;
|
||||
if (aStatus->mWordCount >= mMaxMisspellingsPerCheck ||
|
||||
SpellCheckSelectionIsFull()) {
|
||||
break;
|
||||
RefPtr<nsRange> wordRange;
|
||||
// If we somehow can't make a range for this word, just ignore it.
|
||||
if(NS_SUCCEEDED(aWordUtil.MakeRange(wordNodeOffsetRange.Begin(),
|
||||
wordNodeOffsetRange.End(),
|
||||
getter_AddRefs(wordRange)))) {
|
||||
AddRange(aSpellCheckSelection, wordRange);
|
||||
aStatus->mWordCount++;
|
||||
if (aStatus->mWordCount >= mMaxMisspellingsPerCheck ||
|
||||
SpellCheckSelectionIsFull()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -231,6 +231,14 @@ mozInlineSpellWordUtil::MakeRangeForWord(const RealWord& aWord, nsRange** aRange
|
|||
NodeOffset end = MapSoftTextOffsetToDOMPosition(aWord.EndOffset(), HINT_END);
|
||||
return MakeRange(begin, end, aRange);
|
||||
}
|
||||
void
|
||||
mozInlineSpellWordUtil::MakeNodeOffsetRangeForWord(const RealWord& aWord,
|
||||
NodeOffsetRange* aNodeOffsetRange)
|
||||
{
|
||||
NodeOffset begin = MapSoftTextOffsetToDOMPosition(aWord.mSoftTextOffset, HINT_BEGIN);
|
||||
NodeOffset end = MapSoftTextOffsetToDOMPosition(aWord.EndOffset(), HINT_END);
|
||||
*aNodeOffsetRange = NodeOffsetRange(begin, end);
|
||||
}
|
||||
|
||||
// mozInlineSpellWordUtil::GetRangeForWord
|
||||
|
||||
|
@ -289,7 +297,8 @@ NormalizeWord(const nsAString& aInput, int32_t aPos, int32_t aLen, nsAString& aO
|
|||
// range unless the word was misspelled. This may or may not be possible.
|
||||
|
||||
nsresult
|
||||
mozInlineSpellWordUtil::GetNextWord(nsAString& aText, nsRange** aRange,
|
||||
mozInlineSpellWordUtil::GetNextWord(nsAString& aText,
|
||||
NodeOffsetRange* aNodeOffsetRange,
|
||||
bool* aSkipChecking)
|
||||
{
|
||||
#ifdef DEBUG_SPELLCHECK
|
||||
|
@ -299,14 +308,13 @@ mozInlineSpellWordUtil::GetNextWord(nsAString& aText, nsRange** aRange,
|
|||
if (mNextWordIndex < 0 ||
|
||||
mNextWordIndex >= int32_t(mRealWords.Length())) {
|
||||
mNextWordIndex = -1;
|
||||
*aRange = nullptr;
|
||||
*aNodeOffsetRange = NodeOffsetRange();
|
||||
*aSkipChecking = true;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
const RealWord& word = mRealWords[mNextWordIndex];
|
||||
nsresult rv = MakeRangeForWord(word, aRange);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
MakeNodeOffsetRangeForWord(word, aNodeOffsetRange);
|
||||
++mNextWordIndex;
|
||||
*aSkipChecking = !word.mCheckableWord;
|
||||
::NormalizeWord(mSoftText, word.mSoftTextOffset, word.mLength, aText);
|
||||
|
@ -965,7 +973,7 @@ FindLastNongreaterOffset(const nsTArray<T>& aContainer, int32_t aSoftTextOffset,
|
|||
|
||||
} // namespace
|
||||
|
||||
mozInlineSpellWordUtil::NodeOffset
|
||||
NodeOffset
|
||||
mozInlineSpellWordUtil::MapSoftTextOffsetToDOMPosition(int32_t aSoftTextOffset,
|
||||
DOMMapHint aHint)
|
||||
{
|
||||
|
|
|
@ -21,6 +21,53 @@ namespace mozilla {
|
|||
class TextEditor;
|
||||
} // namespace mozilla
|
||||
|
||||
struct NodeOffset
|
||||
{
|
||||
nsINode* mNode;
|
||||
int32_t mOffset;
|
||||
|
||||
NodeOffset(): mNode(nullptr), mOffset(0) {}
|
||||
NodeOffset(nsINode* aNode, int32_t aOffset)
|
||||
: mNode(aNode), mOffset(aOffset) {}
|
||||
|
||||
bool operator==(const NodeOffset& aOther) const
|
||||
{
|
||||
return mNode == aOther.mNode && mOffset == aOther.mOffset;
|
||||
}
|
||||
|
||||
bool operator!=(const NodeOffset& aOther) const
|
||||
{
|
||||
return !(*this == aOther);
|
||||
}
|
||||
};
|
||||
|
||||
class NodeOffsetRange
|
||||
{
|
||||
private:
|
||||
NodeOffset mBegin;
|
||||
NodeOffset mEnd;
|
||||
bool mEmpty;
|
||||
public:
|
||||
NodeOffsetRange() : mEmpty(true) {}
|
||||
NodeOffsetRange(NodeOffset b, NodeOffset e)
|
||||
: mBegin(b), mEnd(e), mEmpty(false) {}
|
||||
|
||||
NodeOffset Begin()
|
||||
{
|
||||
return mBegin;
|
||||
}
|
||||
|
||||
NodeOffset End()
|
||||
{
|
||||
return mEnd;
|
||||
}
|
||||
|
||||
bool Empty()
|
||||
{
|
||||
return mEmpty;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* This class extracts text from the DOM and builds it into a single string.
|
||||
* The string includes whitespace breaks whereever non-inline elements begin
|
||||
|
@ -44,22 +91,6 @@ class TextEditor;
|
|||
class mozInlineSpellWordUtil
|
||||
{
|
||||
public:
|
||||
struct NodeOffset {
|
||||
nsINode* mNode;
|
||||
int32_t mOffset;
|
||||
|
||||
NodeOffset(nsINode* aNode, int32_t aOffset) :
|
||||
mNode(aNode), mOffset(aOffset) {}
|
||||
|
||||
bool operator==(const NodeOffset& aOther) const {
|
||||
return mNode == aOther.mNode && mOffset == aOther.mOffset;
|
||||
}
|
||||
|
||||
bool operator!=(const NodeOffset& aOther) const {
|
||||
return !(*this == aOther);
|
||||
}
|
||||
};
|
||||
|
||||
mozInlineSpellWordUtil()
|
||||
: mRootNode(nullptr),
|
||||
mSoftBegin(nullptr, 0), mSoftEnd(nullptr, 0),
|
||||
|
@ -85,11 +116,15 @@ public:
|
|||
nsresult GetRangeForWord(nsIDOMNode* aWordNode, int32_t aWordOffset,
|
||||
nsRange** aRange);
|
||||
|
||||
// Convenience functions, object must be initialized
|
||||
nsresult MakeRange(NodeOffset aBegin, NodeOffset aEnd, nsRange** aRange);
|
||||
|
||||
// Moves to the the next word in the range, and retrieves it's text and range.
|
||||
// An empty word and a nullptr range are returned when we are done checking.
|
||||
// aSkipChecking will be set if the word is "special" and shouldn't be
|
||||
// checked (e.g., an email address).
|
||||
nsresult GetNextWord(nsAString& aText, nsRange** aRange,
|
||||
nsresult GetNextWord(nsAString& aText,
|
||||
NodeOffsetRange* aNodeOffsetRange,
|
||||
bool* aSkipChecking);
|
||||
|
||||
// Call to normalize some punctuation. This function takes an autostring
|
||||
|
@ -175,9 +210,9 @@ private:
|
|||
|
||||
nsresult SplitDOMWord(int32_t aStart, int32_t aEnd);
|
||||
|
||||
// Convenience functions, object must be initialized
|
||||
nsresult MakeRange(NodeOffset aBegin, NodeOffset aEnd, nsRange** aRange);
|
||||
nsresult MakeRangeForWord(const RealWord& aWord, nsRange** aRange);
|
||||
void MakeNodeOffsetRangeForWord(const RealWord& aWord,
|
||||
NodeOffsetRange* aNodeOffsetRange);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
Загрузка…
Ссылка в новой задаче