Bug 1730442 - part 1: Make all nsITableEditor features flush pending layout at start to handle their jobs r=m_kato

Our table editor depends on layout information for getting raw/column position
of a cell, checking rawspan/colspan information and table size.  Therefore,
they require the latest information, but they don't flush pending layout by
themselves.  Therefore, this patch makes them do it by themselves and deleting
unnecessary hack from their tests.

Differential Revision: https://phabricator.services.mozilla.com/D146359
This commit is contained in:
Masayuki Nakano 2022-05-17 00:12:08 +00:00
parent 2ac0551241
commit 216035e16f
18 changed files with 223 additions and 139 deletions

View File

@ -228,6 +228,23 @@ enum class EditAction {
// <td> or <th>.
eSetTableCellElementType,
// Those edit actions are mapped to the methods in nsITableEditor which
// access table layout information.
eSelectTableCell,
eSelectTableRow,
eSelectTableColumn,
eSelectTable,
eSelectAllTableCells,
eGetCellIndexes,
eGetTableSize,
eGetCellAt,
eGetCellDataAt,
eGetFirstRow,
eGetSelectedOrParentTableElement,
eGetSelectedCellsType,
eGetFirstSelectedCellInTable,
eGetSelectedCells,
// eSetInlineStyleProperty indicates to set CSS another inline style property
// which is not defined below.
eSetInlineStyleProperty,
@ -476,6 +493,26 @@ enum class EditSubAction : int32_t {
eCreatePaddingBRElementForEmptyEditor,
};
// You can use this macro as:
// case NS_EDIT_ACTION_CASES_ACCESSING_TABLE_DATA_WITHOUT_EDITING:
// clang-format off
#define NS_EDIT_ACTION_CASES_ACCESSING_TABLE_DATA_WITHOUT_EDITING \
mozilla::EditAction::eSelectTableCell: \
case mozilla::EditAction::eSelectTableRow: \
case mozilla::EditAction::eSelectTableColumn: \
case mozilla::EditAction::eSelectTable: \
case mozilla::EditAction::eSelectAllTableCells: \
case mozilla::EditAction::eGetCellIndexes: \
case mozilla::EditAction::eGetTableSize: \
case mozilla::EditAction::eGetCellAt: \
case mozilla::EditAction::eGetCellDataAt: \
case mozilla::EditAction::eGetFirstRow: \
case mozilla::EditAction::eGetSelectedOrParentTableElement: \
case mozilla::EditAction::eGetSelectedCellsType: \
case mozilla::EditAction::eGetFirstSelectedCellInTable: \
case mozilla::EditAction::eGetSelectedCells
// clang-format on
inline EditorInputType ToInputType(EditAction aEditAction) {
switch (aEditAction) {
case EditAction::eInsertText:
@ -612,6 +649,16 @@ inline bool MayEditActionDeleteAroundCollapsedSelection(
}
}
inline bool IsEditActionInOrderToEditSomething(const EditAction aEditAction) {
switch (aEditAction) {
case EditAction::eNotEditing:
case NS_EDIT_ACTION_CASES_ACCESSING_TABLE_DATA_WITHOUT_EDITING:
return false;
default:
return true;
}
}
inline bool IsEditActionTableEditing(const EditAction aEditAction) {
switch (aEditAction) {
case EditAction::eInsertTableRowElement:
@ -636,6 +683,7 @@ inline bool MayEditActionDeleteSelection(const EditAction aEditAction) {
case EditAction::eNone:
case EditAction::eNotEditing:
case EditAction::eInitializing:
case NS_EDIT_ACTION_CASES_ACCESSING_TABLE_DATA_WITHOUT_EDITING:
return false;
// EditActions modifying around selection.
@ -779,6 +827,28 @@ inline bool MayEditActionDeleteSelection(const EditAction aEditAction) {
return false;
}
inline bool MayEditActionRequireLayout(const EditAction aEditAction) {
switch (aEditAction) {
// Table editing require layout information for referring table cell data
// such as row/column number and rowspan/colspan.
case EditAction::eInsertTableRowElement:
case EditAction::eRemoveTableRowElement:
case EditAction::eInsertTableColumn:
case EditAction::eRemoveTableColumn:
case EditAction::eRemoveTableElement:
case EditAction::eRemoveTableCellElement:
case EditAction::eDeleteTableCellContents:
case EditAction::eInsertTableCellElement:
case EditAction::eJoinTableCellElements:
case EditAction::eSplitTableCellElement:
case EditAction::eSetTableCellElementType:
case NS_EDIT_ACTION_CASES_ACCESSING_TABLE_DATA_WITHOUT_EDITING:
return true;
default:
return false;
}
}
} // namespace mozilla
inline bool operator!(const mozilla::EditSubAction& aEditSubAction) {

View File

@ -6066,6 +6066,7 @@ EditorBase::AutoEditActionDataSetter::AutoEditActionDataSetter(
mPrincipal(aPrincipal),
mParentData(aEditorBase.mEditActionData),
mData(VoidString()),
mRawEditAction(aEditAction),
mTopLevelEditSubAction(EditSubAction::eNone),
mAborted(false),
mHasTriedToDispatchBeforeInputEvent(false),
@ -6082,10 +6083,10 @@ EditorBase::AutoEditActionDataSetter::AutoEditActionDataSetter(
MOZ_ASSERT(!mSelection ||
(mSelection->GetType() == SelectionType::eNormal));
// If we're eNotEditing, we should inherit the parent's edit action.
// This may occur if creator or its callee use public methods which
// If we're not editing something, we should inherit the parent's edit
// action. This may occur if creator or its callee use public methods which
// just returns something.
if (aEditAction != EditAction::eNotEditing) {
if (IsEditActionInOrderToEditSomething(aEditAction)) {
mEditAction = aEditAction;
} else {
mEditAction = mParentData->mEditAction;
@ -6327,13 +6328,31 @@ bool EditorBase::AutoEditActionDataSetter::IsBeforeInputEventEnabled() const {
return true;
}
nsresult EditorBase::AutoEditActionDataSetter::MaybeFlushPendingNotifications()
const {
MOZ_ASSERT(CanHandle());
if (!MayEditActionRequireLayout(mRawEditAction)) {
return NS_SUCCESS_DOM_NO_OPERATION;
}
OwningNonNull<EditorBase> editorBase = mEditorBase;
RefPtr<PresShell> presShell = editorBase->GetPresShell();
if (MOZ_UNLIKELY(NS_WARN_IF(!presShell))) {
return NS_ERROR_NOT_AVAILABLE;
}
presShell->FlushPendingNotifications(FlushType::Layout);
if (MOZ_UNLIKELY(NS_WARN_IF(editorBase->Destroyed()))) {
return NS_ERROR_EDITOR_DESTROYED;
}
return NS_OK;
}
nsresult EditorBase::AutoEditActionDataSetter::MaybeDispatchBeforeInputEvent(
nsIEditor::EDirection aDeleteDirectionAndAmount /* nsIEditor::eNone */) {
nsIEditor::EDirection aDeleteDirectionAndAmount /* = nsIEditor::eNone */) {
MOZ_ASSERT(!HasTriedToDispatchBeforeInputEvent(),
"We've already handled beforeinput event");
MOZ_ASSERT(CanHandle());
MOZ_ASSERT(!IsBeforeInputEventEnabled() ||
ShouldAlreadyHaveHandledBeforeInputEventDispatching());
MOZ_ASSERT_IF(IsBeforeInputEventEnabled(),
ShouldAlreadyHaveHandledBeforeInputEventDispatching());
MOZ_ASSERT_IF(!MayEditActionDeleteAroundCollapsedSelection(mEditAction),
aDeleteDirectionAndAmount == nsIEditor::eNone);

View File

@ -991,11 +991,23 @@ class EditorBase : public nsIEditor,
}
[[nodiscard]] MOZ_CAN_RUN_SCRIPT nsresult
CanHandleAndMaybeDispatchBeforeInputEvent() {
if (NS_WARN_IF(!CanHandle())) {
if (MOZ_UNLIKELY(NS_WARN_IF(!CanHandle()))) {
return NS_ERROR_NOT_INITIALIZED;
}
nsresult rv = MaybeFlushPendingNotifications();
if (MOZ_UNLIKELY(NS_FAILED(rv))) {
return rv;
}
return MaybeDispatchBeforeInputEvent();
}
[[nodiscard]] MOZ_CAN_RUN_SCRIPT nsresult
CanHandleAndFlushPendingNotifications() {
if (MOZ_UNLIKELY(NS_WARN_IF(!CanHandle()))) {
return NS_ERROR_NOT_INITIALIZED;
}
MOZ_ASSERT(MayEditActionRequireLayout(mRawEditAction));
return MaybeFlushPendingNotifications();
}
[[nodiscard]] bool IsDataAvailable() const {
return mSelection && mEditorBase.IsInitialized();
@ -1277,6 +1289,9 @@ class EditorBase : public nsIEditor,
private:
bool IsBeforeInputEventEnabled() const;
[[nodiscard]] MOZ_CAN_RUN_SCRIPT nsresult
MaybeFlushPendingNotifications() const;
static bool NeedsBeforeInputEventHandling(EditAction aEditAction) {
MOZ_ASSERT(aEditAction != EditAction::eNone);
switch (aEditAction) {
@ -1287,6 +1302,9 @@ class EditorBase : public nsIEditor,
// If we're being initialized, we may need to create a padding <br>
// element, but it shouldn't cause `beforeinput` event.
case EditAction::eInitializing:
// If we're just selecting or getting table cells, we shouldn't
// dispatch `beforeinput` event.
case NS_EDIT_ACTION_CASES_ACCESSING_TABLE_DATA_WITHOUT_EDITING:
// If raw level transaction API is used, the API user needs to handle
// both "beforeinput" event and "input" event if it's necessary.
case EditAction::eUnknown:
@ -1371,7 +1389,12 @@ class EditorBase : public nsIEditor,
// for current edit sub action.
EditSubActionData mEditSubActionData;
// mEditAction and mRawEditActions stores edit action. The difference of
// them is, if and only if edit actions are nested and parent edit action
// is one of trying to edit something, but nested one is not so, it's
// overwritten by the parent edit action.
EditAction mEditAction;
EditAction mRawEditAction;
// Different from its data, you can refer "current" AutoEditActionDataSetter
// instance's mTopLevelEditSubAction member since it's copied from the

View File

@ -1339,7 +1339,7 @@ EditActionResult HTMLEditor::HandleTabKeyPressInTable(
AutoEditActionDataSetter editActionData(*this,
EditAction::eInsertTableRowElement);
rv = editActionData.CanHandleAndMaybeDispatchBeforeInputEvent();
if (NS_FAILED(rv)) {
if (MOZ_UNLIKELY(NS_FAILED(rv))) {
NS_WARNING_ASSERTION(rv == NS_ERROR_EDITOR_ACTION_CANCELED,
"CanHandleAndMaybeDispatchBeforeInputEvent(), failed");
return EditActionHandled(rv);

View File

@ -325,7 +325,7 @@ NS_IMETHODIMP HTMLEditor::InsertTableCell(int32_t aNumberOfCellsToInsert,
AutoEditActionDataSetter editActionData(*this,
EditAction::eInsertTableCellElement);
nsresult rv = editActionData.CanHandleAndMaybeDispatchBeforeInputEvent();
if (NS_FAILED(rv)) {
if (MOZ_UNLIKELY(NS_FAILED(rv))) {
NS_WARNING_ASSERTION(rv == NS_ERROR_EDITOR_ACTION_CANCELED,
"CanHandleAndMaybeDispatchBeforeInputEvent(), failed");
return EditorBase::ToGenericNSResult(rv);
@ -443,9 +443,11 @@ NS_IMETHODIMP HTMLEditor::GetFirstRow(Element* aTableOrElementInTable,
return NS_ERROR_INVALID_ARG;
}
AutoEditActionDataSetter editActionData(*this, EditAction::eNotEditing);
if (NS_WARN_IF(!editActionData.CanHandle())) {
return NS_ERROR_NOT_INITIALIZED;
AutoEditActionDataSetter editActionData(*this, EditAction::eGetFirstRow);
nsresult rv = editActionData.CanHandleAndFlushPendingNotifications();
if (MOZ_UNLIKELY(NS_FAILED(rv))) {
NS_WARNING("HTMLEditor::GetFirstRow() couldn't handle the job");
return EditorBase::ToGenericNSResult(rv);
}
ErrorResult error;
@ -583,7 +585,7 @@ NS_IMETHODIMP HTMLEditor::InsertTableColumn(int32_t aNumberOfColumnsToInsert,
AutoEditActionDataSetter editActionData(*this,
EditAction::eInsertTableColumn);
nsresult rv = editActionData.CanHandleAndMaybeDispatchBeforeInputEvent();
if (NS_FAILED(rv)) {
if (MOZ_UNLIKELY(NS_FAILED(rv))) {
NS_WARNING_ASSERTION(rv == NS_ERROR_EDITOR_ACTION_CANCELED,
"CanHandleAndMaybeDispatchBeforeInputEvent(), failed");
return EditorBase::ToGenericNSResult(rv);
@ -818,7 +820,7 @@ NS_IMETHODIMP HTMLEditor::InsertTableRow(int32_t aNumberOfRowsToInsert,
AutoEditActionDataSetter editActionData(*this,
EditAction::eInsertTableRowElement);
nsresult rv = editActionData.CanHandleAndMaybeDispatchBeforeInputEvent();
if (NS_FAILED(rv)) {
if (MOZ_UNLIKELY(NS_FAILED(rv))) {
NS_WARNING_ASSERTION(rv == NS_ERROR_EDITOR_ACTION_CANCELED,
"CanHandleAndMaybeDispatchBeforeInputEvent(), failed");
return EditorBase::ToGenericNSResult(rv);
@ -1122,7 +1124,7 @@ NS_IMETHODIMP HTMLEditor::DeleteTable() {
AutoEditActionDataSetter editActionData(*this,
EditAction::eRemoveTableElement);
nsresult rv = editActionData.CanHandleAndMaybeDispatchBeforeInputEvent();
if (NS_FAILED(rv)) {
if (MOZ_UNLIKELY(NS_FAILED(rv))) {
NS_WARNING_ASSERTION(rv == NS_ERROR_EDITOR_ACTION_CANCELED,
"CanHandleAndMaybeDispatchBeforeInputEvent(), failed");
return EditorBase::ToGenericNSResult(rv);
@ -1153,7 +1155,7 @@ NS_IMETHODIMP HTMLEditor::DeleteTableCell(int32_t aNumberOfCellsToDelete) {
AutoEditActionDataSetter editActionData(*this,
EditAction::eRemoveTableCellElement);
nsresult rv = editActionData.CanHandleAndMaybeDispatchBeforeInputEvent();
if (NS_FAILED(rv)) {
if (MOZ_UNLIKELY(NS_FAILED(rv))) {
NS_WARNING_ASSERTION(rv == NS_ERROR_EDITOR_ACTION_CANCELED,
"CanHandleAndMaybeDispatchBeforeInputEvent(), failed");
return EditorBase::ToGenericNSResult(rv);
@ -1444,7 +1446,7 @@ NS_IMETHODIMP HTMLEditor::DeleteTableCellContents() {
AutoEditActionDataSetter editActionData(*this,
EditAction::eDeleteTableCellContents);
nsresult rv = editActionData.CanHandleAndMaybeDispatchBeforeInputEvent();
if (NS_FAILED(rv)) {
if (MOZ_UNLIKELY(NS_FAILED(rv))) {
NS_WARNING_ASSERTION(rv == NS_ERROR_EDITOR_ACTION_CANCELED,
"CanHandleAndMaybeDispatchBeforeInputEvent(), failed");
return EditorBase::ToGenericNSResult(rv);
@ -1535,7 +1537,7 @@ NS_IMETHODIMP HTMLEditor::DeleteTableColumn(int32_t aNumberOfColumnsToDelete) {
AutoEditActionDataSetter editActionData(*this,
EditAction::eRemoveTableColumn);
nsresult rv = editActionData.CanHandleAndMaybeDispatchBeforeInputEvent();
if (NS_FAILED(rv)) {
if (MOZ_UNLIKELY(NS_FAILED(rv))) {
NS_WARNING_ASSERTION(rv == NS_ERROR_EDITOR_ACTION_CANCELED,
"CanHandleAndMaybeDispatchBeforeInputEvent(), failed");
return EditorBase::ToGenericNSResult(rv);
@ -1785,7 +1787,7 @@ NS_IMETHODIMP HTMLEditor::DeleteTableRow(int32_t aNumberOfRowsToDelete) {
AutoEditActionDataSetter editActionData(*this,
EditAction::eRemoveTableRowElement);
nsresult rv = editActionData.CanHandleAndMaybeDispatchBeforeInputEvent();
if (NS_FAILED(rv)) {
if (MOZ_UNLIKELY(NS_FAILED(rv))) {
NS_WARNING_ASSERTION(rv == NS_ERROR_EDITOR_ACTION_CANCELED,
"CanHandleAndMaybeDispatchBeforeInputEvent(), failed");
return EditorBase::ToGenericNSResult(rv);
@ -2068,9 +2070,11 @@ nsresult HTMLEditor::DeleteTableRowWithTransaction(Element& aTableElement,
}
NS_IMETHODIMP HTMLEditor::SelectTable() {
AutoEditActionDataSetter editActionData(*this, EditAction::eNotEditing);
if (NS_WARN_IF(!editActionData.CanHandle())) {
return NS_ERROR_NOT_INITIALIZED;
AutoEditActionDataSetter editActionData(*this, EditAction::eSelectTable);
nsresult rv = editActionData.CanHandleAndFlushPendingNotifications();
if (MOZ_UNLIKELY(NS_FAILED(rv))) {
NS_WARNING("HTMLEditor::SelectTable() couldn't handle the job");
return EditorBase::ToGenericNSResult(rv);
}
RefPtr<Element> table =
@ -2082,7 +2086,7 @@ NS_IMETHODIMP HTMLEditor::SelectTable() {
return NS_OK; // Don't fail if we didn't find a table.
}
nsresult rv = ClearSelection();
rv = ClearSelection();
if (NS_FAILED(rv)) {
NS_WARNING("HTMLEditor::ClearSelection() failed");
return EditorBase::ToGenericNSResult(rv);
@ -2094,9 +2098,11 @@ NS_IMETHODIMP HTMLEditor::SelectTable() {
}
NS_IMETHODIMP HTMLEditor::SelectTableCell() {
AutoEditActionDataSetter editActionData(*this, EditAction::eNotEditing);
if (NS_WARN_IF(!editActionData.CanHandle())) {
return NS_ERROR_NOT_INITIALIZED;
AutoEditActionDataSetter editActionData(*this, EditAction::eSelectTableCell);
nsresult rv = editActionData.CanHandleAndFlushPendingNotifications();
if (MOZ_UNLIKELY(NS_FAILED(rv))) {
NS_WARNING("HTMLEditor::SelectTableCell() couldn't handle the job");
return EditorBase::ToGenericNSResult(rv);
}
RefPtr<Element> cell =
@ -2109,7 +2115,7 @@ NS_IMETHODIMP HTMLEditor::SelectTableCell() {
return NS_SUCCESS_EDITOR_ELEMENT_NOT_FOUND;
}
nsresult rv = ClearSelection();
rv = ClearSelection();
if (NS_FAILED(rv)) {
NS_WARNING("HTMLEditor::ClearSelection() failed");
return EditorBase::ToGenericNSResult(rv);
@ -2121,9 +2127,12 @@ NS_IMETHODIMP HTMLEditor::SelectTableCell() {
}
NS_IMETHODIMP HTMLEditor::SelectAllTableCells() {
AutoEditActionDataSetter editActionData(*this, EditAction::eNotEditing);
if (NS_WARN_IF(!editActionData.CanHandle())) {
return NS_ERROR_NOT_INITIALIZED;
AutoEditActionDataSetter editActionData(*this,
EditAction::eSelectAllTableCells);
nsresult rv = editActionData.CanHandleAndFlushPendingNotifications();
if (MOZ_UNLIKELY(NS_FAILED(rv))) {
NS_WARNING("HTMLEditor::SelectAllTableCells() couldn't handle the job");
return EditorBase::ToGenericNSResult(rv);
}
RefPtr<Element> cell =
@ -2161,7 +2170,7 @@ NS_IMETHODIMP HTMLEditor::SelectAllTableCells() {
// It is now safe to clear the selection
// BE SURE TO RESET IT BEFORE LEAVING!
nsresult rv = ClearSelection();
rv = ClearSelection();
if (rv == NS_ERROR_EDITOR_DESTROYED) {
NS_WARNING("HTMLEditor::ClearSelection() caused destroying the editor");
return EditorBase::ToGenericNSResult(rv);
@ -2219,9 +2228,11 @@ NS_IMETHODIMP HTMLEditor::SelectAllTableCells() {
}
NS_IMETHODIMP HTMLEditor::SelectTableRow() {
AutoEditActionDataSetter editActionData(*this, EditAction::eNotEditing);
if (NS_WARN_IF(!editActionData.CanHandle())) {
return NS_ERROR_NOT_INITIALIZED;
AutoEditActionDataSetter editActionData(*this, EditAction::eSelectTableRow);
nsresult rv = editActionData.CanHandleAndFlushPendingNotifications();
if (MOZ_UNLIKELY(NS_FAILED(rv))) {
NS_WARNING("HTMLEditor::SelectTableRow() couldn't handle the job");
return EditorBase::ToGenericNSResult(rv);
}
RefPtr<Element> cell =
@ -2240,9 +2251,8 @@ NS_IMETHODIMP HTMLEditor::SelectTableRow() {
RefPtr<Element> table;
int32_t startRowIndex, startColIndex;
nsresult rv =
GetCellContext(getter_AddRefs(table), getter_AddRefs(cell), nullptr,
nullptr, &startRowIndex, &startColIndex);
rv = GetCellContext(getter_AddRefs(table), getter_AddRefs(cell), nullptr,
nullptr, &startRowIndex, &startColIndex);
if (NS_FAILED(rv)) {
NS_WARNING("HTMLEditor::GetCellContext() failed");
return EditorBase::ToGenericNSResult(rv);
@ -2337,9 +2347,12 @@ NS_IMETHODIMP HTMLEditor::SelectTableRow() {
}
NS_IMETHODIMP HTMLEditor::SelectTableColumn() {
AutoEditActionDataSetter editActionData(*this, EditAction::eNotEditing);
if (NS_WARN_IF(!editActionData.CanHandle())) {
return NS_ERROR_NOT_INITIALIZED;
AutoEditActionDataSetter editActionData(*this,
EditAction::eSelectTableColumn);
nsresult rv = editActionData.CanHandleAndFlushPendingNotifications();
if (MOZ_UNLIKELY(NS_FAILED(rv))) {
NS_WARNING("HTMLEditor::SelectTableColumn() couldn't handle the job");
return EditorBase::ToGenericNSResult(rv);
}
RefPtr<Element> cell =
@ -2358,9 +2371,8 @@ NS_IMETHODIMP HTMLEditor::SelectTableColumn() {
RefPtr<Element> table;
int32_t startRowIndex, startColIndex;
nsresult rv =
GetCellContext(getter_AddRefs(table), getter_AddRefs(cell), nullptr,
nullptr, &startRowIndex, &startColIndex);
rv = GetCellContext(getter_AddRefs(table), getter_AddRefs(cell), nullptr,
nullptr, &startRowIndex, &startColIndex);
if (NS_FAILED(rv)) {
NS_WARNING("HTMLEditor::GetCellContext() failed");
return EditorBase::ToGenericNSResult(rv);
@ -2454,7 +2466,7 @@ NS_IMETHODIMP HTMLEditor::SplitTableCell() {
AutoEditActionDataSetter editActionData(*this,
EditAction::eSplitTableCellElement);
nsresult rv = editActionData.CanHandleAndMaybeDispatchBeforeInputEvent();
if (NS_FAILED(rv)) {
if (MOZ_UNLIKELY(NS_FAILED(rv))) {
NS_WARNING_ASSERTION(rv == NS_ERROR_EDITOR_ACTION_CANCELED,
"CanHandleAndMaybeDispatchBeforeInputEvent(), failed");
return EditorBase::ToGenericNSResult(rv);
@ -2754,7 +2766,7 @@ NS_IMETHODIMP HTMLEditor::SwitchTableCellHeaderType(Element* aSourceCell,
AutoEditActionDataSetter editActionData(*this,
EditAction::eSetTableCellElementType);
nsresult rv = editActionData.CanHandleAndMaybeDispatchBeforeInputEvent();
if (NS_FAILED(rv)) {
if (MOZ_UNLIKELY(NS_FAILED(rv))) {
NS_WARNING_ASSERTION(rv == NS_ERROR_EDITOR_ACTION_CANCELED,
"CanHandleAndMaybeDispatchBeforeInputEvent(), failed");
return EditorBase::ToGenericNSResult(rv);
@ -2806,7 +2818,7 @@ NS_IMETHODIMP HTMLEditor::JoinTableCells(bool aMergeNonContiguousContents) {
AutoEditActionDataSetter editActionData(*this,
EditAction::eJoinTableCellElements);
nsresult rv = editActionData.CanHandleAndMaybeDispatchBeforeInputEvent();
if (NS_FAILED(rv)) {
if (MOZ_UNLIKELY(NS_FAILED(rv))) {
NS_WARNING_ASSERTION(rv == NS_ERROR_EDITOR_ACTION_CANCELED,
"CanHandleAndMaybeDispatchBeforeInputEvent(), failed");
return EditorBase::ToGenericNSResult(rv);
@ -3446,7 +3458,7 @@ nsresult HTMLEditor::FixBadColSpan(Element* aTable, int32_t aColIndex,
NS_IMETHODIMP HTMLEditor::NormalizeTable(Element* aTableOrElementInTable) {
AutoEditActionDataSetter editActionData(*this, EditAction::eNormalizeTable);
nsresult rv = editActionData.CanHandleAndMaybeDispatchBeforeInputEvent();
if (NS_FAILED(rv)) {
if (MOZ_UNLIKELY(NS_FAILED(rv))) {
NS_WARNING_ASSERTION(rv == NS_ERROR_EDITOR_ACTION_CANCELED,
"CanHandleAndMaybeDispatchBeforeInputEvent(), failed");
return EditorBase::ToGenericNSResult(rv);
@ -3582,9 +3594,11 @@ NS_IMETHODIMP HTMLEditor::GetCellIndexes(Element* aCellElement,
return NS_ERROR_INVALID_ARG;
}
AutoEditActionDataSetter editActionData(*this, EditAction::eNotEditing);
if (NS_WARN_IF(!editActionData.CanHandle())) {
return NS_ERROR_NOT_INITIALIZED;
AutoEditActionDataSetter editActionData(*this, EditAction::eGetCellIndexes);
nsresult rv = editActionData.CanHandleAndFlushPendingNotifications();
if (MOZ_UNLIKELY(NS_FAILED(rv))) {
NS_WARNING("HTMLEditor::GetCellIndexes() couldn't handle the job");
return EditorBase::ToGenericNSResult(rv);
}
*aRowIndex = 0;
@ -3659,9 +3673,11 @@ NS_IMETHODIMP HTMLEditor::GetTableSize(Element* aTableOrElementInTable,
return NS_ERROR_INVALID_ARG;
}
AutoEditActionDataSetter editActionData(*this, EditAction::eNotEditing);
if (NS_WARN_IF(!editActionData.CanHandle())) {
return NS_ERROR_NOT_INITIALIZED;
AutoEditActionDataSetter editActionData(*this, EditAction::eGetTableSize);
nsresult rv = editActionData.CanHandleAndFlushPendingNotifications();
if (MOZ_UNLIKELY(NS_FAILED(rv))) {
NS_WARNING("HTMLEditor::GetTableSize() couldn't handle the job");
return EditorBase::ToGenericNSResult(rv);
}
*aRowCount = 0;
@ -3701,9 +3717,11 @@ NS_IMETHODIMP HTMLEditor::GetCellDataAt(
return NS_ERROR_INVALID_ARG;
}
AutoEditActionDataSetter editActionData(*this, EditAction::eNotEditing);
if (NS_WARN_IF(!editActionData.CanHandle())) {
return NS_ERROR_NOT_INITIALIZED;
AutoEditActionDataSetter editActionData(*this, EditAction::eGetCellDataAt);
nsresult rv = editActionData.CanHandleAndFlushPendingNotifications();
if (MOZ_UNLIKELY(NS_FAILED(rv))) {
NS_WARNING("HTMLEditor::GetCellDataAt() couldn't handle the job");
return EditorBase::ToGenericNSResult(rv);
}
*aStartRowIndex = 0;
@ -3753,9 +3771,11 @@ NS_IMETHODIMP HTMLEditor::GetCellAt(Element* aTableElement, int32_t aRowIndex,
return NS_ERROR_INVALID_ARG;
}
AutoEditActionDataSetter editActionData(*this, EditAction::eNotEditing);
if (NS_WARN_IF(!editActionData.CanHandle())) {
return NS_ERROR_NOT_INITIALIZED;
AutoEditActionDataSetter editActionData(*this, EditAction::eGetCellAt);
nsresult rv = editActionData.CanHandleAndFlushPendingNotifications();
if (MOZ_UNLIKELY(NS_FAILED(rv))) {
NS_WARNING("HTMLEditor::GetCellAt() couldn't handle the job");
return EditorBase::ToGenericNSResult(rv);
}
*aCellElement = nullptr;
@ -3927,9 +3947,11 @@ NS_IMETHODIMP HTMLEditor::GetSelectedCells(
nsTArray<RefPtr<Element>>& aOutSelectedCellElements) {
MOZ_ASSERT(aOutSelectedCellElements.IsEmpty());
AutoEditActionDataSetter editActionData(*this, EditAction::eNotEditing);
if (NS_WARN_IF(!editActionData.CanHandle())) {
return NS_ERROR_NOT_INITIALIZED;
AutoEditActionDataSetter editActionData(*this, EditAction::eGetSelectedCells);
nsresult rv = editActionData.CanHandleAndFlushPendingNotifications();
if (MOZ_UNLIKELY(NS_FAILED(rv))) {
NS_WARNING("HTMLEditor::GetSelectedCells() couldn't handle the job");
return EditorBase::ToGenericNSResult(rv);
}
SelectedTableCellScanner scanner(SelectionRef());
@ -3952,9 +3974,13 @@ NS_IMETHODIMP HTMLEditor::GetFirstSelectedCellInTable(int32_t* aRowIndex,
return NS_ERROR_INVALID_ARG;
}
AutoEditActionDataSetter editActionData(*this, EditAction::eNotEditing);
if (NS_WARN_IF(!editActionData.CanHandle())) {
return NS_ERROR_NOT_INITIALIZED;
AutoEditActionDataSetter editActionData(
*this, EditAction::eGetFirstSelectedCellInTable);
nsresult rv = editActionData.CanHandleAndFlushPendingNotifications();
if (MOZ_UNLIKELY(NS_FAILED(rv))) {
NS_WARNING(
"HTMLEditor::GetFirstSelectedCellInTable() couldn't handle the job");
return EditorBase::ToGenericNSResult(rv);
}
if (NS_WARN_IF(!SelectionRef().RangeCount())) {
@ -4076,9 +4102,14 @@ NS_IMETHODIMP HTMLEditor::GetSelectedOrParentTableElement(
*aCellOrRowOrTableElement = nullptr;
*aSelectedCount = 0;
AutoEditActionDataSetter editActionData(*this, EditAction::eNotEditing);
if (NS_WARN_IF(!editActionData.CanHandle())) {
return NS_ERROR_NOT_INITIALIZED;
AutoEditActionDataSetter editActionData(
*this, EditAction::eGetSelectedOrParentTableElement);
nsresult rv = editActionData.CanHandleAndFlushPendingNotifications();
if (MOZ_UNLIKELY(NS_FAILED(rv))) {
NS_WARNING(
"HTMLEditor::GetSelectedOrParentTableElement() couldn't handle the "
"job");
return EditorBase::ToGenericNSResult(rv);
}
bool isCellSelected = false;
@ -4202,9 +4233,12 @@ NS_IMETHODIMP HTMLEditor::GetSelectedCellsType(Element* aElement,
}
*aSelectionType = 0;
AutoEditActionDataSetter editActionData(*this, EditAction::eNotEditing);
if (NS_WARN_IF(!editActionData.CanHandle())) {
return NS_ERROR_NOT_INITIALIZED;
AutoEditActionDataSetter editActionData(*this,
EditAction::eGetSelectedCellsType);
nsresult rv = editActionData.CanHandleAndFlushPendingNotifications();
if (MOZ_UNLIKELY(NS_FAILED(rv))) {
NS_WARNING("HTMLEditor::GetSelectedCellsType() couldn't handle the job");
return EditorBase::ToGenericNSResult(rv);
}
if (NS_WARN_IF(!SelectionRef().RangeCount())) {

View File

@ -661,7 +661,6 @@ SimpleTest.waitForFocus(() => {
'<tr><td id="select">cell1-1</td><td>cell1-2</td><td>cell1-3</td></tr>' +
"<tr><td>cell2-1</td><td>cell2-2</td><td>cell2-3</td></tr>" +
"</table>";
editor.scrollTop; // requires layout information.
beforeInputEvents = [];
inputEvents = [];
selection.setBaseAndExtent(document.getElementById("select").firstChild, 0,
@ -684,7 +683,6 @@ SimpleTest.waitForFocus(() => {
'<tr><td id="select">cell1-1</td><td>cell1-2</td><td>cell1-3</td></tr>' +
"<tr><td>cell2-1</td><td>cell2-2</td><td>cell2-3</td></tr>" +
"</table>";
editor.scrollTop; // requires layout information.
beforeInputEvents = [];
inputEvents = [];
selection.setBaseAndExtent(document.getElementById("select").firstChild, 0,

View File

@ -262,7 +262,6 @@ SimpleTest.waitForFocus(() => {
"<tr><td>cell2-1</td><td>cell2-2</td></tr>" +
"</table>";
editor.focus();
editor.scrollTop; // Requires layout information.
beforeInputEvents = [];
inputEvents = [];
selection.setBaseAndExtent(document.getElementById("select").firstChild, 0,

View File

@ -219,7 +219,6 @@ SimpleTest.waitForFocus(() => {
'<table><tr><td id="select">cell1-1</td><td>cell1-2</td></tr><tr><td>cell2-1</td><td>cell2-2</td></tr></table>';
beforeInputEvents = [];
inputEvents = [];
editor.scrollTop; // Needs to flush pending reflow since we need layout information in this case.
range = document.createRange();
range.selectNode(document.getElementById("select").firstChild);
selection.addRange(range);
@ -238,7 +237,6 @@ SimpleTest.waitForFocus(() => {
'<table><tr><td>cell1-1</td><td>cell1-2</td></tr><tr><td>cell2-1</td><td id="select">cell2-2</td></tr></table>';
beforeInputEvents = [];
inputEvents = [];
editor.scrollTop; // Needs to flush pending reflow since we need layout information in this case.
range = document.createRange();
range.selectNode(document.getElementById("select").firstChild);
selection.addRange(range);
@ -257,7 +255,6 @@ SimpleTest.waitForFocus(() => {
'<table><tr><td id="select">cell1-1</td><td>cell1-2</td></tr><tr><td>cell2-1</td><td>cell2-2</td></tr></table>';
beforeInputEvents = [];
inputEvents = [];
editor.scrollTop; // Needs to flush pending reflow since we need layout information in this case.
range = document.createRange();
range.selectNode(document.getElementById("select").firstChild);
selection.addRange(range);
@ -276,7 +273,6 @@ SimpleTest.waitForFocus(() => {
'<table><tr><td id="select">cell1-1</td><td>cell1-2</td></tr><tr><td>cell2-1</td><td>cell2-2</td></tr></table>';
beforeInputEvents = [];
inputEvents = [];
editor.scrollTop; // Needs to flush pending reflow since we need layout information in this case.
range = document.createRange();
range.selectNode(document.getElementById("select").firstChild);
selection.addRange(range);
@ -295,7 +291,6 @@ SimpleTest.waitForFocus(() => {
'<table><tr><td>cell1-1</td><td id="select">cell1-2</td><td>cell1-3</td></tr><tr><td>cell2-1</td><td>cell2-2</td><td>cell2-3</td></tr></table>';
beforeInputEvents = [];
inputEvents = [];
editor.scrollTop; // Needs to flush pending reflow since we need layout information in this case.
range = document.createRange();
range.selectNode(document.getElementById("select").firstChild);
selection.addRange(range);
@ -314,7 +309,6 @@ SimpleTest.waitForFocus(() => {
'<table><tr><td>cell1-1</td><td>cell1-2</td></tr><tr><td id="select">cell2-1</td><td>cell2-2</td></tr><tr><td>cell3-1</td><td>cell3-2</td></tr></table>';
beforeInputEvents = [];
inputEvents = [];
editor.scrollTop; // Needs to flush pending reflow since we need layout information in this case.
range = document.createRange();
range.selectNode(document.getElementById("select").firstChild);
selection.addRange(range);

View File

@ -217,7 +217,6 @@ SimpleTest.waitForFocus(() => {
selection.removeAllRanges();
editor.innerHTML =
'<table><tr><td id="select">cell1-1</td><td>cell1-2</td></tr><tr><td>cell2-1</td><td>cell2-2</td></tr></table>';
editor.scrollTop; // Needs to flush pending reflow since we need layout information in this case.
beforeInputEvents = [];
inputEvents = [];
range = document.createRange();
@ -236,7 +235,6 @@ SimpleTest.waitForFocus(() => {
selection.removeAllRanges();
editor.innerHTML =
'<table><tr><td>cell1-1</td><td>cell1-2</td></tr><tr><td id="select">cell2-1</td><td>cell2-2</td></tr></table>';
editor.scrollTop; // Needs to flush pending reflow since we need layout information in this case.
beforeInputEvents = [];
inputEvents = [];
range = document.createRange();
@ -255,7 +253,6 @@ SimpleTest.waitForFocus(() => {
selection.removeAllRanges();
editor.innerHTML =
'<table><tr><td id="select">cell1-1</td><td>cell1-2</td></tr><tr><td>cell2-1</td><td>cell2-2</td></tr></table>';
editor.scrollTop; // Needs to flush pending reflow since we need layout information in this case.
beforeInputEvents = [];
inputEvents = [];
range = document.createRange();
@ -274,7 +271,6 @@ SimpleTest.waitForFocus(() => {
selection.removeAllRanges();
editor.innerHTML =
'<table><tr><td id="select">cell1-1</td><td>cell1-2</td></tr><tr><td>cell2-1</td><td>cell2-2</td></tr></table>';
editor.scrollTop; // Needs to flush pending reflow since we need layout information in this case.
beforeInputEvents = [];
inputEvents = [];
range = document.createRange();
@ -293,7 +289,6 @@ SimpleTest.waitForFocus(() => {
selection.removeAllRanges();
editor.innerHTML =
'<table><tr><td>cell1-1</td><td>cell1-2</td></tr><tr><td id="select">cell2-1</td><td>cell2-2</td></tr><tr><td>cell3-1</td><td>cell3-2</td></tr></table>';
editor.scrollTop; // Needs to flush pending reflow since we need layout information in this case.
beforeInputEvents = [];
inputEvents = [];
range = document.createRange();
@ -312,7 +307,6 @@ SimpleTest.waitForFocus(() => {
selection.removeAllRanges();
editor.innerHTML =
'<table><tr><td>cell1-1</td><td>cell1-2</td></tr><tr><td id="select">cell2-1</td><td>cell2-2</td></tr><tr><td>cell3-1</td><td>cell3-2</td></tr></table>';
editor.scrollTop; // Needs to flush pending reflow since we need layout information in this case.
beforeInputEvents = [];
inputEvents = [];
range = document.createRange();

View File

@ -55,7 +55,6 @@ SimpleTest.waitForFocus(function() {
'<tr><td id="c6-2">cell6-2</td><td id="c6-3">cell6-3</td><td id="c6-4"><p>cell6-4</p></td><td id="c6-5">cell6-5</td></tr>' +
'<tr><td id="c7-2" colspan="4">cell7-2</td></tr>' +
"</table>";
editor.scrollTop; // compute layout now.
const kTestsInParent = [
{ row: 0, column: 0, expected: "c1-1" },

View File

@ -176,7 +176,6 @@ SimpleTest.waitForFocus(function() {
"<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,
@ -317,7 +316,6 @@ SimpleTest.waitForFocus(function() {
'<tr><td colspan="3">cell4-1</td><td>cell4-4</td></tr>' +
"</table>";
editor.focus();
editor.scrollTop; // layout information required.
reset();
getTableEditor().getCellDataAt(editor.firstChild, 0, 0,
cellElementWrapper,
@ -563,7 +561,6 @@ SimpleTest.waitForFocus(function() {
'<tr><td rowspan="3" colspan="2">cell1-1</td></tr>' +
"</table>";
editor.focus();
editor.scrollTop; // layout information required.
reset();
getTableEditor().getCellDataAt(editor.firstChild, 0, 0,
cellElementWrapper,
@ -649,7 +646,6 @@ SimpleTest.waitForFocus(function() {
"<tr><td>cell3-2</td></tr>" +
"</table>";
editor.focus();
editor.scrollTop; // layout information required.
reset();
getTableEditor().getCellDataAt(editor.firstChild, 0, 0,
cellElementWrapper,
@ -705,7 +701,6 @@ SimpleTest.waitForFocus(function() {
"<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,

View File

@ -66,7 +66,6 @@ SimpleTest.waitForFocus(function() {
for (const kTest of kTests) {
editor.innerHTML = kTest;
editor.scrollTop; // compute layout now.
let cell = document.getElementById("test");
getTableEditor().getCellIndexes(cell, rowIndex, columnIndex);
is(rowIndex.value.toString(10), cell.getAttribute("data-row"), `Specified cell element directly, row Index value of ${kTest}`);

View File

@ -38,7 +38,6 @@ SimpleTest.waitForFocus(function() {
(function test_without_table() {
editor.innerHTML = "<p>Here is a paragraph</p>";
document.body.scrollTop; // Flush pending layout
selection.collapse(editor.querySelector("p").firstChild, 0);
try {
getTableEditor().getSelectedCellsType(null);
@ -51,7 +50,6 @@ SimpleTest.waitForFocus(function() {
(function test_with_selection_outside_table() {
editor.innerHTML = "<p>Here is a paragraph before the table</p>" +
"<table><tr><td>cell</td></tr></table>";
document.body.scrollTop; // Flush pending layout
selection.collapse(editor.querySelector("p").firstChild, 0);
try {
getTableEditor().getSelectedCellsType(null);
@ -63,7 +61,6 @@ SimpleTest.waitForFocus(function() {
(function test_with_selection_in_text_in_cell() {
editor.innerHTML = "<table><tr><td>cell</td></tr></table>";
document.body.scrollTop; // Flush pending layout
selection.collapse(editor.querySelector("td").firstChild, 0);
is(getTableEditor().getSelectedCellsType(null), kTableSelectionMode_None,
"nsITableEditor.getSelectedCellsType(null) should return None when selection is collapsed in a text node in a cell");
@ -71,7 +68,6 @@ SimpleTest.waitForFocus(function() {
(function test_with_selecting_a_cell_which_is_only_one_cell_in_table() {
editor.innerHTML = "<table><tr><td>cell</td></tr></table>";
document.body.scrollTop; // Flush pending layout
selection.setBaseAndExtent(editor.querySelector("tr"), 0, editor.querySelector("tr"), 1);
is(getTableEditor().getSelectedCellsType(null), kTableSelectionMode_Row,
"nsITableEditor.getSelectedCellsType(null) should return Row when selection selects the cell which is only one in the table");
@ -79,7 +75,6 @@ SimpleTest.waitForFocus(function() {
(function test_with_selecting_a_cell_whose_table_has_one_row() {
editor.innerHTML = "<table><tr><td>cell1</td><td>cell2</td></tr></table>";
document.body.scrollTop; // Flush pending layout
selection.setBaseAndExtent(editor.querySelector("tr"), 0, editor.querySelector("tr"), 1);
is(getTableEditor().getSelectedCellsType(null), kTableSelectionMode_Column,
"nsITableEditor.getSelectedCellsType(null) should return Column when selection selects a cell in the first row which is only one in the table");
@ -87,7 +82,6 @@ SimpleTest.waitForFocus(function() {
(function test_with_selecting_a_cell_whose_table_has_one_column() {
editor.innerHTML = "<table><tr><td>cell1</td></tr><tr><td>cell2</td></tr></table>";
document.body.scrollTop; // Flush pending layout
selection.setBaseAndExtent(editor.querySelector("tr"), 0, editor.querySelector("tr"), 1);
is(getTableEditor().getSelectedCellsType(null), kTableSelectionMode_Row,
"nsITableEditor.getSelectedCellsType(null) should return Row when selection selects a cell in the first row which is only one in the row");
@ -95,7 +89,6 @@ SimpleTest.waitForFocus(function() {
(function test_with_selecting_a_cell_at_1_1_whose_table_has_2x2_cells() {
editor.innerHTML = "<table><tr><td>cell1</td><td>cell2</td></tr><tr><td>cell3</td><td>cell4</td></tr></table>";
document.body.scrollTop; // Flush pending layout
selection.setBaseAndExtent(editor.querySelector("tr"), 0, editor.querySelector("tr"), 1);
is(getTableEditor().getSelectedCellsType(null), kTableSelectionMode_Cell,
"nsITableEditor.getSelectedCellsType(null) should return Cell when selection selects a cell at first row and first column");
@ -103,7 +96,6 @@ SimpleTest.waitForFocus(function() {
(function test_with_selecting_a_cell_at_1_2_whose_table_has_2x2_cells() {
editor.innerHTML = "<table><tr><td>cell1</td><td>cell2</td></tr><tr><td>cell3</td><td>cell4</td></tr></table>";
document.body.scrollTop; // Flush pending layout
selection.setBaseAndExtent(editor.querySelector("tr"), 1, editor.querySelector("tr"), 2);
is(getTableEditor().getSelectedCellsType(null), kTableSelectionMode_Cell,
"nsITableEditor.getSelectedCellsType(null) should return Cell when selection selects a cell at first row and second column");
@ -111,7 +103,6 @@ SimpleTest.waitForFocus(function() {
(function test_with_selecting_a_cell_at_2_1_whose_table_has_2x2_cells() {
editor.innerHTML = "<table><tr><td>cell1</td><td>cell2</td></tr><tr><td>cell3</td><td>cell4</td></tr></table>";
document.body.scrollTop; // Flush pending layout
selection.setBaseAndExtent(editor.querySelector("tr + tr"), 0, editor.querySelector("tr + tr"), 1);
is(getTableEditor().getSelectedCellsType(null), kTableSelectionMode_Cell,
"nsITableEditor.getSelectedCellsType(null) should return Cell when selection selects a cell at second row and first column");
@ -119,7 +110,6 @@ SimpleTest.waitForFocus(function() {
(function test_with_selecting_a_cell_at_2_2_whose_table_has_2x2_cells() {
editor.innerHTML = "<table><tr><td>cell1</td><td>cell2</td></tr><tr><td>cell3</td><td>cell4</td></tr></table>";
document.body.scrollTop; // Flush pending layout
selection.setBaseAndExtent(editor.querySelector("tr + tr"), 1, editor.querySelector("tr + tr"), 2);
is(getTableEditor().getSelectedCellsType(null), kTableSelectionMode_Cell,
"nsITableEditor.getSelectedCellsType(null) should return Cell when selection selects a cell at second row and second column");
@ -127,7 +117,6 @@ SimpleTest.waitForFocus(function() {
(function test_with_selecting_a_cell_at_1_1_whose_colspan_2_and_whose_table_has_2x2_cells() {
editor.innerHTML = "<table><tr><td colspan=\"2\">cell1</td></tr><tr><td>cell3</td><td>cell4</td></tr></table>";
document.body.scrollTop; // Flush pending layout
selection.setBaseAndExtent(editor.querySelector("tr"), 0, editor.querySelector("tr"), 1);
is(getTableEditor().getSelectedCellsType(null), kTableSelectionMode_Row,
"nsITableEditor.getSelectedCellsType(null) should return Row when selection selects a cell whose colspan is 2 at first row");
@ -135,7 +124,6 @@ SimpleTest.waitForFocus(function() {
(function test_with_selecting_a_cell_at_1_1_whose_rowspan_2_and_whose_table_has_2x2_cells() {
editor.innerHTML = "<table><tr><td rowspan=\"2\">cell1</td><td>cell2</td></tr><tr><td>cell4</td></tr></table>";
document.body.scrollTop; // Flush pending layout
selection.setBaseAndExtent(editor.querySelector("tr"), 0, editor.querySelector("tr"), 1);
is(getTableEditor().getSelectedCellsType(null), kTableSelectionMode_Column,
"nsITableEditor.getSelectedCellsType(null) should return Column when selection selects a cell whose row is 2 at first column");
@ -143,7 +131,6 @@ SimpleTest.waitForFocus(function() {
(function test_with_selecting_all_cells_in_first_row_whose_table_has_2x2_cells() {
editor.innerHTML = "<table><tr><td>cell1</td><td>cell2</td></tr><tr><td>cell3</td><td>cell4</td></tr></table>";
document.body.scrollTop; // Flush pending layout
synthesizeMouseAtCenter(editor.querySelector("td"), {accelKey: true});
synthesizeMouseAtCenter(editor.querySelector("td + td"), {accelKey: true});
is(getTableEditor().getSelectedCellsType(null), kTableSelectionMode_Row,
@ -153,7 +140,6 @@ SimpleTest.waitForFocus(function() {
(function test_with_selecting_all_cells_in_first_column_whose_table_has_2x2_cells() {
selection.removeAllRanges();
editor.innerHTML = "<table><tr><td>cell1</td><td>cell2</td></tr><tr><td>cell3</td><td>cell4</td></tr></table>";
document.body.scrollTop; // Flush pending layout
synthesizeMouseAtCenter(editor.querySelector("td"), {accelKey: true});
synthesizeMouseAtCenter(editor.querySelector("tr + tr > td"), {accelKey: true});
is(getTableEditor().getSelectedCellsType(null), kTableSelectionMode_Column,
@ -163,7 +149,6 @@ SimpleTest.waitForFocus(function() {
(function test_with_selecting_all_cells_whose_table_has_2x2_cells() {
selection.removeAllRanges();
editor.innerHTML = "<table><tr><td>cell1</td><td>cell2</td></tr><tr><td>cell3</td><td>cell4</td></tr></table>";
document.body.scrollTop; // Flush pending layout
synthesizeMouseAtCenter(editor.querySelector("td"), {accelKey: true});
synthesizeMouseAtCenter(editor.querySelector("td + td"), {accelKey: true});
synthesizeMouseAtCenter(editor.querySelector("tr + tr > td"), {accelKey: true});
@ -174,7 +159,6 @@ SimpleTest.waitForFocus(function() {
(function test_with_selecting_a_raw() {
editor.innerHTML = "<table><tr><td>cell1</td><td>cell2</td></tr><tr><td>cell3</td><td>cell4</td></tr></table>";
document.body.scrollTop; // Flush pending layout
selection.setBaseAndExtent(editor.querySelector("tbody"), 0, editor.querySelector("tbody"), 1);
is(getTableEditor().getSelectedCellsType(null), kTableSelectionMode_None,
"nsITableEditor.getSelectedCellsType(null) should return None when selection selects a row");
@ -182,7 +166,6 @@ SimpleTest.waitForFocus(function() {
(function test_with_selecting_a_tbody() {
editor.innerHTML = "<table><tr><td>cell1</td><td>cell2</td></tr><tr><td>cell3</td><td>cell4</td></tr></table>";
document.body.scrollTop; // Flush pending layout
selection.setBaseAndExtent(editor.querySelector("table"), 0, editor.querySelector("table"), 1);
is(getTableEditor().getSelectedCellsType(null), kTableSelectionMode_None,
"nsITableEditor.getSelectedCellsType(null) should return None when selection selects a tbody");
@ -190,7 +173,6 @@ SimpleTest.waitForFocus(function() {
(function test_with_selecting_a_table() {
editor.innerHTML = "<table><tr><td>cell1</td><td>cell2</td></tr><tr><td>cell3</td><td>cell4</td></tr></table>";
document.body.scrollTop; // Flush pending layout
selection.setBaseAndExtent(editor, 0, editor, 1);
is(getTableEditor().getSelectedCellsType(null), kTableSelectionMode_None,
"nsITableEditor.getSelectedCellsType(null) should return None when selection selects a table");
@ -200,7 +182,6 @@ SimpleTest.waitForFocus(function() {
selection.removeAllRanges();
editor.innerHTML = "<table><tr><td>cell1</td><td>cell2</td></tr><tr><td>cell3</td><td>cell4</td></tr></table>" +
"<table><tr><td>cell1</td><td>cell2</td></tr><tr><td>cell3</td><td>cell4</td></tr></table>";
document.body.scrollTop; // Flush pending layout
let range = document.createRange();
range.selectNode(editor.querySelector("td"));
selection.addRange(range);
@ -215,7 +196,6 @@ SimpleTest.waitForFocus(function() {
selection.removeAllRanges();
editor.innerHTML = "<table><tr><td>cell1</td><td>cell2</td></tr><tr><td>cell3</td><td>cell4</td></tr></table>" +
"<table><tr><td>cell1</td><td>cell2</td></tr><tr><td>cell3</td><td>cell4</td></tr></table>";
document.body.scrollTop; // Flush pending layout
let range = document.createRange();
range.selectNode(editor.querySelector("td"));
selection.addRange(range);
@ -227,7 +207,6 @@ SimpleTest.waitForFocus(function() {
selection.removeAllRanges();
editor.innerHTML = "<table><tr><td>cell1</td><td>cell2</td></tr><tr><td>cell3</td><td>cell4</td></tr></table>" +
"<table><tr><td>cell1</td><td>cell2</td></tr><tr><td>cell3</td><td>cell4</td></tr></table>";
document.body.scrollTop; // Flush pending layout
let range = document.createRange();
range.selectNode(editor.querySelector("tr + tr > td"));
selection.addRange(range);
@ -239,7 +218,6 @@ SimpleTest.waitForFocus(function() {
selection.removeAllRanges();
editor.innerHTML = "<table><tr><td>cell1</td><td>cell2</td></tr><tr><td>cell3</td><td>cell4</td></tr></table>" +
"<table><tr><td>cell1</td><td>cell2</td></tr><tr><td>cell3</td><td>cell4</td></tr></table>";
document.body.scrollTop; // Flush pending layout
let range = document.createRange();
range.selectNode(editor.querySelector("td"));
selection.addRange(range);
@ -251,7 +229,6 @@ SimpleTest.waitForFocus(function() {
selection.removeAllRanges();
editor.innerHTML = "<table><tr><td>cell1</td><td>cell2</td></tr><tr><td>cell3</td><td>cell4</td></tr></table>" +
"<table><tr><td>cell1</td><td>cell2</td></tr><tr><td>cell3</td><td>cell4</td></tr></table>";
document.body.scrollTop; // Flush pending layout
let range = document.createRange();
range.selectNode(editor.querySelector("td"));
selection.addRange(range);

View File

@ -63,7 +63,6 @@ SimpleTest.waitForFocus(function() {
for (const kTest of kTests) {
editor.innerHTML = kTest;
editor.scrollTop; // compute layout now.
let element = document.getElementById("test");
getTableEditor().getTableSize(element, rowCount, columnCount);
is(rowCount.value.toString(10), element.getAttribute("data-rows"),

View File

@ -129,7 +129,6 @@ SimpleTest.waitForFocus(() => {
"<tr><td>cell3-1</td><td>cell3-2</td></tr>" +
"</table>";
editor.focus();
editor.scrollTop; // layout information required.
beforeInputEvents = [];
inputEvents = [];
selection.setBaseAndExtent(document.getElementById("select").firstChild, 0,
@ -155,7 +154,6 @@ SimpleTest.waitForFocus(() => {
"<tr><td>cell3-1</td><td>cell3-2</td></tr>" +
"</table>";
editor.focus();
editor.scrollTop; // layout information required.
beforeInputEvents = [];
inputEvents = [];
selection.setBaseAndExtent(document.getElementById("select").firstChild, 0,
@ -184,7 +182,6 @@ SimpleTest.waitForFocus(() => {
"<tr><td>cell3-1</td><td>cell3-2</td></tr>" +
"</table>";
editor.focus();
editor.scrollTop; // layout information required.
beforeInputEvents = [];
inputEvents = [];
selection.setBaseAndExtent(document.getElementById("select").firstChild, 0,
@ -210,7 +207,6 @@ SimpleTest.waitForFocus(() => {
"<tr><td>cell3-1</td></tr>" +
"</table>";
editor.focus();
editor.scrollTop; // layout information required.
beforeInputEvents = [];
inputEvents = [];
selection.setBaseAndExtent(document.getElementById("select").firstChild, 0,
@ -236,7 +232,6 @@ SimpleTest.waitForFocus(() => {
"<tr><td>cell3-1</td><td>cell3-2</td></tr>" +
"</table>";
editor.focus();
editor.scrollTop; // layout information required.
beforeInputEvents = [];
inputEvents = [];
selection.setBaseAndExtent(document.getElementById("select").firstChild, 0,
@ -262,7 +257,6 @@ SimpleTest.waitForFocus(() => {
"<tr><td>cell3-1</td><td>cell3-2</td></tr>" +
"</table>";
editor.focus();
editor.scrollTop; // layout information required.
beforeInputEvents = [];
inputEvents = [];
selection.setBaseAndExtent(document.getElementById("select").firstChild, 0,
@ -289,7 +283,6 @@ SimpleTest.waitForFocus(() => {
'<tr><td colspan="2">cell2-1</td><td>cell2-3</td></tr>' +
"</table>";
editor.focus();
editor.scrollTop; // layout information required.
beforeInputEvents = [];
inputEvents = [];
selection.setBaseAndExtent(document.getElementById("select").firstChild, 0,
@ -313,7 +306,6 @@ SimpleTest.waitForFocus(() => {
'<tr><td colspan="3">cell2-1</td></tr>' +
"</table>";
editor.focus();
editor.scrollTop; // layout information required.
beforeInputEvents = [];
inputEvents = [];
selection.setBaseAndExtent(document.getElementById("select").firstChild, 0,
@ -337,7 +329,6 @@ SimpleTest.waitForFocus(() => {
'<tr><td id="select" colspan="2">cell2-1</td><td>cell2-3</td></tr>' +
"</table>";
editor.focus();
editor.scrollTop; // layout information required.
beforeInputEvents = [];
inputEvents = [];
selection.setBaseAndExtent(document.getElementById("select").firstChild, 0,
@ -361,7 +352,6 @@ SimpleTest.waitForFocus(() => {
'<tr><td id="select" colspan="2">cell2-1</td><td>cell2-3</td></tr>' +
"</table>";
editor.focus();
editor.scrollTop; // layout information required.
beforeInputEvents = [];
inputEvents = [];
selection.setBaseAndExtent(document.getElementById("select").firstChild, 0,

View File

@ -128,7 +128,6 @@ SimpleTest.waitForFocus(() => {
"<tr><td>cell2-1</td><td>cell2-2</td><td>cell2-3</td></tr>" +
"</table>";
editor.focus();
editor.scrollTop; // layout information required.
beforeInputEvents = [];
inputEvents = [];
selection.setBaseAndExtent(document.getElementById("select").firstChild, 0,
@ -152,7 +151,6 @@ SimpleTest.waitForFocus(() => {
"<tr><td>cell2-1</td><td>cell2-2</td><td>cell2-3</td></tr>" +
"</table>";
editor.focus();
editor.scrollTop; // layout information required.
beforeInputEvents = [];
inputEvents = [];
selection.setBaseAndExtent(document.getElementById("select").firstChild, 0,
@ -176,7 +174,6 @@ SimpleTest.waitForFocus(() => {
'<tr><td colspan="2">cell2-1</td><td>cell2-3</td></tr>' +
"</table>";
editor.focus();
editor.scrollTop; // layout information required.
beforeInputEvents = [];
inputEvents = [];
selection.setBaseAndExtent(document.getElementById("select").firstChild, 0,
@ -200,7 +197,6 @@ SimpleTest.waitForFocus(() => {
'<tr><td colspan="3">cell2-1</td></tr>' +
"</table>";
editor.focus();
editor.scrollTop; // layout information required.
beforeInputEvents = [];
inputEvents = [];
selection.setBaseAndExtent(document.getElementById("select").firstChild, 0,
@ -224,7 +220,6 @@ SimpleTest.waitForFocus(() => {
'<tr><td id="select" colspan="2">cell2-1</td><td>cell2-3</td></tr>' +
"</table>";
editor.focus();
editor.scrollTop; // layout information required.
beforeInputEvents = [];
inputEvents = [];
selection.setBaseAndExtent(document.getElementById("select").firstChild, 0,
@ -248,7 +243,6 @@ SimpleTest.waitForFocus(() => {
'<tr><td id="select" colspan="2">cell2-1</td><td>cell2-3</td></tr>' +
"</table>";
editor.focus();
editor.scrollTop; // layout information required.
beforeInputEvents = [];
inputEvents = [];
selection.setBaseAndExtent(document.getElementById("select").firstChild, 0,

View File

@ -129,7 +129,6 @@ SimpleTest.waitForFocus(() => {
"<tr><td>cell3-1</td><td>cell3-2</td></tr>" +
"</table>";
editor.focus();
editor.scrollTop; // layout information required.
beforeInputEvents = [];
inputEvents = [];
selection.setBaseAndExtent(document.getElementById("select").firstChild, 0,
@ -156,7 +155,6 @@ SimpleTest.waitForFocus(() => {
"<tr><td>cell3-1</td><td>cell3-2</td></tr>" +
"</table>";
editor.focus();
editor.scrollTop; // layout information required.
beforeInputEvents = [];
inputEvents = [];
selection.setBaseAndExtent(document.getElementById("select").firstChild, 0,
@ -183,7 +181,6 @@ SimpleTest.waitForFocus(() => {
"<tr><td>cell3-1</td><td>cell3-2</td></tr>" +
"</table>";
editor.focus();
editor.scrollTop; // layout information required.
beforeInputEvents = [];
inputEvents = [];
selection.setBaseAndExtent(document.getElementById("select").firstChild, 0,
@ -210,7 +207,6 @@ SimpleTest.waitForFocus(() => {
"<tr><td>cell3-1</td></tr>" +
"</table>";
editor.focus();
editor.scrollTop; // layout information required.
beforeInputEvents = [];
inputEvents = [];
selection.setBaseAndExtent(document.getElementById("select").firstChild, 0,
@ -237,7 +233,6 @@ SimpleTest.waitForFocus(() => {
"<tr><td>cell3-1</td><td>cell3-2</td></tr>" +
"</table>";
editor.focus();
editor.scrollTop; // layout information required.
beforeInputEvents = [];
inputEvents = [];
selection.setBaseAndExtent(document.getElementById("select").firstChild, 0,
@ -265,7 +260,6 @@ SimpleTest.waitForFocus(() => {
"<tr><td>cell3-1</td><td>cell3-2</td></tr>" +
"</table>";
editor.focus();
editor.scrollTop; // layout information required.
beforeInputEvents = [];
inputEvents = [];
selection.setBaseAndExtent(document.getElementById("select").firstChild, 0,

View File

@ -268,6 +268,7 @@ interface nsITableEditor : nsISupports
* number than actual, the value is used
* as this.
*/
[can_run_script]
void getTableSize(in Element aTableOrElementInTable,
out long aRowCount, out long aColCount);
@ -289,6 +290,7 @@ interface nsITableEditor : nsISupports
* is not in any <table> element, throwing an
* exception.
*/
[can_run_script]
Element getCellAt(in Element aTableElement,
in long aRowIndex, in long aColumnIndex);
@ -337,6 +339,7 @@ interface nsITableEditor : nsISupports
* Otherwise, e.g., aCellElement just contains
* selection range, returns false.
*/
[can_run_script]
void getCellDataAt(in Element aTableElement,
in long aRowIndex, in long aColumnIndex,
out Element aCellElement,
@ -363,6 +366,7 @@ interface nsITableEditor : nsISupports
* element if <table> has one or more cells
* but <tr> element is not in the source.
*/
[can_run_script]
Element getFirstRow(in Element aTableElement);
/** Preferred direction to search for neighboring cell
@ -393,6 +397,7 @@ interface nsITableEditor : nsISupports
* and getNextSelectedCell(). I.e., getNextSelectedCell() will
* return second selected cell element.
*/
[can_run_script]
Element getSelectedOrParentTableElement(out AString aTagName,
out long aCount);
@ -450,5 +455,6 @@ interface nsITableEditor : nsISupports
* If second or later ranges do not select only a table cell element, this
* ignores the ranges.
*/
[can_run_script]
Array<Element> getSelectedCells();
};