Bug 1349138 Edit transactions should store their editor instance with strong reference r=smaug

Edit transactions should store their editor instance with strong reference and they should be released at destroying the editor.

MozReview-Commit-ID: D67KU8WFxyo

--HG--
extra : rebase_source : 28c8a37498cad9f2e308eb4416cef76cf395bb9c
This commit is contained in:
Masayuki Nakano 2017-03-21 19:00:36 +09:00
Родитель 0901ad8256
Коммит e877ded333
23 изменённых файлов: 181 добавлений и 81 удалений

Просмотреть файл

@ -33,7 +33,7 @@ CompositionTransaction::CompositionTransaction(
, mReplaceLength(aReplaceLength)
, mRanges(aTextRangeArray)
, mStringToInsert(aStringToInsert)
, mEditorBase(aEditorBase)
, mEditorBase(&aEditorBase)
, mRangeUpdater(aRangeUpdater)
, mFixed(false)
{
@ -45,6 +45,7 @@ CompositionTransaction::~CompositionTransaction()
}
NS_IMPL_CYCLE_COLLECTION_INHERITED(CompositionTransaction, EditTransactionBase,
mEditorBase,
mTextNode)
// mRangeList can't lead to cycles
@ -60,9 +61,13 @@ NS_IMPL_RELEASE_INHERITED(CompositionTransaction, EditTransactionBase)
NS_IMETHODIMP
CompositionTransaction::DoTransaction()
{
if (NS_WARN_IF(!mEditorBase)) {
return NS_ERROR_NOT_INITIALIZED;
}
// Fail before making any changes if there's no selection controller
nsCOMPtr<nsISelectionController> selCon;
mEditorBase.GetSelectionController(getter_AddRefs(selCon));
mEditorBase->GetSelectionController(getter_AddRefs(selCon));
NS_ENSURE_TRUE(selCon, NS_ERROR_NOT_INITIALIZED);
// Advance caret: This requires the presentation shell to get the selection.
@ -108,9 +113,13 @@ CompositionTransaction::DoTransaction()
NS_IMETHODIMP
CompositionTransaction::UndoTransaction()
{
if (NS_WARN_IF(!mEditorBase)) {
return NS_ERROR_NOT_INITIALIZED;
}
// Get the selection first so we'll fail before making any changes if we
// can't get it
RefPtr<Selection> selection = mEditorBase.GetSelection();
RefPtr<Selection> selection = mEditorBase->GetSelection();
NS_ENSURE_TRUE(selection, NS_ERROR_NOT_INITIALIZED);
nsresult rv = mTextNode->DeleteData(mOffset, mStringToInsert.Length());
@ -171,7 +180,10 @@ CompositionTransaction::GetTxnDescription(nsAString& aString)
nsresult
CompositionTransaction::SetSelectionForRanges()
{
return SetIMESelection(mEditorBase, mTextNode, mOffset,
if (NS_WARN_IF(!mEditorBase)) {
return NS_ERROR_NOT_INITIALIZED;
}
return SetIMESelection(*mEditorBase, mTextNode, mOffset,
mStringToInsert.Length(), mRanges);
}

Просмотреть файл

@ -90,7 +90,7 @@ private:
nsString mStringToInsert;
// The editor, which is used to get the selection controller.
EditorBase& mEditorBase;
RefPtr<EditorBase> mEditorBase;
RangeUpdater* mRangeUpdater;

Просмотреть файл

@ -49,6 +49,7 @@ CreateElementTransaction::~CreateElementTransaction()
NS_IMPL_CYCLE_COLLECTION_INHERITED(CreateElementTransaction,
EditTransactionBase,
mEditorBase,
mParent,
mNewNode,
mRefNode)
@ -62,7 +63,9 @@ NS_INTERFACE_MAP_END_INHERITING(EditTransactionBase)
NS_IMETHODIMP
CreateElementTransaction::DoTransaction()
{
MOZ_ASSERT(mEditorBase && mTag && mParent);
if (NS_WARN_IF(!mEditorBase) || NS_WARN_IF(!mTag) || NS_WARN_IF(!mParent)) {
return NS_ERROR_NOT_INITIALIZED;
}
mNewNode = mEditorBase->CreateHTMLContent(mTag);
NS_ENSURE_STATE(mNewNode);
@ -105,7 +108,9 @@ CreateElementTransaction::DoTransaction()
NS_IMETHODIMP
CreateElementTransaction::UndoTransaction()
{
MOZ_ASSERT(mEditorBase && mParent);
if (NS_WARN_IF(!mEditorBase) || NS_WARN_IF(!mParent)) {
return NS_ERROR_NOT_INITIALIZED;
}
ErrorResult rv;
mParent->RemoveChild(*mNewNode, rv);
@ -116,7 +121,9 @@ CreateElementTransaction::UndoTransaction()
NS_IMETHODIMP
CreateElementTransaction::RedoTransaction()
{
MOZ_ASSERT(mEditorBase && mParent);
if (NS_WARN_IF(!mEditorBase) || NS_WARN_IF(!mParent)) {
return NS_ERROR_NOT_INITIALIZED;
}
// First, reset mNewNode so it has no attributes or content
// XXX We never actually did this, we only cleared mNewNode's contents if it

Просмотреть файл

@ -57,7 +57,7 @@ protected:
virtual ~CreateElementTransaction();
// The document into which the new node will be inserted.
EditorBase* mEditorBase;
RefPtr<EditorBase> mEditorBase;
// The tag (mapping to object type) for the new element.
nsCOMPtr<nsIAtom> mTag;

Просмотреть файл

@ -15,7 +15,7 @@ namespace mozilla {
DeleteNodeTransaction::DeleteNodeTransaction(EditorBase& aEditorBase,
nsINode& aNodeToDelete,
RangeUpdater* aRangeUpdater)
: mEditorBase(aEditorBase)
: mEditorBase(&aEditorBase)
, mNodeToDelete(&aNodeToDelete)
, mParentNode(aNodeToDelete.GetParentNode())
, mRangeUpdater(aRangeUpdater)
@ -31,6 +31,7 @@ DeleteNodeTransaction::~DeleteNodeTransaction()
}
NS_IMPL_CYCLE_COLLECTION_INHERITED(DeleteNodeTransaction, EditTransactionBase,
mEditorBase,
mNodeToDelete,
mParentNode,
mRefNode)
@ -43,8 +44,8 @@ NS_INTERFACE_MAP_END_INHERITING(EditTransactionBase)
bool
DeleteNodeTransaction::CanDoIt() const
{
if (NS_WARN_IF(!mNodeToDelete) || !mParentNode ||
!mEditorBase.IsModifiableNode(mParentNode)) {
if (NS_WARN_IF(!mNodeToDelete) || NS_WARN_IF(!mEditorBase) ||
!mParentNode || !mEditorBase->IsModifiableNode(mParentNode)) {
return false;
}
return true;

Просмотреть файл

@ -46,7 +46,7 @@ protected:
virtual ~DeleteNodeTransaction();
// The editor for this transaction.
EditorBase& mEditorBase;
RefPtr<EditorBase> mEditorBase;
// The element to delete.
nsCOMPtr<nsINode> mNodeToDelete;

Просмотреть файл

@ -27,7 +27,7 @@ using namespace dom;
DeleteRangeTransaction::DeleteRangeTransaction(EditorBase& aEditorBase,
nsRange& aRangeToDelete,
RangeUpdater* aRangeUpdater)
: mEditorBase(aEditorBase)
: mEditorBase(&aEditorBase)
, mRangeToDelete(aRangeToDelete.CloneRange())
, mRangeUpdater(aRangeUpdater)
{
@ -35,6 +35,7 @@ DeleteRangeTransaction::DeleteRangeTransaction(EditorBase& aEditorBase,
NS_IMPL_CYCLE_COLLECTION_INHERITED(DeleteRangeTransaction,
EditAggregateTransaction,
mEditorBase,
mRangeToDelete)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(DeleteRangeTransaction)
@ -43,7 +44,9 @@ NS_INTERFACE_MAP_END_INHERITING(EditAggregateTransaction)
NS_IMETHODIMP
DeleteRangeTransaction::DoTransaction()
{
MOZ_ASSERT(mRangeToDelete);
if (NS_WARN_IF(!mEditorBase) || NS_WARN_IF(!mRangeToDelete)) {
return NS_ERROR_NOT_AVAILABLE;
}
// build the child transactions
nsCOMPtr<nsINode> startParent = mRangeToDelete->GetStartParent();
@ -77,9 +80,9 @@ DeleteRangeTransaction::DoTransaction()
// only set selection to deletion point if editor gives permission
bool bAdjustSelection;
mEditorBase.ShouldTxnSetSelection(&bAdjustSelection);
mEditorBase->ShouldTxnSetSelection(&bAdjustSelection);
if (bAdjustSelection) {
RefPtr<Selection> selection = mEditorBase.GetSelection();
RefPtr<Selection> selection = mEditorBase->GetSelection();
NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);
rv = selection->Collapse(startParent, startOffset);
NS_ENSURE_SUCCESS(rv, rv);
@ -117,6 +120,10 @@ DeleteRangeTransaction::CreateTxnsToDeleteBetween(nsINode* aNode,
int32_t aStartOffset,
int32_t aEndOffset)
{
if (NS_WARN_IF(!mEditorBase)) {
return NS_ERROR_NOT_AVAILABLE;
}
// see what kind of node we have
if (aNode->IsNodeOfType(nsINode::eDATA_NODE)) {
// if the node is a chardata node, then delete chardata content
@ -131,7 +138,7 @@ DeleteRangeTransaction::CreateTxnsToDeleteBetween(nsINode* aNode,
static_cast<nsGenericDOMDataNode*>(aNode);
RefPtr<DeleteTextTransaction> deleteTextTransaction =
new DeleteTextTransaction(mEditorBase, *charDataNode, aStartOffset,
new DeleteTextTransaction(*mEditorBase, *charDataNode, aStartOffset,
numToDel, mRangeUpdater);
// If the text node isn't editable, it should be never undone/redone.
// So, the transaction shouldn't be recorded.
@ -150,7 +157,7 @@ DeleteRangeTransaction::CreateTxnsToDeleteBetween(nsINode* aNode,
break;
}
RefPtr<DeleteNodeTransaction> deleteNodeTransaction =
new DeleteNodeTransaction(mEditorBase, *child, mRangeUpdater);
new DeleteNodeTransaction(*mEditorBase, *child, mRangeUpdater);
// XXX This is odd handling. Even if some children are not editable,
// editor should append transactions because they could be editable
// at undoing/redoing. Additionally, if the transaction needs to
@ -169,6 +176,10 @@ DeleteRangeTransaction::CreateTxnsToDeleteContent(nsINode* aNode,
int32_t aOffset,
nsIEditor::EDirection aAction)
{
if (NS_WARN_IF(!mEditorBase)) {
return NS_ERROR_NOT_AVAILABLE;
}
// see what kind of node we have
if (aNode->IsNodeOfType(nsINode::eDATA_NODE)) {
// if the node is a chardata node, then delete chardata content
@ -185,7 +196,7 @@ DeleteRangeTransaction::CreateTxnsToDeleteContent(nsINode* aNode,
RefPtr<nsGenericDOMDataNode> dataNode =
static_cast<nsGenericDOMDataNode*>(aNode);
RefPtr<DeleteTextTransaction> deleteTextTransaction =
new DeleteTextTransaction(mEditorBase, *dataNode, start, numToDelete,
new DeleteTextTransaction(*mEditorBase, *dataNode, start, numToDelete,
mRangeUpdater);
// If the text node isn't editable, it should be never undone/redone.
// So, the transaction shouldn't be recorded.
@ -202,6 +213,10 @@ DeleteRangeTransaction::CreateTxnsToDeleteContent(nsINode* aNode,
nsresult
DeleteRangeTransaction::CreateTxnsToDeleteNodesBetween()
{
if (NS_WARN_IF(!mEditorBase)) {
return NS_ERROR_NOT_AVAILABLE;
}
nsCOMPtr<nsIContentIterator> iter = NS_NewContentSubtreeIterator();
nsresult rv = iter->Init(mRangeToDelete);
@ -214,7 +229,7 @@ DeleteRangeTransaction::CreateTxnsToDeleteNodesBetween()
}
RefPtr<DeleteNodeTransaction> deleteNodeTransaction =
new DeleteNodeTransaction(mEditorBase, *node, mRangeUpdater);
new DeleteNodeTransaction(*mEditorBase, *node, mRangeUpdater);
// XXX This is odd handling. Even if some nodes in the range are not
// editable, editor should append transactions because they could
// at undoing/redoing. Additionally, if the transaction needs to

Просмотреть файл

@ -61,7 +61,7 @@ protected:
nsIEditor::EDirection aAction);
// The editor for this transaction.
EditorBase& mEditorBase;
RefPtr<EditorBase> mEditorBase;
// P1 in the range.
RefPtr<nsRange> mRangeToDelete;

Просмотреть файл

@ -25,7 +25,7 @@ DeleteTextTransaction::DeleteTextTransaction(
uint32_t aOffset,
uint32_t aNumCharsToDelete,
RangeUpdater* aRangeUpdater)
: mEditorBase(aEditorBase)
: mEditorBase(&aEditorBase)
, mCharData(&aCharData)
, mOffset(aOffset)
, mNumCharsToDelete(aNumCharsToDelete)
@ -36,6 +36,7 @@ DeleteTextTransaction::DeleteTextTransaction(
}
NS_IMPL_CYCLE_COLLECTION_INHERITED(DeleteTextTransaction, EditTransactionBase,
mEditorBase,
mCharData)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(DeleteTextTransaction)
@ -44,16 +45,18 @@ NS_INTERFACE_MAP_END_INHERITING(EditTransactionBase)
bool
DeleteTextTransaction::CanDoIt() const
{
if (NS_WARN_IF(!mCharData)) {
if (NS_WARN_IF(!mCharData) || NS_WARN_IF(!mEditorBase)) {
return false;
}
return mEditorBase.IsModifiableNode(mCharData);
return mEditorBase->IsModifiableNode(mCharData);
}
NS_IMETHODIMP
DeleteTextTransaction::DoTransaction()
{
MOZ_ASSERT(mCharData);
if (NS_WARN_IF(!mEditorBase) || NS_WARN_IF(!mCharData)) {
return NS_ERROR_NOT_AVAILABLE;
}
// Get the text that we're about to delete
nsresult rv = mCharData->SubstringData(mOffset, mNumCharsToDelete,
@ -67,8 +70,8 @@ DeleteTextTransaction::DoTransaction()
}
// Only set selection to deletion point if editor gives permission
if (mEditorBase.GetShouldTxnSetSelection()) {
RefPtr<Selection> selection = mEditorBase.GetSelection();
if (mEditorBase->GetShouldTxnSetSelection()) {
RefPtr<Selection> selection = mEditorBase->GetSelection();
NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);
rv = selection->Collapse(mCharData, mOffset);
NS_ASSERTION(NS_SUCCEEDED(rv),
@ -84,8 +87,9 @@ DeleteTextTransaction::DoTransaction()
NS_IMETHODIMP
DeleteTextTransaction::UndoTransaction()
{
MOZ_ASSERT(mCharData);
if (NS_WARN_IF(!mCharData)) {
return NS_ERROR_NOT_INITIALIZED;
}
return mCharData->InsertData(mOffset, mDeletedText);
}

Просмотреть файл

@ -57,7 +57,7 @@ public:
protected:
// The provider of basic editing operations.
EditorBase& mEditorBase;
RefPtr<EditorBase> mEditorBase;
// The CharacterData node to operate upon.
RefPtr<nsGenericDOMDataNode> mCharData;

Просмотреть файл

@ -465,6 +465,13 @@ EditorBase::PreDestroy(bool aDestroyingFrames)
mSpellcheckCheckboxState = eTriUnset;
mRootElement = nullptr;
// Transaction may grab this instance. Therefore, they should be released
// here for stopping the circular reference with this instance.
if (mTxnMgr) {
mTxnMgr->Clear();
mTxnMgr = nullptr;
}
mDidPreDestroy = true;
return NS_OK;
}

Просмотреть файл

@ -28,7 +28,7 @@ InsertNodeTransaction::InsertNodeTransaction(nsIContent& aNode,
: mNode(&aNode)
, mParent(&aParent)
, mOffset(aOffset)
, mEditorBase(aEditorBase)
, mEditorBase(&aEditorBase)
{
}
@ -37,6 +37,7 @@ InsertNodeTransaction::~InsertNodeTransaction()
}
NS_IMPL_CYCLE_COLLECTION_INHERITED(InsertNodeTransaction, EditTransactionBase,
mEditorBase,
mNode,
mParent)
@ -48,7 +49,9 @@ NS_INTERFACE_MAP_END_INHERITING(EditTransactionBase)
NS_IMETHODIMP
InsertNodeTransaction::DoTransaction()
{
MOZ_ASSERT(mNode && mParent);
if (NS_WARN_IF(!mEditorBase) || NS_WARN_IF(!mNode) || NS_WARN_IF(!mParent)) {
return NS_ERROR_NOT_INITIALIZED;
}
uint32_t count = mParent->GetChildCount();
if (mOffset > static_cast<int32_t>(count) || mOffset == -1) {
@ -59,15 +62,15 @@ InsertNodeTransaction::DoTransaction()
// Note, it's ok for ref to be null. That means append.
nsCOMPtr<nsIContent> ref = mParent->GetChildAt(mOffset);
mEditorBase.MarkNodeDirty(GetAsDOMNode(mNode));
mEditorBase->MarkNodeDirty(GetAsDOMNode(mNode));
ErrorResult rv;
mParent->InsertBefore(*mNode, ref, rv);
NS_ENSURE_TRUE(!rv.Failed(), rv.StealNSResult());
// Only set selection to insertion point if editor gives permission
if (mEditorBase.GetShouldTxnSetSelection()) {
RefPtr<Selection> selection = mEditorBase.GetSelection();
if (mEditorBase->GetShouldTxnSetSelection()) {
RefPtr<Selection> selection = mEditorBase->GetSelection();
NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);
// Place the selection just after the inserted element
selection->Collapse(mParent, mOffset + 1);
@ -80,8 +83,9 @@ InsertNodeTransaction::DoTransaction()
NS_IMETHODIMP
InsertNodeTransaction::UndoTransaction()
{
MOZ_ASSERT(mNode && mParent);
if (NS_WARN_IF(!mNode) || NS_WARN_IF(!mParent)) {
return NS_ERROR_NOT_INITIALIZED;
}
ErrorResult rv;
mParent->RemoveChild(*mNode, rv);
return rv.StealNSResult();

Просмотреть файл

@ -50,7 +50,7 @@ protected:
int32_t mOffset;
// The editor for this transaction.
EditorBase& mEditorBase;
RefPtr<EditorBase> mEditorBase;
};
} // namespace mozilla

Просмотреть файл

@ -26,7 +26,7 @@ InsertTextTransaction::InsertTextTransaction(Text& aTextNode,
: mTextNode(&aTextNode)
, mOffset(aOffset)
, mStringToInsert(aStringToInsert)
, mEditorBase(aEditorBase)
, mEditorBase(&aEditorBase)
, mRangeUpdater(aRangeUpdater)
{
}
@ -36,6 +36,7 @@ InsertTextTransaction::~InsertTextTransaction()
}
NS_IMPL_CYCLE_COLLECTION_INHERITED(InsertTextTransaction, EditTransactionBase,
mEditorBase,
mTextNode)
NS_IMPL_ADDREF_INHERITED(InsertTextTransaction, EditTransactionBase)
@ -50,12 +51,16 @@ NS_INTERFACE_MAP_END_INHERITING(EditTransactionBase)
NS_IMETHODIMP
InsertTextTransaction::DoTransaction()
{
if (NS_WARN_IF(!mEditorBase) || NS_WARN_IF(!mTextNode)) {
return NS_ERROR_NOT_AVAILABLE;
}
nsresult rv = mTextNode->InsertData(mOffset, mStringToInsert);
NS_ENSURE_SUCCESS(rv, rv);
// Only set selection to insertion point if editor gives permission
if (mEditorBase.GetShouldTxnSetSelection()) {
RefPtr<Selection> selection = mEditorBase.GetSelection();
if (mEditorBase->GetShouldTxnSetSelection()) {
RefPtr<Selection> selection = mEditorBase->GetSelection();
NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);
DebugOnly<nsresult> rv =
selection->Collapse(mTextNode, mOffset + mStringToInsert.Length());

Просмотреть файл

@ -76,7 +76,7 @@ private:
nsString mStringToInsert;
// The editor, which we'll need to get the selection.
EditorBase& mEditorBase;
RefPtr<EditorBase> mEditorBase;
RangeUpdater* mRangeUpdater;
};

Просмотреть файл

@ -21,7 +21,7 @@ using namespace dom;
JoinNodeTransaction::JoinNodeTransaction(EditorBase& aEditorBase,
nsINode& aLeftNode,
nsINode& aRightNode)
: mEditorBase(aEditorBase)
: mEditorBase(&aEditorBase)
, mLeftNode(&aLeftNode)
, mRightNode(&aRightNode)
, mOffset(0)
@ -29,6 +29,7 @@ JoinNodeTransaction::JoinNodeTransaction(EditorBase& aEditorBase,
}
NS_IMPL_CYCLE_COLLECTION_INHERITED(JoinNodeTransaction, EditTransactionBase,
mEditorBase,
mLeftNode,
mRightNode,
mParent)
@ -41,10 +42,11 @@ JoinNodeTransaction::CanDoIt() const
{
if (NS_WARN_IF(!mLeftNode) ||
NS_WARN_IF(!mRightNode) ||
NS_WARN_IF(!mEditorBase) ||
!mLeftNode->GetParentNode()) {
return false;
}
return mEditorBase.IsModifiableNode(mLeftNode->GetParentNode());
return mEditorBase->IsModifiableNode(mLeftNode->GetParentNode());
}
// After DoTransaction() and RedoTransaction(), the left node is removed from
@ -52,6 +54,12 @@ JoinNodeTransaction::CanDoIt() const
NS_IMETHODIMP
JoinNodeTransaction::DoTransaction()
{
if (NS_WARN_IF(!mEditorBase) ||
NS_WARN_IF(!mLeftNode) ||
NS_WARN_IF(!mRightNode)) {
return NS_ERROR_NOT_INITIALIZED;
}
// Get the parent node
nsCOMPtr<nsINode> leftParent = mLeftNode->GetParentNode();
NS_ENSURE_TRUE(leftParent, NS_ERROR_NULL_POINTER);
@ -67,7 +75,7 @@ JoinNodeTransaction::DoTransaction()
mParent = leftParent;
mOffset = mLeftNode->Length();
return mEditorBase.JoinNodesImpl(mRightNode, mLeftNode, mParent);
return mEditorBase->JoinNodesImpl(mRightNode, mLeftNode, mParent);
}
//XXX: What if instead of split, we just deleted the unneeded children of
@ -75,7 +83,11 @@ JoinNodeTransaction::DoTransaction()
NS_IMETHODIMP
JoinNodeTransaction::UndoTransaction()
{
MOZ_ASSERT(mParent);
if (NS_WARN_IF(!mParent) ||
NS_WARN_IF(!mLeftNode) ||
NS_WARN_IF(!mRightNode)) {
return NS_ERROR_NOT_INITIALIZED;
}
// First, massage the existing node so it is in its post-split state
ErrorResult rv;

Просмотреть файл

@ -48,7 +48,7 @@ public:
NS_DECL_EDITTRANSACTIONBASE
protected:
EditorBase& mEditorBase;
RefPtr<EditorBase> mEditorBase;
// The nodes to operate upon. After the merge, mRightNode remains and
// mLeftNode is removed from the content tree.

Просмотреть файл

@ -25,7 +25,7 @@ PlaceholderTransaction::PlaceholderTransaction(
, mCompositionTransaction(nullptr)
, mCommitted(false)
, mStartSel(Move(aSelState))
, mEditorBase(aEditorBase)
, mEditorBase(&aEditorBase)
{
mName = aName;
}
@ -41,6 +41,7 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(PlaceholderTransaction,
if (tmp->mStartSel) {
ImplCycleCollectionUnlink(*tmp->mStartSel);
}
NS_IMPL_CYCLE_COLLECTION_UNLINK(mEditorBase);
NS_IMPL_CYCLE_COLLECTION_UNLINK(mEndSel);
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
@ -49,6 +50,7 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(PlaceholderTransaction,
if (tmp->mStartSel) {
ImplCycleCollectionTraverse(cb, *tmp->mStartSel, "mStartSel", 0);
}
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mEditorBase);
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mEndSel);
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
@ -69,6 +71,10 @@ PlaceholderTransaction::DoTransaction()
NS_IMETHODIMP
PlaceholderTransaction::UndoTransaction()
{
if (NS_WARN_IF(!mEditorBase)) {
return NS_ERROR_NOT_INITIALIZED;
}
// Undo transactions.
nsresult rv = EditAggregateTransaction::UndoTransaction();
NS_ENSURE_SUCCESS(rv, rv);
@ -76,7 +82,7 @@ PlaceholderTransaction::UndoTransaction()
NS_ENSURE_TRUE(mStartSel, NS_ERROR_NULL_POINTER);
// now restore selection
RefPtr<Selection> selection = mEditorBase.GetSelection();
RefPtr<Selection> selection = mEditorBase->GetSelection();
NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);
return mStartSel->RestoreSelection(selection);
}
@ -84,12 +90,16 @@ PlaceholderTransaction::UndoTransaction()
NS_IMETHODIMP
PlaceholderTransaction::RedoTransaction()
{
if (NS_WARN_IF(!mEditorBase)) {
return NS_ERROR_NOT_INITIALIZED;
}
// Redo transactions.
nsresult rv = EditAggregateTransaction::RedoTransaction();
NS_ENSURE_SUCCESS(rv, rv);
// now restore selection
RefPtr<Selection> selection = mEditorBase.GetSelection();
RefPtr<Selection> selection = mEditorBase->GetSelection();
NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);
return mEndSel.RestoreSelection(selection);
}
@ -254,7 +264,11 @@ PlaceholderTransaction::Commit()
nsresult
PlaceholderTransaction::RememberEndingSelection()
{
RefPtr<Selection> selection = mEditorBase.GetSelection();
if (NS_WARN_IF(!mEditorBase)) {
return NS_ERROR_NOT_INITIALIZED;
}
RefPtr<Selection> selection = mEditorBase->GetSelection();
NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);
mEndSel.SaveSelection(selection);
return NS_OK;

Просмотреть файл

@ -82,7 +82,7 @@ protected:
SelectionState mEndSel;
// The editor for this transaction.
EditorBase& mEditorBase;
RefPtr<EditorBase> mEditorBase;
};
} // namespace mozilla

Просмотреть файл

@ -19,7 +19,7 @@ using namespace dom;
SplitNodeTransaction::SplitNodeTransaction(EditorBase& aEditorBase,
nsIContent& aNode,
int32_t aOffset)
: mEditorBase(aEditorBase)
: mEditorBase(&aEditorBase)
, mExistingRightNode(&aNode)
, mOffset(aOffset)
{
@ -30,6 +30,7 @@ SplitNodeTransaction::~SplitNodeTransaction()
}
NS_IMPL_CYCLE_COLLECTION_INHERITED(SplitNodeTransaction, EditTransactionBase,
mEditorBase,
mParent,
mNewLeftNode)
@ -41,6 +42,10 @@ NS_INTERFACE_MAP_END_INHERITING(EditTransactionBase)
NS_IMETHODIMP
SplitNodeTransaction::DoTransaction()
{
if (NS_WARN_IF(!mEditorBase)) {
return NS_ERROR_NOT_INITIALIZED;
}
// Create a new node
ErrorResult rv;
// Don't use .downcast directly because AsContent has an assertion we want
@ -48,16 +53,16 @@ SplitNodeTransaction::DoTransaction()
NS_ASSERTION(!rv.Failed() && clone, "Could not create clone");
NS_ENSURE_TRUE(!rv.Failed() && clone, rv.StealNSResult());
mNewLeftNode = dont_AddRef(clone.forget().take()->AsContent());
mEditorBase.MarkNodeDirty(mExistingRightNode->AsDOMNode());
mEditorBase->MarkNodeDirty(mExistingRightNode->AsDOMNode());
// Get the parent node
mParent = mExistingRightNode->GetParentNode();
NS_ENSURE_TRUE(mParent, NS_ERROR_NULL_POINTER);
// Insert the new node
rv = mEditorBase.SplitNodeImpl(*mExistingRightNode, mOffset, *mNewLeftNode);
if (mEditorBase.GetShouldTxnSetSelection()) {
RefPtr<Selection> selection = mEditorBase.GetSelection();
rv = mEditorBase->SplitNodeImpl(*mExistingRightNode, mOffset, *mNewLeftNode);
if (mEditorBase->GetShouldTxnSetSelection()) {
RefPtr<Selection> selection = mEditorBase->GetSelection();
NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);
rv = selection->Collapse(mNewLeftNode, mOffset);
}
@ -67,10 +72,14 @@ SplitNodeTransaction::DoTransaction()
NS_IMETHODIMP
SplitNodeTransaction::UndoTransaction()
{
MOZ_ASSERT(mNewLeftNode && mParent);
if (NS_WARN_IF(!mEditorBase) ||
NS_WARN_IF(!mNewLeftNode) ||
NS_WARN_IF(!mParent)) {
return NS_ERROR_NOT_INITIALIZED;
}
// This assumes Do inserted the new node in front of the prior existing node
return mEditorBase.JoinNodesImpl(mExistingRightNode, mNewLeftNode, mParent);
return mEditorBase->JoinNodesImpl(mExistingRightNode, mNewLeftNode, mParent);
}
/* Redo cannot simply resplit the right node, because subsequent transactions
@ -80,7 +89,10 @@ SplitNodeTransaction::UndoTransaction()
NS_IMETHODIMP
SplitNodeTransaction::RedoTransaction()
{
MOZ_ASSERT(mNewLeftNode && mParent);
if (NS_WARN_IF(!mNewLeftNode) ||
NS_WARN_IF(!mParent)) {
return NS_ERROR_NOT_INITIALIZED;
}
ErrorResult rv;
// First, massage the existing node so it is in its post-split state

Просмотреть файл

@ -49,7 +49,7 @@ public:
protected:
virtual ~SplitNodeTransaction();
EditorBase& mEditorBase;
RefPtr<EditorBase> mEditorBase;
// The node to operate upon.
nsCOMPtr<nsIContent> mExistingRightNode;

Просмотреть файл

@ -44,9 +44,9 @@ RemoveStyleSheet(EditorBase& aEditor, StyleSheet* aSheet)
* AddStyleSheetTransaction
******************************************************************************/
AddStyleSheetTransaction::AddStyleSheetTransaction(EditorBase& aEditor,
AddStyleSheetTransaction::AddStyleSheetTransaction(EditorBase& aEditorBase,
StyleSheet* aSheet)
: mEditor(aEditor)
: mEditorBase(&aEditorBase)
, mSheet(aSheet)
{
MOZ_ASSERT(aSheet);
@ -54,6 +54,7 @@ AddStyleSheetTransaction::AddStyleSheetTransaction(EditorBase& aEditor,
NS_IMPL_CYCLE_COLLECTION_INHERITED(AddStyleSheetTransaction,
EditTransactionBase,
mEditorBase,
mSheet)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(AddStyleSheetTransaction)
@ -62,18 +63,20 @@ NS_INTERFACE_MAP_END_INHERITING(EditTransactionBase)
NS_IMETHODIMP
AddStyleSheetTransaction::DoTransaction()
{
NS_ENSURE_TRUE(mSheet, NS_ERROR_NOT_INITIALIZED);
AddStyleSheet(mEditor, mSheet);
if (NS_WARN_IF(!mEditorBase) || NS_WARN_IF(!mSheet)) {
return NS_ERROR_NOT_INITIALIZED;
}
AddStyleSheet(*mEditorBase, mSheet);
return NS_OK;
}
NS_IMETHODIMP
AddStyleSheetTransaction::UndoTransaction()
{
NS_ENSURE_TRUE(mSheet, NS_ERROR_NOT_INITIALIZED);
RemoveStyleSheet(mEditor, mSheet);
if (NS_WARN_IF(!mEditorBase) || NS_WARN_IF(!mSheet)) {
return NS_ERROR_NOT_INITIALIZED;
}
RemoveStyleSheet(*mEditorBase, mSheet);
return NS_OK;
}
@ -88,9 +91,10 @@ AddStyleSheetTransaction::GetTxnDescription(nsAString& aString)
* RemoveStyleSheetTransaction
******************************************************************************/
RemoveStyleSheetTransaction::RemoveStyleSheetTransaction(EditorBase& aEditor,
StyleSheet* aSheet)
: mEditor(aEditor)
RemoveStyleSheetTransaction::RemoveStyleSheetTransaction(
EditorBase& aEditorBase,
StyleSheet* aSheet)
: mEditorBase(&aEditorBase)
, mSheet(aSheet)
{
MOZ_ASSERT(aSheet);
@ -98,6 +102,7 @@ RemoveStyleSheetTransaction::RemoveStyleSheetTransaction(EditorBase& aEditor,
NS_IMPL_CYCLE_COLLECTION_INHERITED(RemoveStyleSheetTransaction,
EditTransactionBase,
mEditorBase,
mSheet)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(RemoveStyleSheetTransaction)
@ -106,18 +111,20 @@ NS_INTERFACE_MAP_END_INHERITING(EditTransactionBase)
NS_IMETHODIMP
RemoveStyleSheetTransaction::DoTransaction()
{
NS_ENSURE_TRUE(mSheet, NS_ERROR_NOT_INITIALIZED);
RemoveStyleSheet(mEditor, mSheet);
if (NS_WARN_IF(!mEditorBase) || NS_WARN_IF(!mSheet)) {
return NS_ERROR_NOT_INITIALIZED;
}
RemoveStyleSheet(*mEditorBase, mSheet);
return NS_OK;
}
NS_IMETHODIMP
RemoveStyleSheetTransaction::UndoTransaction()
{
NS_ENSURE_TRUE(mSheet, NS_ERROR_NOT_INITIALIZED);
AddStyleSheet(mEditor, mSheet);
if (NS_WARN_IF(!mEditorBase) || NS_WARN_IF(!mSheet)) {
return NS_ERROR_NOT_INITIALIZED;
}
AddStyleSheet(*mEditorBase, mSheet);
return NS_OK;
}

Просмотреть файл

@ -32,7 +32,7 @@ public:
protected:
// The editor that created this transaction.
EditorBase& mEditor;
RefPtr<EditorBase> mEditorBase;
// The style sheet to add.
RefPtr<mozilla::StyleSheet> mSheet;
};
@ -55,7 +55,7 @@ public:
protected:
// The editor that created this transaction.
EditorBase& mEditor;
RefPtr<EditorBase> mEditorBase;
// The style sheet to remove.
RefPtr<StyleSheet> mSheet;