Bug 1484126 - part 1: Create CellData struct which implements nsITableEditor::GetCellDataAt() r=m_kato
authorMasayuki Nakano <masayuki@d-toybox.com>
Fri, 12 Oct 2018 13:40:25 +0000
changeset 499826 bf74fc63e8163598d8978e014ee28bdab9bb4455
parent 499825 d7f0492bf2620cd6c18b7ab57726677cb5827f10
child 499827 d3609fcd3c88b1b424ccd09cff8c8279853cba2b
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 1: Create CellData struct which implements nsITableEditor::GetCellDataAt() r=m_kato nsITableEditor::GetCellDataAt() is an XPCOM method but used internally a lot. Additionally, it scatters a lot of variables (including unused) since it takes a lot of out arguments to return. Therefore, this should be implemented as struct and users should refer each member as result. This does not replaces the callers yet since it's too risky if the caller is not tested by automated test. Following patches will replace the method call and each variable step by step. Differential Revision: https://phabricator.services.mozilla.com/D8338
editor/libeditor/HTMLEditor.h
editor/libeditor/HTMLTableEditor.cpp
editor/libeditor/tests/test_nsITableEditor_getCellDataAt.html
editor/nsITableEditor.idl
--- a/editor/libeditor/HTMLEditor.h
+++ b/editor/libeditor/HTMLEditor.h
@@ -1120,16 +1120,17 @@ protected: // Shouldn't be used by frien
    *                            there is no next <tr> element, this returns
    *                            nullptr but does not return error.
    */
   Element*
   GetNextTableRowElement(Element& aTableRowElement,
                          ErrorResult& aRv) const;
 
   struct CellAndIndexes;
+  struct CellData;
 
   /**
    * CellIndexes store both row index and column index of a table cell.
    */
   struct MOZ_STACK_CLASS CellIndexes final
   {
     int32_t mRow;
     int32_t mColumn;
@@ -1179,24 +1180,34 @@ protected: // Shouldn't be used by frien
      * Update mRowIndex and mColumnIndex with indexes of cell element which
      * contains anchor of Selection.
      *
      * @param                   See above.
      */
     void Update(HTMLEditor& aHTMLEditor, Selection& aSelection,
                 ErrorResult& aRv);
 
+    bool operator==(const CellIndexes& aOther) const
+    {
+      return mRow == aOther.mRow && mColumn == aOther.mColumn;
+    }
+    bool operator!=(const CellIndexes& aOther) const
+    {
+      return mRow != aOther.mRow || mColumn != aOther.mColumn;
+    }
+
   private:
     CellIndexes()
       : mRow(-1)
       , mColumn(-1)
     {
     }
 
     friend struct CellAndIndexes;
+    friend struct CellData;
   };
 
   struct MOZ_STACK_CLASS CellAndIndexes final
   {
     RefPtr<Element> mElement;
     CellIndexes mIndexes;
 
     /**
@@ -1216,16 +1227,194 @@ protected: // Shouldn't be used by frien
      * first range of the Selection.  Note that even if the first range is
      * in the cell element, this does not treat it as the cell element is
      * selected.
      */
     void Update(HTMLEditor& aHTMLEditor, Selection& aSelection,
                 ErrorResult& aRv);
   };
 
+  struct MOZ_STACK_CLASS CellData final
+  {
+    RefPtr<Element> mElement;
+    // Current indexes which this is initialized with.
+    CellIndexes mCurrent;
+    // First column/row indexes of the cell.  When current position is spanned
+    // from other column/row, this value becomes different from mCurrent.
+    CellIndexes mFirst;
+    // Computed rowspan/colspan values which are specified to the cell.
+    // Note that if the cell has larger rowspan/colspan value than actual
+    // table size, these values are the larger values.
+    int32_t mRowSpan;
+    int32_t mColSpan;
+    // Effective rowspan/colspan value at the index.  For example, if first
+    // cell element in first row has rowspan="3", then, if this is initialized
+    // with 0-0 indexes, effective rowspan is 3.  However, if this is
+    // initialized with 1-0 indexes, effective rowspan is 2.
+    int32_t mEffectiveRowSpan;
+    int32_t mEffectiveColSpan;
+    // mIsSelected is set to true if mElement itself or its parent <tr> or
+    // <table> is selected.  Otherwise, e.g., the cell just contains selection
+    // range, this is set to false.
+    bool mIsSelected;
+
+    /**
+     * Those constructors initializes the members with a <table> element and
+     * both row and column index to specify a cell element.
+     */
+    CellData(HTMLEditor& aHTMLEditor,
+             Element& aTableElement,
+             int32_t aRowIndex,
+             int32_t aColumnIndex,
+             ErrorResult& aRv)
+    {
+      Update(aHTMLEditor, aTableElement, aRowIndex, aColumnIndex, aRv);
+    }
+
+    CellData(HTMLEditor& aHTMLEditor,
+             Element& aTableElement,
+             const CellIndexes& aIndexes,
+             ErrorResult& aRv)
+    {
+      Update(aHTMLEditor, aTableElement, aIndexes, aRv);
+    }
+
+    /**
+     * Those Update() methods updates the members with a <table> element and
+     * both row and column index to specify a cell element.
+     */
+    void Update(HTMLEditor& aHTMLEditor,
+                Element& aTableElement,
+                int32_t aRowIndex,
+                int32_t aColumnIndex,
+                ErrorResult& aRv)
+    {
+      mCurrent.mRow = aRowIndex;
+      mCurrent.mColumn = aColumnIndex;
+      Update(aHTMLEditor, aTableElement, aRv);
+    }
+
+    void Update(HTMLEditor& aHTMLEditor,
+                Element& aTableElement,
+                const CellIndexes& aIndexes,
+                ErrorResult& aRv)
+    {
+      mCurrent = aIndexes;
+      Update(aHTMLEditor, aTableElement, aRv);
+    }
+
+    void Update(HTMLEditor& aHTMLEditor,
+                Element& aTableElement,
+                ErrorResult& aRv);
+
+    /**
+     * FailedOrNotFound() returns true if this failed to initialize/update
+     * or succeeded but found no cell element.
+     */
+    bool FailedOrNotFound() const { return !mElement; }
+
+    /**
+     * IsSpannedFromOtherRowOrColumn(), IsSpannedFromOtherColumn and
+     * IsSpannedFromOtherRow() return true if there is no cell element
+     * at the index because of spanning from other row and/or column.
+     */
+    bool IsSpannedFromOtherRowOrColumn() const
+    {
+      return mElement && mCurrent != mFirst;
+    }
+    bool IsSpannedFromOtherColumn() const
+    {
+      return mElement && mCurrent.mColumn != mFirst.mColumn;
+    }
+    bool IsSpannedFromOtherRow() const
+    {
+      return mElement && mCurrent.mRow != mFirst.mRow;
+    }
+
+    /**
+     * NextColumnIndex() and NextRowIndex() return column/row index of
+     * next cell.  Note that this does not check whether there is next
+     * cell or not actually.
+     */
+    int32_t NextColumnIndex() const
+    {
+      if (NS_WARN_IF(FailedOrNotFound())) {
+        return -1;
+      }
+      return mCurrent.mColumn + mEffectiveColSpan;
+    }
+    int32_t NextRowIndex() const
+    {
+      if (NS_WARN_IF(FailedOrNotFound())) {
+        return -1;
+      }
+      return mCurrent.mRow + mEffectiveRowSpan;
+    }
+
+    /**
+     * LastColumnIndex() and LastRowIndex() return column/row index of
+     * column/row which is spanned by the cell.
+     */
+    int32_t LastColumnIndex() const
+    {
+      if (NS_WARN_IF(FailedOrNotFound())) {
+        return -1;
+      }
+      return NextColumnIndex() - 1;
+    }
+    int32_t LastRowIndex() const
+    {
+      if (NS_WARN_IF(FailedOrNotFound())) {
+        return -1;
+      }
+      return NextRowIndex() - 1;
+    }
+
+    /**
+     * NumberOfPrecedingColmuns() and NumberOfPrecedingRows() return number of
+     * preceding columns/rows if current index is spanned from other column/row.
+     * Otherwise, i.e., current point is not spanned form other column/row,
+     * returns 0.
+     */
+    int32_t NumberOfPrecedingColmuns() const
+    {
+      if (NS_WARN_IF(FailedOrNotFound())) {
+        return -1;
+      }
+      return mCurrent.mColumn - mFirst.mColumn;
+    }
+    int32_t NumberOfPrecedingRows() const
+    {
+      if (NS_WARN_IF(FailedOrNotFound())) {
+        return -1;
+      }
+      return mCurrent.mRow - mFirst.mRow;
+    }
+
+    /**
+     * NumberOfFollowingColumns() and NumberOfFollowingRows() return
+     * number of remaining columns/rows if the cell spans to other
+     * column/row.
+     */
+    int32_t NumberOfFollowingColumns() const
+    {
+      if (NS_WARN_IF(FailedOrNotFound())) {
+        return -1;
+      }
+      return mEffectiveColSpan - 1;
+    }
+    int32_t NumberOfFollowingRows() const
+    {
+      if (NS_WARN_IF(FailedOrNotFound())) {
+        return -1;
+      }
+      return mEffectiveRowSpan - 1;
+    }
+  };
+
   /**
    * TableSize stores and computes number of rows and columns of a <table>
    * element.
    */
   struct MOZ_STACK_CLASS TableSize final
   {
     int32_t mRowCount;
     int32_t mColumnCount;
--- a/editor/libeditor/HTMLTableEditor.cpp
+++ b/editor/libeditor/HTMLTableEditor.cpp
@@ -3353,88 +3353,125 @@ HTMLEditor::TableSize::Update(HTMLEditor
     aRv.Throw(NS_ERROR_FAILURE);
     return;
   }
   mRowCount = tableFrame->GetRowCount();
   mColumnCount = tableFrame->GetColCount();
 }
 
 NS_IMETHODIMP
