Bug 699703 - Need reframe before calling SetSelectionAfterTableEdit. r?masayuki draft
authorMakoto Kato <m_kato@ga2.so-net.ne.jp>
Fri, 14 Jul 2017 15:48:40 +0900
changeset 618922 2578fb9f793550eb654192961f3ed49ca710fdaa
parent 618757 44121dbcac6a9d3ff18ed087a09b3205e5a04db1
child 618923 0c3874528aa69ae2b8676d05111c5f581f375c1c
child 618925 6879ec0a9a42a9cba38a85b98a2fb347ccafaba1
push id71501
push userbmo:m_kato@ga2.so-net.ne.jp
push dateTue, 01 Aug 2017 08:28:27 +0000
reviewersmasayuki
bugs699703
milestone56.0a1
Bug 699703 - Need reframe before calling SetSelectionAfterTableEdit. r?masayuki HTMLEditor::TabInTable inserts row element, then it selects a cell. But when enabling lazy frame construction for editable node, it selects invalid cell and table. Because HTMLEditor::SetSelectionAfterTableEdit doesn't select cell correctly on InsertTableRow(). HTMLEditor::SetSelectionAfterTableEdit uses HTMLEditor::GetCellAt, so it depends on frame. So we need flush frame before calling it. Also, a comment of HTMLEditor::InsertTableRow is invalid now because we don't use nsresult version of CreateElementWithDefualts. MozReview-Commit-ID: 698TvmMZgwB
editor/libeditor/EditorBase.h
editor/libeditor/HTMLEditor.cpp
editor/libeditor/HTMLEditor.h
editor/libeditor/HTMLEditorEventListener.cpp
editor/libeditor/HTMLInlineTableEditor.cpp
editor/libeditor/HTMLTableEditor.cpp
--- a/editor/libeditor/EditorBase.h
+++ b/editor/libeditor/EditorBase.h
@@ -1001,16 +1001,21 @@ public:
    * IsSuppressingDispatchingInputEvent() returns true if the editor stops
    * dispatching input event.  Otherwise, false.
    */
   bool IsSuppressingDispatchingInputEvent() const
   {
     return !mDispatchInputEvent;
   }
 
+  bool Destroyed() const
+  {
+    return mDidPreDestroy;
+  }
+
   /**
    * GetTransactionManager() returns transaction manager associated with the
    * editor.  This may return nullptr if undo/redo hasn't been enabled.
    */
   already_AddRefed<nsITransactionManager> GetTransactionManager() const;
 
   /**
    * Get the input event target. This might return null.
--- a/editor/libeditor/HTMLEditor.cpp
+++ b/editor/libeditor/HTMLEditor.cpp
@@ -652,16 +652,20 @@ HTMLEditor::HandleKeyPressEvent(WidgetKe
       if (!blockParent) {
         break;
       }
 
       bool handled = false;
       nsresult rv = NS_OK;
       if (HTMLEditUtils::IsTableElement(blockParent)) {
         rv = TabInTable(aKeyboardEvent->IsShift(), &handled);
+        // TabInTable might cause reframe
+        if (Destroyed()) {
+          return NS_OK;
+        }
         if (handled) {
           ScrollSelectionIntoView(false);
         }
       } else if (HTMLEditUtils::IsListItem(blockParent)) {
         rv = Indent(aKeyboardEvent->IsShift()
                     ? NS_LITERAL_STRING("outdent")
                     : NS_LITERAL_STRING("indent"));
         handled = true;
@@ -1015,17 +1019,17 @@ HTMLEditor::TypedText(const nsAString& a
     // only inserts a br node
     nsCOMPtr<nsIDOMNode> brNode;
     return InsertBR(address_of(brNode));
   }
 
   return TextEditor::TypedText(aString, aAction);
 }
 
-NS_IMETHODIMP
+nsresult
 HTMLEditor::TabInTable(bool inIsShift,
                        bool* outHandled)
 {
   NS_ENSURE_TRUE(outHandled, NS_ERROR_NULL_POINTER);
   *outHandled = false;
 
   // Find enclosing table cell from selection (cell may be selected element)
   nsCOMPtr<Element> cellElement =
--- a/editor/libeditor/HTMLEditor.h
+++ b/editor/libeditor/HTMLEditor.h
@@ -428,17 +428,17 @@ protected:
    */
   already_AddRefed<nsINode> GetFocusedNode();
 
   /**
    * Return TRUE if aElement is a table-related elemet and caret was set.
    */
   bool SetCaretInTableCell(nsIDOMElement* aElement);
 
