Bug 1484126 - part 15: Make all CellData users refer CellData::mEffectiveColspan directly r=m_kato
authorMasayuki Nakano <masayuki@d-toybox.com>
Mon, 15 Oct 2018 11:33:33 +0000
changeset 499840 e5c8e5cbaf3dbbc60d6d2dce5db844820c6009b9
parent 499839 ed17432df28cf6e49cd8909835ae1b684d66f14c
child 499841 4c70964d90fda77a9c06094accf3815fdfac1f2c
push id1864
push userffxbld-merge
push dateMon, 03 Dec 2018 15:51:40 +0000
treeherdermozilla-release@f040763d99ad [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersm_kato
bugs1484126
milestone64.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1484126 - part 15: Make all CellData users refer CellData::mEffectiveColspan directly r=m_kato Differential Revision: https://phabricator.services.mozilla.com/D8352
editor/libeditor/HTMLTableEditor.cpp
--- a/editor/libeditor/HTMLTableEditor.cpp
+++ b/editor/libeditor/HTMLTableEditor.cpp
@@ -206,17 +206,16 @@ HTMLEditor::InsertTableCellsWithTransact
   IgnoredErrorResult ignoredError;
   CellData cellDataAtSelection(*this, *table, startRowIndex, startColIndex,
                                ignoredError);
   if (NS_WARN_IF(cellDataAtSelection.FailedOrNotFound())) {
     return NS_ERROR_FAILURE;
   }
   MOZ_ASSERT(curCell == cellDataAtSelection.mElement);
 
-  // int32_t actualColSpan =    cellDataAtSelection.mEffectiveColSpan;
   // bool    isSelected =       cellDataAtSelection.mIsSelected;
 
   int32_t newCellIndex;
   switch (aInsertPosition) {
     case InsertPosition::eBeforeSelectedCell:
       newCellIndex = cellDataAtSelection.mCurrent.mColumn;
       break;
     case InsertPosition::eAfterSelectedCell:
@@ -441,17 +440,16 @@ HTMLEditor::InsertTableColumnsWithTransa
   IgnoredErrorResult ignoredError;
   CellData cellDataAtSelection(*this, *table, startRowIndex, startColIndex,
                                ignoredError);
   if (NS_WARN_IF(cellDataAtSelection.FailedOrNotFound())) {
     return NS_ERROR_FAILURE;
   }
   MOZ_ASSERT(curCell == cellDataAtSelection.mElement);
 
-  int32_t    actualColSpan =    cellDataAtSelection.mEffectiveColSpan;
   // bool    isSelected =       cellDataAtSelection.mIsSelected;
 
   ErrorResult error;
   TableSize tableSize(*this, *table, error);
   if (NS_WARN_IF(error.Failed())) {
     return error.StealNSResult();
   }
   // Should not be empty since we've already found a cell.
@@ -463,23 +461,24 @@ HTMLEditor::InsertTableColumnsWithTransa
                                       *this, EditSubAction::eInsertNode,
                                       nsIEditor::eNext);
 
   switch (aInsertPosition) {
     case InsertPosition::eBeforeSelectedCell:
       break;
     case InsertPosition::eAfterSelectedCell:
       // Use column after current cell.
-      startColIndex += actualColSpan;
+      startColIndex += cellDataAtSelection.mEffectiveColSpan;
 
       // Detect when user is adding after a colspan=0 case.
       // Assume they want to stop the "0" behavior and really add a new column.
       // Thus we set the colspan to its true value.
       if (!cellDataAtSelection.mColSpan) {
-        SetColSpan(cellDataAtSelection.mElement, actualColSpan);
+        SetColSpan(cellDataAtSelection.mElement,
+                   cellDataAtSelection.mEffectiveColSpan);
       }
       break;
     default:
       MOZ_ASSERT_UNREACHABLE("Invalid InsertPosition");
   }
 
   // We control selection resetting after the insert.
   AutoSelectionSetterAfterTableEdit setCaret(*this, table,
@@ -506,17 +505,16 @@ HTMLEditor::InsertTableColumnsWithTransa
   for (int32_t rowIndex = 0; rowIndex < tableSize.mRowCount; rowIndex++) {
     if (startColIndex < tableSize.mColumnCount) {
       // We are inserting before an existing column.
       CellData cellData(*this, *table, rowIndex, startColIndex, ignoredError);
       if (NS_WARN_IF(cellData.FailedOrNotFound())) {
         return NS_ERROR_FAILURE;
       }
 
-      // int32_t actualColSpan =          cellData.mEffectiveColSpan;
       // bool    isSelected =             cellData.mIsSelected;
 
       // Don't fail entire process if we fail to find a cell (may fail just in
       // particular rows with < adequate cells per row).
       // XXX So, here wants to know whether the CellData actually failed above.
       //     Fix this later.
       if (!cellData.mElement) {
         continue;
@@ -635,17 +633,16 @@ HTMLEditor::InsertTableRowsWithTransacti
   IgnoredErrorResult ignoredError;
   CellData cellDataAtSelection(*this, *table, startRowIndex, startColIndex,
                                ignoredError);
   if (NS_WARN_IF(cellDataAtSelection.FailedOrNotFound())) {
     return NS_ERROR_FAILURE;
   }
   MOZ_ASSERT(curCell == cellDataAtSelection.mElement);
 
-  // int32_t actualColSpan =    cellDataAtSelection.mEffectiveColSpan;
   // bool isSelected =          cellDataAtSelection.mIsSelected;
 
   ErrorResult error;
   TableSize tableSize(*this, *table, error);
   if (NS_WARN_IF(error.Failed())) {
     return error.StealNSResult();
   }
   // Should not be empty since we've already found a cell.
@@ -690,25 +687,26 @@ HTMLEditor::InsertTableRowsWithTransacti
     // row to adjust for colspan effects while we count how many cells are
     // needed.
     for (int32_t colIndex = 0, actualColSpan = 0;; colIndex += actualColSpan) {
       CellData cellData(*this, *table, startRowIndex, colIndex, ignoredError);
       if (cellData.FailedOrNotFound()) {
         break; // Perhaps, we reach end of the row.
       }
 
-                 actualColSpan =              cellData.mEffectiveColSpan;
       // bool    isSelected =                 cellData.mIsSelected;
 
       // XXX So, this is impossible case. Will be removed.
       if (NS_WARN_IF(!cellData.mElement)) {
         actualColSpan = 1;
         continue;
       }
 
+      actualColSpan = cellData.mEffectiveColSpan;
+
       if (cellData.IsSpannedFromOtherRow()) {
         // We have a cell spanning this location.  Increase its rowspan.
         // Note that if rowspan is 0, we do nothing since that cell should
         // automatically extend into the new row.
         if (cellData.mRowSpan > 0) {
           SetRowSpan(cellData.mElement,
                      cellData.mRowSpan + aNumberOfRowsToInsert);
         }
@@ -731,19 +729,20 @@ HTMLEditor::InsertTableRowsWithTransacti
     // but we must compensate for all cells with rowspan = 0 in the last row.
     const int32_t kLastRowIndex = tableSize.mRowCount - 1;
     for (int32_t colIndex = 0, actualColSpan = 0;; colIndex += actualColSpan) {
       CellData cellData(*this, *table, kLastRowIndex, colIndex, ignoredError);
       if (cellData.FailedOrNotFound()) {
         break; // Perhaps, we reach end of the row.
       }
 
-                 actualColSpan =              cellData.mEffectiveColSpan;
       // bool    isSelected =                 cellData.mIsSelected;
 
+     actualColSpan = cellData.mEffectiveColSpan;
+
       if (!cellData.mRowSpan) {
         MOZ_ASSERT(cellsInRow >= actualColSpan);
         cellsInRow -= actualColSpan;
       }
 
       // Save cell from the last row that we will use below
       if (!cellForRowParent && !cellData.IsSpannedFromOtherRow()) {
         cellForRowParent = std::move(cellData.mElement);
@@ -1380,17 +1379,16 @@ HTMLEditor::DeleteTableColumnWithTransac
     // Failure means that there is no more row in the table.  In this case,
     // we shouldn't return error since we just reach the end of the table.
     // XXX Should distinguish whether CellData returns error or just not found
     //     later.
     if (cellData.FailedOrNotFound()) {
       return NS_OK;
     }
 
-    // int32_t actualColSpan =       cellData.mEffectiveColSpan;
     // bool    isSelected =          cellData.mIsSelected;
 
     // Find cells that don't start in column we are deleting.
     MOZ_ASSERT(cellData.mColSpan >= 0);
     if (cellData.IsSpannedFromOtherColumn() || cellData.mColSpan != 1) {
       // If we have a cell spanning this location, decrease its colspan to
       // keep table rectangular, but if colspan is 0, it'll be adjusted
       // automatically.
@@ -1652,17 +1650,16 @@ HTMLEditor::DeleteTableRowWithTransactio
   while (aRowIndex < tableSize.mRowCount &&
          columnIndex < tableSize.mColumnCount) {
     CellData cellData(*this, aTableElement, aRowIndex, columnIndex,
                       ignoredError);
     if (NS_WARN_IF(cellData.FailedOrNotFound())) {
       return NS_ERROR_FAILURE;
     }
 
-    int32_t    actualColSpan =       cellData.mEffectiveColSpan;
     // bool    isSelected =          cellData.mIsSelected;
 
     // XXX So, we should distinguish if CellDate returns error or just not
     //     found later.
     if (!cellData.mElement) {
       break;
     }
 
@@ -1698,17 +1695,17 @@ HTMLEditor::DeleteTableRowWithTransactio
         }
       }
       if (!cellInDeleteRow) {
         // Reference cell to find row to delete.
         cellInDeleteRow = std::move(cellData.mElement);
       }
     }
     // Skip over other columns spanned by this cell
-    columnIndex += actualColSpan;
+    columnIndex += cellData.mEffectiveColSpan;
   }
 
   // Things are messed up if we didn't find a cell in the row!
   if (NS_WARN_IF(!cellInDeleteRow)) {
     return NS_ERROR_FAILURE;
   }
 
   // Delete the entire row.
@@ -1871,29 +1868,30 @@ HTMLEditor::SelectBlockOfCells(Element* 
     for (int32_t col = minColumn, actualColSpan = 0;
          col <= maxColumn;
          col += std::max(actualColSpan, 1)) {
       CellData cellData(*this, *table, row, col, ignoredError);
       if (cellData.FailedOrNotFound()) {
         return NS_ERROR_FAILURE;
       }
 
-                 actualColSpan =       cellData.mEffectiveColSpan;
       bool       isSelected =          cellData.mIsSelected;
 
       // Skip cells that already selected or are spanned from previous locations
       // XXX So, we should distinguish whether CellData returns error or just
       //     not found later.
       if (!isSelected && cellData.mElement &&
           !cellData.IsSpannedFromOtherRowOrColumn()) {
         rv = AppendNodeToSelectionAsRange(cellData.mElement);
         if (NS_FAILED(rv)) {
           break;
         }
       }
+
+      actualColSpan = cellData.mEffectiveColSpan;
     }
   }
   // NS_OK, otherwise, the last failure of AppendNodeToSelectionAsRange().
   return rv;
 }
 
 NS_IMETHODIMP
 HTMLEditor::SelectAllTableCells()
@@ -1940,30 +1938,31 @@ HTMLEditor::SelectAllTableCells()
          col < tableSize.mColumnCount;
          col += std::max(actualColSpan, 1)) {
       CellData cellData(*this, *table, row, col, ignoredError);
       if (NS_WARN_IF(cellData.FailedOrNotFound())) {
         rv = NS_ERROR_FAILURE;
         break;
       }
 
-                 actualColSpan =       cellData.mEffectiveColSpan;
       // bool    isSelected =          cellData.mIsSelected;
 
       // Skip cells that are spanned from previous rows or columns
       // XXX So, we should distinguish whether CellData returns error or just
       //     not found later.
       if (cellData.mElement &&
           !cellData.IsSpannedFromOtherRowOrColumn()) {
         rv =  AppendNodeToSelectionAsRange(cellData.mElement);
         if (NS_FAILED(rv)) {
           break;
         }
         cellSelected = true;
       }
+
+      actualColSpan = cellData.mEffectiveColSpan;
     }
   }
   // Safety code to select starting cell if nothing else was selected
   if (!cellSelected) {
     return AppendNodeToSelectionAsRange(startCell);
   }
   // NS_OK, otherwise, the error of ClearSelection() when there is no column or
   // the last failure of CellData or AppendNodeToSelectionAsRange().
@@ -2028,30 +2027,31 @@ HTMLEditor::SelectTableRow()
        col < tableSize.mColumnCount;
        col += std::max(actualColSpan, 1)) {
     CellData cellData(*this, *table, startRowIndex, col, ignoredError);
     if (NS_WARN_IF(cellData.FailedOrNotFound())) {
       rv = NS_ERROR_FAILURE;
       break;
     }
 
-               actualColSpan =       cellData.mEffectiveColSpan;
     // bool    isSelected =          cellData.mIsSelected;
 
     // Skip cells that are spanned from previous rows or columns
     // XXX So, we should distinguish whether CellData returns error or just
     //     not found later.
     if (cellData.mElement &&
         !cellData.IsSpannedFromOtherRowOrColumn()) {
       rv = AppendNodeToSelectionAsRange(cellData.mElement);
       if (NS_FAILED(rv)) {
         break;
       }
       cellSelected = true;
     }
+
+    actualColSpan = cellData.mEffectiveColSpan;
   }
   // Safety code to select starting cell if nothing else was selected
   if (!cellSelected) {
     return AppendNodeToSelectionAsRange(startCell);
   }
   // NS_OK, otherwise, the error of ClearSelection() when there is no column or
   // the last failure of CellData or AppendNodeToSelectionAsRange().
   return rv;
@@ -2111,17 +2111,16 @@ HTMLEditor::SelectTableColumn()
        row < tableSize.mRowCount;
        row += std::max(actualRowSpan, 1)) {
     CellData cellData(*this, *table, row, startColIndex, ignoredError);
     if (NS_WARN_IF(cellData.FailedOrNotFound())) {
       rv = NS_ERROR_FAILURE;
       break;
     }
 
-    // int32_t actualColSpan =       cellData.mEffectiveColSpan;
     // bool    isSelected =          cellData.mIsSelected;
 
     // Skip cells that are spanned from previous rows or columns
     // XXX So, we should distinguish whether CellData returns error or just
     //     not found later.
     if (cellData.mElement &&
         !cellData.IsSpannedFromOtherRowOrColumn()) {
       rv = AppendNodeToSelectionAsRange(cellData.mElement);
@@ -2249,21 +2248,21 @@ HTMLEditor::SplitCellIntoColumns(Element
   }
 
   IgnoredErrorResult ignoredError;
   CellData cellData(*this, *aTable, aRowIndex, aColIndex, ignoredError);
   if (NS_WARN_IF(cellData.FailedOrNotFound())) {
     return NS_ERROR_FAILURE;
   }
 
-  int32_t    actualColSpan =       cellData.mEffectiveColSpan;
   // bool    isSelected =          cellData.mIsSelected;
 
   // We can't split!
-  if (actualColSpan <= 1 || (aColSpanLeft + aColSpanRight) > actualColSpan) {
+  if (cellData.mEffectiveColSpan <= 1 ||
+      aColSpanLeft + aColSpanRight > cellData.mEffectiveColSpan) {
     return NS_OK;
   }
 
   // Reduce colspan of cell to split
   nsresult rv = SetColSpan(cellData.mElement, aColSpanLeft);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
@@ -2307,17 +2306,16 @@ HTMLEditor::SplitCellIntoRows(Element* a
   }
 
   IgnoredErrorResult ignoredError;
   CellData cellData(*this, *aTable, aRowIndex, aColIndex, ignoredError);
   if (NS_WARN_IF(cellData.FailedOrNotFound())) {
     return NS_ERROR_FAILURE;
   }
 
-  int32_t    actualColSpan =       cellData.mEffectiveColSpan;
   // bool    isSelected =          cellData.mIsSelected;
 
   // We can't split!
   if (cellData.mEffectiveRowSpan <= 1 ||
       aRowSpanAbove + aRowSpanBelow > cellData.mEffectiveRowSpan) {
     return NS_OK;
   }
 
@@ -2342,17 +2340,16 @@ HTMLEditor::SplitCellIntoRows(Element* a
     // XXX According to the comment, this does not assume that
     //     FixRowSpan() doesn't work well and user can create non-rectangular
     //     table.  So, we should not return error when CellData cannot find
     //     a cell.
     if (NS_WARN_IF(cellDataAtInsertionPoint.FailedOrNotFound())) {
       return NS_ERROR_FAILURE;
     }
 
-               actualColSpan2 = cellDataAtInsertionPoint.mEffectiveColSpan;
     // bool    isSelected2 =    cellDataAtInsertionPoint.mIsSelected;
 
     // FYI: Don't use std::move() here since the following checks will use
     //      utility methods of cellDataAtInsertionPoint, but some of them
     //      check whether its mElement is not nullptr.
     cellElementAtInsertionPoint = cellDataAtInsertionPoint.mElement;
 
     // Skip over cells spanned from above (like the one we are splitting!)
@@ -2360,30 +2357,33 @@ HTMLEditor::SplitCellIntoRows(Element* a
         !cellDataAtInsertionPoint.IsSpannedFromOtherRow()) {
       if (!insertAfter) {
         // Inserting before, so stop at first cell in row we want to insert
         // into.
         break;
       }
       // New cell isn't first in row,
       // so stop after we find the cell just before new cell's column
-      if (cellDataAtInsertionPoint.mFirst.mColumn + actualColSpan2 ==
-            cellData.mFirst.mColumn) {
+      if (cellDataAtInsertionPoint.mFirst.mColumn +
+            cellDataAtInsertionPoint.mEffectiveColSpan ==
+              cellData.mFirst.mColumn) {
         break;
       }
       // If cell found is AFTER desired new cell colum,
       //  we have multiple cells with rowspan > 1 that
       //  prevented us from finding a cell to insert after...
       if (cellDataAtInsertionPoint.mFirst.mColumn > cellData.mFirst.mColumn) {
         // ... so instead insert before the cell we found
         insertAfter = false;
         break;
       }
       lastCellFound = std::move(cellDataAtInsertionPoint.mElement);
     }
+
+    actualColSpan2 = cellDataAtInsertionPoint.mEffectiveColSpan;
   }
 
   if (!cellElementAtInsertionPoint && lastCellFound) {
     // Edge case where we didn't find a cell to insert after
     //  or before because column(s) before desired column
     //  and all columns after it are spanned from above.
     //  We can insert after the last cell we found
     cellElementAtInsertionPoint = std::move(lastCellFound);
@@ -2394,17 +2394,18 @@ HTMLEditor::SplitCellIntoRows(Element* a
   nsresult rv = SetRowSpan(cellData.mElement, aRowSpanAbove);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
   // Insert new cell after using the remaining span
   //  and always get the new cell so we can copy the background color;
   RefPtr<Element> newCell;
-  rv = InsertCell(cellElementAtInsertionPoint, aRowSpanBelow, actualColSpan,
+  rv = InsertCell(cellElementAtInsertionPoint,
+                  aRowSpanBelow, cellData.mEffectiveColSpan,
                   insertAfter, false, getter_AddRefs(newCell));
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
   if (!newCell) {
     return NS_OK;
   }
   if (aNewCell) {
@@ -2563,17 +2564,16 @@ HTMLEditor::JoinTableCells(bool aMergeNo
       for (int32_t actualColSpan2 = 0;
            colIndex < tableSize.mColumnCount;
            colIndex += std::max(actualColSpan2, 1)) {
         CellData cellData(*this, *table, rowIndex, colIndex, ignoredError);
         if (NS_WARN_IF(cellData.FailedOrNotFound())) {
           return NS_ERROR_FAILURE;
         }
 
-                   actualColSpan2 =          cellData.mEffectiveColSpan;
         bool       isSelected2 =             cellData.mIsSelected;
 
         if (isSelected2) {
           if (!cellFoundInRow) {
             // We've just found the first selected cell in this row
             firstColInRow = cellData.mCurrent.mColumn;
           }
           if (cellData.mCurrent.mRow > firstSelectedCell.mIndexes.mRow &&
@@ -2584,30 +2584,32 @@ HTMLEditor::JoinTableCells(bool aMergeNo
             // and keep previous lastColIndex
             //TODO: We could try to find the Maximum firstColInRow
             //      so our block can still extend down more rows?
             lastRowIndex = std::max(0, cellData.mCurrent.mRow - 1);
             lastRowIsSet = true;
             break;
           }
           // Save max selected column in this row, including extra colspan
-          lastColInRow = cellData.mCurrent.mColumn + actualColSpan2 - 1;
+          lastColInRow =
+            cellData.mCurrent.mColumn + cellData.mEffectiveColSpan - 1;
           cellFoundInRow = true;
         } else if (cellFoundInRow) {
           // No cell or not selected, but at least one cell in row was found
           if (cellData.mCurrent.mRow > firstSelectedCell.mIndexes.mRow + 1 &&
               cellData.mCurrent.mColumn <= lastColIndex) {
             // Cell is in a column less than current right border in
             //  the third or higher selected row, so stop block at the previous row
             lastRowIndex = std::max(0, cellData.mCurrent.mRow - 1);
             lastRowIsSet = true;
           }
           // We're done with this row
           break;
         }
+        actualColSpan2 = cellData.mEffectiveColSpan;
       } // End of column loop
 
       // Done with this row
       if (cellFoundInRow) {
         if (rowIndex == firstSelectedCell.mIndexes.mRow) {
           // First row always initializes the right boundary
           lastColIndex = lastColInRow;
         }
@@ -2641,48 +2643,48 @@ HTMLEditor::JoinTableCells(bool aMergeNo
       for (int32_t colIndex = 0, actualColSpan2 = 0;
            colIndex < tableSize.mColumnCount;
            colIndex += std::max(actualColSpan2, 1)) {
         CellData cellData(*this, *table, rowIndex, colIndex, ignoredError);
         if (NS_WARN_IF(cellData.FailedOrNotFound())) {
           return NS_ERROR_FAILURE;
         }
 
-                   actualColSpan2 =       cellData.mEffectiveColSpan;
         bool       isSelected2 =          cellData.mIsSelected;
 
         // If this is 0, we are past last cell in row, so exit the loop
-        if (!actualColSpan2) {
+        if (!cellData.mEffectiveColSpan) {
           break;
         }
 
         // Merge only selected cells (skip cell we're merging into, of course)
         if (isSelected2 && cellData.mElement != firstSelectedCell.mElement) {
           if (cellData.mCurrent.mRow >= firstSelectedCell.mIndexes.mRow &&
               cellData.mCurrent.mRow <= lastRowIndex &&
               cellData.mCurrent.mColumn >= firstSelectedCell.mIndexes.mColumn &&
               cellData.mCurrent.mColumn <= lastColIndex) {
             // We are within the join region
             // Problem: It is very tricky to delete cells as we merge,
             //  since that will upset the cellmap
             //  Instead, build a list of cells to delete and do it later
             NS_ASSERTION(!cellData.IsSpannedFromOtherRow(),
                          "JoinTableCells: StartRowIndex is in row above");
 
-            if (actualColSpan2 > 1) {
+            if (cellData.mEffectiveColSpan > 1) {
               //Check if cell "hangs" off the boundary because of colspan > 1
               //  Use split methods to chop off excess
               int32_t extraColSpan =
-                cellData.mFirst.mColumn + actualColSpan2 - (lastColIndex + 1);
+                cellData.mFirst.mColumn + cellData.mEffectiveColSpan -
+                  (lastColIndex + 1);
               if ( extraColSpan > 0) {
-                rv = SplitCellIntoColumns(table,
-                                          cellData.mFirst.mRow,
-                                          cellData.mFirst.mColumn,
-                                          actualColSpan2 - extraColSpan,
-                                          extraColSpan, nullptr);
+                rv = SplitCellIntoColumns(
+                       table,
+                       cellData.mFirst.mRow, cellData.mFirst.mColumn,
+                       cellData.mEffectiveColSpan - extraColSpan,
+                       extraColSpan, nullptr);
                 if (NS_WARN_IF(NS_FAILED(rv))) {
                   return rv;
                 }
               }
             }
 
             rv =
               MergeCells(firstSelectedCell.mElement, cellData.mElement, false);
@@ -2696,16 +2698,17 @@ HTMLEditor::JoinTableCells(bool aMergeNo
             // Cell is outside join region -- just merge the contents
             rv =
               MergeCells(firstSelectedCell.mElement, cellData.mElement, false);
             if (NS_WARN_IF(NS_FAILED(rv))) {
               return rv;
             }
           }
         }
+        actualColSpan2 = cellData.mEffectiveColSpan;
       }
     }
 
     // All cell contents are merged. Delete the empty cells we accumulated
     // Prevent rules testing until we're done
     AutoTopLevelEditSubActionNotifier maybeTopLevelEditSubAction(
                                         *this, EditSubAction::eDeleteNode,
                                         nsIEditor::eNext);
@@ -2759,29 +2762,28 @@ HTMLEditor::JoinTableCells(bool aMergeNo
     // cell.
     IgnoredErrorResult ignoredError;
     CellData leftCellData(*this, *table, startRowIndex, startColIndex,
                           ignoredError);
     if (NS_WARN_IF(leftCellData.FailedOrNotFound())) {
       return NS_ERROR_FAILURE;
     }
 
-    int32_t    actualColSpan =             leftCellData.mEffectiveColSpan;
     // bool    isSelected =                leftCellData.mIsSelected;
 
     // Get data for cell to the right.
-    CellData rightCellData(*this, *table,
-                           leftCellData.mFirst.mRow,
-                           leftCellData.mFirst.mColumn + actualColSpan,
-                           ignoredError);
+    CellData rightCellData(
+               *this, *table,
+               leftCellData.mFirst.mRow,
+               leftCellData.mFirst.mColumn + leftCellData.mEffectiveColSpan,
+               ignoredError);
     if (NS_WARN_IF(rightCellData.FailedOrNotFound())) {
       return NS_ERROR_FAILURE;
     }
 
-    int32_t    actualColSpan2 =       rightCellData.mEffectiveColSpan;
     // bool    isSelected2 =          rightCellData.mIsSelected;
 
     // XXX So, this does not assume that CellData returns error when just not
     //     found.  We need to fix this later.
     if (!rightCellData.mElement) {
       return NS_OK; // Don't fail if there's no cell
     }
 
@@ -2832,17 +2834,19 @@ HTMLEditor::JoinTableCells(bool aMergeNo
       // Reduce rowspan to give room where target cell will extend its colspan
       rv = SetRowSpan(rightCellData.mElement, spanAboveMergedCell);
       if (NS_WARN_IF(NS_FAILED(rv))) {
         return rv;
       }
     }
 
     // Reset target cell's colspan to encompass cell to the right
-    rv = SetColSpan(leftCellData.mElement, actualColSpan+actualColSpan2);
+    rv = SetColSpan(leftCellData.mElement,
+                    leftCellData.mEffectiveColSpan +
+                      rightCellData.mEffectiveColSpan);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
   }
   return NS_OK;
 }
 
 nsresult
@@ -2938,59 +2942,59 @@ HTMLEditor::FixBadRowSpan(Element* aTabl
     // CellData passes if cell is missing from cellmap
     // XXX If <table> has large rowspan value or colspan value than actual
     //     cells, we may hit error.  So, this method is always failed to
     //     "fix" the rowspan...
     if (NS_WARN_IF(cellData.FailedOrNotFound())) {
       return NS_ERROR_FAILURE;
     }
 
-               actualColSpan =       cellData.mEffectiveColSpan;
     // bool    isSelected =          cellData.mIsSelected;
 
     // XXX So, this does not assume that CellData returns error when just not
     //     found.  We need to fix this later.
     if (!cellData.mElement) {
       break;
     }
 
     if (cellData.mRowSpan > 0 &&
         !cellData.IsSpannedFromOtherRow() &&
         (cellData.mRowSpan < minRowSpan || minRowSpan == -1)) {
       minRowSpan = cellData.mRowSpan;
     }
-    NS_ASSERTION((actualColSpan > 0),"ActualColSpan = 0 in FixBadRowSpan");
+    MOZ_ASSERT(cellData.mEffectiveColSpan > 0);
+    actualColSpan = cellData.mEffectiveColSpan;
   }
   if (minRowSpan > 1) {
     // The amount to reduce everyone's rowspan
     // so at least one cell has rowspan = 1
     int32_t rowsReduced = minRowSpan - 1;
     for (int32_t colIndex = 0, actualColSpan = 0;
          colIndex < tableSize.mColumnCount;
          colIndex += std::max(actualColSpan, 1)) {
       CellData cellData(*this, *aTable, aRowIndex, colIndex, ignoredError);
       if (NS_WARN_IF(cellData.FailedOrNotFound())) {
         return NS_ERROR_FAILURE;
       }
 
-                 actualColSpan =       cellData.mEffectiveColSpan;
       // bool    isSelected =          cellData.mIsSelected;
 
       // Fixup rowspans only for cells starting in current row
       // XXX So, this does not assume that CellData returns error when just
       //     not found a cell.  Fix this later.
       if (cellData.mElement && cellData.mRowSpan > 0 &&
           !cellData.IsSpannedFromOtherRowOrColumn()) {
         nsresult rv =
           SetRowSpan(cellData.mElement, cellData.mRowSpan - rowsReduced);
         if (NS_WARN_IF(NS_FAILED(rv))) {
           return rv;
         }
       }
-      NS_ASSERTION((actualColSpan > 0),"ActualColSpan = 0 in FixBadRowSpan");
+      MOZ_ASSERT(cellData.mEffectiveColSpan > 0);
+      actualColSpan = cellData.mEffectiveColSpan;
     }
   }
   tableSize.Update(*this, *aTable, error);
   if (NS_WARN_IF(error.Failed())) {
     return error.StealNSResult();
   }
   aNewRowCount = tableSize.mRowCount;
   return NS_OK;
@@ -3021,17 +3025,16 @@ HTMLEditor::FixBadColSpan(Element* aTabl
     // CellData passes if cell is missing from cellmap
     // XXX If <table> has large rowspan value or colspan value than actual
     //     cells, we may hit error.  So, this method is always failed to
     //     "fix" the colspan...
     if (NS_WARN_IF(cellData.FailedOrNotFound())) {
       return NS_ERROR_FAILURE;
     }
 
-    // int32_t actualColSpan =       cellData.mEffectiveColSpan;
     // bool    isSelected =          cellData.mIsSelected;
 
     // XXX So, this does not assume that CellData returns error when just
     //     not found a cell.  Fix this later.
     if (!cellData.mElement) {
       break;
     }
     if (cellData.mColSpan > 0 &&
@@ -3049,17 +3052,16 @@ HTMLEditor::FixBadColSpan(Element* aTabl
     for (int32_t rowIndex = 0, actualRowSpan = 0;
          rowIndex < tableSize.mRowCount;
          rowIndex += std::max(actualRowSpan, 1)) {
       CellData cellData(*this, *aTable, rowIndex, aColIndex, ignoredError);
       if (NS_WARN_IF(cellData.FailedOrNotFound())) {
         return NS_ERROR_FAILURE;
       }
 
-      // int32_t actualColSpan =       cellData.mEffectiveColSpan;
       // bool    isSelected =          cellData.mIsSelected;
 
       // Fixup colspans only for cells starting in current column
       // XXX So, this does not assume that CellData returns error when just
       //     not found a cell.  Fix this later.
       if (cellData.mElement && cellData.mColSpan > 0 &&
           !cellData.IsSpannedFromOtherRowOrColumn()) {
         nsresult rv =
@@ -3160,17 +3162,16 @@ HTMLEditor::NormalizeTable(Selection& aS
       // NOTE: This is a *real* failure.
       // CellData passes if cell is missing from cellmap
       // XXX So, this method assumes that CellData won't return error when
       //     just not found.  Fix this later.
       if (NS_WARN_IF(cellData.FailedOrNotFound())) {
         return NS_ERROR_FAILURE;
       }
 
-      // int32_t actualColSpan =              cellData.mEffectiveColSpan;
       // bool    isSelected =                 cellData.mIsSelected;
 
       if (cellData.mElement) {
         // Save the last cell found in the same row we are scanning
         if (!cellData.IsSpannedFromOtherRow()) {
           previousCellElementInRow = std::move(cellData.mElement);
         }
         continue;
@@ -3310,26 +3311,25 @@ HTMLEditor::GetNumberOfCellsInRow(Elemen
     // Failure means that there is no more cell in the row.  In this case,
     // we shouldn't return error since we just reach the end of the row.
     // XXX So, this method assumes that CellData won't return error when
     //     just not found.  Fix this later.
     if (cellData.FailedOrNotFound()) {
       break;
     }
 
-    int32_t    actualColSpan =              cellData.mEffectiveColSpan;
     // bool    isSelected =                 cellData.mIsSelected;
 
     if (cellData.mElement) {
       // Only count cells that start in row we are working with
       if (!cellData.IsSpannedFromOtherRow()) {
         numberOfCells++;
       }
       // Next possible location for a cell
-      columnIndex += actualColSpan;
+      columnIndex += cellData.mEffectiveColSpan;
     } else {
       columnIndex++;
     }
   }
   return numberOfCells;
 }
 
 NS_IMETHODIMP
@@ -4292,17 +4292,16 @@ HTMLEditor::AllCellsInRowSelected(Elemen
   for (int32_t col = 0, actualColSpan = 0;
        col < aNumberOfColumns;
        col += std::max(actualColSpan, 1)) {
     CellData cellData(*this, *aTable, aRowIndex, col, ignoredError);
     if (NS_WARN_IF(cellData.FailedOrNotFound())) {
       return false;
     }
 
-               actualColSpan =       cellData.mEffectiveColSpan;
     bool       isSelected =          cellData.mIsSelected;
 
     // If no cell, we may have a "ragged" right edge, so return TRUE only if
     // we already found a cell in the row.
     // XXX So, this does not assume that CellData returns error when just
     //     not found a cell.  Fix this later.
     if (NS_WARN_IF(!cellData.mElement)) {
       return cellData.mCurrent.mColumn > 0;
@@ -4310,17 +4309,18 @@ HTMLEditor::AllCellsInRowSelected(Elemen
 
     // Return as soon as a non-selected cell is found.
     // XXX Odd, this is testing if each cell element is selected.  Why do
     //     we need to warn if it's false??
     if (NS_WARN_IF(!isSelected)) {
       return false;
     }
 
-    MOZ_ASSERT(actualColSpan > 0);
+    MOZ_ASSERT(cellData.mEffectiveColSpan > 0);
+    actualColSpan = cellData.mEffectiveColSpan;
   }
   return true;
 }
 
 bool
 HTMLEditor::AllCellsInColumnSelected(Element* aTable,
                                      int32_t aColIndex,
                                      int32_t aNumberOfRows)
@@ -4333,17 +4333,16 @@ HTMLEditor::AllCellsInColumnSelected(Ele
   for (int32_t row = 0, actualRowSpan = 0;
        row < aNumberOfRows;
        row += std::max(actualRowSpan, 1)) {
     CellData cellData(*this, *aTable, row, aColIndex, ignoredError);
     if (NS_WARN_IF(cellData.FailedOrNotFound())) {
       return false;
     }
 
-    // int32_t actualColSpan =       cellData.mEffectiveColSpan;
     bool       isSelected =          cellData.mIsSelected;
 
     // If no cell, we must have a "ragged" right edge on the last column so
     // return TRUE only if we already found a cell in the row.
     // XXX So, this does not assume that CellData returns error when just
     //     not found a cell.  Fix this later.
     if (NS_WARN_IF(!cellData.mElement)) {
       return cellData.mCurrent.mRow > 0;