-HTMLEditor::GetCellDataAt(Element* aTable,
+HTMLEditor::GetCellDataAt(Element* aTableElement,
                           int32_t aRowIndex,
-                          int32_t aColIndex,
-                          Element** aCell,
+                          int32_t aColumnIndex,
+                          Element** aCellElement,
                           int32_t* aStartRowIndex,
-                          int32_t* aStartColIndex,
+                          int32_t* aStartColumnIndex,
                           int32_t* aRowSpan,
                           int32_t* aColSpan,
-                          int32_t* aActualRowSpan,
-                          int32_t* aActualColSpan,
+                          int32_t* aEffectiveRowSpan,
+                          int32_t* aEffectiveColSpan,
                           bool* aIsSelected)
 {
-  NS_ENSURE_ARG_POINTER(aStartRowIndex);
-  NS_ENSURE_ARG_POINTER(aStartColIndex);
-  NS_ENSURE_ARG_POINTER(aRowSpan);
-  NS_ENSURE_ARG_POINTER(aColSpan);
-  NS_ENSURE_ARG_POINTER(aActualRowSpan);
-  NS_ENSURE_ARG_POINTER(aActualColSpan);
-  NS_ENSURE_ARG_POINTER(aIsSelected);
-  NS_ENSURE_TRUE(aCell, NS_ERROR_NULL_POINTER);
+  if (NS_WARN_IF(!aCellElement) ||
+      NS_WARN_IF(!aStartRowIndex) || NS_WARN_IF(!aStartColumnIndex) ||
+      NS_WARN_IF(!aRowSpan) || NS_WARN_IF(!aColSpan) ||
+      NS_WARN_IF(!aEffectiveRowSpan) || NS_WARN_IF(!aEffectiveColSpan) ||
+      NS_WARN_IF(!aIsSelected)) {
+    return NS_ERROR_INVALID_ARG;
+  }
 
   *aStartRowIndex = 0;
-  *aStartColIndex = 0;
+  *aStartColumnIndex = 0;
   *aRowSpan = 0;
   *aColSpan = 0;
-  *aActualRowSpan = 0;
-  *aActualColSpan = 0;
+  *aEffectiveRowSpan = 0;
+  *aEffectiveColSpan = 0;
   *aIsSelected = false;
-
-  *aCell = nullptr;
-
-  // needs to live while we use aTable
-  // XXX Really? Looks like it's safe to use raw pointer here.
-  //     However, layout code change won't be handled by editor developers
-  //     so that it must be safe to keep using RefPtr here.
-  RefPtr<Element> table;
-  if (!aTable) {
+  *aCellElement = nullptr;
+
+  // Let's keep the table element with strong pointer since editor developers
+  // may not handle layout code of <table>, however, this method depends on
+  // them.
+  RefPtr<Element> table = aTableElement;
+  if (!table) {
     RefPtr<Selection> selection = GetSelection();
     if (NS_WARN_IF(!selection)) {
       return NS_ERROR_FAILURE;
     }
     // Get the selected table or the table enclosing the selection anchor.
     table =
       GetElementOrParentByTagNameAtSelection(*selection, *nsGkAtoms::table);
     if (NS_WARN_IF(!table)) {
       return NS_ERROR_FAILURE;
     }
-    aTable = table;
-  }
-
-  nsTableWrapperFrame* tableFrame = HTMLEditor::GetTableFrame(aTable);
-  NS_ENSURE_TRUE(tableFrame, NS_ERROR_FAILURE);
-
-  nsTableCellFrame* cellFrame =
-    tableFrame->GetCellFrameAt(aRowIndex, aColIndex);
-  if (NS_WARN_IF(!cellFrame)) {
+  }
+
+  IgnoredErrorResult ignoredError;
+  CellData cellData(*this, *table, aRowIndex, aColumnIndex, ignoredError);
+  if (NS_WARN_IF(cellData.FailedOrNotFound())) {
     return NS_ERROR_FAILURE;
   }
-
-  *aIsSelected = cellFrame->IsSelected();
-  *aStartRowIndex = cellFrame->RowIndex();
-  *aStartColIndex = cellFrame->ColIndex();
-  *aRowSpan = cellFrame->GetRowSpan();
-  *aColSpan = cellFrame->GetColSpan();
-  *aActualRowSpan = tableFrame->GetEffectiveRowSpanAt(aRowIndex, aColIndex);
-  *aActualColSpan = tableFrame->GetEffectiveColSpanAt(aRowIndex, aColIndex);
-  RefPtr<Element> domCell = cellFrame->GetContent()->AsElement();
-  domCell.forget(aCell);
-
+  cellData.mElement.forget(aCellElement);
+  *aIsSelected = cellData.mIsSelected;
+  *aStartRowIndex = cellData.mFirst.mRow;
+  *aStartColumnIndex = cellData.mFirst.mColumn;
+  *aRowSpan = cellData.mRowSpan;
+  *aColSpan = cellData.mColSpan;
+  *aEffectiveRowSpan = cellData.mEffectiveRowSpan;
+  *aEffectiveColSpan = cellData.mEffectiveColSpan;
   return NS_OK;
 }
 
+void
+HTMLEditor::CellData::Update(HTMLEditor& aHTMLEditor,
+                             Element& aTableElement,
+                             ErrorResult& aRv)
+{
+  MOZ_ASSERT(!aRv.Failed());
+
+  mElement = nullptr;
+  mIsSelected = false;
+  mFirst.mRow = -1;
+  mFirst.mColumn = -1;
+  mRowSpan = -1;
+  mColSpan = -1;
+  mEffectiveRowSpan = -1;
+  mEffectiveColSpan = -1;
+
+  nsTableWrapperFrame* tableFrame = HTMLEditor::GetTableFrame(&aTableElement);
+  if (NS_WARN_IF(!tableFrame)) {
+    aRv.Throw(NS_ERROR_FAILURE);
+    return;
+  }
+
+  // If there is no cell at the indexes.  Don't return error.
+  // XXX If we have pending layout and that causes the cell frame hasn't been
+  //     created, we should return error, but how can we do it?
+  nsTableCellFrame* cellFrame =
+    tableFrame->GetCellFrameAt(mCurrent.mRow, mCurrent.mColumn);
+  if (!cellFrame) {
+    return;
+  }
+
+  mElement = cellFrame->GetContent()->AsElement();
+  if (NS_WARN_IF(!mElement)) {
+    aRv.Throw(NS_ERROR_FAILURE);
+    return;
+  }
+  mIsSelected = cellFrame->IsSelected();
+  mFirst.mRow = cellFrame->RowIndex();
+  mFirst.mColumn = cellFrame->ColIndex();
+  mRowSpan = cellFrame->GetRowSpan();
+  mColSpan = cellFrame->GetColSpan();
+  mEffectiveRowSpan =
+    tableFrame->GetEffectiveRowSpanAt(mCurrent.mRow, mCurrent.mColumn);
+  mEffectiveColSpan =
+    tableFrame->GetEffectiveColSpanAt(mCurrent.mRow, mCurrent.mColumn);
+}
+
 NS_IMETHODIMP
 HTMLEditor::GetCellAt(Element* aTableElement,
                       int32_t aRowIndex,
                       int32_t aColumnIndex,
                       Element** aCellElement)
 {
   if (NS_WARN_IF(!aCellElement)) {
     return NS_ERROR_INVALID_ARG;
--- a/editor/libeditor/tests/test_nsITableEditor_getCellDataAt.html
+++ b/editor/libeditor/tests/test_nsITableEditor_getCellDataAt.html
@@ -17,297 +17,297 @@
 SimpleTest.waitForExplicitFinish();
 SimpleTest.waitForFocus(function() {
   let editor = document.getElementById("content");
   let selection = document.getSelection();
 
   let cellElementWrapper;
   let startRowIndexWrapper, startColumnIndexWrapper;
   let rowspanWrapper, colspanWrapper;
-  let actualRowspanWrapper, actualColspanWrapper;
+  let effectiveRowspanWrapper, effectiveColspanWrapper;
   let isSelectedWrapper;
 
   function reset() {
     cellElementWrapper = {};
     startRowIndexWrapper = {};
     startColumnIndexWrapper = {};
     rowspanWrapper = {};
     colspanWrapper = {};
-    actualRowspanWrapper = {};
-    actualColspanWrapper = {};
+    effectiveRowspanWrapper = {};
+    effectiveColspanWrapper = {};
     isSelectedWrapper = {};
   }
 
   editor.focus();
   selection.collapse(editor.firstChild, 0);
   try {
     getTableEditor().getCellDataAt(null, 0, 0,
                                    cellElementWrapper,
                                    startRowIndexWrapper, startColumnIndexWrapper,
                                    rowspanWrapper, colspanWrapper,
-                                   actualRowspanWrapper, actualColspanWrapper,
+                                   effectiveRowspanWrapper, effectiveColspanWrapper,
                                    isSelectedWrapper);
     ok(false, "getTableEditor().getCellDataAt(null, 0, 0) should throw exception when selection is outside of any <table>s");
   } catch (e) {
     ok(true, "getTableEditor().getCellDataAt(null, 0, 0) should throw exception when selection is outside of any <table>s");
   }
 
   selection.removeAllRanges();
   try {
     getTableEditor().getCellDataAt(null, 0, 0,
                                    cellElementWrapper,
                                    startRowIndexWrapper, startColumnIndexWrapper,
                                    rowspanWrapper, colspanWrapper,
-                                   actualRowspanWrapper, actualColspanWrapper,
+                                   effectiveRowspanWrapper, effectiveColspanWrapper,
                                    isSelectedWrapper);
     ok(false, "getTableEditor().getCellDataAt(null, 0, 0) should throw exception when selection has no ranges");
   } catch (e) {
     ok(true, "getTableEditor().getCellDataAt(null, 0, 0) should throw exception when selection has no ranges");
   }
 
   // Collapse in text node in the cell element.
   selection.collapse(editor.firstChild.nextSibling.firstChild.firstChild.firstChild.firstChild, 0);
   reset();
   getTableEditor().getCellDataAt(null, 0, 0,
                                  cellElementWrapper,
                                  startRowIndexWrapper, startColumnIndexWrapper,
                                  rowspanWrapper, colspanWrapper,
-                                 actualRowspanWrapper, actualColspanWrapper,
+                                 effectiveRowspanWrapper, effectiveColspanWrapper,
                                  isSelectedWrapper);
   is(cellElementWrapper.value, editor.firstChild.nextSibling.firstChild.firstChild.firstChild,
      "getTableEditor().getCellDataAt(null, 0, 0) should return the <td> element when selection is in it");
   is(startRowIndexWrapper.value, 0,
      "getTableEditor().getCellDataAt(null, 0, 0) should return 0 for startRowIndex when selection is in the cell");
   is(startColumnIndexWrapper.value, 0,
      "getTableEditor().getCellDataAt(null, 0, 0) should return 0 for startColumnIndex when selection is in the cell");
   is(rowspanWrapper.value, 1,
      "getTableEditor().getCellDataAt(null, 0, 0) should return 1 for rowspan when selection is in the cell");
   is(colspanWrapper.value, 1,
      "getTableEditor().getCellDataAt(null, 0, 0) should return 1 for colspan when selection is in the cell");
-  is(actualRowspanWrapper.value, 1,
-     "getTableEditor().getCellDataAt(null, 0, 0) should return 1 for actualRowspan when selection is in the cell");
-  is(actualColspanWrapper.value, 1,
-     "getTableEditor().getCellDataAt(null, 0, 0) should return 1 for actualColspan when selection is in the cell");
+  is(effectiveRowspanWrapper.value, 1,
+     "getTableEditor().getCellDataAt(null, 0, 0) should return 1 for effectiveRowspan when selection is in the cell");
+  is(effectiveColspanWrapper.value, 1,
+     "getTableEditor().getCellDataAt(null, 0, 0) should return 1 for effectiveColspan when selection is in the cell");
   is(isSelectedWrapper.value, false,
      "getTableEditor().getCellDataAt(null, 0, 0) should return false for isSelected when selection is in the cell");
 
   // Select the cell
   selection.setBaseAndExtent(editor.firstChild.nextSibling.firstChild.firstChild, 0,
                              editor.firstChild.nextSibling.firstChild.firstChild, 1);
   reset();
   getTableEditor().getCellDataAt(null, 0, 0,
                                  cellElementWrapper,
                                  startRowIndexWrapper, startColumnIndexWrapper,
                                  rowspanWrapper, colspanWrapper,
-                                 actualRowspanWrapper, actualColspanWrapper,
+                                 effectiveRowspanWrapper, effectiveColspanWrapper,
                                  isSelectedWrapper);
   is(cellElementWrapper.value, editor.firstChild.nextSibling.firstChild.firstChild.firstChild,
      "getTableEditor().getCellDataAt(null, 0, 0) should return the <td> element when it's selected");
   is(startRowIndexWrapper.value, 0,
      "getTableEditor().getCellDataAt(null, 0, 0) should return 0 for startRowIndex when the cell is selected");
   is(startColumnIndexWrapper.value, 0,
      "getTableEditor().getCellDataAt(null, 0, 0) should return 0 for startColumnIndex when the cell is selected");
   is(rowspanWrapper.value, 1,
      "getTableEditor().getCellDataAt(null, 0, 0) should return 1 for rowspan when the cell is selected");
   is(colspanWrapper.value, 1,
      "getTableEditor().getCellDataAt(null, 0, 0) should return 1 for colspan when the cell is selected");
-  is(actualRowspanWrapper.value, 1,
-     "getTableEditor().getCellDataAt(null, 0, 0) should return 1 for actualRowspan when the cell is selected");
-  is(actualColspanWrapper.value, 1,
-     "getTableEditor().getCellDataAt(null, 0, 0) should return 1 for actualColspan when the cell is selected");
+  is(effectiveRowspanWrapper.value, 1,
+     "getTableEditor().getCellDataAt(null, 0, 0) should return 1 for effectiveRowspan when the cell is selected");
+  is(effectiveColspanWrapper.value, 1,
+     "getTableEditor().getCellDataAt(null, 0, 0) should return 1 for effectiveColspan when the cell is selected");
   is(isSelectedWrapper.value, true,
      "getTableEditor().getCellDataAt(null, 0, 0) should return true for isSelected when the cell is selected");
 
   // Select the <tr>
   selection.setBaseAndExtent(editor.firstChild.nextSibling.firstChild, 0,
                              editor.firstChild.nextSibling.firstChild, 1);
   reset();
   getTableEditor().getCellDataAt(null, 0, 0,
                                  cellElementWrapper,
                                  startRowIndexWrapper, startColumnIndexWrapper,
                                  rowspanWrapper, colspanWrapper,
-                                 actualRowspanWrapper, actualColspanWrapper,
+                                 effectiveRowspanWrapper, effectiveColspanWrapper,
                                  isSelectedWrapper);
   is(cellElementWrapper.value, editor.firstChild.nextSibling.firstChild.firstChild.firstChild,
      "getTableEditor().getCellDataAt(null, 0, 0) should return the <td> element when the <tr> is selected");
   is(startRowIndexWrapper.value, 0,
      "getTableEditor().getCellDataAt(null, 0, 0) should return 0 for startRowIndex when the <tr> is selected");
   is(startColumnIndexWrapper.value, 0,
      "getTableEditor().getCellDataAt(null, 0, 0) should return 0 for startColumnIndex when the <tr> is selected");
   is(rowspanWrapper.value, 1,
      "getTableEditor().getCellDataAt(null, 0, 0) should return 1 for rowspan when the <tr> is selected");
   is(colspanWrapper.value, 1,
      "getTableEditor().getCellDataAt(null, 0, 0) should return 1 for colspan when the <tr> is selected");
-  is(actualRowspanWrapper.value, 1,
-     "getTableEditor().getCellDataAt(null, 0, 0) should return 1 for actualRowspan when the <tr> is selected");
-  is(actualColspanWrapper.value, 1,
-     "getTableEditor().getCellDataAt(null, 0, 0) should return 1 for actualColspan when the <tr> is selected");
+  is(effectiveRowspanWrapper.value, 1,
+     "getTableEditor().getCellDataAt(null, 0, 0) should return 1 for effectiveRowspan when the <tr> is selected");
+  is(effectiveColspanWrapper.value, 1,
+     "getTableEditor().getCellDataAt(null, 0, 0) should return 1 for effectiveColspan when the <tr> is selected");
   is(isSelectedWrapper.value, true,
      "getTableEditor().getCellDataAt(null, 0, 0) should return true for isSelected when the <tr> is selected");
 
   // Select the <table>
   selection.setBaseAndExtent(editor, 1, editor, 2);
   reset();
   getTableEditor().getCellDataAt(null, 0, 0,
                                  cellElementWrapper,
                                  startRowIndexWrapper, startColumnIndexWrapper,
                                  rowspanWrapper, colspanWrapper,
-                                 actualRowspanWrapper, actualColspanWrapper,
+                                 effectiveRowspanWrapper, effectiveColspanWrapper,
                                  isSelectedWrapper);
   is(cellElementWrapper.value, editor.firstChild.nextSibling.firstChild.firstChild.firstChild,
      "getTableEditor().getCellDataAt(null, 0, 0) should return the <td> element when the <table> is selected");
   is(startRowIndexWrapper.value, 0,
      "getTableEditor().getCellDataAt(null, 0, 0) should return 0 for startRowIndex when the <table> is selected");
   is(startColumnIndexWrapper.value, 0,
      "getTableEditor().getCellDataAt(null, 0, 0) should return 0 for startColumnIndex when the <table> is selected");
   is(rowspanWrapper.value, 1,
      "getTableEditor().getCellDataAt(null, 0, 0) should return 1 for rowspan when the <table> is selected");
   is(colspanWrapper.value, 1,
      "getTableEditor().getCellDataAt(null, 0, 0) should return 1 for colspan when the <table> is selected");
-  is(actualRowspanWrapper.value, 1,
-     "getTableEditor().getCellDataAt(null, 0, 0) should return 1 for actualRowspan when the <table> is selected");
-  is(actualColspanWrapper.value, 1,
-     "getTableEditor().getCellDataAt(null, 0, 0) should return 1 for actualColspan when the <table> is selected");
+  is(effectiveRowspanWrapper.value, 1,
+     "getTableEditor().getCellDataAt(null, 0, 0) should return 1 for effectiveRowspan when the <table> is selected");
+  is(effectiveColspanWrapper.value, 1,
+     "getTableEditor().getCellDataAt(null, 0, 0) should return 1 for effectiveColspan when the <table> is selected");
   is(isSelectedWrapper.value, true,
      "getTableEditor().getCellDataAt(null, 0, 0) should return true for isSelected when the <table> is selected");
 
   selection.removeAllRanges();
   editor.innerHTML = "<table>" +
                        "<tr><td>cell1-1</td><td>cell1-2</td></tr>" +
                        "<tr><td>cell2-1</td><td>cell2-2</td></tr>" +
                        "<tr><td>cell3-1</td><td>cell3-2</td></tr>" +
                      "</table>";
   editor.focus();
   editor.scrollTop; // layout information required.
   reset();
   getTableEditor().getCellDataAt(editor.firstChild, 0, 0,
                                  cellElementWrapper,
                                  startRowIndexWrapper, startColumnIndexWrapper,
                                  rowspanWrapper, colspanWrapper,
-                                 actualRowspanWrapper, actualColspanWrapper,
+                                 effectiveRowspanWrapper, effectiveColspanWrapper,
                                  isSelectedWrapper);
   is(cellElementWrapper.value, editor.firstChild.firstChild.firstChild.firstChild,
      "getTableEditor().getCellDataAt(<table>, 0, 0) should return the first <td> element");
   is(startRowIndexWrapper.value, 0,
      "getTableEditor().getCellDataAt(<table>, 0, 0) should return 0 for startRowIndex");
   is(startColumnIndexWrapper.value, 0,
      "getTableEditor().getCellDataAt(<table>, 0, 0) should return 0 for startColumnIndex");
   is(rowspanWrapper.value, 1,
      "getTableEditor().getCellDataAt(<table>, 0, 0) should return 1 for rowspan");
   is(colspanWrapper.value, 1,
      "getTableEditor().getCellDataAt(<table>, 0, 0) should return 1 for colspan");
-  is(actualRowspanWrapper.value, 1,
-     "getTableEditor().getCellDataAt(<table>, 0, 0) should return 1 for actualRowspan");
-  is(actualColspanWrapper.value, 1,
-     "getTableEditor().getCellDataAt(<table>, 0, 0) should return 1 for actualColspan");
+  is(effectiveRowspanWrapper.value, 1,
+     "getTableEditor().getCellDataAt(<table>, 0, 0) should return 1 for effectiveRowspan");
+  is(effectiveColspanWrapper.value, 1,
+     "getTableEditor().getCellDataAt(<table>, 0, 0) should return 1 for effectiveColspan");
   is(isSelectedWrapper.value, false,
      "getTableEditor().getCellDataAt(<table>, 0, 0) should return false for isSelected");
 
   reset();
   getTableEditor().getCellDataAt(editor.firstChild, 0, 1,
                                  cellElementWrapper,
                                  startRowIndexWrapper, startColumnIndexWrapper,
                                  rowspanWrapper, colspanWrapper,
-                                 actualRowspanWrapper, actualColspanWrapper,
+                                 effectiveRowspanWrapper, effectiveColspanWrapper,
                                  isSelectedWrapper);
   is(cellElementWrapper.value, editor.firstChild.firstChild.firstChild.firstChild.nextSibling,
      "getTableEditor().getCellDataAt(<table>, 0, 1) should return the second <td> element");
   is(startRowIndexWrapper.value, 0,
      "getTableEditor().getCellDataAt(<table>, 0, 1) should return 0 for startRowIndex");
   is(startColumnIndexWrapper.value, 1,
      "getTableEditor().getCellDataAt(<table>, 0, 1) should return 1 for startColumnIndex");
   is(rowspanWrapper.value, 1,
      "getTableEditor().getCellDataAt(<table>, 0, 1) should return 1 for rowspan");
   is(colspanWrapper.value, 1,
      "getTableEditor().getCellDataAt(<table>, 0, 1) should return 1 for colspan");
-  is(actualRowspanWrapper.value, 1,
-     "getTableEditor().getCellDataAt(<table>, 0, 1) should return 1 for actualRowspan");
-  is(actualColspanWrapper.value, 1,
-     "getTableEditor().getCellDataAt(<table>, 0, 1) should return 1 for actualColspan");
+  is(effectiveRowspanWrapper.value, 1,
+     "getTableEditor().getCellDataAt(<table>, 0, 1) should return 1 for effectiveRowspan");
+  is(effectiveColspanWrapper.value, 1,
+     "getTableEditor().getCellDataAt(<table>, 0, 1) should return 1 for effectiveColspan");
   is(isSelectedWrapper.value, false,
      "getTableEditor().getCellDataAt(<table>, 0, 1) should return false for isSelected");
 
   try {
     getTableEditor().getCellDataAt(editor.firstChild, 0, 2,
                                    cellElementWrapper,
                                    startRowIndexWrapper, startColumnIndexWrapper,
                                    rowspanWrapper, colspanWrapper,
-                                   actualRowspanWrapper, actualColspanWrapper,
+                                   effectiveRowspanWrapper, effectiveColspanWrapper,
                                    isSelectedWrapper);
     ok(false, "getTableEditor().getCellDataAt(<table>, 0, 2) should throw exception since column index is out of bounds");
   } catch (e) {
     ok(true, "getTableEditor().getCellDataAt(<table>, 0, 2) should throw exception since column index is out of bounds");
   }
 
   reset();
   getTableEditor().getCellDataAt(editor.firstChild, 1, 0,
                                  cellElementWrapper,
                                  startRowIndexWrapper, startColumnIndexWrapper,
                                  rowspanWrapper, colspanWrapper,
-                                 actualRowspanWrapper, actualColspanWrapper,
+                                 effectiveRowspanWrapper, effectiveColspanWrapper,
                                  isSelectedWrapper);
   is(cellElementWrapper.value, editor.firstChild.firstChild.firstChild.nextSibling.firstChild,
      "getTableEditor().getCellDataAt(<table>, 1, 0) should return the first <td> element in the second row");
   is(startRowIndexWrapper.value, 1,
      "getTableEditor().getCellDataAt(<table>, 1, 0) should return 1 for startRowIndex");
   is(startColumnIndexWrapper.value, 0,
      "getTableEditor().getCellDataAt(<table>, 1, 0) should return 0 for startColumnIndex");
   is(rowspanWrapper.value, 1,
      "getTableEditor().getCellDataAt(<table>, 1, 0) should return 1 for rowspan");
   is(colspanWrapper.value, 1,
      "getTableEditor().getCellDataAt(<table>, 1, 0) should return 1 for colspan");
-  is(actualRowspanWrapper.value, 1,
-     "getTableEditor().getCellDataAt(<table>, 1, 0) should return 1 for actualRowspan");
-  is(actualColspanWrapper.value, 1,
-     "getTableEditor().getCellDataAt(<table>, 1, 0) should return 1 for actualColspan");
+  is(effectiveRowspanWrapper.value, 1,
+     "getTableEditor().getCellDataAt(<table>, 1, 0) should return 1 for effectiveRowspan");
+  is(effectiveColspanWrapper.value, 1,
+     "getTableEditor().getCellDataAt(<table>, 1, 0) should return 1 for effectiveColspan");
   is(isSelectedWrapper.value, false,
      "getTableEditor().getCellDataAt(<table>, 1, 0) should return false for isSelected");
 
   reset();
   getTableEditor().getCellDataAt(editor.firstChild, 2, 1,
                                  cellElementWrapper,
                                  startRowIndexWrapper, startColumnIndexWrapper,
                                  rowspanWrapper, colspanWrapper,
-                                 actualRowspanWrapper, actualColspanWrapper,
+                                 effectiveRowspanWrapper, effectiveColspanWrapper,
                                  isSelectedWrapper);
   is(cellElementWrapper.value, editor.firstChild.firstChild.firstChild.nextSibling.nextSibling.firstChild.nextSibling,
      "getTableEditor().getCellDataAt(<table>, 2, 1) should return the second <td> element in the last row");
   is(startRowIndexWrapper.value, 2,
      "getTableEditor().getCellDataAt(<table>, 2, 1) should return 1 for startRowIndex");
   is(startColumnIndexWrapper.value, 1,
      "getTableEditor().getCellDataAt(<table>, 2, 1) should return 1 for startColumnIndex");
   is(rowspanWrapper.value, 1,
      "getTableEditor().getCellDataAt(<table>, 2, 1) should return 1 for rowspan");
   is(colspanWrapper.value, 1,
      "getTableEditor().getCellDataAt(<table>, 2, 1) should return 1 for colspan");
-  is(actualRowspanWrapper.value, 1,
-     "getTableEditor().getCellDataAt(<table>, 2, 1) should return 1 for actualRowspan");
-  is(actualColspanWrapper.value, 1,
-     "getTableEditor().getCellDataAt(<table>, 2, 1) should return 1 for actualColspan");
+  is(effectiveRowspanWrapper.value, 1,
+     "getTableEditor().getCellDataAt(<table>, 2, 1) should return 1 for effectiveRowspan");
+  is(effectiveColspanWrapper.value, 1,
+     "getTableEditor().getCellDataAt(<table>, 2, 1) should return 1 for effectiveColspan");
   is(isSelectedWrapper.value, false,
      "getTableEditor().getCellDataAt(<table>, 2, 1) should return false for isSelected");
 
   try {
     getTableEditor().getCellDataAt(editor.firstChild, 2, 2,
                                    cellElementWrapper,
                                    startRowIndexWrapper, startColumnIndexWrapper,
                                    rowspanWrapper, colspanWrapper,
-                                   actualRowspanWrapper, actualColspanWrapper,
+                                   effectiveRowspanWrapper, effectiveColspanWrapper,
                                    isSelectedWrapper);
     ok(false, "getTableEditor().getCellDataAt(<table>, 2, 2) should throw exception since column index is out of bounds");
   } catch (e) {
     ok(true, "getTableEditor().getCellDataAt(<table>, 2, 2) should throw exception since column index is out of bounds");
   }
 
   try {
     getTableEditor().getCellDataAt(editor.firstChild, 3, 0,
                                    cellElementWrapper,
                                    startRowIndexWrapper, startColumnIndexWrapper,
                                    rowspanWrapper, colspanWrapper,
-                                   actualRowspanWrapper, actualColspanWrapper,
+                                   effectiveRowspanWrapper, effectiveColspanWrapper,
                                    isSelectedWrapper);
     ok(false, "getTableEditor().getCellDataAt(<table>, 3, 0) should throw exception since row index is out of bounds");
   } catch (e) {
     ok(true, "getTableEditor().getCellDataAt(<table>, 3, 0) should throw exception since row index is out of bounds");
   }
 
   selection.removeAllRanges();
   editor.innerHTML = "<table>" +
@@ -318,245 +318,245 @@ SimpleTest.waitForFocus(function() {
                      "</table>";
   editor.focus();
   editor.scrollTop; // layout information required.
   reset();
   getTableEditor().getCellDataAt(editor.firstChild, 0, 0,
                                  cellElementWrapper,
                                  startRowIndexWrapper, startColumnIndexWrapper,
                                  rowspanWrapper, colspanWrapper,
-                                 actualRowspanWrapper, actualColspanWrapper,
+                                 effectiveRowspanWrapper, effectiveColspanWrapper,
                                  isSelectedWrapper);
   is(cellElementWrapper.value, editor.firstChild.firstChild.firstChild.firstChild,
      "getTableEditor().getCellDataAt(<table>, 0, 0) should return the first <td> element whose rowspan is 3");
   is(startRowIndexWrapper.value, 0,
      "getTableEditor().getCellDataAt(<table>, 0, 0) should return 0 for startRowIndex (the cell's rowspan is 3)");
   is(startColumnIndexWrapper.value, 0,
      "getTableEditor().getCellDataAt(<table>, 0, 0) should return 0 for startColumnIndex (the cell's rowspan is 3)");
   is(rowspanWrapper.value, 3,
      "getTableEditor().getCellDataAt(<table>, 0, 0) should return 3 for rowspan (the cell's rowspan is 3)");
   is(colspanWrapper.value, 1,
      "getTableEditor().getCellDataAt(<table>, 0, 0) should return 1 for colspan (the cell's rowspan is 3)");
-  is(actualRowspanWrapper.value, 3,
-     "getTableEditor().getCellDataAt(<table>, 0, 0) should return 3 for actualRowspan (the cell's rowspan is 3)");
-  is(actualColspanWrapper.value, 1,
-     "getTableEditor().getCellDataAt(<table>, 0, 0) should return 1 for actualColspan (the cell's rowspan is 3)");
+  is(effectiveRowspanWrapper.value, 3,
+     "getTableEditor().getCellDataAt(<table>, 0, 0) should return 3 for effectiveRowspan (the cell's rowspan is 3)");
+  is(effectiveColspanWrapper.value, 1,
+     "getTableEditor().getCellDataAt(<table>, 0, 0) should return 1 for effectiveColspan (the cell's rowspan is 3)");
   is(isSelectedWrapper.value, false,
      "getTableEditor().getCellDataAt(<table>, 0, 0) should return false for isSelected (the cell's rowspan is 3)");
 
   reset();
   getTableEditor().getCellDataAt(editor.firstChild, 1, 0,
                                  cellElementWrapper,
                                  startRowIndexWrapper, startColumnIndexWrapper,
                                  rowspanWrapper, colspanWrapper,
-                                 actualRowspanWrapper, actualColspanWrapper,
+                                 effectiveRowspanWrapper, effectiveColspanWrapper,
                                  isSelectedWrapper);
   is(cellElementWrapper.value, editor.firstChild.firstChild.firstChild.firstChild,
      "getTableEditor().getCellDataAt(<table>, 1, 0) should return the first <td> element whose rowspan is 3");
   is(startRowIndexWrapper.value, 0,
      "getTableEditor().getCellDataAt(<table>, 1, 0) should return 0 for startRowIndex (the cell's rowspan is 3)");
   is(startColumnIndexWrapper.value, 0,
      "getTableEditor().getCellDataAt(<table>, 1, 0) should return 0 for startColumnIndex (the cell's rowspan is 3)");
   is(rowspanWrapper.value, 3,
      "getTableEditor().getCellDataAt(<table>, 1, 0) should return 3 for rowspan (the cell's rowspan is 3)");
   is(colspanWrapper.value, 1,
      "getTableEditor().getCellDataAt(<table>, 1, 0) should return 1 for colspan (the cell's rowspan is 3)");
-  is(actualRowspanWrapper.value, 2,
-     "getTableEditor().getCellDataAt(<table>, 1, 0) should return 2 for actualRowspan (the cell's rowspan is 3)");
-  is(actualColspanWrapper.value, 1,
-     "getTableEditor().getCellDataAt(<table>, 1, 0) should return 1 for actualColspan (the cell's rowspan is 3)");
+  is(effectiveRowspanWrapper.value, 2,
+     "getTableEditor().getCellDataAt(<table>, 1, 0) should return 2 for effectiveRowspan (the cell's rowspan is 3)");
+  is(effectiveColspanWrapper.value, 1,
+     "getTableEditor().getCellDataAt(<table>, 1, 0) should return 1 for effectiveColspan (the cell's rowspan is 3)");
   is(isSelectedWrapper.value, false,
      "getTableEditor().getCellDataAt(<table>, 1, 0) should return false for isSelected (the cell's rowspan is 3)");
 
   reset();
   getTableEditor().getCellDataAt(editor.firstChild, 2, 0,
                                  cellElementWrapper,
                                  startRowIndexWrapper, startColumnIndexWrapper,
                                  rowspanWrapper, colspanWrapper,
-                                 actualRowspanWrapper, actualColspanWrapper,
+                                 effectiveRowspanWrapper, effectiveColspanWrapper,
                                  isSelectedWrapper);
   is(cellElementWrapper.value, editor.firstChild.firstChild.firstChild.firstChild,
      "getTableEditor().getCellDataAt(<table>, 2, 0) should return the first <td> element whose rowspan is 3");
   is(startRowIndexWrapper.value, 0,
      "getTableEditor().getCellDataAt(<table>, 2, 0) should return 0 for startRowIndex (the cell's rowspan is 3)");
   is(startColumnIndexWrapper.value, 0,
      "getTableEditor().getCellDataAt(<table>, 2, 0) should return 0 for startColumnIndex (the cell's rowspan is 3)");
   is(rowspanWrapper.value, 3,
      "getTableEditor().getCellDataAt(<table>, 2, 0) should return 3 for rowspan (the cell's rowspan is 3)");
   is(colspanWrapper.value, 1,
      "getTableEditor().getCellDataAt(<table>, 2, 0) should return 1 for colspan (the cell's rowspan is 3)");
-  is(actualRowspanWrapper.value, 1,
-     "getTableEditor().getCellDataAt(<table>, 2, 0) should return 1 for actualRowspan (the cell's rowspan is 3)");
-  is(actualColspanWrapper.value, 1,
-     "getTableEditor().getCellDataAt(<table>, 2, 0) should return 1 for actualColspan (the cell's rowspan is 3)");
+  is(effectiveRowspanWrapper.value, 1,
+     "getTableEditor().getCellDataAt(<table>, 2, 0) should return 1 for effectiveRowspan (the cell's rowspan is 3)");
+  is(effectiveColspanWrapper.value, 1,
+     "getTableEditor().getCellDataAt(<table>, 2, 0) should return 1 for effectiveColspan (the cell's rowspan is 3)");
   is(isSelectedWrapper.value, false,
      "getTableEditor().getCellDataAt(<table>, 2, 0) should return false for isSelected (the cell's rowspan is 3)");
 
   reset();
   getTableEditor().getCellDataAt(editor.firstChild, 3, 0,
                                  cellElementWrapper,
                                  startRowIndexWrapper, startColumnIndexWrapper,
                                  rowspanWrapper, colspanWrapper,
-                                 actualRowspanWrapper, actualColspanWrapper,
+                                 effectiveRowspanWrapper, effectiveColspanWrapper,
                                  isSelectedWrapper);
   is(cellElementWrapper.value, editor.firstChild.firstChild.firstChild.nextSibling.nextSibling.nextSibling.firstChild,
      "getTableEditor().getCellDataAt(<table>, 3, 0) should return the first <td> element in the last row whose colspan is 3");
   is(startRowIndexWrapper.value, 3,
      "getTableEditor().getCellDataAt(<table>, 3, 0) should return 3 for startRowIndex (the cell's colspan is 3)");
   is(startColumnIndexWrapper.value, 0,
      "getTableEditor().getCellDataAt(<table>, 3, 0) should return 0 for startColumnIndex (the cell's colspan is 3)");
   is(rowspanWrapper.value, 1,
      "getTableEditor().getCellDataAt(<table>, 3, 0) should return 1 for rowspan (the cell's colspan is 3)");
   is(colspanWrapper.value, 3,
      "getTableEditor().getCellDataAt(<table>, 3, 0) should return 3 for colspan (the cell's colspan is 3)");
-  is(actualRowspanWrapper.value, 1,
-     "getTableEditor().getCellDataAt(<table>, 3, 0) should return 1 for actualRowspan (the cell's colspan is 3)");
-  is(actualColspanWrapper.value, 3,
-     "getTableEditor().getCellDataAt(<table>, 3, 0) should return 3 for actualColspan (the cell's colspan is 3)");
+  is(effectiveRowspanWrapper.value, 1,
+     "getTableEditor().getCellDataAt(<table>, 3, 0) should return 1 for effectiveRowspan (the cell's colspan is 3)");
+  is(effectiveColspanWrapper.value, 3,
+     "getTableEditor().getCellDataAt(<table>, 3, 0) should return 3 for effectiveColspan (the cell's colspan is 3)");
   is(isSelectedWrapper.value, false,
      "getTableEditor().getCellDataAt(<table>, 3, 0) should return false for isSelected (the cell's colspan is 3)");
 
   reset();
   getTableEditor().getCellDataAt(editor.firstChild, 3, 1,
                                  cellElementWrapper,
                                  startRowIndexWrapper, startColumnIndexWrapper,
                                  rowspanWrapper, colspanWrapper,
-                                 actualRowspanWrapper, actualColspanWrapper,
+                                 effectiveRowspanWrapper, effectiveColspanWrapper,
                                  isSelectedWrapper);
   is(cellElementWrapper.value, editor.firstChild.firstChild.firstChild.nextSibling.nextSibling.nextSibling.firstChild,
      "getTableEditor().getCellDataAt(<table>, 3, 1) should return the first <td> element in the last row whose colspan is 3");
   is(startRowIndexWrapper.value, 3,
      "getTableEditor().getCellDataAt(<table>, 3, 1) should return 3 for startRowIndex (the cell's colspan is 3)");
   is(startColumnIndexWrapper.value, 0,
      "getTableEditor().getCellDataAt(<table>, 3, 1) should return 0 for startColumnIndex (the cell's colspan is 3)");
   is(rowspanWrapper.value, 1,
      "getTableEditor().getCellDataAt(<table>, 3, 1) should return 1 for rowspan (the cell's colspan is 3)");
   is(colspanWrapper.value, 3,
      "getTableEditor().getCellDataAt(<table>, 3, 1) should return 3 for colspan (the cell's colspan is 3)");
-  is(actualRowspanWrapper.value, 1,
-     "getTableEditor().getCellDataAt(<table>, 3, 1) should return 1 for actualRowspan (the cell's colspan is 3)");
-  is(actualColspanWrapper.value, 2,
-     "getTableEditor().getCellDataAt(<table>, 3, 1) should return 2 for actualColspan (the cell's colspan is 3)");
+  is(effectiveRowspanWrapper.value, 1,
+     "getTableEditor().getCellDataAt(<table>, 3, 1) should return 1 for effectiveRowspan (the cell's colspan is 3)");
+  is(effectiveColspanWrapper.value, 2,
+     "getTableEditor().getCellDataAt(<table>, 3, 1) should return 2 for effectiveColspan (the cell's colspan is 3)");
   is(isSelectedWrapper.value, false,
      "getTableEditor().getCellDataAt(<table>, 3, 1) should return false for isSelected (the cell's colspan is 3)");
 
   reset();
   getTableEditor().getCellDataAt(editor.firstChild, 3, 2,
                                  cellElementWrapper,
                                  startRowIndexWrapper, startColumnIndexWrapper,
                                  rowspanWrapper, colspanWrapper,
-                                 actualRowspanWrapper, actualColspanWrapper,
+                                 effectiveRowspanWrapper, effectiveColspanWrapper,
                                  isSelectedWrapper);
   is(cellElementWrapper.value, editor.firstChild.firstChild.firstChild.nextSibling.nextSibling.nextSibling.firstChild,
      "getTableEditor().getCellDataAt(<table>, 3, 2) should return the first <td> element in the last row whose colspan is 3");
   is(startRowIndexWrapper.value, 3,
      "getTableEditor().getCellDataAt(<table>, 3, 2) should return 3 for startRowIndex (the cell's colspan is 3)");
   is(startColumnIndexWrapper.value, 0,
      "getTableEditor().getCellDataAt(<table>, 3, 2) should return 0 for startColumnIndex (the cell's colspan is 3)");
   is(rowspanWrapper.value, 1,
      "getTableEditor().getCellDataAt(<table>, 3, 2) should return 1 for rowspan (the cell's colspan is 3)");
   is(colspanWrapper.value, 3,
      "getTableEditor().getCellDataAt(<table>, 3, 2) should return 3 for colspan (the cell's colspan is 3)");
-  is(actualRowspanWrapper.value, 1,
-     "getTableEditor().getCellDataAt(<table>, 3, 2) should return 1 for actualRowspan (the cell's colspan is 3)");
-  is(actualColspanWrapper.value, 1,
-     "getTableEditor().getCellDataAt(<table>, 3, 2) should return 1 for actualColspan (the cell's colspan is 3)");
+  is(effectiveRowspanWrapper.value, 1,
+     "getTableEditor().getCellDataAt(<table>, 3, 2) should return 1 for effectiveRowspan (the cell's colspan is 3)");
+  is(effectiveColspanWrapper.value, 1,
+     "getTableEditor().getCellDataAt(<table>, 3, 2) should return 1 for effectiveColspan (the cell's colspan is 3)");
   is(isSelectedWrapper.value, false,
      "getTableEditor().getCellDataAt(<table>, 3, 2) should return false for isSelected (the cell's colspan is 3)");
 
   reset();
   getTableEditor().getCellDataAt(editor.firstChild, 3, 3,
                                  cellElementWrapper,
                                  startRowIndexWrapper, startColumnIndexWrapper,
                                  rowspanWrapper, colspanWrapper,
-                                 actualRowspanWrapper, actualColspanWrapper,
+                                 effectiveRowspanWrapper, effectiveColspanWrapper,
                                  isSelectedWrapper);
   is(cellElementWrapper.value, editor.firstChild.firstChild.firstChild.nextSibling.nextSibling.nextSibling.firstChild.nextSibling,
      "getTableEditor().getCellDataAt(<table>, 3, 3) should return the second <td> element in the last row");
   is(startRowIndexWrapper.value, 3,
      "getTableEditor().getCellDataAt(<table>, 3, 3) should return 3 for startRowIndex (right cell of the cell whose colspan is 3)");
   is(startColumnIndexWrapper.value, 3,
      "getTableEditor().getCellDataAt(<table>, 3, 3) should return 3 for startColumnIndex (right cell of the cell whose colspan is 3)");
   is(rowspanWrapper.value, 1,
      "getTableEditor().getCellDataAt(<table>, 3, 3) should return 1 for rowspan (right cell of the cell whose colspan is 3)");
   is(colspanWrapper.value, 1,
      "getTableEditor().getCellDataAt(<table>, 3, 3) should return 1 for colspan (right cell of the cell whose colspan is 3)");
-  is(actualRowspanWrapper.value, 1,
-     "getTableEditor().getCellDataAt(<table>, 3, 3) should return 1 for actualRowspan (right cell of the cell whose colspan is 3)");
-  is(actualColspanWrapper.value, 1,
-     "getTableEditor().getCellDataAt(<table>, 3, 3) should return 1 for actualColspan (right cell of the cell whose colspan is 3)");
+  is(effectiveRowspanWrapper.value, 1,
+     "getTableEditor().getCellDataAt(<table>, 3, 3) should return 1 for effectiveRowspan (right cell of the cell whose colspan is 3)");
+  is(effectiveColspanWrapper.value, 1,
+     "getTableEditor().getCellDataAt(<table>, 3, 3) should return 1 for effectiveColspan (right cell of the cell whose colspan is 3)");
   is(isSelectedWrapper.value, false,
      "getTableEditor().getCellDataAt(<table>, 3, 3) should return false for isSelected (right cell of the cell whose colspan is 3)");
 
   try {
     getTableEditor().getCellDataAt(editor.firstChild, 3, 4,
                                    cellElementWrapper,
                                    startRowIndexWrapper, startColumnIndexWrapper,
                                    rowspanWrapper, colspanWrapper,
-                                   actualRowspanWrapper, actualColspanWrapper,
+                                   effectiveRowspanWrapper, effectiveColspanWrapper,
                                    isSelectedWrapper);
     ok(false, "getTableEditor().getCellDataAt(<table>, 3, 4) should throw exception since column index is out of bounds");
   } catch (e) {
     ok(true, "getTableEditor().getCellDataAt(<table>, 3, 4) should throw exception since column index is out of bounds");
   }
 
   reset();
   getTableEditor().getCellDataAt(editor.firstChild, 0, 1,
                                  cellElementWrapper,
                                  startRowIndexWrapper, startColumnIndexWrapper,
                                  rowspanWrapper, colspanWrapper,
-                                 actualRowspanWrapper, actualColspanWrapper,
+                                 effectiveRowspanWrapper, effectiveColspanWrapper,
                                  isSelectedWrapper);
   is(cellElementWrapper.value, editor.firstChild.firstChild.firstChild.firstChild.nextSibling,
      "getTableEditor().getCellDataAt(<table>, 0, 1) should return the second <td> element in the first row");
   is(startRowIndexWrapper.value, 0,
      "getTableEditor().getCellDataAt(<table>, 0, 1) should return 0 for startRowIndex (right cell of the cell whose rowspan is 3)");
   is(startColumnIndexWrapper.value, 1,
      "getTableEditor().getCellDataAt(<table>, 0, 1) should return 1 for startColumnIndex (right cell of the cell whose rowspan is 3)");
   is(rowspanWrapper.value, 1,
      "getTableEditor().getCellDataAt(<table>, 0, 1) should return 1 for rowspan (right cell of the cell whose rowspan is 3)");
   is(colspanWrapper.value, 1,
      "getTableEditor().getCellDataAt(<table>, 0, 1) should return 1 for colspan (right cell of the cell whose rowspan is 3)");
-  is(actualRowspanWrapper.value, 1,
-     "getTableEditor().getCellDataAt(<table>, 0, 1) should return 1 for actualRowspan (right cell of the cell whose rowspan is 3)");
-  is(actualColspanWrapper.value, 1,
-     "getTableEditor().getCellDataAt(<table>, 0, 1) should return 1 for actualColspan (right cell of the cell whose rowspan is 3)");
+  is(effectiveRowspanWrapper.value, 1,
+     "getTableEditor().getCellDataAt(<table>, 0, 1) should return 1 for effectiveRowspan (right cell of the cell whose rowspan is 3)");
+  is(effectiveColspanWrapper.value, 1,
+     "getTableEditor().getCellDataAt(<table>, 0, 1) should return 1 for effectiveColspan (right cell of the cell whose rowspan is 3)");
   is(isSelectedWrapper.value, false,
      "getTableEditor().getCellDataAt(<table>, 0, 1) should return false for isSelected (right cell of the cell whose rowspan is 3)");
 
   reset();
   getTableEditor().getCellDataAt(editor.firstChild, 1, 1,
                                  cellElementWrapper,
                                  startRowIndexWrapper, startColumnIndexWrapper,
                                  rowspanWrapper, colspanWrapper,
-                                 actualRowspanWrapper, actualColspanWrapper,
+                                 effectiveRowspanWrapper, effectiveColspanWrapper,
                                  isSelectedWrapper);
   is(cellElementWrapper.value, editor.firstChild.firstChild.firstChild.nextSibling.firstChild,
      "getTableEditor().getCellDataAt(<table>, 1, 1) should return the first <td> element in the second row");
   is(startRowIndexWrapper.value, 1,
      "getTableEditor().getCellDataAt(<table>, 1, 1) should return 1 for startRowIndex (right cell of the cell whose rowspan is 3)");
   is(startColumnIndexWrapper.value, 1,
      "getTableEditor().getCellDataAt(<table>, 1, 1) should return 1 for startColumnIndex (right cell of the cell whose rowspan is 3)");
   is(rowspanWrapper.value, 1,
      "getTableEditor().getCellDataAt(<table>, 1, 1) should return 1 for rowspan (right cell of the cell whose rowspan is 3)");
   is(colspanWrapper.value, 1,
      "getTableEditor().getCellDataAt(<table>, 1, 1) should return 1 for colspan (right cell of the cell whose rowspan is 3)");
-  is(actualRowspanWrapper.value, 1,
-     "getTableEditor().getCellDataAt(<table>, 1, 1) should return 1 for actualRowspan (right cell of the cell whose rowspan is 3)");
-  is(actualColspanWrapper.value, 1,
-     "getTableEditor().getCellDataAt(<table>, 1, 1) should return 1 for actualColspan (right cell of the cell whose rowspan is 3)");
+  is(effectiveRowspanWrapper.value, 1,
+     "getTableEditor().getCellDataAt(<table>, 1, 1) should return 1 for effectiveRowspan (right cell of the cell whose rowspan is 3)");
+  is(effectiveColspanWrapper.value, 1,
+     "getTableEditor().getCellDataAt(<table>, 1, 1) should return 1 for effectiveColspan (right cell of the cell whose rowspan is 3)");
   is(isSelectedWrapper.value, false,
      "getTableEditor().getCellDataAt(<table>, 1, 1) should return false for isSelected (right cell of the cell whose rowspan is 3)");
 
   try {
     getTableEditor().getCellDataAt(editor.firstChild, 1, 2,
                                    cellElementWrapper,
                                    startRowIndexWrapper, startColumnIndexWrapper,
                                    rowspanWrapper, colspanWrapper,
-                                   actualRowspanWrapper, actualColspanWrapper,
+                                   effectiveRowspanWrapper, effectiveColspanWrapper,
                                    isSelectedWrapper);
     ok(false, "getTableEditor().getCellDataAt(<table>, 1, 2) should throw exception since there is no cell due to non-rectangular table");
   } catch (e) {
     ok(true, "getTableEditor().getCellDataAt(<table>, 1, 2) should throw exception since there is no cell due to non-rectangular table");
   }
 
   selection.removeAllRanges();
   editor.innerHTML = "<table>" +
@@ -564,83 +564,83 @@ SimpleTest.waitForFocus(function() {
                      "</table>";
   editor.focus();
   editor.scrollTop; // layout information required.
   reset();
   getTableEditor().getCellDataAt(editor.firstChild, 0, 0,
                                  cellElementWrapper,
                                  startRowIndexWrapper, startColumnIndexWrapper,
                                  rowspanWrapper, colspanWrapper,
-                                 actualRowspanWrapper, actualColspanWrapper,
+                                 effectiveRowspanWrapper, effectiveColspanWrapper,
                                  isSelectedWrapper);
   is(cellElementWrapper.value, editor.firstChild.firstChild.firstChild.firstChild,
      "getTableEditor().getCellDataAt(<table>, 0, 0) should return the first <td> element whose rowspan is 3 and colspan is 2");
   is(startRowIndexWrapper.value, 0,
      "getTableEditor().getCellDataAt(<table>, 0, 0) should return 0 for startRowIndex (the cell's rowspan is 3 and colspan is 2)");
   is(startColumnIndexWrapper.value, 0,
      "getTableEditor().getCellDataAt(<table>, 0, 0) should return 0 for startColumnIndex (the cell's rowspan is 3 and colspan is 2)");
   is(rowspanWrapper.value, 3,
      "getTableEditor().getCellDataAt(<table>, 0, 0) should return 3 for rowspan (the cell's rowspan is 3 and colspan is 2)");
   is(colspanWrapper.value, 2,
      "getTableEditor().getCellDataAt(<table>, 0, 0) should return 2 for colspan (the cell's rowspan is 3 and colspan is 2)");
   // XXX Not sure whether expected behavior or not.
-  todo_is(actualRowspanWrapper.value, 3,
-          "getTableEditor().getCellDataAt(<table>, 0, 0) should return 3 for actualRowspan (the cell's rowspan is 3 and colspan is 2)");
-  is(actualColspanWrapper.value, 2,
-     "getTableEditor().getCellDataAt(<table>, 0, 0) should return 2 for actualColspan (the cell's rowspan is 3 and colspan is 2)");
+  todo_is(effectiveRowspanWrapper.value, 3,
+          "getTableEditor().getCellDataAt(<table>, 0, 0) should return 3 for effectiveRowspan (the cell's rowspan is 3 and colspan is 2)");
+  is(effectiveColspanWrapper.value, 2,
+     "getTableEditor().getCellDataAt(<table>, 0, 0) should return 2 for effectiveColspan (the cell's rowspan is 3 and colspan is 2)");
   is(isSelectedWrapper.value, false,
      "getTableEditor().getCellDataAt(<table>, 0, 0) should return false for isSelected (the cell's rowspan is 3 and colspan is 2)");
 
   reset();
   getTableEditor().getCellDataAt(editor.firstChild, 0, 1,
                                  cellElementWrapper,
                                  startRowIndexWrapper, startColumnIndexWrapper,
                                  rowspanWrapper, colspanWrapper,
-                                 actualRowspanWrapper, actualColspanWrapper,
+                                 effectiveRowspanWrapper, effectiveColspanWrapper,
                                  isSelectedWrapper);
   is(cellElementWrapper.value, editor.firstChild.firstChild.firstChild.firstChild,
      "getTableEditor().getCellDataAt(<table>, 0, 1) should return the first <td> element whose rowspan is 3 and colspan is 2");
   is(startRowIndexWrapper.value, 0,
      "getTableEditor().getCellDataAt(<table>, 0, 1) should return 0 for startRowIndex (the cell's rowspan is 3 and colspan is 2)");
   is(startColumnIndexWrapper.value, 0,
      "getTableEditor().getCellDataAt(<table>, 0, 1) should return 0 for startColumnIndex (the cell's rowspan is 3 and colspan is 2)");
   is(rowspanWrapper.value, 3,
      "getTableEditor().getCellDataAt(<table>, 0, 1) should return 3 for rowspan (the cell's rowspan is 3 and colspan is 2)");
   is(colspanWrapper.value, 2,
      "getTableEditor().getCellDataAt(<table>, 0, 1) should return 2 for colspan (the cell's rowspan is 3 and colspan is 2)");
   // XXX Not sure whether expected behavior or not.
-  todo_is(actualRowspanWrapper.value, 3,
-          "getTableEditor().getCellDataAt(<table>, 0, 1) should return 3 for actualRowspan (the cell's rowspan is 3 and colspan is 2)");
-  is(actualColspanWrapper.value, 1,
-     "getTableEditor().getCellDataAt(<table>, 0, 1) should return 1 for actualColspan (the cell's rowspan is 3 and colspan is 2)");
+  todo_is(effectiveRowspanWrapper.value, 3,
+          "getTableEditor().getCellDataAt(<table>, 0, 1) should return 3 for effectiveRowspan (the cell's rowspan is 3 and colspan is 2)");
+  is(effectiveColspanWrapper.value, 1,
+     "getTableEditor().getCellDataAt(<table>, 0, 1) should return 1 for effectiveColspan (the cell's rowspan is 3 and colspan is 2)");
   is(isSelectedWrapper.value, false,
      "getTableEditor().getCellDataAt(<table>, 0, 1) should return false for isSelected (the cell's rowspan is 3 and colspan is 2)");
 
   try {
     getTableEditor().getCellDataAt(editor.firstChild, 1, 0,
                                    cellElementWrapper,
                                    startRowIndexWrapper, startColumnIndexWrapper,
                                    rowspanWrapper, colspanWrapper,
-                                   actualRowspanWrapper, actualColspanWrapper,
+                                   effectiveRowspanWrapper, effectiveColspanWrapper,
                                    isSelectedWrapper);
     is(cellElementWrapper.value, editor.firstChild.firstChild.firstChild.firstChild,
        "getTableEditor().getCellDataAt(<table>, 1, 0) should return the first <td> element whose rowspan is 3 and colspan is 2");
     is(startRowIndexWrapper.value, 0,
        "getTableEditor().getCellDataAt(<table>, 1, 0) should return 0 for startRowIndex (the cell's rowspan is 3 and colspan is 2)");
     is(startColumnIndexWrapper.value, 0,
        "getTableEditor().getCellDataAt(<table>, 1, 0) should return 0 for startColumnIndex (the cell's rowspan is 3 and colspan is 2)");
     is(rowspanWrapper.value, 3,
        "getTableEditor().getCellDataAt(<table>, 1, 0) should return 3 for rowspan (the cell's rowspan is 3 and colspan is 2)");
     is(colspanWrapper.value, 2,
        "getTableEditor().getCellDataAt(<table>, 1, 0) should return 2 for colspan (the cell's rowspan is 3 and colspan is 2)");
     // XXX Not sure whether expected behavior or not.
-    todo_is(actualRowspanWrapper.value, 2,
-            "getTableEditor().getCellDataAt(<table>, 1, 0) should return 2 for actualRowspan (the cell's rowspan is 3 and colspan is 2)");
-    is(actualColspanWrapper.value, 1,
-       "getTableEditor().getCellDataAt(<table>, 1, 0) should return 1 for actualColspan (the cell's rowspan is 3 and colspan is 2)");
+    todo_is(effectiveRowspanWrapper.value, 2,
+            "getTableEditor().getCellDataAt(<table>, 1, 0) should return 2 for effectiveRowspan (the cell's rowspan is 3 and colspan is 2)");
+    is(effectiveColspanWrapper.value, 1,
+       "getTableEditor().getCellDataAt(<table>, 1, 0) should return 1 for effectiveColspan (the cell's rowspan is 3 and colspan is 2)");
     is(isSelectedWrapper.value, false,
        "getTableEditor().getCellDataAt(<table>, 1, 0) should return false for isSelected (the cell's rowspan is 3 and colspan is 2)");
   } catch (e) {
     todo(false, "getTableEditor().getCellDataAt(<table>, 1, 0) shouldn't throw exception since rowspan expands the table");
   }
 
   selection.removeAllRanges();
   editor.innerHTML = "<table>" +
@@ -650,97 +650,97 @@ SimpleTest.waitForFocus(function() {
                      "</table>";
   editor.focus();
   editor.scrollTop; // layout information required.
   reset();
   getTableEditor().getCellDataAt(editor.firstChild, 0, 0,
                                  cellElementWrapper,
                                  startRowIndexWrapper, startColumnIndexWrapper,
                                  rowspanWrapper, colspanWrapper,
-                                 actualRowspanWrapper, actualColspanWrapper,
+                                 effectiveRowspanWrapper, effectiveColspanWrapper,
                                  isSelectedWrapper);
   is(cellElementWrapper.value, editor.firstChild.firstChild.firstChild.firstChild,
      "getTableEditor().getCellDataAt(<table>, 0, 0) should return the first <td> element whose rowspan is 0");
   is(startRowIndexWrapper.value, 0,
      "getTableEditor().getCellDataAt(<table>, 0, 0) should return 0 for startRowIndex (the cell's rowspan is 0)");
   is(startColumnIndexWrapper.value, 0,
      "getTableEditor().getCellDataAt(<table>, 0, 0) should return 0 for startColumnIndex (the cell's rowspan is 0)");
   is(rowspanWrapper.value, 0,
      "getTableEditor().getCellDataAt(<table>, 0, 0) should return 0 for rowspan (the cell's rowspan is 0)");
   is(colspanWrapper.value, 1,
      "getTableEditor().getCellDataAt(<table>, 0, 0) should return 1 for colspan (the cell's rowspan is 0)");
-  is(actualRowspanWrapper.value, 3,
-     "getTableEditor().getCellDataAt(<table>, 0, 0) should return 3 for actualRowspan (the cell's rowspan is 0)");
-  is(actualColspanWrapper.value, 1,
-     "getTableEditor().getCellDataAt(<table>, 0, 0) should return 1 for actualColspan (the cell's rowspan is 0)");
+  is(effectiveRowspanWrapper.value, 3,
+     "getTableEditor().getCellDataAt(<table>, 0, 0) should return 3 for effectiveRowspan (the cell's rowspan is 0)");
+  is(effectiveColspanWrapper.value, 1,
+     "getTableEditor().getCellDataAt(<table>, 0, 0) should return 1 for effectiveColspan (the cell's rowspan is 0)");
   is(isSelectedWrapper.value, false,
      "getTableEditor().getCellDataAt(<table>, 0, 0) should return false for isSelected (the cell's rowspan is 0)");
 
   reset();
   getTableEditor().getCellDataAt(editor.firstChild, 1, 0,
                                  cellElementWrapper,
                                  startRowIndexWrapper, startColumnIndexWrapper,
                                  rowspanWrapper, colspanWrapper,
-                                 actualRowspanWrapper, actualColspanWrapper,
+                                 effectiveRowspanWrapper, effectiveColspanWrapper,
                                  isSelectedWrapper);
   is(cellElementWrapper.value, editor.firstChild.firstChild.firstChild.firstChild,
      "getTableEditor().getCellDataAt(<table>, 1, 0) should return the first <td> element whose rowspan is 0");
   is(startRowIndexWrapper.value, 0,
      "getTableEditor().getCellDataAt(<table>, 1, 0) should return 0 for startRowIndex (the cell's rowspan is 0)");
   is(startColumnIndexWrapper.value, 0,
      "getTableEditor().getCellDataAt(<table>, 1, 0) should return 0 for startColumnIndex (the cell's rowspan is 0)");
   is(rowspanWrapper.value, 0,
      "getTableEditor().getCellDataAt(<table>, 1, 0) should return 0 for rowspan (the cell's rowspan is 0)");
   is(colspanWrapper.value, 1,
      "getTableEditor().getCellDataAt(<table>, 1, 0) should return 1 for colspan (the cell's rowspan is 0)");
-  is(actualRowspanWrapper.value, 2,
-     "getTableEditor().getCellDataAt(<table>, 1, 0) should return 3 for actualRowspan (the cell's rowspan is 0)");
-  is(actualColspanWrapper.value, 1,
-     "getTableEditor().getCellDataAt(<table>, 1, 0) should return 1 for actualColspan (the cell's rowspan is 0)");
+  is(effectiveRowspanWrapper.value, 2,
+     "getTableEditor().getCellDataAt(<table>, 1, 0) should return 3 for effectiveRowspan (the cell's rowspan is 0)");
+  is(effectiveColspanWrapper.value, 1,
+     "getTableEditor().getCellDataAt(<table>, 1, 0) should return 1 for effectiveColspan (the cell's rowspan is 0)");
   is(isSelectedWrapper.value, false,
      "getTableEditor().getCellDataAt(<table>, 1, 0) should return false for isSelected (the cell's rowspan is 0)");
 
   // FYI: colspan must be 1 - 1000, 0 is invalid.
   selection.removeAllRanges();
   editor.innerHTML = "<table>" +
                        '<tr><td colspan="0">cell1-1</td></tr>' +
                        "<tr><td>cell2-1</td><td>cell2-2</td><td>cell2-3</td></tr>" +
                      "</table>";
   editor.focus();
   editor.scrollTop; // layout information required.
   reset();
   getTableEditor().getCellDataAt(editor.firstChild, 0, 0,
                                  cellElementWrapper,
                                  startRowIndexWrapper, startColumnIndexWrapper,
                                  rowspanWrapper, colspanWrapper,
-                                 actualRowspanWrapper, actualColspanWrapper,
+                                 effectiveRowspanWrapper, effectiveColspanWrapper,
                                  isSelectedWrapper);
   is(cellElementWrapper.value, editor.firstChild.firstChild.firstChild.firstChild,
      "getTableEditor().getCellDataAt(<table>, 0, 0) should return the first <td> element whose colspan is 0");
   is(startRowIndexWrapper.value, 0,
      "getTableEditor().getCellDataAt(<table>, 0, 0) should return 0 for startRowIndex (the cell's colspan is 0)");
   is(startColumnIndexWrapper.value, 0,
      "getTableEditor().getCellDataAt(<table>, 0, 0) should return 0 for startColumnIndex (the cell's colspan is 0)");
   is(rowspanWrapper.value, 1,
      "getTableEditor().getCellDataAt(<table>, 0, 0) should return 1 for rowspan (the cell's colspan is 0)");
   is(colspanWrapper.value, 1,
      "getTableEditor().getCellDataAt(<table>, 0, 0) should return 1 for colspan (the cell's colspan is 0)");
-  is(actualRowspanWrapper.value, 1,
-     "getTableEditor().getCellDataAt(<table>, 0, 0) should return 3 for actualRowspan (the cell's colspan is 0)");
-  is(actualColspanWrapper.value, 1,
-     "getTableEditor().getCellDataAt(<table>, 0, 0) should return 1 for actualColspan (the cell's colspan is 0)");
+  is(effectiveRowspanWrapper.value, 1,
+     "getTableEditor().getCellDataAt(<table>, 0, 0) should return 3 for effectiveRowspan (the cell's colspan is 0)");
+  is(effectiveColspanWrapper.value, 1,
+     "getTableEditor().getCellDataAt(<table>, 0, 0) should return 1 for effectiveColspan (the cell's colspan is 0)");
   is(isSelectedWrapper.value, false,
      "getTableEditor().getCellDataAt(<table>, 0, 0) should return false for isSelected (the cell's colspan is 0)");
 
   try {
     getTableEditor().getCellDataAt(editor.firstChild, 0, 1,
                                    cellElementWrapper,
                                    startRowIndexWrapper, startColumnIndexWrapper,
                                    rowspanWrapper, colspanWrapper,
-                                   actualRowspanWrapper, actualColspanWrapper,
+                                   effectiveRowspanWrapper, effectiveColspanWrapper,
                                    isSelectedWrapper);
     ok(false, "getTableEditor().getCellDataAt(<table>, 0, 1) should throw exception since there is no cell due to right side of a cell whose colspan is 0");
   } catch (e) {
     ok(true, "getTableEditor().getCellDataAt(<table>, 0, 1) should throw exception since there is no cell due to right side of a cell whose colspan is 0");
   }
 
   SimpleTest.finish();
 });
--- a/editor/nsITableEditor.idl
+++ b/editor/nsITableEditor.idl
@@ -280,47 +280,67 @@ interface nsITableEditor : nsISupports
    *                            element, throwing an exception.
    *                            If aTableElement is null and anchor of Selection
    *                            is not in any <table> element, throwing an
    *                            exception.
    */
   Element getCellAt(in Element aTableElement,
                     in long aRowIndex, in long aColumnIndex);
 
-  /** Get a cell at cellmap grid coordinates and associated data
-    * A cell that spans across multiple cellmap locations will
-    *   be returned multiple times, once for each location it occupies
-    * Examine the returned aStartRowIndex and aStartColIndex to see
-    *   if it is in the same layout column or layout row:
-    *   A "layout row" is all cells sharing the same top edge
-    *   A "layout column" is all cells sharing the same left edge
-    *   This is important to determine what to do when inserting or deleting a column or row
-    *
-    *  @param aTable                   A table in the document
-    *  @param aRowIndex, aColIndex     The 0-based cellmap indexes
-    * returns values:
-    *  @param aCell                    The cell at this cellmap location
-    *  @param aStartRowIndex           The row index where cell starts
-    *  @param aStartColIndex           The col index where cell starts
-    *  @param aRowSpan                 May be 0 (to span down entire table) or number of cells spanned
-    *  @param aColSpan                 May be 0 (to span across entire table) or number of cells spanned
-    *  @param aActualRowSpan           The actual number of cellmap locations (rows) spanned by the cell
-    *  @param aActualColSpan           The actual number of cellmap locations (columns) spanned by the cell
-    *  @param aIsSelected
-    *  @param
-    *
-    * (in C++ returns: NS_EDITOR_ELEMENT_NOT_FOUND if an element is not found
-    *  passes NS_SUCCEEDED macro)
-    */
-  void getCellDataAt(in Element aTable,
-                     in long  aRowIndex, in long  aColIndex,
-                     out Element aCell,
-                     out long  aStartRowIndex, out long  aStartColIndex,
-                     out long  aRowSpan, out long  aColSpan,
-                     out long  aActualRowSpan, out long  aActualColSpan,
+  /**
+   * Get cell element and its various information from <table> element and
+   * indexes in it.  If aTableElement is null, this looks for an ancestor
+   * <table> element of anchor of Selection.  If there is no <table> element
+   * at that point, this throws exception.  Note that this requires layout
+   * information.  So, you need to flush the layout after changing the DOM
+   * tree.
+   * If there is no cell element at the indexes, this throws exception.
+   * XXX Perhaps, this is wrong behavior, this should return null without
+   *     exception since the caller cannot distinguish whether the exception
+   *     is caused by "not found" or other unexpected situation.
+   *
+   * @param aTableElement       A <table> element.  If this is null, this
+   *                            uses ancestor of anchor of Selection.
+   * @param aRowIndex           Row index in aTableElement.  Starting from 0.
+   * @param aColumnIndex        Column index in aTableElement.  Starting from
+   *                            0.
+   * @param aCellElement        [OUT] The cell element at the indexes.
+   * @param aStartRowIndex      [OUT] First row index which contains
+   *                            aCellElement.  E.g., if the cell's rowspan is
+   *                            not 1, this returns its first row index.
+   *                            I.e., this can be smaller than aRowIndex.
+   * @param aStartColumnIndex   [OUT] First column index which contains the
+   *                            aCellElement.  E.g., if the cell's colspan is
+   *                            larger than 1, this returns its first column
+   *                            index.  I.e., this can be smaller than
+   *                            aColumIndex.
+   * @param aRowSpan            [OUT] rowspan attribute value in most cases.
+   *                            If the specified value is invalid, this
+   *                            returns 1.  Only when the document is written
+   *                            in HTML5 or later, this can be 0.
+   * @param aColSpan            [OUT] colspan attribute value in most cases.
+   *                            If the specified value is invalid, this
+   *                            returns 1.
+   * @param aEffectiveRowSpan   [OUT] Effective rowspan value at aRowIndex.
+   *                            This is same as:
+   *                              aRowSpan - (aRowIndex - aStartRowIndex)
+   * @param aEffectiveColSpan   [OUT] Effective colspan value at aColumnIndex.
+   *                            This is same as:
+   *                              aColSpan - (aColumnIndex - aStartColumnIndex)
+   * @param aIsSelected         [OUT] Returns true if aCellElement or its
+   *                            <tr> or <table> element is selected.
+   *                            Otherwise, e.g., aCellElement just contains
+   *                            selection range, returns false.
+   */
+  void getCellDataAt(in Element aTableElement,
+                     in long aRowIndex, in long aColumnIndex,
+                     out Element aCellElement,
+                     out long aStartRowIndex, out long aStartColumnIndex,
+                     out long aRowSpan, out long aColSpan,
+                     out long aEffectiveRowSpan, out long aEffectiveColSpan,
                      out boolean aIsSelected);
 
   /**
    * getFirstRow() returns first <tr> element in a <table> element.
    *
    * @param aTableOrElementInTable  If a <table> element, returns its first
    *                                <tr> element.
    *                                If another element, looks for nearest