-  NS_IMETHOD TabInTable(bool inIsShift, bool* outHandled);
+  nsresult TabInTable(bool inIsShift, bool* outHandled);
   already_AddRefed<Element> CreateBR(nsINode* aNode, int32_t aOffset,
                                      EDirection aSelect = eNone);
   NS_IMETHOD CreateBR(
                nsIDOMNode* aNode, int32_t aOffset,
                nsCOMPtr<nsIDOMNode>* outBRNode,
                nsIEditor::EDirection aSelect = nsIEditor::eNone) override;
 
   nsresult InsertBR(nsCOMPtr<nsIDOMNode>* outBRNode);
--- a/editor/libeditor/HTMLEditorEventListener.cpp
+++ b/editor/libeditor/HTMLEditorEventListener.cpp
@@ -212,16 +212,21 @@ HTMLEditorEventListener::MouseClick(nsID
   }
 
   nsCOMPtr<nsIDOMEventTarget> target;
   nsresult rv = aMouseEvent->AsEvent()->GetTarget(getter_AddRefs(target));
   NS_ENSURE_SUCCESS(rv, rv);
   NS_ENSURE_TRUE(target, NS_ERROR_NULL_POINTER);
   nsCOMPtr<nsIDOMElement> element = do_QueryInterface(target);
 
-  HTMLEditor* htmlEditor = mEditorBase->AsHTMLEditor();
+  RefPtr<HTMLEditor> htmlEditor = mEditorBase->AsHTMLEditor();
   MOZ_ASSERT(htmlEditor);
   htmlEditor->DoInlineTableEditingAction(element);
+  // DoInlineTableEditingAction might cause reframe
+  // Editor is destroyed.
+  if (htmlEditor->Destroyed()) {
+    return NS_OK;
+  }
 
   return EditorEventListener::MouseClick(aMouseEvent);
 }
 
 } // namespace mozilla
--- a/editor/libeditor/HTMLInlineTableEditor.cpp
+++ b/editor/libeditor/HTMLInlineTableEditor.cpp
@@ -169,16 +169,21 @@ HTMLEditor::DoInlineTableEditingAction(n
       DeleteTableRow(1);
 #ifndef DISABLE_TABLE_DELETION
       hideUI = (rowCount == 1);
 #endif
     }
     else
       return NS_OK;
 
+    // InsertTableRow might causes reframe
+    if (Destroyed()) {
+      return NS_OK;
+    }
+
     if (hideUI) {
       HideInlineTableEditingUI();
       if (hideResizersWithInlineTableUI)
         HideResizers();
     }
   }
 
   return NS_OK;
--- a/editor/libeditor/HTMLTableEditor.cpp
+++ b/editor/libeditor/HTMLTableEditor.cpp
@@ -5,16 +5,17 @@
 
 #include <stdio.h>
 
 #include "mozilla/HTMLEditor.h"
 
 #include "HTMLEditUtils.h"
 #include "mozilla/Assertions.h"
 #include "mozilla/EditorUtils.h"
+#include "mozilla/FlushType.h"
 #include "mozilla/dom/Selection.h"
 #include "mozilla/dom/Element.h"
 #include "nsAString.h"
 #include "nsAlgorithm.h"
 #include "nsCOMPtr.h"
 #include "nsDebug.h"
 #include "nsError.h"
 #include "nsGkAtoms.h"
@@ -685,19 +686,26 @@ HTMLEditor::InsertTableRow(int32_t aNumb
       }
 
       // Use transaction system to insert the entire row+cells
       // (Note that rows are inserted at same childoffset each time)
       rv = InsertNode(*newRow, *parentOfRow, newRowOffset);
       NS_ENSURE_SUCCESS(rv, rv);
     }
   }
-  // XXX This might be the result of the last call of
-  //     CreateElementWithDefaults(), otherwise, NS_OK.
-  return rv;
+
+  // SetSelectionAfterTableEdit from AutoSelectionSetterAfterTableEdit will
+  // access frame selection, so we need reframe.
+  // Because GetCellAt depends on frame.
+  nsCOMPtr<nsIPresShell> ps = GetPresShell();
+  if (ps) {
+    ps->FlushPendingNotifications(FlushType::Frames);
+  }
+
+  return NS_OK;
 }
 
 // Editor helper only
 // XXX Code changed for bug 217717 and now we don't need aSelection param
 //     TODO: Remove aSelection param
 nsresult
 HTMLEditor::DeleteTable2(nsIDOMElement* aTable,
                          Selection* aSelection)