Bug 1362858 - Part 2: Exclude script and style tags when building soft text.r=ehsan draft
authorEvelyn Hung <jj.evelyn@gmail.com>
Mon, 12 Jun 2017 17:27:12 +0800
changeset 593180 ccf0f0e453819cb4f782ab081a42e10b470a8e91
parent 592469 601390e03132687befc9205771161b9253d20262
child 633042 55415fdb853b820487d307bbbdfc2f9ac282a1fb
push id63620
push userbmo:ehung@mozilla.com
push dateTue, 13 Jun 2017 09:01:55 +0000
reviewersehsan
bugs1362858
milestone55.0a1
Bug 1362858 - Part 2: Exclude script and style tags when building soft text.r=ehsan We keep checking if a node is a text node when building soft text and set spell checking range in DoSpellCheck. However, simply checking text node is not optimal, we could furthur exclude text node in script and style tags. There might be more cases we could consider to exclude.
extensions/spellcheck/src/mozInlineSpellChecker.cpp
extensions/spellcheck/src/mozInlineSpellWordUtil.cpp
--- a/extensions/spellcheck/src/mozInlineSpellChecker.cpp
+++ b/extensions/spellcheck/src/mozInlineSpellChecker.cpp
@@ -1257,17 +1257,17 @@ mozInlineSpellChecker::SpellCheckBetween
 //    for these cases.
 
 bool
 mozInlineSpellChecker::ShouldSpellCheckNode(nsIEditor* aEditor,
                                             nsINode *aNode)
 {
   MOZ_ASSERT(aNode);
   if (!aNode->IsContent())
-    return true;
+    return false;
 
   nsIContent *content = aNode->AsContent();
 
   uint32_t flags;
   aEditor->GetFlags(&flags);
   if (flags & nsIPlaintextEditor::eEditorMailMask) {
     nsIContent *parent = content->GetParent();
     while (parent) {
--- a/extensions/spellcheck/src/mozInlineSpellWordUtil.cpp
+++ b/extensions/spellcheck/src/mozInlineSpellWordUtil.cpp
@@ -76,18 +76,21 @@ mozInlineSpellWordUtil::Init(const nsWea
 
   nsCOMPtr<nsINode> rootNode = do_QueryInterface(rootElt);
   mRootNode = rootNode;
   NS_ASSERTION(mRootNode, "GetRootElement returned null *and* claimed to suceed!");
   return NS_OK;
 }
 
 static inline bool
-IsTextNode(nsINode* aNode)
+IsSpellCheckingTextNode(nsINode* aNode)
 {
+  nsIContent *parent = aNode->GetParent();
+  if (parent && parent->IsAnyOfHTMLElements(nsGkAtoms::script, nsGkAtoms::style))
+      return false;
   return aNode->IsNodeOfType(nsINode::eTEXT);
 }
 
 typedef void (* OnLeaveNodeFunPtr)(nsINode* aNode, void* aClosure);
 
 // Find the next node in the DOM tree in preorder.
 // Calls OnLeaveNodeFunPtr when the traversal leaves a node, which is
 // why we can't just use GetNextNode here, sadly.
@@ -127,32 +130,32 @@ FindNextNode(nsINode* aNode, nsINode* aR
 }
 
 // aNode is not a text node. Find the first text node starting at aNode/aOffset
 // in a preorder DOM traversal.
 static nsINode*
 FindNextTextNode(nsINode* aNode, int32_t aOffset, nsINode* aRoot)
 {
   NS_PRECONDITION(aNode, "Null starting node?");
-  NS_ASSERTION(!IsTextNode(aNode), "FindNextTextNode should start with a non-text node");
+  NS_ASSERTION(!IsSpellCheckingTextNode(aNode), "FindNextTextNode should start with a non-text node");
 
   nsINode* checkNode;
   // Need to start at the aOffset'th child
   nsIContent* child = aNode->GetChildAt(aOffset);
 
   if (child) {
     checkNode = child;
   } else {
     // aOffset was beyond the end of the child list. 
     // goto next node after the last descendant of aNode in
     // a preorder DOM traversal.
     checkNode = aNode->GetNextNonChildNode(aRoot);
   }
   
-  while (checkNode && !IsTextNode(checkNode)) {
+  while (checkNode && !IsSpellCheckingTextNode(checkNode)) {
     checkNode = checkNode->GetNextNode(aRoot);
   }
   return checkNode;
 }
 
 // mozInlineSpellWordUtil::SetEnd
 //
 //    We have two ranges "hard" and "soft". The hard boundary is simply
@@ -174,31 +177,31 @@ nsresult
 mozInlineSpellWordUtil::SetEnd(nsINode* aEndNode, int32_t aEndOffset)
 {
   NS_PRECONDITION(aEndNode, "Null end node?");
 
   NS_ASSERTION(mRootNode, "Not initialized");
 
   InvalidateWords();
 
-  if (!IsTextNode(aEndNode)) {
+  if (!IsSpellCheckingTextNode(aEndNode)) {
     // End at the start of the first text node after aEndNode/aEndOffset.
     aEndNode = FindNextTextNode(aEndNode, aEndOffset, mRootNode);
     aEndOffset = 0;
   }
   mSoftEnd = NodeOffset(aEndNode, aEndOffset);
   return NS_OK;
 }
 
 nsresult
 mozInlineSpellWordUtil::SetPosition(nsINode* aNode, int32_t aOffset)
 {
   InvalidateWords();
 
-  if (!IsTextNode(aNode)) {
+  if (!IsSpellCheckingTextNode(aNode)) {
     // Start at the start of the first text node after aNode/aOffset.
     aNode = FindNextTextNode(aNode, aOffset, mRootNode);
     aOffset = 0;
   }
   mSoftBegin = NodeOffset(aNode, aOffset);
 
   nsresult rv = EnsureWords();
   if (NS_FAILED(rv)) {
@@ -683,17 +686,17 @@ static bool
 ContainsDOMWordSeparator(nsINode* aNode, int32_t aBeforeOffset,
                          int32_t* aSeparatorOffset)
 {
   if (IsBRElement(aNode)) {
     *aSeparatorOffset = 0;
     return true;
   }
 
-  if (!IsTextNode(aNode))
+  if (!IsSpellCheckingTextNode(aNode))
     return false;
 
   return TextNodeContainsDOMWordSeparator(aNode, aBeforeOffset,
                                           aSeparatorOffset);
 }
 
 static bool
 IsBreakElement(nsINode* aNode)
@@ -764,17 +767,17 @@ mozInlineSpellWordUtil::BuildSoftText()
           // not a text node, or we run out of previous sibling nodes. In the
           // event that we simply cannot find any preceding word separator, the
           // offset is set to 0, and the soft text beginning node is set to the
           // "most previous" text node before the original starting node, or
           // kept at the original starting node if no previous text nodes exist.
           if (!ContainsDOMWordSeparator(node, firstOffsetInNode - 1,
                                         &newOffset)) {
             nsINode* prevNode = node->GetPreviousSibling();
-            while (prevNode && IsTextNode(prevNode)) {
+            while (prevNode && IsSpellCheckingTextNode(prevNode)) {
               mSoftBegin.mNode = prevNode;
               if (TextNodeContainsDOMWordSeparator(prevNode, INT32_MAX,
                                                    &newOffset)) {
                 break;
               }
               prevNode = prevNode->GetPreviousSibling();
             }
           }
@@ -807,17 +810,17 @@ mozInlineSpellWordUtil::BuildSoftText()
   // Leave this outside the loop so large heap string allocations can be reused
   // across iterations
   while (node) {
     if (node == mSoftEnd.mNode) {
       seenSoftEnd = true;
     }
 
     bool exit = false;
-    if (IsTextNode(node)) {
+    if (IsSpellCheckingTextNode(node)) {
       nsIContent* content = static_cast<nsIContent*>(node);
       NS_ASSERTION(content, "Where is our content?");
       const nsTextFragment* textFragment = content->GetText();
       NS_ASSERTION(textFragment, "Where is our text?");
       int32_t lastOffsetInNode = textFragment->GetLength();
 
       if (seenSoftEnd) {
         // check whether we can stop after this