summaryrefslogtreecommitdiffstats
path: root/editor/libeditor
diff options
context:
space:
mode:
authorMoonchild <moonchild@palemoon.org>2020-04-17 16:02:56 +0200
committerGitHub <noreply@github.com>2020-04-17 16:02:56 +0200
commitd5102d6beafc2a2a0cec3cc3ee5f7ebde31ae7bf (patch)
tree2bfef192cbb748b675ce8308c242a376798e265d /editor/libeditor
parent5caf99795aa81e1fc145b8e937b1ee8197ed2486 (diff)
parentf35aa3e15fedf3cd4ad163d60ab74a9537ca5c82 (diff)
downloadUXP-d5102d6beafc2a2a0cec3cc3ee5f7ebde31ae7bf.tar
UXP-d5102d6beafc2a2a0cec3cc3ee5f7ebde31ae7bf.tar.gz
UXP-d5102d6beafc2a2a0cec3cc3ee5f7ebde31ae7bf.tar.lz
UXP-d5102d6beafc2a2a0cec3cc3ee5f7ebde31ae7bf.tar.xz
UXP-d5102d6beafc2a2a0cec3cc3ee5f7ebde31ae7bf.zip
Merge pull request #1518 from MoonchildProductions/shadowdom-merge
Incremental shadowdom-merge
Diffstat (limited to 'editor/libeditor')
-rw-r--r--editor/libeditor/EditorBase.cpp497
-rw-r--r--editor/libeditor/EditorBase.h94
-rw-r--r--editor/libeditor/HTMLEditRules.cpp214
-rw-r--r--editor/libeditor/HTMLEditUtils.cpp72
-rw-r--r--editor/libeditor/HTMLEditor.cpp264
-rw-r--r--editor/libeditor/HTMLEditor.h4
-rw-r--r--editor/libeditor/HTMLEditorDataTransfer.cpp7
-rw-r--r--editor/libeditor/HTMLStyleEditor.cpp28
-rw-r--r--editor/libeditor/HTMLTableEditor.cpp16
-rw-r--r--editor/libeditor/PlaceholderTransaction.cpp24
-rw-r--r--editor/libeditor/PlaceholderTransaction.h25
-rw-r--r--editor/libeditor/SelectionState.cpp3
-rw-r--r--editor/libeditor/TextEditRules.cpp9
-rw-r--r--editor/libeditor/TextEditRules.h2
-rw-r--r--editor/libeditor/TextEditor.cpp10
-rw-r--r--editor/libeditor/TypeInState.cpp8
-rw-r--r--editor/libeditor/TypeInState.h5
-rw-r--r--editor/libeditor/WSRunObject.cpp2
-rw-r--r--editor/libeditor/crashtests/1348851.html19
-rw-r--r--editor/libeditor/crashtests/crashtests.list1
-rw-r--r--editor/libeditor/nsIAbsorbingTransaction.h7
-rw-r--r--editor/libeditor/nsIEditRules.h2
22 files changed, 728 insertions, 585 deletions
diff --git a/editor/libeditor/EditorBase.cpp b/editor/libeditor/EditorBase.cpp
index f7988cd1a..3f419a74e 100644
--- a/editor/libeditor/EditorBase.cpp
+++ b/editor/libeditor/EditorBase.cpp
@@ -37,6 +37,7 @@
#include "mozilla/TextComposition.h" // for TextComposition
#include "mozilla/TextEvents.h"
#include "mozilla/dom/Element.h" // for Element, nsINode::AsElement
+#include "mozilla/dom/HTMLBodyElement.h"
#include "mozilla/dom/Text.h"
#include "mozilla/dom/Event.h"
#include "mozilla/mozalloc.h" // for operator new, etc.
@@ -71,7 +72,6 @@
#include "nsIDOMNode.h" // for nsIDOMNode, etc.
#include "nsIDOMNodeList.h" // for nsIDOMNodeList
#include "nsIDOMText.h" // for nsIDOMText
-#include "nsIDocument.h" // for nsIDocument
#include "nsIDocumentStateListener.h" // for nsIDocumentStateListener
#include "nsIEditActionListener.h" // for nsIEditActionListener
#include "nsIEditorObserver.h" // for nsIEditorObserver
@@ -107,16 +107,12 @@
#include "prtime.h" // for PR_Now
class nsIOutputStream;
-class nsIParserService;
class nsITransferable;
#ifdef DEBUG
#include "nsIDOMHTMLDocument.h" // for nsIDOMHTMLDocument
#endif
-// Defined in nsEditorRegistration.cpp
-extern nsIParserService *sParserService;
-
namespace mozilla {
using namespace dom;
@@ -127,13 +123,13 @@ using namespace widget;
*****************************************************************************/
EditorBase::EditorBase()
- : mPlaceHolderName(nullptr)
+ : mPlaceholderName(nullptr)
, mSelState(nullptr)
, mPhonetic(nullptr)
, mModCount(0)
, mFlags(0)
, mUpdateCount(0)
- , mPlaceHolderBatch(0)
+ , mPlaceholderBatch(0)
, mAction(EditAction::none)
, mIMETextOffset(0)
, mIMETextLength(0)
@@ -151,7 +147,8 @@ EditorBase::EditorBase()
EditorBase::~EditorBase()
{
- NS_ASSERTION(!mDocWeak || mDidPreDestroy, "Why PreDestroy hasn't been called?");
+ MOZ_ASSERT(!IsInitialized() || mDidPreDestroy,
+ "Why PreDestroy hasn't been called?");
if (mComposition) {
mComposition->OnEditorDestroyed();
@@ -220,20 +217,21 @@ NS_IMPL_CYCLE_COLLECTING_RELEASE(EditorBase)
NS_IMETHODIMP
-EditorBase::Init(nsIDOMDocument* aDoc,
+EditorBase::Init(nsIDOMDocument* aDOMDocument,
nsIContent* aRoot,
- nsISelectionController* aSelCon,
+ nsISelectionController* aSelectionController,
uint32_t aFlags,
const nsAString& aValue)
{
MOZ_ASSERT(mAction == EditAction::none,
"Initializing during an edit action is an error");
- MOZ_ASSERT(aDoc);
- if (!aDoc)
+ MOZ_ASSERT(aDOMDocument);
+ if (!aDOMDocument) {
return NS_ERROR_NULL_POINTER;
+ }
// First only set flags, but other stuff shouldn't be initialized now.
- // Don't move this call after initializing mDocWeak.
+ // Don't move this call after initializing mDocumentWeak.
// SetFlags() can check whether it's called during initialization or not by
// them. Note that SetFlags() will be called by PostCreate().
#ifdef DEBUG
@@ -242,19 +240,21 @@ EditorBase::Init(nsIDOMDocument* aDoc,
SetFlags(aFlags);
NS_ASSERTION(NS_SUCCEEDED(rv), "SetFlags() failed");
- mDocWeak = do_GetWeakReference(aDoc); // weak reference to doc
+ nsCOMPtr<nsIDocument> document = do_QueryInterface(aDOMDocument);
+ mDocumentWeak = document.get();
// HTML editors currently don't have their own selection controller,
// so they'll pass null as aSelCon, and we'll get the selection controller
// off of the presshell.
- nsCOMPtr<nsISelectionController> selCon;
- if (aSelCon) {
- mSelConWeak = do_GetWeakReference(aSelCon); // weak reference to selectioncontroller
- selCon = aSelCon;
+ nsCOMPtr<nsISelectionController> selectionController;
+ if (aSelectionController) {
+ mSelectionControllerWeak = aSelectionController;
+ selectionController = aSelectionController;
} else {
nsCOMPtr<nsIPresShell> presShell = GetPresShell();
- selCon = do_QueryInterface(presShell);
+ selectionController = do_QueryInterface(presShell);
}
- NS_ASSERTION(selCon, "Selection controller should be available at this point");
+ MOZ_ASSERT(selectionController,
+ "Selection controller should be available at this point");
//set up root element if we are passed one.
if (aRoot)
@@ -271,13 +271,14 @@ EditorBase::Init(nsIDOMDocument* aDoc,
mIMETextNode = nullptr;
}
- /* Show the caret */
- selCon->SetCaretReadOnly(false);
- selCon->SetDisplaySelection(nsISelectionController::SELECTION_ON);
+ // Show the caret.
+ selectionController->SetCaretReadOnly(false);
+ selectionController->SetDisplaySelection(
+ nsISelectionController::SELECTION_ON);
+ // Show all the selection reflected to user.
+ selectionController->SetSelectionFlags(nsISelectionDisplay::DISPLAY_ALL);
- selCon->SetSelectionFlags(nsISelectionDisplay::DISPLAY_ALL);//we want to see all the selection reflected to user
-
- NS_POSTCONDITION(mDocWeak, "bad state");
+ MOZ_ASSERT(IsInitialized());
// Make sure that the editor will be destroyed properly
mDidPreDestroy = false;
@@ -356,8 +357,9 @@ EditorBase::CreateEventListeners()
nsresult
EditorBase::InstallEventListeners()
{
- NS_ENSURE_TRUE(mDocWeak && mEventListener,
- NS_ERROR_NOT_INITIALIZED);
+ if (NS_WARN_IF(!IsInitialized()) || NS_WARN_IF(!mEventListener)) {
+ return NS_ERROR_NOT_INITIALIZED;
+ }
// Initialize the event target.
nsCOMPtr<nsIContent> rootContent = GetRoot();
@@ -378,7 +380,7 @@ EditorBase::InstallEventListeners()
void
EditorBase::RemoveEventListeners()
{
- if (!mDocWeak || !mEventListener) {
+ if (!IsInitialized() || !mEventListener) {
return;
}
reinterpret_cast<EditorEventListener*>(mEventListener.get())->Disconnect();
@@ -501,7 +503,7 @@ EditorBase::SetFlags(uint32_t aFlags)
bool spellcheckerWasEnabled = CanEnableSpellCheck();
mFlags = aFlags;
- if (!mDocWeak) {
+ if (!IsInitialized()) {
// If we're initializing, we shouldn't do anything now.
// SetFlags() will be called by PostCreate(),
// we should synchronize some stuff for the flags at that time.
@@ -567,17 +569,15 @@ EditorBase::GetIsDocumentEditable(bool* aIsDocumentEditable)
already_AddRefed<nsIDocument>
EditorBase::GetDocument()
{
- NS_PRECONDITION(mDocWeak, "bad state, mDocWeak weak pointer not initialized");
- nsCOMPtr<nsIDocument> doc = do_QueryReferent(mDocWeak);
- return doc.forget();
+ nsCOMPtr<nsIDocument> document = mDocumentWeak.get();
+ return document.forget();
}
already_AddRefed<nsIDOMDocument>
EditorBase::GetDOMDocument()
{
- NS_PRECONDITION(mDocWeak, "bad state, mDocWeak weak pointer not initialized");
- nsCOMPtr<nsIDOMDocument> doc = do_QueryReferent(mDocWeak);
- return doc.forget();
+ nsCOMPtr<nsIDOMDocument> domDocument = do_QueryInterface(mDocumentWeak);
+ return domDocument.forget();
}
NS_IMETHODIMP
@@ -590,11 +590,12 @@ EditorBase::GetDocument(nsIDOMDocument** aDoc)
already_AddRefed<nsIPresShell>
EditorBase::GetPresShell()
{
- NS_PRECONDITION(mDocWeak, "bad state, null mDocWeak");
- nsCOMPtr<nsIDocument> doc = do_QueryReferent(mDocWeak);
- NS_ENSURE_TRUE(doc, nullptr);
- nsCOMPtr<nsIPresShell> ps = doc->GetShell();
- return ps.forget();
+ nsCOMPtr<nsIDocument> document = GetDocument();
+ if (NS_WARN_IF(!document)) {
+ return nullptr;
+ }
+ nsCOMPtr<nsIPresShell> presShell = document->GetShell();
+ return presShell.forget();
}
already_AddRefed<nsIWidget>
@@ -629,20 +630,27 @@ EditorBase::GetSelectionController(nsISelectionController** aSel)
{
NS_ENSURE_TRUE(aSel, NS_ERROR_NULL_POINTER);
*aSel = nullptr; // init out param
- nsCOMPtr<nsISelectionController> selCon;
- if (mSelConWeak) {
- selCon = do_QueryReferent(mSelConWeak);
- } else {
- nsCOMPtr<nsIPresShell> presShell = GetPresShell();
- selCon = do_QueryInterface(presShell);
- }
- if (!selCon) {
+ nsCOMPtr<nsISelectionController> selCon = GetSelectionController();
+ if (NS_WARN_IF(!selCon)) {
return NS_ERROR_NOT_INITIALIZED;
}
- NS_ADDREF(*aSel = selCon);
+ selCon.forget(aSel);
return NS_OK;
}
+already_AddRefed<nsISelectionController>
+EditorBase::GetSelectionController()
+{
+ nsCOMPtr<nsISelectionController> selectionController;
+ if (mSelectionControllerWeak) {
+ selectionController = mSelectionControllerWeak.get();
+ } else {
+ nsCOMPtr<nsIPresShell> presShell = GetPresShell();
+ selectionController = do_QueryInterface(presShell);
+ }
+ return selectionController.forget();
+}
+
NS_IMETHODIMP
EditorBase::DeleteSelection(EDirection aAction,
EStripWrappers aStripWrappers)
@@ -663,8 +671,7 @@ EditorBase::GetSelection(SelectionType aSelectionType,
{
NS_ENSURE_TRUE(aSelection, NS_ERROR_NULL_POINTER);
*aSelection = nullptr;
- nsCOMPtr<nsISelectionController> selcon;
- GetSelectionController(getter_AddRefs(selcon));
+ nsCOMPtr<nsISelectionController> selcon = GetSelectionController();
if (!selcon) {
return NS_ERROR_NOT_INITIALIZED;
}
@@ -686,32 +693,29 @@ EditorBase::GetSelection(SelectionType aSelectionType)
NS_IMETHODIMP
EditorBase::DoTransaction(nsITransaction* aTxn)
{
- if (mPlaceHolderBatch && !mPlaceHolderTxn) {
- nsCOMPtr<nsIAbsorbingTransaction> placeholderTransaction =
- new PlaceholderTransaction();
+ if (mPlaceholderBatch && !mPlaceholderTransactionWeak) {
+ RefPtr<PlaceholderTransaction> placeholderTransaction =
+ new PlaceholderTransaction(*this, mPlaceholderName, Move(mSelState));
// Save off weak reference to placeholder transaction
- mPlaceHolderTxn = do_GetWeakReference(placeholderTransaction);
- placeholderTransaction->Init(mPlaceHolderName, mSelState, this);
- // placeholder txn took ownership of this pointer
- mSelState = nullptr;
-
- // QI to an nsITransaction since that's what DoTransaction() expects
- nsCOMPtr<nsITransaction> transaction =
- do_QueryInterface(placeholderTransaction);
+ mPlaceholderTransactionWeak = placeholderTransaction;
+
// We will recurse, but will not hit this case in the nested call
- DoTransaction(transaction);
+ DoTransaction(placeholderTransaction);
if (mTxnMgr) {
- nsCOMPtr<nsITransaction> topTxn = mTxnMgr->PeekUndoStack();
- if (topTxn) {
- placeholderTransaction = do_QueryInterface(topTxn);
- if (placeholderTransaction) {
+ nsCOMPtr<nsITransaction> topTransaction = mTxnMgr->PeekUndoStack();
+ nsCOMPtr<nsIAbsorbingTransaction> topAbsorbingTransaction =
+ do_QueryInterface(topTransaction);
+ if (topAbsorbingTransaction) {
+ RefPtr<PlaceholderTransaction> topPlaceholderTransaction =
+ topAbsorbingTransaction->AsPlaceholderTransaction();
+ if (topPlaceholderTransaction) {
// there is a placeholder transaction on top of the undo stack. It
// is either the one we just created, or an earlier one that we are
// now merging into. From here on out remember this placeholder
// instead of the one we just created.
- mPlaceHolderTxn = do_GetWeakReference(placeholderTransaction);
+ mPlaceholderTransactionWeak = topPlaceholderTransaction;
}
}
}
@@ -935,28 +939,28 @@ EditorBase::EndTransaction()
NS_IMETHODIMP
EditorBase::BeginPlaceHolderTransaction(nsIAtom* aName)
{
- NS_PRECONDITION(mPlaceHolderBatch >= 0, "negative placeholder batch count!");
- if (!mPlaceHolderBatch) {
+ MOZ_ASSERT(mPlaceholderBatch >= 0, "negative placeholder batch count!");
+ if (!mPlaceholderBatch) {
NotifyEditorObservers(eNotifyEditorObserversOfBefore);
// time to turn on the batch
BeginUpdateViewBatch();
- mPlaceHolderTxn = nullptr;
- mPlaceHolderName = aName;
+ mPlaceholderTransactionWeak = nullptr;
+ mPlaceholderName = aName;
RefPtr<Selection> selection = GetSelection();
if (selection) {
- mSelState = new SelectionState();
+ mSelState = MakeUnique<SelectionState>();
mSelState->SaveSelection(selection);
// Composition transaction can modify multiple nodes and it merges text
// node for ime into single text node.
// So if current selection is into IME text node, it might be failed
// to restore selection by UndoTransaction.
// So we need update selection by range updater.
- if (mPlaceHolderName == nsGkAtoms::IMETxnName) {
+ if (mPlaceholderName == nsGkAtoms::IMETxnName) {
mRangeUpdater.RegisterSelectionState(*mSelState);
}
}
}
- mPlaceHolderBatch++;
+ mPlaceholderBatch++;
return NS_OK;
}
@@ -964,8 +968,9 @@ EditorBase::BeginPlaceHolderTransaction(nsIAtom* aName)
NS_IMETHODIMP
EditorBase::EndPlaceHolderTransaction()
{
- NS_PRECONDITION(mPlaceHolderBatch > 0, "zero or negative placeholder batch count when ending batch!");
- if (mPlaceHolderBatch == 1) {
+ MOZ_ASSERT(mPlaceholderBatch > 0,
+ "zero or negative placeholder batch count when ending batch!");
+ if (mPlaceholderBatch == 1) {
RefPtr<Selection> selection = GetSelection();
// By making the assumption that no reflow happens during the calls
@@ -1005,22 +1010,16 @@ EditorBase::EndPlaceHolderTransaction()
if (mSelState) {
// we saved the selection state, but never got to hand it to placeholder
// (else we ould have nulled out this pointer), so destroy it to prevent leaks.
- if (mPlaceHolderName == nsGkAtoms::IMETxnName) {
+ if (mPlaceholderName == nsGkAtoms::IMETxnName) {
mRangeUpdater.DropSelectionState(*mSelState);
}
- delete mSelState;
mSelState = nullptr;
}
// We might have never made a placeholder if no action took place.
- if (mPlaceHolderTxn) {
- nsCOMPtr<nsIAbsorbingTransaction> plcTxn = do_QueryReferent(mPlaceHolderTxn);
- if (plcTxn) {
- plcTxn->EndPlaceHolderBatch();
- } else {
- // in the future we will check to make sure undo is off here,
- // since that is the only known case where the placeholdertxn would disappear on us.
- // For now just removing the assert.
- }
+ if (mPlaceholderTransactionWeak) {
+ RefPtr<PlaceholderTransaction> placeholderTransaction =
+ mPlaceholderTransactionWeak.get();
+ placeholderTransaction->EndPlaceHolderBatch();
// notify editor observers of action but if composing, it's done by
// compositionchange event handler.
if (!mComposition) {
@@ -1030,7 +1029,7 @@ EditorBase::EndPlaceHolderTransaction()
NotifyEditorObservers(eNotifyEditorObserversOfCancel);
}
}
- mPlaceHolderBatch--;
+ mPlaceholderBatch--;
return NS_OK;
}
@@ -1067,7 +1066,8 @@ EditorBase::GetDocumentIsEmpty(bool* aDocumentIsEmpty)
NS_IMETHODIMP
EditorBase::SelectAll()
{
- if (!mDocWeak) {
+ // XXX Why doesn't this check if the document is alive?
+ if (!IsInitialized()) {
return NS_ERROR_NOT_INITIALIZED;
}
ForceCompositionEnd();
@@ -1080,7 +1080,8 @@ EditorBase::SelectAll()
NS_IMETHODIMP
EditorBase::BeginningOfDocument()
{
- if (!mDocWeak) {
+ // XXX Why doesn't this check if the document is alive?
+ if (!IsInitialized()) {
return NS_ERROR_NOT_INITIALIZED;
}
@@ -1117,7 +1118,10 @@ EditorBase::BeginningOfDocument()
NS_IMETHODIMP
EditorBase::EndOfDocument()
{
- NS_ENSURE_TRUE(mDocWeak, NS_ERROR_NOT_INITIALIZED);
+ // XXX Why doesn't this check if the document is alive?
+ if (NS_WARN_IF(!IsInitialized())) {
+ return NS_ERROR_NOT_INITIALIZED;
+ }
// get selection
RefPtr<Selection> selection = GetSelection();
@@ -1152,20 +1156,22 @@ EditorBase::GetDocumentModified(bool* outDocModified)
NS_IMETHODIMP
EditorBase::GetDocumentCharacterSet(nsACString& characterSet)
{
- nsCOMPtr<nsIDocument> doc = do_QueryReferent(mDocWeak);
- NS_ENSURE_TRUE(doc, NS_ERROR_UNEXPECTED);
-
- characterSet = doc->GetDocumentCharacterSet();
+ nsCOMPtr<nsIDocument> document = GetDocument();
+ if (NS_WARN_IF(!document)) {
+ return NS_ERROR_UNEXPECTED;
+ }
+ characterSet = document->GetDocumentCharacterSet();
return NS_OK;
}
NS_IMETHODIMP
EditorBase::SetDocumentCharacterSet(const nsACString& characterSet)
{
- nsCOMPtr<nsIDocument> doc = do_QueryReferent(mDocWeak);
- NS_ENSURE_TRUE(doc, NS_ERROR_UNEXPECTED);
-
- doc->SetDocumentCharacterSet(characterSet);
+ nsCOMPtr<nsIDocument> document = GetDocument();
+ if (NS_WARN_IF(!document)) {
+ return NS_ERROR_UNEXPECTED;
+ }
+ document->SetDocumentCharacterSet(characterSet);
return NS_OK;
}
@@ -1385,9 +1391,12 @@ EditorBase::CreateNode(nsIAtom* aTag,
AutoRules beginRulesSniffing(this, EditAction::createNode, nsIEditor::eNext);
- for (auto& listener : mActionListeners) {
- listener->WillCreateNode(nsDependentAtomString(aTag),
- GetAsDOMNode(aParent), aPosition);
+ {
+ AutoActionListenerArray listeners(mActionListeners);
+ for (auto& listener : listeners) {
+ listener->WillCreateNode(nsDependentAtomString(aTag),
+ GetAsDOMNode(aParent), aPosition);
+ }
}
nsCOMPtr<Element> ret;
@@ -1402,9 +1411,12 @@ EditorBase::CreateNode(nsIAtom* aTag,
mRangeUpdater.SelAdjCreateNode(aParent, aPosition);
- for (auto& listener : mActionListeners) {
- listener->DidCreateNode(nsDependentAtomString(aTag), GetAsDOMNode(ret),
- GetAsDOMNode(aParent), aPosition, rv);
+ {
+ AutoActionListenerArray listeners(mActionListeners);
+ for (auto& listener : listeners) {
+ listener->DidCreateNode(nsDependentAtomString(aTag), GetAsDOMNode(ret),
+ GetAsDOMNode(aParent), aPosition, rv);
+ }
}
return ret.forget();
@@ -1429,9 +1441,12 @@ EditorBase::InsertNode(nsIContent& aNode,
{
AutoRules beginRulesSniffing(this, EditAction::insertNode, nsIEditor::eNext);
- for (auto& listener : mActionListeners) {
- listener->WillInsertNode(aNode.AsDOMNode(), aParent.AsDOMNode(),
- aPosition);
+ {
+ AutoActionListenerArray listeners(mActionListeners);
+ for (auto& listener : listeners) {
+ listener->WillInsertNode(aNode.AsDOMNode(), aParent.AsDOMNode(),
+ aPosition);
+ }
}
RefPtr<InsertNodeTransaction> transaction =
@@ -1440,9 +1455,12 @@ EditorBase::InsertNode(nsIContent& aNode,
mRangeUpdater.SelAdjInsertNode(aParent.AsDOMNode(), aPosition);
- for (auto& listener : mActionListeners) {
- listener->DidInsertNode(aNode.AsDOMNode(), aParent.AsDOMNode(), aPosition,
- rv);
+ {
+ AutoActionListenerArray listeners(mActionListeners);
+ for (auto& listener : listeners) {
+ listener->DidInsertNode(aNode.AsDOMNode(), aParent.AsDOMNode(), aPosition,
+ rv);
+ }
}
return rv;
@@ -1468,8 +1486,11 @@ EditorBase::SplitNode(nsIContent& aNode,
{
AutoRules beginRulesSniffing(this, EditAction::splitNode, nsIEditor::eNext);
- for (auto& listener : mActionListeners) {
- listener->WillSplitNode(aNode.AsDOMNode(), aOffset);
+ {
+ AutoActionListenerArray listeners(mActionListeners);
+ for (auto& listener : listeners) {
+ listener->WillSplitNode(aNode.AsDOMNode(), aOffset);
+ }
}
RefPtr<SplitNodeTransaction> transaction =
@@ -1482,9 +1503,12 @@ EditorBase::SplitNode(nsIContent& aNode,
mRangeUpdater.SelAdjSplitNode(aNode, aOffset, newNode);
nsresult rv = aResult.StealNSResult();
- for (auto& listener : mActionListeners) {
- listener->DidSplitNode(aNode.AsDOMNode(), aOffset, GetAsDOMNode(newNode),
- rv);
+ {
+ AutoActionListenerArray listeners(mActionListeners);
+ for (auto& listener : listeners) {
+ listener->DidSplitNode(aNode.AsDOMNode(), aOffset, GetAsDOMNode(newNode),
+ rv);
+ }
}
// Note: result might be a success code, so we can't use Throw() to
// set it on aResult.
@@ -1520,9 +1544,12 @@ EditorBase::JoinNodes(nsINode& aLeftNode,
// Find the number of children of the lefthand node
uint32_t oldLeftNodeLen = aLeftNode.Length();
- for (auto& listener : mActionListeners) {
- listener->WillJoinNodes(aLeftNode.AsDOMNode(), aRightNode.AsDOMNode(),
- parent->AsDOMNode());
+ {
+ AutoActionListenerArray listeners(mActionListeners);
+ for (auto& listener : listeners) {
+ listener->WillJoinNodes(aLeftNode.AsDOMNode(), aRightNode.AsDOMNode(),
+ parent->AsDOMNode());
+ }
}
nsresult rv = NS_OK;
@@ -1535,9 +1562,12 @@ EditorBase::JoinNodes(nsINode& aLeftNode,
mRangeUpdater.SelAdjJoinNodes(aLeftNode, aRightNode, *parent, offset,
(int32_t)oldLeftNodeLen);
- for (auto& listener : mActionListeners) {
- listener->DidJoinNodes(aLeftNode.AsDOMNode(), aRightNode.AsDOMNode(),
- parent->AsDOMNode(), rv);
+ {
+ AutoActionListenerArray listeners(mActionListeners);
+ for (auto& listener : listeners) {
+ listener->DidJoinNodes(aLeftNode.AsDOMNode(), aRightNode.AsDOMNode(),
+ parent->AsDOMNode(), rv);
+ }
}
return rv;
@@ -1558,8 +1588,11 @@ EditorBase::DeleteNode(nsINode* aNode)
nsIEditor::ePrevious);
// save node location for selection updating code.
- for (auto& listener : mActionListeners) {
- listener->WillDeleteNode(aNode->AsDOMNode());
+ {
+ AutoActionListenerArray listeners(mActionListeners);
+ for (auto& listener : listeners) {
+ listener->WillDeleteNode(aNode->AsDOMNode());
+ }
}
RefPtr<DeleteNodeTransaction> transaction;
@@ -1568,8 +1601,11 @@ EditorBase::DeleteNode(nsINode* aNode)
rv = DoTransaction(transaction);
}
- for (auto& listener : mActionListeners) {
- listener->DidDeleteNode(aNode->AsDOMNode(), rv);
+ {
+ AutoActionListenerArray listeners(mActionListeners);
+ for (auto& listener : listeners) {
+ listener->DidDeleteNode(aNode->AsDOMNode(), rv);
+ }
}
NS_ENSURE_SUCCESS(rv, rv);
@@ -1844,7 +1880,7 @@ void
EditorBase::NotifyEditorObservers(NotificationForEditorObservers aNotification)
{
// Copy the observers since EditAction()s can modify mEditorObservers.
- nsTArray<mozilla::OwningNonNull<nsIEditorObserver>> observers(mEditorObservers);
+ AutoEditorObserverArray observers(mEditorObservers);
switch (aNotification) {
case eNotifyEditorObserversOfEnd:
mIsInEditAction = false;
@@ -1976,12 +2012,17 @@ NS_IMETHODIMP
EditorBase::DebugDumpContent()
{
#ifdef DEBUG
- nsCOMPtr<nsIDOMHTMLDocument> doc = do_QueryReferent(mDocWeak);
- NS_ENSURE_TRUE(doc, NS_ERROR_NOT_INITIALIZED);
-
- nsCOMPtr<nsIDOMHTMLElement>bodyElem;
- doc->GetBody(getter_AddRefs(bodyElem));
- nsCOMPtr<nsIContent> content = do_QueryInterface(bodyElem);
+ nsCOMPtr<nsIDocument> document = GetDocument();
+ if (NS_WARN_IF(!document)) {
+ return NS_ERROR_NOT_INITIALIZED;
+ }
+ nsCOMPtr<nsIDOMHTMLDocument> domHTMLDocument = do_QueryInterface(document);
+ if (NS_WARN_IF(!domHTMLDocument)) {
+ return NS_ERROR_NOT_INITIALIZED;
+ }
+ nsCOMPtr<nsIDOMHTMLElement> bodyElement;
+ domHTMLDocument->GetBody(getter_AddRefs(bodyElement));
+ nsCOMPtr<nsIContent> content = do_QueryInterface(bodyElement);
if (content) {
content->List();
}
@@ -2295,18 +2336,20 @@ EditorBase::CloneAttributes(Element* aDest,
NS_IMETHODIMP
EditorBase::ScrollSelectionIntoView(bool aScrollToAnchor)
{
- nsCOMPtr<nsISelectionController> selCon;
- if (NS_SUCCEEDED(GetSelectionController(getter_AddRefs(selCon))) && selCon) {
- int16_t region = nsISelectionController::SELECTION_FOCUS_REGION;
-
- if (aScrollToAnchor) {
- region = nsISelectionController::SELECTION_ANCHOR_REGION;
- }
-
- selCon->ScrollSelectionIntoView(nsISelectionController::SELECTION_NORMAL,
- region, nsISelectionController::SCROLL_OVERFLOW_HIDDEN);
+ nsCOMPtr<nsISelectionController> selectionController =
+ GetSelectionController();
+ if (!selectionController) {
+ return NS_OK;
}
+ int16_t region = nsISelectionController::SELECTION_FOCUS_REGION;
+ if (aScrollToAnchor) {
+ region = nsISelectionController::SELECTION_ANCHOR_REGION;
+ }
+ selectionController->ScrollSelectionIntoView(
+ nsISelectionController::SELECTION_NORMAL,
+ region,
+ nsISelectionController::SCROLL_OVERFLOW_HIDDEN);
return NS_OK;
}
@@ -2505,10 +2548,13 @@ EditorBase::InsertTextIntoTextNodeImpl(const nsAString& aStringToInsert,
}
// Let listeners know what's up
- for (auto& listener : mActionListeners) {
- listener->WillInsertText(
- static_cast<nsIDOMCharacterData*>(insertedTextNode->AsDOMNode()),
- insertedOffset, aStringToInsert);
+ {
+ AutoActionListenerArray listeners(mActionListeners);
+ for (auto& listener : listeners) {
+ listener->WillInsertText(
+ static_cast<nsIDOMCharacterData*>(insertedTextNode->AsDOMNode()),
+ insertedOffset, aStringToInsert);
+ }
}
// XXX We may not need these view batches anymore. This is handled at a
@@ -2518,10 +2564,13 @@ EditorBase::InsertTextIntoTextNodeImpl(const nsAString& aStringToInsert,
EndUpdateViewBatch();
// let listeners know what happened
- for (auto& listener : mActionListeners) {
- listener->DidInsertText(
- static_cast<nsIDOMCharacterData*>(insertedTextNode->AsDOMNode()),
- insertedOffset, aStringToInsert, rv);
+ {
+ AutoActionListenerArray listeners(mActionListeners);
+ for (auto& listener : listeners) {
+ listener->DidInsertText(
+ static_cast<nsIDOMCharacterData*>(insertedTextNode->AsDOMNode()),
+ insertedOffset, aStringToInsert, rv);
+ }
}
// Added some cruft here for bug 43366. Layout was crashing because we left
@@ -2583,8 +2632,7 @@ EditorBase::NotifyDocumentListeners(
return NS_OK;
}
- nsTArray<OwningNonNull<nsIDocumentStateListener>>
- listeners(mDocStateListeners);
+ AutoDocumentStateListenerArray listeners(mDocStateListeners);
nsresult rv = NS_OK;
switch (aNotificationType) {
@@ -2656,19 +2704,25 @@ EditorBase::DeleteText(nsGenericDOMDataNode& aCharData,
nsIEditor::ePrevious);
// Let listeners know what's up
- for (auto& listener : mActionListeners) {
- listener->WillDeleteText(
- static_cast<nsIDOMCharacterData*>(GetAsDOMNode(&aCharData)), aOffset,
- aLength);
+ {
+ AutoActionListenerArray listeners(mActionListeners);
+ for (auto& listener : listeners) {
+ listener->WillDeleteText(
+ static_cast<nsIDOMCharacterData*>(GetAsDOMNode(&aCharData)), aOffset,
+ aLength);
+ }
}
nsresult rv = DoTransaction(transaction);
// Let listeners know what happened
- for (auto& listener : mActionListeners) {
- listener->DidDeleteText(
- static_cast<nsIDOMCharacterData*>(GetAsDOMNode(&aCharData)), aOffset,
- aLength, rv);
+ {
+ AutoActionListenerArray listeners(mActionListeners);
+ for (auto& listener : listeners) {
+ listener->DidDeleteText(
+ static_cast<nsIDOMCharacterData*>(GetAsDOMNode(&aCharData)), aOffset,
+ aLength, rv);
+ }
}
return rv;
@@ -4034,17 +4088,20 @@ EditorBase::DeleteSelectionImpl(EDirection aAction,
if (NS_SUCCEEDED(rv)) {
AutoRules beginRulesSniffing(this, EditAction::deleteSelection, aAction);
// Notify nsIEditActionListener::WillDelete[Selection|Text|Node]
- if (!deleteNode) {
- for (auto& listener : mActionListeners) {
- listener->WillDeleteSelection(selection);
- }
- } else if (deleteCharData) {
- for (auto& listener : mActionListeners) {
- listener->WillDeleteText(deleteCharData, deleteCharOffset, 1);
- }
- } else {
- for (auto& listener : mActionListeners) {
- listener->WillDeleteNode(deleteNode->AsDOMNode());
+ {
+ AutoActionListenerArray listeners(mActionListeners);
+ if (!deleteNode) {
+ for (auto& listener : listeners) {
+ listener->WillDeleteSelection(selection);
+ }
+ } else if (deleteCharData) {
+ for (auto& listener : listeners) {
+ listener->WillDeleteText(deleteCharData, deleteCharOffset, 1);
+ }
+ } else {
+ for (auto& listener : listeners) {
+ listener->WillDeleteNode(deleteNode->AsDOMNode());
+ }
}
}
@@ -4052,17 +4109,20 @@ EditorBase::DeleteSelectionImpl(EDirection aAction,
rv = DoTransaction(transaction);
// Notify nsIEditActionListener::DidDelete[Selection|Text|Node]
- if (!deleteNode) {
- for (auto& listener : mActionListeners) {
- listener->DidDeleteSelection(selection);
- }
- } else if (deleteCharData) {
- for (auto& listener : mActionListeners) {
- listener->DidDeleteText(deleteCharData, deleteCharOffset, 1, rv);
- }
- } else {
- for (auto& listener : mActionListeners) {
- listener->DidDeleteNode(deleteNode->AsDOMNode(), rv);
+ {
+ AutoActionListenerArray listeners(mActionListeners);
+ if (!deleteNode) {
+ for (auto& listener : mActionListeners) {
+ listener->DidDeleteSelection(selection);
+ }
+ } else if (deleteCharData) {
+ for (auto& listener : mActionListeners) {
+ listener->DidDeleteText(deleteCharData, deleteCharOffset, 1, rv);
+ }
+ } else {
+ for (auto& listener : mActionListeners) {
+ listener->DidDeleteNode(deleteNode->AsDOMNode(), rv);
+ }
}
}
}
@@ -4739,22 +4799,27 @@ EditorBase::InitializeSelection(nsIDOMEventTarget* aFocusEventTarget)
nsCOMPtr<nsIPresShell> presShell = GetPresShell();
NS_ENSURE_TRUE(presShell, NS_ERROR_NOT_INITIALIZED);
- nsCOMPtr<nsISelectionController> selCon;
- nsresult rv = GetSelectionController(getter_AddRefs(selCon));
- NS_ENSURE_SUCCESS(rv, rv);
+ nsCOMPtr<nsISelectionController> selectionController =
+ GetSelectionController();
+ if (NS_WARN_IF(!selectionController)) {
+ return NS_ERROR_FAILURE;
+ }
// Init the caret
RefPtr<nsCaret> caret = presShell->GetCaret();
NS_ENSURE_TRUE(caret, NS_ERROR_UNEXPECTED);
caret->SetIgnoreUserModify(false);
caret->SetSelection(selection);
- selCon->SetCaretReadOnly(IsReadonly());
- selCon->SetCaretEnabled(true);
+ selectionController->SetCaretReadOnly(IsReadonly());
+ selectionController->SetCaretEnabled(true);
// Init selection
- selCon->SetDisplaySelection(nsISelectionController::SELECTION_ON);
- selCon->SetSelectionFlags(nsISelectionDisplay::DISPLAY_ALL);
- selCon->RepaintSelection(nsISelectionController::SELECTION_NORMAL);
+ selectionController->SetDisplaySelection(
+ nsISelectionController::SELECTION_ON);
+ selectionController->SetSelectionFlags(
+ nsISelectionDisplay::DISPLAY_ALL);
+ selectionController->RepaintSelection(
+ nsISelectionController::SELECTION_NORMAL);
// If the computed selection root isn't root content, we should set it
// as selection ancestor limit. However, if that is root element, it means
// there is not limitation of the selection, then, we must set nullptr.
@@ -4822,9 +4887,11 @@ private:
NS_IMETHODIMP
EditorBase::FinalizeSelection()
{
- nsCOMPtr<nsISelectionController> selCon;
- nsresult rv = GetSelectionController(getter_AddRefs(selCon));
- NS_ENSURE_SUCCESS(rv, rv);
+ nsCOMPtr<nsISelectionController> selectionController =
+ GetSelectionController();
+ if (NS_WARN_IF(!selectionController)) {
+ return NS_ERROR_FAILURE;
+ }
RefPtr<Selection> selection = GetSelection();
NS_ENSURE_STATE(selection);
@@ -4834,7 +4901,7 @@ EditorBase::FinalizeSelection()
nsCOMPtr<nsIPresShell> presShell = GetPresShell();
NS_ENSURE_TRUE(presShell, NS_ERROR_NOT_INITIALIZED);
- selCon->SetCaretEnabled(false);
+ selectionController->SetCaretEnabled(false);
nsFocusManager* fm = nsFocusManager::GetFocusManager();
NS_ENSURE_TRUE(fm, NS_ERROR_NOT_INITIALIZED);
@@ -4849,29 +4916,33 @@ EditorBase::FinalizeSelection()
ErrorResult ret;
if (!doc || !doc->HasFocus(ret)) {
// If the document already lost focus, mark the selection as disabled.
- selCon->SetDisplaySelection(nsISelectionController::SELECTION_DISABLED);
+ selectionController->SetDisplaySelection(
+ nsISelectionController::SELECTION_DISABLED);
} else {
// Otherwise, mark selection as normal because outside of a
// contenteditable element should be selected with normal selection
// color after here.
- selCon->SetDisplaySelection(nsISelectionController::SELECTION_ON);
+ selectionController->SetDisplaySelection(
+ nsISelectionController::SELECTION_ON);
}
} else if (IsFormWidget() || IsPasswordEditor() ||
IsReadonly() || IsDisabled() || IsInputFiltered()) {
// In <input> or <textarea>, the independent selection should be hidden
// while this editor doesn't have focus.
- selCon->SetDisplaySelection(nsISelectionController::SELECTION_HIDDEN);
+ selectionController->SetDisplaySelection(
+ nsISelectionController::SELECTION_HIDDEN);
} else {
// Otherwise, although we're not sure how this case happens, the
// independent selection should be marked as disabled.
- selCon->SetDisplaySelection(nsISelectionController::SELECTION_DISABLED);
+ selectionController->SetDisplaySelection(
+ nsISelectionController::SELECTION_DISABLED);
}
// FinalizeSelection might be called from ContentRemoved even if selection
// isn't updated. So we need to call RepaintSelection after updated it.
nsContentUtils::AddScriptRunner(
- new RepaintSelectionRunner(selCon));
+ new RepaintSelectionRunner(selectionController));
return NS_OK;
}
@@ -5082,8 +5153,11 @@ EditorBase::IsActiveInDOMWindow()
nsFocusManager* fm = nsFocusManager::GetFocusManager();
NS_ENSURE_TRUE(fm, false);
- nsCOMPtr<nsIDocument> doc = do_QueryReferent(mDocWeak);
- nsPIDOMWindowOuter* ourWindow = doc->GetWindow();
+ nsCOMPtr<nsIDocument> document = GetDocument();
+ if (NS_WARN_IF(!document)) {
+ return false;
+ }
+ nsPIDOMWindowOuter* ourWindow = document->GetWindow();
nsCOMPtr<nsPIDOMWindowOuter> win;
nsIContent* content =
nsFocusManager::GetFocusedDescendant(ourWindow, false,
@@ -5191,12 +5265,13 @@ EditorBase::GetIMESelectionStartOffsetIn(nsINode* aTextNode)
{
MOZ_ASSERT(aTextNode, "aTextNode must not be nullptr");
- nsCOMPtr<nsISelectionController> selectionController;
- nsresult rv = GetSelectionController(getter_AddRefs(selectionController));
- NS_ENSURE_SUCCESS(rv, -1);
- NS_ENSURE_TRUE(selectionController, -1);
+ nsCOMPtr<nsISelectionController> selectionController =
+ GetSelectionController();
+ if (NS_WARN_IF(!selectionController)) {
+ return -1;
+ }
- int32_t minOffset = INT32_MAX;
+ uint32_t minOffset = UINT32_MAX;
static const SelectionType kIMESelectionTypes[] = {
SelectionType::eIMERawClause,
SelectionType::eIMESelectedRawClause,
@@ -5216,15 +5291,11 @@ EditorBase::GetIMESelectionStartOffsetIn(nsINode* aTextNode)
if (NS_WARN_IF(range->GetStartParent() != aTextNode)) {
// ignore the start offset...
} else {
- MOZ_ASSERT(range->StartOffset() >= 0,
- "start offset shouldn't be negative");
minOffset = std::min(minOffset, range->StartOffset());
}
if (NS_WARN_IF(range->GetEndParent() != aTextNode)) {
// ignore the end offset...
} else {
- MOZ_ASSERT(range->EndOffset() >= 0,
- "start offset shouldn't be negative");
minOffset = std::min(minOffset, range->EndOffset());
}
}
diff --git a/editor/libeditor/EditorBase.h b/editor/libeditor/EditorBase.h
index dbd00771e..618da12a8 100644
--- a/editor/libeditor/EditorBase.h
+++ b/editor/libeditor/EditorBase.h
@@ -10,11 +10,14 @@
#include "mozFlushType.h" // for mozFlushType enum
#include "mozilla/OwningNonNull.h" // for OwningNonNull
#include "mozilla/SelectionState.h" // for RangeUpdater, etc.
-#include "mozilla/StyleSheet.h" // for StyleSheet
+#include "mozilla/StyleSheet.h" // for StyleSheet
+#include "mozilla/UniquePtr.h"
+#include "mozilla/WeakPtr.h" // for WeakPtr
#include "mozilla/dom/Text.h"
#include "nsCOMPtr.h" // for already_AddRefed, nsCOMPtr
#include "nsCycleCollectionParticipant.h"
#include "nsGkAtoms.h"
+#include "nsIDocument.h" // for nsIDocument
#include "nsIEditor.h" // for nsIEditor::EDirection, etc.
#include "nsIEditorIMESupport.h" // for NS_DECL_NSIEDITORIMESUPPORT, etc.
#include "nsIObserver.h" // for NS_DECL_NSIOBSERVER, etc.
@@ -30,7 +33,6 @@
class nsIAtom;
class nsIContent;
-class nsIDOMDocument;
class nsIDOMEvent;
class nsIDOMEventListener;
class nsIDOMEventTarget;
@@ -115,6 +117,7 @@ class ErrorResult;
class InsertNodeTransaction;
class InsertTextTransaction;
class JoinNodeTransaction;
+class PlaceholderTransaction;
class RemoveStyleSheetTransaction;
class SplitNodeTransaction;
class TextComposition;
@@ -132,6 +135,57 @@ namespace widget {
struct IMEState;
} // namespace widget
+/**
+ * CachedWeakPtr stores a pointer to a class which inherits nsIWeakReference.
+ * If the instance of the class has already been destroyed, this returns
+ * nullptr. Otherwise, returns cached pointer.
+ */
+template<class T>
+class CachedWeakPtr final
+{
+public:
+ CachedWeakPtr<T>()
+ : mCache(nullptr)
+ {
+ }
+
+ CachedWeakPtr<T>& operator=(T* aObject)
+ {
+ mWeakPtr = do_GetWeakReference(aObject);
+ mCache = aObject;
+ return *this;
+ }
+ CachedWeakPtr<T>& operator=(const nsCOMPtr<T>& aOther)
+ {
+ mWeakPtr = do_GetWeakReference(aOther);
+ mCache = aOther;
+ return *this;
+ }
+ CachedWeakPtr<T>& operator=(already_AddRefed<T>& aOther)
+ {
+ nsCOMPtr<T> other = aOther;
+ mWeakPtr = do_GetWeakReference(other);
+ mCache = other;
+ return *this;
+ }
+
+ bool IsAlive() const { return mWeakPtr && mWeakPtr->IsAlive(); }
+
+ explicit operator bool() const { return mWeakPtr; }
+ operator T*() const { return get(); }
+ T* get() const
+ {
+ if (mCache && !mWeakPtr->IsAlive()) {
+ const_cast<CachedWeakPtr<T>*>(this)->mCache = nullptr;
+ }
+ return mCache;
+ }
+
+private:
+ nsWeakPtr mWeakPtr;
+ T* MOZ_NON_OWNING_REF mCache;
+};
+
#define kMOZEditorBogusNodeAttrAtom nsGkAtoms::mozeditorbogusnode
#define kMOZEditorBogusNodeValue NS_LITERAL_STRING("TRUE")
@@ -175,6 +229,7 @@ public:
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(EditorBase, nsIEditor)
+ bool IsInitialized() const { return !!mDocumentWeak; }
already_AddRefed<nsIDOMDocument> GetDOMDocument();
already_AddRefed<nsIDocument> GetDocument();
already_AddRefed<nsIPresShell> GetPresShell();
@@ -452,6 +507,7 @@ protected:
*/
bool EnsureComposition(WidgetCompositionEvent* aCompositionEvent);
+ already_AddRefed<nsISelectionController> GetSelectionController();
nsresult GetSelection(SelectionType aSelectionType,
nsISelection** aSelection);
@@ -844,7 +900,7 @@ public:
bool HasIndependentSelection() const
{
- return !!mSelConWeak;
+ return !!mSelectionControllerWeak;
}
/**
@@ -950,6 +1006,14 @@ public:
}
}
+private:
+ // Weak reference to the nsISelectionController.
+ // Use GetSelectionController() to retrieve actual pointer.
+ CachedWeakPtr<nsISelectionController> mSelectionControllerWeak;
+ // Weak reference to the nsIDocument.
+ // Use GetDocument() to retrieve actual pointer.
+ CachedWeakPtr<nsIDocument> mDocumentWeak;
+
protected:
enum Tristate
{
@@ -971,27 +1035,29 @@ protected:
// The form field as an event receiver.
nsCOMPtr<dom::EventTarget> mEventTarget;
nsCOMPtr<nsIDOMEventListener> mEventListener;
- // Weak reference to the nsISelectionController.
- nsWeakPtr mSelConWeak;
// Weak reference to placeholder for begin/end batch purposes.
- nsWeakPtr mPlaceHolderTxn;
- // Weak reference to the nsIDOMDocument.
- nsWeakPtr mDocWeak;
+ WeakPtr<PlaceholderTransaction> mPlaceholderTransactionWeak;
// Name of placeholder transaction.
- nsIAtom* mPlaceHolderName;
+ nsIAtom* mPlaceholderName;
// Saved selection state for placeholder transaction batching.
- SelectionState* mSelState;
+ mozilla::UniquePtr<SelectionState> mSelState;
nsString* mPhonetic;
// IME composition this is not null between compositionstart and
// compositionend.
RefPtr<TextComposition> mComposition;
// Listens to all low level actions on the doc.
- nsTArray<OwningNonNull<nsIEditActionListener>> mActionListeners;
+ typedef AutoTArray<OwningNonNull<nsIEditActionListener>, 5>
+ AutoActionListenerArray;
+ AutoActionListenerArray mActionListeners;
// Just notify once per high level change.
- nsTArray<OwningNonNull<nsIEditorObserver>> mEditorObservers;
+ typedef AutoTArray<OwningNonNull<nsIEditorObserver>, 3>
+ AutoEditorObserverArray;
+ AutoEditorObserverArray mEditorObservers;
// Listen to overall doc state (dirty or not, just created, etc.).
- nsTArray<OwningNonNull<nsIDocumentStateListener>> mDocStateListeners;
+ typedef AutoTArray<OwningNonNull<nsIDocumentStateListener>, 1>
+ AutoDocumentStateListenerArray;
+ AutoDocumentStateListenerArray mDocStateListeners;
// Cached selection for AutoSelectionRestorer.
SelectionState mSavedSel;
@@ -1006,7 +1072,7 @@ protected:
int32_t mUpdateCount;
// Nesting count for batching.
- int32_t mPlaceHolderBatch;
+ int32_t mPlaceholderBatch;
// The current editor action.
EditAction mAction;
diff --git a/editor/libeditor/HTMLEditRules.cpp b/editor/libeditor/HTMLEditRules.cpp
index 545e22f70..805092eb7 100644
--- a/editor/libeditor/HTMLEditRules.cpp
+++ b/editor/libeditor/HTMLEditRules.cpp
@@ -16,12 +16,13 @@
#include "mozilla/EditorUtils.h"
#include "mozilla/HTMLEditor.h"
#include "mozilla/MathAlgorithms.h"
+#include "mozilla/Move.h"
#include "mozilla/Preferences.h"
+#include "mozilla/UniquePtr.h"
#include "mozilla/dom/Selection.h"
#include "mozilla/dom/Element.h"
#include "mozilla/OwningNonNull.h"
#include "mozilla/mozalloc.h"
-#include "nsAutoPtr.h"
#include "nsAString.h"
#include "nsAlgorithm.h"
#include "nsCRT.h"
@@ -426,7 +427,7 @@ HTMLEditRules::AfterEditInner(EditAction action,
NS_ENSURE_STATE(selection);
nsCOMPtr<nsIDOMNode> rangeStartParent, rangeEndParent;
- int32_t rangeStartOffset = 0, rangeEndOffset = 0;
+ uint32_t rangeStartOffset = 0, rangeEndOffset = 0;
// do we have a real range to act on?
bool bDamagedRange = false;
if (mDocChangeRange) {
@@ -534,8 +535,8 @@ HTMLEditRules::AfterEditInner(EditAction action,
mHTMLEditor->HandleInlineSpellCheck(action, selection,
GetAsDOMNode(mRangeItem->startNode),
mRangeItem->startOffset,
- rangeStartParent, rangeStartOffset,
- rangeEndParent, rangeEndOffset);
+ rangeStartParent, static_cast<int32_t>(rangeStartOffset),
+ rangeEndParent, static_cast<int32_t>(rangeEndOffset));
NS_ENSURE_SUCCESS(rv, rv);
// detect empty doc
@@ -1422,16 +1423,15 @@ HTMLEditRules::WillInsertText(EditAction aAction,
if (!mDocChangeRange) {
mDocChangeRange = new nsRange(selNode);
}
- rv = mDocChangeRange->SetStart(selNode, selOffset);
- NS_ENSURE_SUCCESS(rv, rv);
if (curNode) {
- rv = mDocChangeRange->SetEnd(curNode, curOffset);
+ rv = mDocChangeRange->SetStartAndEnd(selNode, selOffset,
+ curNode, curOffset);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
} else {
- rv = mDocChangeRange->SetEnd(selNode, selOffset);
+ rv = mDocChangeRange->CollapseTo(selNode, selOffset);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
@@ -4411,20 +4411,21 @@ HTMLEditRules::CreateStyleForInsertText(Selection& aSelection,
NS_ENSURE_STATE(rootElement);
// process clearing any styles first
- nsAutoPtr<PropItem> item(mHTMLEditor->mTypeInState->TakeClearProperty());
+ UniquePtr<PropItem> item =
+ Move(mHTMLEditor->mTypeInState->TakeClearProperty());
while (item && node != rootElement) {
NS_ENSURE_STATE(mHTMLEditor);
nsresult rv =
mHTMLEditor->ClearStyle(address_of(node), &offset,
item->tag, &item->attr);
NS_ENSURE_SUCCESS(rv, rv);
- item = mHTMLEditor->mTypeInState->TakeClearProperty();
+ item = Move(mHTMLEditor->mTypeInState->TakeClearProperty());
weDidSomething = true;
}
// then process setting any styles
int32_t relFontSize = mHTMLEditor->mTypeInState->TakeRelativeFontSize();
- item = mHTMLEditor->mTypeInState->TakeSetProperty();
+ item = Move(mHTMLEditor->mTypeInState->TakeSetProperty());
if (item || relFontSize) {
// we have at least one style to add; make a new text node to insert style
@@ -5093,10 +5094,11 @@ HTMLEditRules::ExpandSelectionForDeletion(Selection& aSelection)
// Create a range that represents expanded selection
RefPtr<nsRange> range = new nsRange(selStartNode);
- nsresult rv = range->SetStart(selStartNode, selStartOffset);
- NS_ENSURE_SUCCESS(rv, rv);
- rv = range->SetEnd(selEndNode, selEndOffset);
- NS_ENSURE_SUCCESS(rv, rv);
+ nsresult rv = range->SetStartAndEnd(selStartNode, selStartOffset,
+ selEndNode, selEndOffset);
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return rv;
+ }
// Check if block is entirely inside range
if (brBlock) {
@@ -5149,9 +5151,8 @@ HTMLEditRules::NormalizeSelection(Selection* inSelection)
RefPtr<nsRange> range = inSelection->GetRangeAt(0);
NS_ENSURE_TRUE(range, NS_ERROR_NULL_POINTER);
nsCOMPtr<nsIDOMNode> startNode, endNode;
- int32_t startOffset, endOffset;
+ uint32_t startOffset, endOffset;
nsCOMPtr<nsIDOMNode> newStartNode, newEndNode;
- int32_t newStartOffset, newEndOffset;
rv = range->GetStartContainer(getter_AddRefs(startNode));
NS_ENSURE_SUCCESS(rv, rv);
@@ -5164,22 +5165,22 @@ HTMLEditRules::NormalizeSelection(Selection* inSelection)
// adjusted values default to original values
newStartNode = startNode;
- newStartOffset = startOffset;
+ uint32_t newStartOffset = startOffset;
newEndNode = endNode;
- newEndOffset = endOffset;
+ uint32_t newEndOffset = endOffset;
// some locals we need for whitespace code
nsCOMPtr<nsINode> unused;
- int32_t offset;
+ int32_t offset = -1;
WSType wsType;
// let the whitespace code do the heavy lifting
- WSRunObject wsEndObj(mHTMLEditor, endNode, endOffset);
+ WSRunObject wsEndObj(mHTMLEditor, endNode, static_cast<int32_t>(endOffset));
// is there any intervening visible whitespace? if so we can't push selection past that,
// it would visibly change maening of users selection
nsCOMPtr<nsINode> endNode_(do_QueryInterface(endNode));
- wsEndObj.PriorVisibleNode(endNode_, endOffset, address_of(unused),
- &offset, &wsType);
+ wsEndObj.PriorVisibleNode(endNode_, static_cast<int32_t>(endOffset),
+ address_of(unused), &offset, &wsType);
if (wsType != WSType::text && wsType != WSType::normalWS) {
// eThisBlock and eOtherBlock conveniently distinquish cases
// of going "down" into a block and "up" out of a block.
@@ -5189,36 +5190,44 @@ HTMLEditRules::NormalizeSelection(Selection* inSelection)
GetAsDOMNode(mHTMLEditor->GetRightmostChild(wsEndObj.mStartReasonNode,
true));
if (child) {
- newEndNode = EditorBase::GetNodeLocation(child, &newEndOffset);
- ++newEndOffset; // offset *after* child
+ int32_t offset = -1;
+ newEndNode = EditorBase::GetNodeLocation(child, &offset);
+ // offset *after* child
+ newEndOffset = static_cast<uint32_t>(offset + 1);
}
// else block is empty - we can leave selection alone here, i think.
} else if (wsEndObj.mStartReason == WSType::thisBlock) {
// endpoint is just after start of this block
nsCOMPtr<nsIDOMNode> child;
NS_ENSURE_STATE(mHTMLEditor);
- mHTMLEditor->GetPriorHTMLNode(endNode, endOffset, address_of(child));
+ mHTMLEditor->GetPriorHTMLNode(endNode, static_cast<int32_t>(endOffset),
+ address_of(child));
if (child) {
- newEndNode = EditorBase::GetNodeLocation(child, &newEndOffset);
- ++newEndOffset; // offset *after* child
+ int32_t offset = -1;
+ newEndNode = EditorBase::GetNodeLocation(child, &offset);
+ // offset *after* child
+ newEndOffset = static_cast<uint32_t>(offset + 1);
}
// else block is empty - we can leave selection alone here, i think.
} else if (wsEndObj.mStartReason == WSType::br) {
// endpoint is just after break. lets adjust it to before it.
+ int32_t offset = -1;
newEndNode =
EditorBase::GetNodeLocation(GetAsDOMNode(wsEndObj.mStartReasonNode),
- &newEndOffset);
+ &offset);
+ newEndOffset = static_cast<uint32_t>(offset);;
}
}
// similar dealio for start of range
- WSRunObject wsStartObj(mHTMLEditor, startNode, startOffset);
+ WSRunObject wsStartObj(mHTMLEditor, startNode,
+ static_cast<int32_t>(startOffset));
// is there any intervening visible whitespace? if so we can't push selection past that,
// it would visibly change maening of users selection
nsCOMPtr<nsINode> startNode_(do_QueryInterface(startNode));
- wsStartObj.NextVisibleNode(startNode_, startOffset, address_of(unused),
- &offset, &wsType);
+ wsStartObj.NextVisibleNode(startNode_, static_cast<int32_t>(startOffset),
+ address_of(unused), &offset, &wsType);
if (wsType != WSType::text && wsType != WSType::normalWS) {
// eThisBlock and eOtherBlock conveniently distinquish cases
// of going "down" into a block and "up" out of a block.
@@ -5228,23 +5237,31 @@ HTMLEditRules::NormalizeSelection(Selection* inSelection)
GetAsDOMNode(mHTMLEditor->GetLeftmostChild(wsStartObj.mEndReasonNode,
true));
if (child) {
- newStartNode = EditorBase::GetNodeLocation(child, &newStartOffset);
+ int32_t offset = -1;
+ newStartNode = EditorBase::GetNodeLocation(child, &offset);
+ newStartOffset = static_cast<uint32_t>(offset);
}
// else block is empty - we can leave selection alone here, i think.
} else if (wsStartObj.mEndReason == WSType::thisBlock) {
// startpoint is just before end of this block
nsCOMPtr<nsIDOMNode> child;
NS_ENSURE_STATE(mHTMLEditor);
- mHTMLEditor->GetNextHTMLNode(startNode, startOffset, address_of(child));
+ mHTMLEditor->GetNextHTMLNode(startNode, static_cast<int32_t>(startOffset),
+ address_of(child));
if (child) {
- newStartNode = EditorBase::GetNodeLocation(child, &newStartOffset);
+ int32_t offset = -1;
+ newStartNode = EditorBase::GetNodeLocation(child, &offset);
+ newStartOffset = static_cast<uint32_t>(offset);
}
// else block is empty - we can leave selection alone here, i think.
} else if (wsStartObj.mEndReason == WSType::br) {
// startpoint is just before a break. lets adjust it to after it.
+ int32_t offset = -1;
newStartNode =
EditorBase::GetNodeLocation(GetAsDOMNode(wsStartObj.mEndReasonNode),
- &newStartOffset);
+ &offset);
+ // offset *after* break
+ newStartOffset = static_cast<uint32_t>(offset + 1);
++newStartOffset; // offset *after* break
}
}
@@ -5558,26 +5575,27 @@ HTMLEditRules::PromoteRange(nsRange& aRange,
// This is tricky. The basic idea is to push out the range endpoints to
// truly enclose the blocks that we will affect.
- nsCOMPtr<nsIDOMNode> opStartNode;
- nsCOMPtr<nsIDOMNode> opEndNode;
+ nsCOMPtr<nsIDOMNode> opDOMStartNode;
+ nsCOMPtr<nsIDOMNode> opDOMEndNode;
int32_t opStartOffset, opEndOffset;
GetPromotedPoint(kStart, GetAsDOMNode(startNode), startOffset,
- aOperationType, address_of(opStartNode), &opStartOffset);
+ aOperationType, address_of(opDOMStartNode), &opStartOffset);
GetPromotedPoint(kEnd, GetAsDOMNode(endNode), endOffset, aOperationType,
- address_of(opEndNode), &opEndOffset);
+ address_of(opDOMEndNode), &opEndOffset);
// Make sure that the new range ends up to be in the editable section.
if (!htmlEditor->IsDescendantOfEditorRoot(
- EditorBase::GetNodeAtRangeOffsetPoint(opStartNode, opStartOffset)) ||
+ EditorBase::GetNodeAtRangeOffsetPoint(opDOMStartNode, opStartOffset)) ||
!htmlEditor->IsDescendantOfEditorRoot(
- EditorBase::GetNodeAtRangeOffsetPoint(opEndNode, opEndOffset - 1))) {
+ EditorBase::GetNodeAtRangeOffsetPoint(opDOMEndNode, opEndOffset - 1))) {
return;
}
- DebugOnly<nsresult> rv = aRange.SetStart(opStartNode, opStartOffset);
- MOZ_ASSERT(NS_SUCCEEDED(rv));
- rv = aRange.SetEnd(opEndNode, opEndOffset);
+ nsCOMPtr<nsINode> opStartNode = do_QueryInterface(opDOMStartNode);
+ nsCOMPtr<nsINode> opEndNode = do_QueryInterface(opDOMEndNode);
+ DebugOnly<nsresult> rv =
+ aRange.SetStartAndEnd(opStartNode, opStartOffset, opEndNode, opEndOffset);
MOZ_ASSERT(NS_SUCCEEDED(rv));
}
@@ -7179,42 +7197,44 @@ HTMLEditRules::PinSelectionToNewBlock(Selection* aSelection)
return NS_OK;
}
+ if (NS_WARN_IF(!mNewBlock)) {
+ return NS_ERROR_NULL_POINTER;
+ }
+
// get the (collapsed) selection location
- nsCOMPtr<nsIDOMNode> selNode, temp;
+ nsCOMPtr<nsIDOMNode> selNode;
int32_t selOffset;
NS_ENSURE_STATE(mHTMLEditor);
nsresult rv =
mHTMLEditor->GetStartNodeAndOffset(aSelection,
getter_AddRefs(selNode), &selOffset);
NS_ENSURE_SUCCESS(rv, rv);
- temp = selNode;
// use ranges and sRangeHelper to compare sel point to new block
nsCOMPtr<nsINode> node = do_QueryInterface(selNode);
NS_ENSURE_STATE(node);
RefPtr<nsRange> range = new nsRange(node);
- rv = range->SetStart(selNode, selOffset);
- NS_ENSURE_SUCCESS(rv, rv);
- rv = range->SetEnd(selNode, selOffset);
- NS_ENSURE_SUCCESS(rv, rv);
- nsCOMPtr<nsIContent> block = mNewBlock.get();
- NS_ENSURE_TRUE(block, NS_ERROR_NO_INTERFACE);
+ rv = range->CollapseTo(node, selOffset);
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return rv;
+ }
bool nodeBefore, nodeAfter;
- rv = nsRange::CompareNodeToRange(block, range, &nodeBefore, &nodeAfter);
+ rv = nsRange::CompareNodeToRange(mNewBlock, range, &nodeBefore, &nodeAfter);
NS_ENSURE_SUCCESS(rv, rv);
if (nodeBefore && nodeAfter) {
return NS_OK; // selection is inside block
} else if (nodeBefore) {
// selection is after block. put at end of block.
- nsCOMPtr<nsIDOMNode> tmp = GetAsDOMNode(mNewBlock);
NS_ENSURE_STATE(mHTMLEditor);
- tmp = GetAsDOMNode(mHTMLEditor->GetLastEditableChild(*block));
+ nsCOMPtr<nsINode> tmp = mHTMLEditor->GetLastEditableChild(*mNewBlock);
+ if (!tmp) {
+ tmp = mNewBlock;
+ }
uint32_t endPoint;
if (mHTMLEditor->IsTextNode(tmp) ||
mHTMLEditor->IsContainer(tmp)) {
- rv = EditorBase::GetLengthOfDOMNode(tmp, endPoint);
- NS_ENSURE_SUCCESS(rv, rv);
+ endPoint = tmp->Length();
} else {
tmp = EditorBase::GetNodeLocation(tmp, (int32_t*)&endPoint);
endPoint++; // want to be after this node
@@ -7222,9 +7242,11 @@ HTMLEditRules::PinSelectionToNewBlock(Selection* aSelection)
return aSelection->Collapse(tmp, (int32_t)endPoint);
} else {
// selection is before block. put at start of block.
- nsCOMPtr<nsIDOMNode> tmp = GetAsDOMNode(mNewBlock);
NS_ENSURE_STATE(mHTMLEditor);
- tmp = GetAsDOMNode(mHTMLEditor->GetFirstEditableChild(*block));
+ nsCOMPtr<nsINode> tmp = mHTMLEditor->GetFirstEditableChild(*mNewBlock);
+ if (!tmp) {
+ tmp = mNewBlock;
+ }
int32_t offset;
if (mHTMLEditor->IsTextNode(tmp) ||
mHTMLEditor->IsContainer(tmp)) {
@@ -7967,7 +7989,7 @@ HTMLEditRules::UpdateDocChangeRange(nsRange* aRange)
NS_ENSURE_SUCCESS(rv, rv);
// Positive result means mDocChangeRange start is after aRange start.
if (result > 0) {
- int32_t startOffset;
+ uint32_t startOffset;
rv = aRange->GetStartOffset(&startOffset);
NS_ENSURE_SUCCESS(rv, rv);
rv = mDocChangeRange->SetStart(startNode, startOffset);
@@ -7981,9 +8003,9 @@ HTMLEditRules::UpdateDocChangeRange(nsRange* aRange)
// Negative result means mDocChangeRange end is before aRange end.
if (result < 0) {
nsCOMPtr<nsIDOMNode> endNode;
- int32_t endOffset;
rv = aRange->GetEndContainer(getter_AddRefs(endNode));
NS_ENSURE_SUCCESS(rv, rv);
+ uint32_t endOffset;
rv = aRange->GetEndOffset(&endOffset);
NS_ENSURE_SUCCESS(rv, rv);
rv = mDocChangeRange->SetEnd(endNode, endOffset);
@@ -8091,10 +8113,13 @@ HTMLEditRules::DidSplitNode(nsIDOMNode* aExistingRightNode,
if (!mListenerEnabled) {
return NS_OK;
}
- nsresult rv = mUtilRange->SetStart(aNewLeftNode, 0);
- NS_ENSURE_SUCCESS(rv, rv);
- rv = mUtilRange->SetEnd(aExistingRightNode, 0);
- NS_ENSURE_SUCCESS(rv, rv);
+ nsCOMPtr<nsINode> newLeftNode = do_QueryInterface(aNewLeftNode);
+ nsCOMPtr<nsINode> existingRightNode = do_QueryInterface(aExistingRightNode);
+ nsresult rv = mUtilRange->SetStartAndEnd(newLeftNode, 0,
+ existingRightNode, 0);
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return rv;
+ }
return UpdateDocChangeRange(mUtilRange);
}
@@ -8119,11 +8144,12 @@ HTMLEditRules::DidJoinNodes(nsIDOMNode* aLeftNode,
if (!mListenerEnabled) {
return NS_OK;
}
+ nsCOMPtr<nsINode> rightNode = do_QueryInterface(aRightNode);
// assumption that Join keeps the righthand node
- nsresult rv = mUtilRange->SetStart(aRightNode, mJoinOffset);
- NS_ENSURE_SUCCESS(rv, rv);
- rv = mUtilRange->SetEnd(aRightNode, mJoinOffset);
- NS_ENSURE_SUCCESS(rv, rv);
+ nsresult rv = mUtilRange->CollapseTo(rightNode, mJoinOffset);
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return rv;
+ }
return UpdateDocChangeRange(mUtilRange);
}
@@ -8145,11 +8171,12 @@ HTMLEditRules::DidInsertText(nsIDOMCharacterData* aTextNode,
return NS_OK;
}
int32_t length = aString.Length();
- nsCOMPtr<nsIDOMNode> theNode = do_QueryInterface(aTextNode);
- nsresult rv = mUtilRange->SetStart(theNode, aOffset);
- NS_ENSURE_SUCCESS(rv, rv);
- rv = mUtilRange->SetEnd(theNode, aOffset+length);
- NS_ENSURE_SUCCESS(rv, rv);
+ nsCOMPtr<nsINode> theNode = do_QueryInterface(aTextNode);
+ nsresult rv = mUtilRange->SetStartAndEnd(theNode, aOffset,
+ theNode, aOffset + length);
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return rv;
+ }
return UpdateDocChangeRange(mUtilRange);
}
@@ -8170,11 +8197,11 @@ HTMLEditRules::DidDeleteText(nsIDOMCharacterData* aTextNode,
if (!mListenerEnabled) {
return NS_OK;
}
- nsCOMPtr<nsIDOMNode> theNode = do_QueryInterface(aTextNode);
- nsresult rv = mUtilRange->SetStart(theNode, aOffset);
- NS_ENSURE_SUCCESS(rv, rv);
- rv = mUtilRange->SetEnd(theNode, aOffset);
- NS_ENSURE_SUCCESS(rv, rv);
+ nsCOMPtr<nsINode> theNode = do_QueryInterface(aTextNode);
+ nsresult rv = mUtilRange->CollapseTo(theNode, aOffset);
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return rv;
+ }
return UpdateDocChangeRange(mUtilRange);
}
@@ -8189,22 +8216,27 @@ HTMLEditRules::WillDeleteSelection(nsISelection* aSelection)
}
RefPtr<Selection> selection = aSelection->AsSelection();
// get the (collapsed) selection location
- nsCOMPtr<nsIDOMNode> selNode;
- int32_t selOffset;
-
+ nsCOMPtr<nsINode> startNode;
+ int32_t startOffset;
NS_ENSURE_STATE(mHTMLEditor);
nsresult rv =
mHTMLEditor->GetStartNodeAndOffset(selection,
- getter_AddRefs(selNode), &selOffset);
- NS_ENSURE_SUCCESS(rv, rv);
- rv = mUtilRange->SetStart(selNode, selOffset);
- NS_ENSURE_SUCCESS(rv, rv);
+ getter_AddRefs(startNode), &startOffset);
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return rv;
+ }
+ nsCOMPtr<nsINode> endNode;
+ int32_t endOffset;
NS_ENSURE_STATE(mHTMLEditor);
rv = mHTMLEditor->GetEndNodeAndOffset(selection,
- getter_AddRefs(selNode), &selOffset);
- NS_ENSURE_SUCCESS(rv, rv);
- rv = mUtilRange->SetEnd(selNode, selOffset);
- NS_ENSURE_SUCCESS(rv, rv);
+ getter_AddRefs(endNode), &endOffset);
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return rv;
+ }
+ rv = mUtilRange->SetStartAndEnd(startNode, startOffset, endNode, endOffset);
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return rv;
+ }
return UpdateDocChangeRange(mUtilRange);
}
diff --git a/editor/libeditor/HTMLEditUtils.cpp b/editor/libeditor/HTMLEditUtils.cpp
index 0adc5d511..aa0afda98 100644
--- a/editor/libeditor/HTMLEditUtils.cpp
+++ b/editor/libeditor/HTMLEditUtils.cpp
@@ -583,7 +583,7 @@ HTMLEditUtils::SupportsAlignAttr(nsIDOMNode* aNode)
struct ElementInfo final
{
#ifdef DEBUG
- eHTMLTags mTag;
+ nsHTMLTag mTag;
#endif
uint32_t mGroup;
uint32_t mCanContainGroups;
@@ -603,9 +603,11 @@ static const ElementInfo kElements[eHTMLTag_userdefined] = {
ELEM(a, true, false, GROUP_SPECIAL, GROUP_INLINE_ELEMENT),
ELEM(abbr, true, true, GROUP_PHRASE, GROUP_INLINE_ELEMENT),
ELEM(acronym, true, true, GROUP_PHRASE, GROUP_INLINE_ELEMENT),
- ELEM(address, true, true, GROUP_BLOCK,
- GROUP_INLINE_ELEMENT | GROUP_P),
- ELEM(applet, true, true, GROUP_SPECIAL | GROUP_BLOCK,
+ ELEM(address, true, true, GROUP_BLOCK, GROUP_INLINE_ELEMENT | GROUP_P),
+ ELEM(applet,
+ true,
+ true,
+ GROUP_SPECIAL | GROUP_BLOCK,
GROUP_FLOW_ELEMENT | GROUP_OBJECT_CONTENT),
ELEM(area, false, false, GROUP_MAP_CONTENT, GROUP_NONE),
ELEM(article, true, true, GROUP_BLOCK, GROUP_FLOW_ELEMENT),
@@ -620,19 +622,23 @@ static const ElementInfo kElements[eHTMLTag_userdefined] = {
ELEM(blockquote, true, true, GROUP_BLOCK, GROUP_FLOW_ELEMENT),
ELEM(body, true, true, GROUP_TOPLEVEL, GROUP_FLOW_ELEMENT),
ELEM(br, false, false, GROUP_SPECIAL, GROUP_NONE),
- ELEM(button, true, true, GROUP_FORMCONTROL | GROUP_BLOCK,
- GROUP_FLOW_ELEMENT),
+ ELEM(button, true, true, GROUP_FORMCONTROL | GROUP_BLOCK, GROUP_FLOW_ELEMENT),
ELEM(canvas, false, false, GROUP_NONE, GROUP_NONE),
ELEM(caption, true, true, GROUP_NONE, GROUP_INLINE_ELEMENT),
ELEM(center, true, true, GROUP_BLOCK, GROUP_FLOW_ELEMENT),
ELEM(cite, true, true, GROUP_PHRASE, GROUP_INLINE_ELEMENT),
ELEM(code, true, true, GROUP_PHRASE, GROUP_INLINE_ELEMENT),
- ELEM(col, false, false, GROUP_TABLE_CONTENT | GROUP_COLGROUP_CONTENT,
+ ELEM(col,
+ false,
+ false,
+ GROUP_TABLE_CONTENT | GROUP_COLGROUP_CONTENT,
GROUP_NONE),
ELEM(colgroup, true, false, GROUP_NONE, GROUP_COLGROUP_CONTENT),
- ELEM(content, true, false, GROUP_NONE, GROUP_INLINE_ELEMENT),
ELEM(data, true, false, GROUP_PHRASE, GROUP_INLINE_ELEMENT),
- ELEM(datalist, true, false, GROUP_PHRASE,
+ ELEM(datalist,
+ true,
+ false,
+ GROUP_PHRASE,
GROUP_OPTIONS | GROUP_INLINE_ELEMENT),
ELEM(dd, true, false, GROUP_DL_CONTENT, GROUP_FLOW_ELEMENT),
ELEM(del, true, true, GROUP_PHRASE | GROUP_BLOCK, GROUP_FLOW_ELEMENT),
@@ -647,33 +653,25 @@ static const ElementInfo kElements[eHTMLTag_userdefined] = {
ELEM(embed, false, false, GROUP_NONE, GROUP_NONE),
ELEM(fieldset, true, true, GROUP_BLOCK, GROUP_FLOW_ELEMENT),
ELEM(figcaption, true, false, GROUP_FIGCAPTION, GROUP_FLOW_ELEMENT),
- ELEM(figure, true, true, GROUP_BLOCK,
- GROUP_FLOW_ELEMENT | GROUP_FIGCAPTION),
+ ELEM(figure, true, true, GROUP_BLOCK, GROUP_FLOW_ELEMENT | GROUP_FIGCAPTION),
ELEM(font, true, true, GROUP_SPECIAL, GROUP_INLINE_ELEMENT),
ELEM(footer, true, true, GROUP_BLOCK, GROUP_FLOW_ELEMENT),
ELEM(form, true, true, GROUP_BLOCK, GROUP_FLOW_ELEMENT),
ELEM(frame, false, false, GROUP_FRAME, GROUP_NONE),
ELEM(frameset, true, true, GROUP_FRAME, GROUP_FRAME),
- ELEM(h1, true, false, GROUP_BLOCK | GROUP_HEADING,
- GROUP_INLINE_ELEMENT),
- ELEM(h2, true, false, GROUP_BLOCK | GROUP_HEADING,
- GROUP_INLINE_ELEMENT),
- ELEM(h3, true, false, GROUP_BLOCK | GROUP_HEADING,
- GROUP_INLINE_ELEMENT),
- ELEM(h4, true, false, GROUP_BLOCK | GROUP_HEADING,
- GROUP_INLINE_ELEMENT),
- ELEM(h5, true, false, GROUP_BLOCK | GROUP_HEADING,
- GROUP_INLINE_ELEMENT),
- ELEM(h6, true, false, GROUP_BLOCK | GROUP_HEADING,
- GROUP_INLINE_ELEMENT),
+ ELEM(h1, true, false, GROUP_BLOCK | GROUP_HEADING, GROUP_INLINE_ELEMENT),
+ ELEM(h2, true, false, GROUP_BLOCK | GROUP_HEADING, GROUP_INLINE_ELEMENT),
+ ELEM(h3, true, false, GROUP_BLOCK | GROUP_HEADING, GROUP_INLINE_ELEMENT),
+ ELEM(h4, true, false, GROUP_BLOCK | GROUP_HEADING, GROUP_INLINE_ELEMENT),
+ ELEM(h5, true, false, GROUP_BLOCK | GROUP_HEADING, GROUP_INLINE_ELEMENT),
+ ELEM(h6, true, false, GROUP_BLOCK | GROUP_HEADING, GROUP_INLINE_ELEMENT),
ELEM(head, true, false, GROUP_TOPLEVEL, GROUP_HEAD_CONTENT),
ELEM(header, true, true, GROUP_BLOCK, GROUP_FLOW_ELEMENT),
ELEM(hgroup, true, false, GROUP_BLOCK, GROUP_HEADING),
ELEM(hr, false, false, GROUP_BLOCK, GROUP_NONE),
ELEM(html, true, false, GROUP_TOPLEVEL, GROUP_TOPLEVEL),
ELEM(i, true, true, GROUP_FONTSTYLE, GROUP_INLINE_ELEMENT),
- ELEM(iframe, true, true, GROUP_SPECIAL | GROUP_BLOCK,
- GROUP_FLOW_ELEMENT),
+ ELEM(iframe, true, true, GROUP_SPECIAL | GROUP_BLOCK, GROUP_FLOW_ELEMENT),
ELEM(image, false, false, GROUP_NONE, GROUP_NONE),
ELEM(img, false, false, GROUP_SPECIAL | GROUP_PICTURE_CONTENT, GROUP_NONE),
ELEM(input, false, false, GROUP_FORMCONTROL, GROUP_NONE),
@@ -699,15 +697,15 @@ static const ElementInfo kElements[eHTMLTag_userdefined] = {
ELEM(noembed, false, false, GROUP_NONE, GROUP_NONE),
ELEM(noframes, true, true, GROUP_BLOCK, GROUP_FLOW_ELEMENT),
ELEM(noscript, true, true, GROUP_BLOCK, GROUP_FLOW_ELEMENT),
- ELEM(object, true, true, GROUP_SPECIAL | GROUP_BLOCK,
+ ELEM(object,
+ true,
+ true,
+ GROUP_SPECIAL | GROUP_BLOCK,
GROUP_FLOW_ELEMENT | GROUP_OBJECT_CONTENT),
// XXX Can contain self and ul because editor does sublists illegally.
- ELEM(ol, true, true, GROUP_BLOCK | GROUP_OL_UL,
- GROUP_LI | GROUP_OL_UL),
- ELEM(optgroup, true, false, GROUP_SELECT_CONTENT,
- GROUP_OPTIONS),
- ELEM(option, true, false,
- GROUP_SELECT_CONTENT | GROUP_OPTIONS, GROUP_LEAF),
+ ELEM(ol, true, true, GROUP_BLOCK | GROUP_OL_UL, GROUP_LI | GROUP_OL_UL),
+ ELEM(optgroup, true, false, GROUP_SELECT_CONTENT, GROUP_OPTIONS),
+ ELEM(option, true, false, GROUP_SELECT_CONTENT | GROUP_OPTIONS, GROUP_LEAF),
ELEM(output, true, true, GROUP_SPECIAL, GROUP_INLINE_ELEMENT),
ELEM(p, true, false, GROUP_BLOCK | GROUP_P, GROUP_INLINE_ELEMENT),
ELEM(param, false, false, GROUP_OBJECT_CONTENT, GROUP_NONE),
@@ -723,12 +721,11 @@ static const ElementInfo kElements[eHTMLTag_userdefined] = {
ELEM(ruby, true, true, GROUP_PHRASE, GROUP_INLINE_ELEMENT),
ELEM(s, true, true, GROUP_FONTSTYLE, GROUP_INLINE_ELEMENT),
ELEM(samp, true, true, GROUP_PHRASE, GROUP_INLINE_ELEMENT),
- ELEM(script, true, false, GROUP_HEAD_CONTENT | GROUP_SPECIAL,
- GROUP_LEAF),
+ ELEM(script, true, false, GROUP_HEAD_CONTENT | GROUP_SPECIAL, GROUP_LEAF),
ELEM(section, true, true, GROUP_BLOCK, GROUP_FLOW_ELEMENT),
ELEM(select, true, false, GROUP_FORMCONTROL, GROUP_SELECT_CONTENT),
- ELEM(shadow, true, false, GROUP_NONE, GROUP_INLINE_ELEMENT),
ELEM(small, true, true, GROUP_FONTSTYLE, GROUP_INLINE_ELEMENT),
+ ELEM(slot, true, false, GROUP_NONE, GROUP_FLOW_ELEMENT),
ELEM(source, false, false, GROUP_PICTURE_CONTENT, GROUP_NONE),
ELEM(span, true, true, GROUP_SPECIAL, GROUP_INLINE_ELEMENT),
ELEM(strike, true, true, GROUP_FONTSTYLE, GROUP_INLINE_ELEMENT),
@@ -752,8 +749,7 @@ static const ElementInfo kElements[eHTMLTag_userdefined] = {
ELEM(tt, true, true, GROUP_FONTSTYLE, GROUP_INLINE_ELEMENT),
ELEM(u, true, true, GROUP_FONTSTYLE, GROUP_INLINE_ELEMENT),
// XXX Can contain self and ol because editor does sublists illegally.
- ELEM(ul, true, true, GROUP_BLOCK | GROUP_OL_UL,
- GROUP_LI | GROUP_OL_UL),
+ ELEM(ul, true, true, GROUP_BLOCK | GROUP_OL_UL, GROUP_LI | GROUP_OL_UL),
ELEM(var, true, true, GROUP_PHRASE, GROUP_INLINE_ELEMENT),
ELEM(video, false, false, GROUP_NONE, GROUP_NONE),
ELEM(wbr, false, false, GROUP_NONE, GROUP_NONE),
@@ -794,7 +790,7 @@ HTMLEditUtils::CanContain(int32_t aParent, int32_t aChild)
// Special-case button.
if (aParent == eHTMLTag_button) {
- static const eHTMLTags kButtonExcludeKids[] = {
+ static const nsHTMLTag kButtonExcludeKids[] = {
eHTMLTag_a,
eHTMLTag_fieldset,
eHTMLTag_form,
diff --git a/editor/libeditor/HTMLEditor.cpp b/editor/libeditor/HTMLEditor.cpp
index 532da7a15..c2f0bdc6d 100644
--- a/editor/libeditor/HTMLEditor.cpp
+++ b/editor/libeditor/HTMLEditor.cpp
@@ -63,13 +63,13 @@
#include "nsIWidget.h"
#include "nsIFrame.h"
-#include "nsIParserService.h"
#include "mozilla/dom/Selection.h"
#include "mozilla/dom/DocumentFragment.h"
#include "mozilla/dom/Element.h"
#include "mozilla/dom/Event.h"
#include "mozilla/dom/EventTarget.h"
#include "mozilla/dom/HTMLBodyElement.h"
+#include "nsElementTable.h"
#include "nsTextFragment.h"
#include "nsContentList.h"
#include "mozilla/StyleSheet.h"
@@ -165,7 +165,7 @@ HTMLEditor::~HTMLEditor()
// free any default style propItems
RemoveAllDefaultProperties();
- if (mLinkHandler && mDocWeak) {
+ if (mLinkHandler && IsInitialized()) {
nsCOMPtr<nsIPresShell> ps = GetPresShell();
if (ps && ps->GetPresContext()) {
@@ -287,7 +287,7 @@ HTMLEditor::Init(nsIDOMDocument* aDoc,
}
// Init the HTML-CSS utils
- mCSSEditUtils = new CSSEditUtils(this);
+ mCSSEditUtils = MakeUnique<CSSEditUtils>(this);
// disable links
nsCOMPtr<nsIPresShell> presShell = GetPresShell();
@@ -335,7 +335,7 @@ HTMLEditor::PreDestroy(bool aDestroyingFrames)
return NS_OK;
}
- nsCOMPtr<nsINode> document = do_QueryReferent(mDocWeak);
+ nsCOMPtr<nsIDocument> document = GetDocument();
if (document) {
document->RemoveMutationObserver(this);
}
@@ -365,7 +365,7 @@ HTMLEditor::UpdateRootElement()
} else {
// If there is no HTML body element,
// we should use the document root element instead.
- nsCOMPtr<nsIDOMDocument> doc = do_QueryReferent(mDocWeak);
+ nsCOMPtr<nsIDOMDocument> doc = GetDOMDocument();
if (doc) {
doc->GetDocumentElement(getter_AddRefs(rootElement));
}
@@ -430,8 +430,9 @@ HTMLEditor::CreateEventListeners()
nsresult
HTMLEditor::InstallEventListeners()
{
- NS_ENSURE_TRUE(mDocWeak && mEventListener,
- NS_ERROR_NOT_INITIALIZED);
+ if (NS_WARN_IF(!IsInitialized()) || NS_WARN_IF(!mEventListener)) {
+ return NS_ERROR_NOT_INITIALIZED;
+ }
// NOTE: HTMLEditor doesn't need to initialize mEventTarget here because
// the target must be document node and it must be referenced as weak pointer.
@@ -444,7 +445,7 @@ HTMLEditor::InstallEventListeners()
void
HTMLEditor::RemoveEventListeners()
{
- if (!mDocWeak) {
+ if (!IsInitialized()) {
return;
}
@@ -506,7 +507,8 @@ HTMLEditor::InitRules()
NS_IMETHODIMP
HTMLEditor::BeginningOfDocument()
{
- if (!mDocWeak) {
+ // XXX Why doesn't this check if the document is alive?
+ if (!IsInitialized()) {
return NS_ERROR_NOT_INITIALIZED;
}
@@ -688,49 +690,6 @@ HTMLEditor::HandleKeyPressEvent(nsIDOMKeyEvent* aKeyEvent)
return TypedText(str, eTypedText);
}
-static void
-AssertParserServiceIsCorrect(nsIAtom* aTag, bool aIsBlock)
-{
-#ifdef DEBUG
- // Check this against what we would have said with the old code:
- if (aTag == nsGkAtoms::p ||
- aTag == nsGkAtoms::div ||
- aTag == nsGkAtoms::blockquote ||
- aTag == nsGkAtoms::h1 ||
- aTag == nsGkAtoms::h2 ||
- aTag == nsGkAtoms::h3 ||
- aTag == nsGkAtoms::h4 ||
- aTag == nsGkAtoms::h5 ||
- aTag == nsGkAtoms::h6 ||
- aTag == nsGkAtoms::ul ||
- aTag == nsGkAtoms::ol ||
- aTag == nsGkAtoms::dl ||
- aTag == nsGkAtoms::noscript ||
- aTag == nsGkAtoms::form ||
- aTag == nsGkAtoms::hr ||
- aTag == nsGkAtoms::table ||
- aTag == nsGkAtoms::fieldset ||
- aTag == nsGkAtoms::address ||
- aTag == nsGkAtoms::col ||
- aTag == nsGkAtoms::colgroup ||
- aTag == nsGkAtoms::li ||
- aTag == nsGkAtoms::dt ||
- aTag == nsGkAtoms::dd ||
- aTag == nsGkAtoms::legend) {
- if (!aIsBlock) {
- nsAutoString assertmsg (NS_LITERAL_STRING("Parser and editor disagree on blockness: "));
-
- nsAutoString tagName;
- aTag->ToString(tagName);
- assertmsg.Append(tagName);
- char* assertstr = ToNewCString(assertmsg);
- NS_ASSERTION(aIsBlock, assertstr);
- free(assertstr);
- }
- }
-#endif // DEBUG
-}
-
/**
* Returns true if the id represents an element of block type.
* Can be used to determine if a new paragraph should be started.
@@ -740,8 +699,8 @@ HTMLEditor::NodeIsBlockStatic(const nsINode* aElement)
{
MOZ_ASSERT(aElement);
- // Nodes we know we want to treat as block
- // even though the parser says they're not:
+ // We want to treat these as block nodes even though nsHTMLElement says
+ // they're not.
if (aElement->IsAnyOfHTMLElements(nsGkAtoms::body,
nsGkAtoms::head,
nsGkAtoms::tbody,
@@ -750,27 +709,13 @@ HTMLEditor::NodeIsBlockStatic(const nsINode* aElement)
nsGkAtoms::tr,
nsGkAtoms::th,
nsGkAtoms::td,
- nsGkAtoms::li,
nsGkAtoms::dt,
- nsGkAtoms::dd,
- nsGkAtoms::pre)) {
+ nsGkAtoms::dd)) {
return true;
}
- bool isBlock;
-#ifdef DEBUG
- // XXX we can't use DebugOnly here because VC++ is stupid (bug 802884)
- nsresult rv =
-#endif
- nsContentUtils::GetParserService()->
- IsBlock(nsContentUtils::GetParserService()->HTMLAtomTagToId(
- aElement->NodeInfo()->NameAtom()),
- isBlock);
- MOZ_ASSERT(rv == NS_OK);
-
- AssertParserServiceIsCorrect(aElement->NodeInfo()->NameAtom(), isBlock);
-
- return isBlock;
+ return nsHTMLElement::IsBlock(
+ nsHTMLTags::AtomTagToId(aElement->NodeInfo()->NameAtom()));
}
nsresult
@@ -1183,11 +1128,13 @@ HTMLEditor::ReplaceHeadContentsWithHTML(const nsAString& aSourceToInsert)
// Do not use AutoRules -- rules code won't let us insert in <head>. Use
// the head node as a parent and delete/insert directly.
- nsCOMPtr<nsIDocument> doc = do_QueryReferent(mDocWeak);
- NS_ENSURE_TRUE(doc, NS_ERROR_NOT_INITIALIZED);
+ nsCOMPtr<nsIDocument> document = GetDocument();
+ if (NS_WARN_IF(!document)) {
+ return NS_ERROR_NOT_INITIALIZED;
+ }
RefPtr<nsContentList> nodeList =
- doc->GetElementsByTagName(NS_LITERAL_STRING("head"));
+ document->GetElementsByTagName(NS_LITERAL_STRING("head"));
NS_ENSURE_TRUE(nodeList, NS_ERROR_NULL_POINTER);
nsCOMPtr<nsIContent> headNode = nodeList->Item(0);
@@ -2401,21 +2348,19 @@ HTMLEditor::GetSelectedElement(const nsAString& aTagName,
NS_ENSURE_STATE(range);
nsCOMPtr<nsIDOMNode> startParent;
- int32_t startOffset, endOffset;
nsresult rv = range->GetStartContainer(getter_AddRefs(startParent));
NS_ENSURE_SUCCESS(rv, rv);
- rv = range->GetStartOffset(&startOffset);
- NS_ENSURE_SUCCESS(rv, rv);
+ uint32_t startOffset = range->StartOffset();
nsCOMPtr<nsIDOMNode> endParent;
rv = range->GetEndContainer(getter_AddRefs(endParent));
NS_ENSURE_SUCCESS(rv, rv);
- rv = range->GetEndOffset(&endOffset);
- NS_ENSURE_SUCCESS(rv, rv);
+ uint32_t endOffset = range->EndOffset();
// Optimization for a single selected element
if (startParent && startParent == endParent && endOffset - startOffset == 1) {
- nsCOMPtr<nsIDOMNode> selectedNode = GetChildAt(startParent, startOffset);
+ nsCOMPtr<nsIDOMNode> selectedNode =
+ GetChildAt(startParent, static_cast<int32_t>(startOffset));
NS_ENSURE_SUCCESS(rv, NS_OK);
if (selectedNode) {
selectedNode->GetNodeName(domTagName);
@@ -2705,7 +2650,7 @@ HTMLEditor::InsertLinkAroundSelection(nsIDOMElement* aAnchorElement)
nsresult
HTMLEditor::SetHTMLBackgroundColor(const nsAString& aColor)
{
- NS_PRECONDITION(mDocWeak, "Missing Editor DOM Document");
+ MOZ_ASSERT(IsInitialized(), "The HTMLEditor hasn't been initialized yet");
// Find a selected or enclosing table element to set background on
nsCOMPtr<nsIDOMElement> element;
@@ -2753,7 +2698,7 @@ HTMLEditor::SetBodyAttribute(const nsAString& aAttribute,
{
// TODO: Check selection for Cell, Row, Column or table and do color on appropriate level
- NS_ASSERTION(mDocWeak, "Missing Editor DOM Document");
+ MOZ_ASSERT(IsInitialized(), "The HTMLEditor hasn't been initialized yet");
// Set the background color attribute on the body tag
nsCOMPtr<nsIDOMElement> bodyElement = do_QueryInterface(GetRoot());
@@ -2832,7 +2777,9 @@ HTMLEditor::ReplaceStyleSheet(const nsAString& aURL)
}
// Make sure the pres shell doesn't disappear during the load.
- NS_ENSURE_TRUE(mDocWeak, NS_ERROR_NOT_INITIALIZED);
+ if (NS_WARN_IF(!IsInitialized())) {
+ return NS_ERROR_NOT_INITIALIZED;
+ }
nsCOMPtr<nsIPresShell> ps = GetPresShell();
NS_ENSURE_TRUE(ps, NS_ERROR_NOT_INITIALIZED);
@@ -2941,7 +2888,9 @@ HTMLEditor::RemoveOverrideStyleSheet(const nsAString& aURL)
NS_ENSURE_TRUE(sheet, NS_OK); /// Don't fail if sheet not found
- NS_ENSURE_TRUE(mDocWeak, NS_ERROR_NOT_INITIALIZED);
+ if (NS_WARN_IF(!IsInitialized())) {
+ return NS_ERROR_NOT_INITIALIZED;
+ }
nsCOMPtr<nsIPresShell> ps = GetPresShell();
NS_ENSURE_TRUE(ps, NS_ERROR_NOT_INITIALIZED);
@@ -2960,8 +2909,8 @@ HTMLEditor::EnableStyleSheet(const nsAString& aURL,
NS_ENSURE_TRUE(sheet, NS_OK); // Don't fail if sheet not found
// Ensure the style sheet is owned by our document.
- nsCOMPtr<nsIDocument> doc = do_QueryReferent(mDocWeak);
- sheet->SetOwningDocument(doc);
+ nsCOMPtr<nsIDocument> document = GetDocument();
+ sheet->SetAssociatedDocument(document, StyleSheet::NotOwnedByDocument);
if (sheet->IsServo()) {
// XXXheycam ServoStyleSheets don't support being enabled/disabled yet.
@@ -2982,8 +2931,8 @@ HTMLEditor::EnableExistingStyleSheet(const nsAString& aURL)
}
// Ensure the style sheet is owned by our document.
- nsCOMPtr<nsIDocument> doc = do_QueryReferent(mDocWeak);
- sheet->SetOwningDocument(doc);
+ nsCOMPtr<nsIDocument> document = GetDocument();
+ sheet->SetAssociatedDocument(document, StyleSheet::NotOwnedByDocument);
if (sheet->IsServo()) {
// XXXheycam ServoStyleSheets don't support being enabled/disabled yet.
@@ -3284,8 +3233,8 @@ HTMLEditor::DoContentInserted(nsIDocument* aDocument,
sibling = sibling->GetNextSibling();
}
}
- nsresult rv = range->Set(aContainer, aIndexInContainer,
- aContainer, endIndex);
+ nsresult rv = range->SetStartAndEnd(aContainer, aIndexInContainer,
+ aContainer, endIndex);
if (NS_SUCCEEDED(rv)) {
mInlineSpellChecker->SpellCheckRange(range);
}
@@ -3374,13 +3323,12 @@ HTMLEditor::GetIsSelectionEditable(bool* aIsSelectionEditable)
static nsresult
SetSelectionAroundHeadChildren(Selection* aSelection,
- nsIWeakReference* aDocWeak)
+ nsCOMPtr<nsIDocument>& aDocument)
{
- // Set selection around <head> node
- nsCOMPtr<nsIDocument> doc = do_QueryReferent(aDocWeak);
- NS_ENSURE_TRUE(doc, NS_ERROR_NOT_INITIALIZED);
+ MOZ_ASSERT(aDocument);
- dom::Element* headNode = doc->GetHeadElement();
+ // Set selection around <head> node
+ dom::Element* headNode = aDocument->GetHeadElement();
NS_ENSURE_STATE(headNode);
// Collapse selection to before first child of the head,
@@ -3401,7 +3349,11 @@ HTMLEditor::GetHeadContentsAsHTML(nsAString& aOutputString)
// Save current selection
AutoSelectionRestorer selectionRestorer(selection, this);
- nsresult rv = SetSelectionAroundHeadChildren(selection, mDocWeak);
+ nsCOMPtr<nsIDocument> document = GetDocument();
+ if (NS_WARN_IF(!document)) {
+ return NS_ERROR_NOT_INITIALIZED;
+ }
+ nsresult rv = SetSelectionAroundHeadChildren(selection, document);
NS_ENSURE_SUCCESS(rv, rv);
rv = OutputToString(NS_LITERAL_STRING("text/html"),
@@ -3529,17 +3481,15 @@ bool
HTMLEditor::TagCanContainTag(nsIAtom& aParentTag,
nsIAtom& aChildTag)
{
- nsIParserService* parserService = nsContentUtils::GetParserService();
-
int32_t childTagEnum;
// XXX Should this handle #cdata-section too?
if (&aChildTag == nsGkAtoms::textTagName) {
childTagEnum = eHTMLTag_text;
} else {
- childTagEnum = parserService->HTMLAtomTagToId(&aChildTag);
+ childTagEnum = nsHTMLTags::AtomTagToId(&aChildTag);
}
- int32_t parentTagEnum = parserService->HTMLAtomTagToId(&aParentTag);
+ int32_t parentTagEnum = nsHTMLTags::AtomTagToId(&aParentTag);
return HTMLEditUtils::CanContain(parentTagEnum, childTagEnum);
}
@@ -3553,8 +3503,7 @@ HTMLEditor::IsContainer(nsINode* aNode)
if (aNode->IsNodeOfType(nsINode::eTEXT)) {
tagEnum = eHTMLTag_text;
} else {
- tagEnum =
- nsContentUtils::GetParserService()->HTMLStringTagToId(aNode->NodeName());
+ tagEnum = nsHTMLTags::StringTagToId(aNode->NodeName());
}
return HTMLEditUtils::IsContainer(tagEnum);
@@ -3581,15 +3530,11 @@ HTMLEditor::SelectEntireDocument(Selection* aSelection)
// Protect the edit rules object from dying
nsCOMPtr<nsIEditRules> rules(mRules);
- // get editor root node
- nsCOMPtr<nsIDOMElement> rootElement = do_QueryInterface(GetRoot());
-
// is doc empty?
- bool bDocIsEmpty;
- nsresult rv = rules->DocumentIsEmpty(&bDocIsEmpty);
- NS_ENSURE_SUCCESS(rv, rv);
+ if (rules->DocumentIsEmpty()) {
+ // get editor root node
+ Element* rootElement = GetRoot();
- if (bDocIsEmpty) {
// if its empty dont select entire doc - that would select the bogus node
return aSelection->Collapse(rootElement, 0);
}
@@ -4275,10 +4220,11 @@ HTMLEditor::IsVisTextNode(nsIContent* aNode,
uint32_t length = aNode->TextLength();
if (aSafeToAskFrames) {
- nsCOMPtr<nsISelectionController> selCon;
- nsresult rv = GetSelectionController(getter_AddRefs(selCon));
- NS_ENSURE_SUCCESS(rv, rv);
- NS_ENSURE_TRUE(selCon, NS_ERROR_FAILURE);
+ nsCOMPtr<nsISelectionController> selectionController =
+ GetSelectionController();
+ if (NS_WARN_IF(!selectionController)) {
+ return NS_ERROR_FAILURE;
+ }
bool isVisible = false;
// ask the selection controller for information about whether any
// of the data in the node is really rendered. This is really
@@ -4286,7 +4232,8 @@ HTMLEditor::IsVisTextNode(nsIContent* aNode,
// So we put a call in the selection controller interface, since it's already
// in bed with frames anyway. (this is a fix for bug 22227, and a
// partial fix for bug 46209)
- rv = selCon->CheckVisibilityContent(aNode, 0, length, &isVisible);
+ nsresult rv = selectionController->CheckVisibilityContent(aNode, 0, length,
+ &isVisible);
NS_ENSURE_SUCCESS(rv, rv);
if (isVisible) {
*outIsEmptyNode = false;
@@ -4802,7 +4749,9 @@ HTMLEditor::GetElementOrigin(nsIDOMElement* aElement,
aX = 0;
aY = 0;
- NS_ENSURE_TRUE(mDocWeak, NS_ERROR_NOT_INITIALIZED);
+ if (NS_WARN_IF(!IsInitialized())) {
+ return NS_ERROR_NOT_INITIALIZED;
+ }
nsCOMPtr<nsIPresShell> ps = GetPresShell();
NS_ENSURE_TRUE(ps, NS_ERROR_NOT_INITIALIZED);
@@ -4944,28 +4893,29 @@ HTMLEditor::GetReturnInParagraphCreatesNewParagraph(bool* aCreatesNewParagraph)
already_AddRefed<nsIContent>
HTMLEditor::GetFocusedContent()
{
- NS_ENSURE_TRUE(mDocWeak, nullptr);
-
nsFocusManager* fm = nsFocusManager::GetFocusManager();
NS_ENSURE_TRUE(fm, nullptr);
nsCOMPtr<nsIContent> focusedContent = fm->GetFocusedContent();
- nsCOMPtr<nsIDocument> doc = do_QueryReferent(mDocWeak);
- bool inDesignMode = doc->HasFlag(NODE_IS_EDITABLE);
+ nsCOMPtr<nsIDocument> document = GetDocument();
+ if (NS_WARN_IF(!document)) {
+ return nullptr;
+ }
+ bool inDesignMode = document->HasFlag(NODE_IS_EDITABLE);
if (!focusedContent) {
// in designMode, nobody gets focus in most cases.
if (inDesignMode && OurWindowHasFocus()) {
- nsCOMPtr<nsIContent> docRoot = doc->GetRootElement();
- return docRoot.forget();
+ nsCOMPtr<nsIContent> rootContent = document->GetRootElement();
+ return rootContent.forget();
}
return nullptr;
}
if (inDesignMode) {
return OurWindowHasFocus() &&
- nsContentUtils::ContentIsDescendantOf(focusedContent, doc) ?
- focusedContent.forget() : nullptr;
+ nsContentUtils::ContentIsDescendantOf(focusedContent, document) ?
+ focusedContent.forget() : nullptr;
}
// We're HTML editor for contenteditable
@@ -4988,28 +4938,32 @@ HTMLEditor::GetFocusedContentForIME()
return nullptr;
}
- nsCOMPtr<nsIDocument> doc = do_QueryReferent(mDocWeak);
- NS_ENSURE_TRUE(doc, nullptr);
- return doc->HasFlag(NODE_IS_EDITABLE) ? nullptr : focusedContent.forget();
+ nsCOMPtr<nsIDocument> document = GetDocument();
+ if (NS_WARN_IF(!document)) {
+ return nullptr;
+ }
+ return document->HasFlag(NODE_IS_EDITABLE) ? nullptr :
+ focusedContent.forget();
}
bool
HTMLEditor::IsActiveInDOMWindow()
{
- NS_ENSURE_TRUE(mDocWeak, false);
-
nsFocusManager* fm = nsFocusManager::GetFocusManager();
NS_ENSURE_TRUE(fm, false);
- nsCOMPtr<nsIDocument> doc = do_QueryReferent(mDocWeak);
- bool inDesignMode = doc->HasFlag(NODE_IS_EDITABLE);
+ nsCOMPtr<nsIDocument> document = GetDocument();
+ if (NS_WARN_IF(!document)) {
+ return false;
+ }
+ bool inDesignMode = document->HasFlag(NODE_IS_EDITABLE);
// If we're in designMode, we're always active in the DOM window.
if (inDesignMode) {
return true;
}
- nsPIDOMWindowOuter* ourWindow = doc->GetWindow();
+ nsPIDOMWindowOuter* ourWindow = document->GetWindow();
nsCOMPtr<nsPIDOMWindowOuter> win;
nsIContent* content =
nsFocusManager::GetFocusedDescendant(ourWindow, false,
@@ -5032,12 +4986,12 @@ HTMLEditor::IsActiveInDOMWindow()
Element*
HTMLEditor::GetActiveEditingHost()
{
- NS_ENSURE_TRUE(mDocWeak, nullptr);
-
- nsCOMPtr<nsIDocument> doc = do_QueryReferent(mDocWeak);
- NS_ENSURE_TRUE(doc, nullptr);
- if (doc->HasFlag(NODE_IS_EDITABLE)) {
- return doc->GetBodyElement();
+ nsCOMPtr<nsIDocument> document = GetDocument();
+ if (NS_WARN_IF(!document)) {
+ return nullptr;
+ }
+ if (document->HasFlag(NODE_IS_EDITABLE)) {
+ return document->GetBodyElement();
}
// We're HTML editor for contenteditable
@@ -5066,8 +5020,8 @@ HTMLEditor::GetDOMEventTarget()
// Don't use getDocument here, because we have no way of knowing
// whether Init() was ever called. So we need to get the document
// ourselves, if it exists.
- NS_PRECONDITION(mDocWeak, "This editor has not been initialized yet");
- nsCOMPtr<mozilla::dom::EventTarget> target = do_QueryReferent(mDocWeak);
+ MOZ_ASSERT(IsInitialized(), "The HTMLEditor has not been initialized yet");
+ nsCOMPtr<mozilla::dom::EventTarget> target = GetDocument();
return target.forget();
}
@@ -5121,12 +5075,16 @@ HTMLEditor::NotifyRootChanged()
nsresult
HTMLEditor::GetBodyElement(nsIDOMHTMLElement** aBody)
{
- NS_PRECONDITION(mDocWeak, "bad state, null mDocWeak");
- nsCOMPtr<nsIDOMHTMLDocument> htmlDoc = do_QueryReferent(mDocWeak);
- if (!htmlDoc) {
+ MOZ_ASSERT(IsInitialized(), "The HTMLEditor hasn't been initialized yet");
+ nsCOMPtr<nsIDocument> document = GetDocument();
+ if (NS_WARN_IF(!document)) {
+ return NS_ERROR_NOT_INITIALIZED;
+ }
+ nsCOMPtr<nsIDOMHTMLDocument> domHTMLDocument = do_QueryInterface(document);
+ if (!domHTMLDocument) {
return NS_ERROR_NOT_INITIALIZED;
}
- return htmlDoc->GetBody(aBody);
+ return domHTMLDocument->GetBody(aBody);
}
already_AddRefed<nsINode>
@@ -5146,14 +5104,13 @@ HTMLEditor::GetFocusedNode()
return node.forget();
}
- nsCOMPtr<nsIDocument> doc = do_QueryReferent(mDocWeak);
- return doc.forget();
+ nsCOMPtr<nsIDocument> document = GetDocument();
+ return document.forget();
}
bool
HTMLEditor::OurWindowHasFocus()
{
- NS_ENSURE_TRUE(mDocWeak, false);
nsIFocusManager* fm = nsFocusManager::GetFocusManager();
NS_ENSURE_TRUE(fm, false);
nsCOMPtr<mozIDOMWindowProxy> focusedWindow;
@@ -5161,8 +5118,11 @@ HTMLEditor::OurWindowHasFocus()
if (!focusedWindow) {
return false;
}
- nsCOMPtr<nsIDocument> doc = do_QueryReferent(mDocWeak);
- nsPIDOMWindowOuter* ourWindow = doc->GetWindow();
+ nsCOMPtr<nsIDocument> document = GetDocument();
+ if (NS_WARN_IF(!document)) {
+ return false;
+ }
+ nsPIDOMWindowOuter* ourWindow = document->GetWindow();
return ourWindow == focusedWindow;
}
@@ -5180,12 +5140,14 @@ HTMLEditor::IsAcceptableInputEvent(WidgetGUIEvent* aGUIEvent)
return true;
}
- NS_ENSURE_TRUE(mDocWeak, false);
-
nsCOMPtr<nsIDOMEventTarget> target = aGUIEvent->GetDOMEventTarget();
NS_ENSURE_TRUE(target, false);
- nsCOMPtr<nsIDocument> document = do_QueryReferent(mDocWeak);
+ nsCOMPtr<nsIDocument> document = GetDocument();
+ if (NS_WARN_IF(!document)) {
+ return false;
+ }
+
if (document->HasFlag(NODE_IS_EDITABLE)) {
// If this editor is in designMode and the event target is the document,
// the event is for this editor.
diff --git a/editor/libeditor/HTMLEditor.h b/editor/libeditor/HTMLEditor.h
index dfcdd8d6b..dc1a41b70 100644
--- a/editor/libeditor/HTMLEditor.h
+++ b/editor/libeditor/HTMLEditor.h
@@ -10,11 +10,11 @@
#include "mozilla/CSSEditUtils.h"
#include "mozilla/StyleSheet.h"
#include "mozilla/TextEditor.h"
+#include "mozilla/UniquePtr.h"
#include "mozilla/dom/Element.h"
#include "mozilla/dom/File.h"
#include "nsAttrName.h"
-#include "nsAutoPtr.h"
#include "nsCOMPtr.h"
#include "nsIContentFilter.h"
#include "nsICSSLoaderObserver.h"
@@ -896,7 +896,7 @@ protected:
bool mCRInParagraphCreatesParagraph;
bool mCSSAware;
- nsAutoPtr<CSSEditUtils> mCSSEditUtils;
+ UniquePtr<CSSEditUtils> mCSSEditUtils;
// Used by GetFirstSelectedCell and GetNextSelectedCell
int32_t mSelectedCellIndex;
diff --git a/editor/libeditor/HTMLEditorDataTransfer.cpp b/editor/libeditor/HTMLEditorDataTransfer.cpp
index c56fbead7..0c01bdd1c 100644
--- a/editor/libeditor/HTMLEditorDataTransfer.cpp
+++ b/editor/libeditor/HTMLEditorDataTransfer.cpp
@@ -145,14 +145,13 @@ HTMLEditor::LoadHTML(const nsAString& aInputString)
rv = range->GetStartContainer(getter_AddRefs(parent));
NS_ENSURE_SUCCESS(rv, rv);
NS_ENSURE_TRUE(parent, NS_ERROR_NULL_POINTER);
- int32_t childOffset;
- rv = range->GetStartOffset(&childOffset);
- NS_ENSURE_SUCCESS(rv, rv);
+ uint32_t childOffset = range->StartOffset();
nsCOMPtr<nsIDOMNode> nodeToInsert;
docfrag->GetFirstChild(getter_AddRefs(nodeToInsert));
while (nodeToInsert) {
- rv = InsertNode(nodeToInsert, parent, childOffset++);
+ rv = InsertNode(nodeToInsert, parent,
+ static_cast<int32_t>(childOffset++));
NS_ENSURE_SUCCESS(rv, rv);
docfrag->GetFirstChild(getter_AddRefs(nodeToInsert));
}
diff --git a/editor/libeditor/HTMLStyleEditor.cpp b/editor/libeditor/HTMLStyleEditor.cpp
index 6a1ffe8b4..7d1217069 100644
--- a/editor/libeditor/HTMLStyleEditor.cpp
+++ b/editor/libeditor/HTMLStyleEditor.cpp
@@ -541,9 +541,11 @@ HTMLEditor::SplitStyleAboveRange(nsRange* inRange,
NS_ENSURE_SUCCESS(rv, rv);
// reset the range
- rv = inRange->SetStart(startNode, startOffset);
- NS_ENSURE_SUCCESS(rv, rv);
- return inRange->SetEnd(endNode, endOffset);
+ rv = inRange->SetStartAndEnd(startNode, startOffset, endNode, endOffset);
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return rv;
+ }
+ return NS_OK;
}
nsresult
@@ -885,10 +887,11 @@ HTMLEditor::PromoteRangeIfStartsOrEndsInNamedAnchor(nsRange& aRange)
endOffset = endNode ? endNode->IndexOf(parent) + 1 : 0;
}
- nsresult rv = aRange.SetStart(startNode, startOffset);
- NS_ENSURE_SUCCESS(rv, rv);
- rv = aRange.SetEnd(endNode, endOffset);
- NS_ENSURE_SUCCESS(rv, rv);
+ nsresult rv = aRange.SetStartAndEnd(startNode, startOffset,
+ endNode, endOffset);
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return rv;
+ }
return NS_OK;
}
@@ -918,10 +921,11 @@ HTMLEditor::PromoteInlineRange(nsRange& aRange)
endNode = parent;
}
- nsresult rv = aRange.SetStart(startNode, startOffset);
- NS_ENSURE_SUCCESS(rv, rv);
- rv = aRange.SetEnd(endNode, endOffset);
- NS_ENSURE_SUCCESS(rv, rv);
+ nsresult rv = aRange.SetStartAndEnd(startNode, startOffset,
+ endNode, endOffset);
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return rv;
+ }
return NS_OK;
}
@@ -1074,7 +1078,7 @@ HTMLEditor::GetInlinePropertyBase(nsIAtom& aProperty,
if (content->GetAsText()) {
if (!isCollapsed && first && firstNodeInRange) {
firstNodeInRange = false;
- if (range->StartOffset() == (int32_t)content->Length()) {
+ if (range->StartOffset() == content->Length()) {
continue;
}
} else if (content == endNode && !endOffset) {
diff --git a/editor/libeditor/HTMLTableEditor.cpp b/editor/libeditor/HTMLTableEditor.cpp
index 778bf1d2d..b26466179 100644
--- a/editor/libeditor/HTMLTableEditor.cpp
+++ b/editor/libeditor/HTMLTableEditor.cpp
@@ -2594,7 +2594,6 @@ HTMLEditor::GetCellIndexes(nsIDOMElement* aCell,
aCell = cell;
}
- NS_ENSURE_TRUE(mDocWeak, NS_ERROR_NOT_INITIALIZED);
nsCOMPtr<nsIPresShell> ps = GetPresShell();
NS_ENSURE_TRUE(ps, NS_ERROR_NOT_INITIALIZED);
@@ -2933,11 +2932,10 @@ HTMLEditor::GetCellFromRange(nsRange* aRange,
NS_ENSURE_SUCCESS(rv, rv);
NS_ENSURE_TRUE(startParent, NS_ERROR_FAILURE);
- int32_t startOffset;
- rv = aRange->GetStartOffset(&startOffset);
- NS_ENSURE_SUCCESS(rv, rv);
+ uint32_t startOffset = aRange->StartOffset();
- nsCOMPtr<nsIDOMNode> childNode = GetChildAt(startParent, startOffset);
+ nsCOMPtr<nsIDOMNode> childNode =
+ GetChildAt(startParent, static_cast<int32_t>(startOffset));
// This means selection is probably at a text node (or end of doc?)
if (!childNode) {
return NS_ERROR_FAILURE;
@@ -2948,15 +2946,11 @@ HTMLEditor::GetCellFromRange(nsRange* aRange,
NS_ENSURE_SUCCESS(rv, rv);
NS_ENSURE_TRUE(startParent, NS_ERROR_FAILURE);
- int32_t endOffset;
- rv = aRange->GetEndOffset(&endOffset);
- NS_ENSURE_SUCCESS(rv, rv);
-
// If a cell is deleted, the range is collapse
- // (startOffset == endOffset)
+ // (startOffset == aRange->EndOffset())
// so tell caller the cell wasn't found
if (startParent == endParent &&
- endOffset == startOffset+1 &&
+ aRange->EndOffset() == startOffset+1 &&
HTMLEditUtils::IsTableCell(childNode)) {
// Should we also test if frame is selected? (Use GetCellDataAt())
// (Let's not for now -- more efficient)
diff --git a/editor/libeditor/PlaceholderTransaction.cpp b/editor/libeditor/PlaceholderTransaction.cpp
index fa808afad..142a85075 100644
--- a/editor/libeditor/PlaceholderTransaction.cpp
+++ b/editor/libeditor/PlaceholderTransaction.cpp
@@ -8,6 +8,7 @@
#include "CompositionTransaction.h"
#include "mozilla/EditorBase.h"
#include "mozilla/dom/Selection.h"
+#include "mozilla/Move.h"
#include "nsGkAtoms.h"
#include "nsQueryObject.h"
@@ -15,13 +16,18 @@ namespace mozilla {
using namespace dom;
-PlaceholderTransaction::PlaceholderTransaction()
+PlaceholderTransaction::PlaceholderTransaction(
+ EditorBase& aEditorBase,
+ nsIAtom* aName,
+ UniquePtr<SelectionState> aSelState)
: mAbsorb(true)
, mForwarding(nullptr)
, mCompositionTransaction(nullptr)
, mCommitted(false)
- , mEditorBase(nullptr)
+ , mStartSel(Move(aSelState))
+ , mEditorBase(&aEditorBase)
{
+ mName = aName;
}
PlaceholderTransaction::~PlaceholderTransaction()
@@ -50,26 +56,12 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(PlaceholderTransaction)
NS_INTERFACE_MAP_ENTRY(nsIAbsorbingTransaction)
- NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
NS_INTERFACE_MAP_END_INHERITING(EditAggregateTransaction)
NS_IMPL_ADDREF_INHERITED(PlaceholderTransaction, EditAggregateTransaction)
NS_IMPL_RELEASE_INHERITED(PlaceholderTransaction, EditAggregateTransaction)
NS_IMETHODIMP
-PlaceholderTransaction::Init(nsIAtom* aName,
- SelectionState* aSelState,
- EditorBase* aEditorBase)
-{
- NS_ENSURE_TRUE(aEditorBase && aSelState, NS_ERROR_NULL_POINTER);
-
- mName = aName;
- mStartSel = aSelState;
- mEditorBase = aEditorBase;
- return NS_OK;
-}
-
-NS_IMETHODIMP
PlaceholderTransaction::DoTransaction()
{
return NS_OK;
diff --git a/editor/libeditor/PlaceholderTransaction.h b/editor/libeditor/PlaceholderTransaction.h
index 8193239be..5fa58a1e9 100644
--- a/editor/libeditor/PlaceholderTransaction.h
+++ b/editor/libeditor/PlaceholderTransaction.h
@@ -8,12 +8,13 @@
#include "EditAggregateTransaction.h"
#include "mozilla/EditorUtils.h"
+#include "mozilla/UniquePtr.h"
+#include "mozilla/WeakPtr.h"
#include "nsIAbsorbingTransaction.h"
#include "nsIDOMNode.h"
#include "nsCOMPtr.h"
#include "nsWeakPtr.h"
#include "nsWeakReference.h"
-#include "nsAutoPtr.h"
namespace mozilla {
@@ -26,14 +27,18 @@ class CompositionTransaction;
* transactions it has absorbed.
*/
-class PlaceholderTransaction final : public EditAggregateTransaction,
- public nsIAbsorbingTransaction,
- public nsSupportsWeakReference
+class PlaceholderTransaction final
+ : public EditAggregateTransaction
+ , public nsIAbsorbingTransaction
+ , public SupportsWeakPtr<PlaceholderTransaction>
{
public:
+ MOZ_DECLARE_WEAKREFERENCE_TYPENAME(PlaceholderTransaction)
+
NS_DECL_ISUPPORTS_INHERITED
- PlaceholderTransaction();
+ PlaceholderTransaction(EditorBase& aEditorBase, nsIAtom* aName,
+ UniquePtr<SelectionState> aSelState);
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(PlaceholderTransaction,
EditAggregateTransaction)
@@ -46,9 +51,6 @@ public:
// ------------ nsIAbsorbingTransaction -----------------------
- NS_IMETHOD Init(nsIAtom* aName, SelectionState* aSelState,
- EditorBase* aEditorBase) override;
-
NS_IMETHOD GetTxnName(nsIAtom** aName) override;
NS_IMETHOD StartSelectionEquals(SelectionState* aSelState,
@@ -61,6 +63,11 @@ public:
NS_IMETHOD Commit() override;
+ NS_IMETHOD_(PlaceholderTransaction*) AsPlaceholderTransaction() override
+ {
+ return this;
+ }
+
nsresult RememberEndingSelection();
protected:
@@ -80,7 +87,7 @@ protected:
// restore the selection properly.
// Use a pointer because this is constructed before we exist.
- nsAutoPtr<SelectionState> mStartSel;
+ UniquePtr<SelectionState> mStartSel;
SelectionState mEndSel;
// The editor for this transaction.
diff --git a/editor/libeditor/SelectionState.cpp b/editor/libeditor/SelectionState.cpp
index f9ad5947a..057e04875 100644
--- a/editor/libeditor/SelectionState.cpp
+++ b/editor/libeditor/SelectionState.cpp
@@ -686,7 +686,8 @@ already_AddRefed<nsRange>
RangeItem::GetRange()
{
RefPtr<nsRange> range = new nsRange(startNode);
- if (NS_FAILED(range->Set(startNode, startOffset, endNode, endOffset))) {
+ if (NS_FAILED(range->SetStartAndEnd(startNode, startOffset,
+ endNode, endOffset))) {
return nullptr;
}
return range.forget();
diff --git a/editor/libeditor/TextEditRules.cpp b/editor/libeditor/TextEditRules.cpp
index 8f8f34e8b..35d4a2f3d 100644
--- a/editor/libeditor/TextEditRules.cpp
+++ b/editor/libeditor/TextEditRules.cpp
@@ -329,13 +329,10 @@ TextEditRules::DidDoAction(Selection* aSelection,
}
}
-NS_IMETHODIMP
-TextEditRules::DocumentIsEmpty(bool* aDocumentIsEmpty)
+NS_IMETHODIMP_(bool)
+TextEditRules::DocumentIsEmpty()
{
- NS_ENSURE_TRUE(aDocumentIsEmpty, NS_ERROR_NULL_POINTER);
-
- *aDocumentIsEmpty = (mBogusNode != nullptr);
- return NS_OK;
+ return (mBogusNode != nullptr);
}
void
diff --git a/editor/libeditor/TextEditRules.h b/editor/libeditor/TextEditRules.h
index 6d4915f15..208e14d23 100644
--- a/editor/libeditor/TextEditRules.h
+++ b/editor/libeditor/TextEditRules.h
@@ -66,7 +66,7 @@ public:
bool* aCancel, bool* aHandled) override;
NS_IMETHOD DidDoAction(Selection* aSelection, RulesInfo* aInfo,
nsresult aResult) override;
- NS_IMETHOD DocumentIsEmpty(bool* aDocumentIsEmpty) override;
+ NS_IMETHOD_(bool) DocumentIsEmpty() override;
NS_IMETHOD DocumentModified() override;
protected:
diff --git a/editor/libeditor/TextEditor.cpp b/editor/libeditor/TextEditor.cpp
index 1e855d769..c3cfa4a72 100644
--- a/editor/libeditor/TextEditor.cpp
+++ b/editor/libeditor/TextEditor.cpp
@@ -864,7 +864,7 @@ TextEditor::UpdateIMEComposition(WidgetCompositionEvent* aCompositionChangeEvent
// of NotifiyEditorObservers(eNotifyEditorObserversOfEnd) or
// NotifiyEditorObservers(eNotifyEditorObserversOfCancel) which notifies
// TextComposition of a selection change.
- MOZ_ASSERT(!mPlaceHolderBatch,
+ MOZ_ASSERT(!mPlaceholderBatch,
"UpdateIMEComposition() must be called without place holder batch");
TextComposition::CompositionChangeEventHandlingMarker
compositionChangeEventHandlingMarker(mComposition, aCompositionChangeEvent);
@@ -913,7 +913,8 @@ TextEditor::GetDocumentIsEmpty(bool* aDocumentIsEmpty)
// Protect the edit rules object from dying
nsCOMPtr<nsIEditRules> rules(mRules);
- return rules->DocumentIsEmpty(aDocumentIsEmpty);
+ *aDocumentIsEmpty = rules->DocumentIsEmpty();
+ return NS_OK;
}
NS_IMETHODIMP
@@ -1237,7 +1238,7 @@ TextEditor::GetAndInitDocEncoder(const nsAString& aFormatType,
nsCOMPtr<nsIDocumentEncoder> docEncoder (do_CreateInstance(formatType.get(), &rv));
NS_ENSURE_SUCCESS(rv, rv);
- nsCOMPtr<nsIDOMDocument> domDoc = do_QueryReferent(mDocWeak);
+ nsCOMPtr<nsIDOMDocument> domDoc = GetDOMDocument();
NS_ASSERTION(domDoc, "Need a document");
rv = docEncoder->Init(domDoc, aFormatType, aFlags);
@@ -1580,8 +1581,7 @@ TextEditor::SelectEntireDocument(Selection* aSelection)
nsCOMPtr<nsIEditRules> rules(mRules);
// is doc empty?
- bool bDocIsEmpty;
- if (NS_SUCCEEDED(rules->DocumentIsEmpty(&bDocIsEmpty)) && bDocIsEmpty) {
+ if (rules->DocumentIsEmpty()) {
// get root node
nsCOMPtr<nsIDOMElement> rootElement = do_QueryInterface(GetRoot());
NS_ENSURE_TRUE(rootElement, NS_ERROR_FAILURE);
diff --git a/editor/libeditor/TypeInState.cpp b/editor/libeditor/TypeInState.cpp
index ce43e5e4d..840139fee 100644
--- a/editor/libeditor/TypeInState.cpp
+++ b/editor/libeditor/TypeInState.cpp
@@ -193,7 +193,7 @@ TypeInState::ClearProp(nsIAtom* aProp,
* TakeClearProperty() hands back next property item on the clear list.
* Caller assumes ownership of PropItem and must delete it.
*/
-PropItem*
+UniquePtr<PropItem>
TypeInState::TakeClearProperty()
{
size_t count = mClearedArray.Length();
@@ -204,14 +204,14 @@ TypeInState::TakeClearProperty()
--count; // indices are zero based
PropItem* propItem = mClearedArray[count];
mClearedArray.RemoveElementAt(count);
- return propItem;
+ return UniquePtr<PropItem>(propItem);
}
/**
* TakeSetProperty() hands back next poroperty item on the set list.
* Caller assumes ownership of PropItem and must delete it.
*/
-PropItem*
+UniquePtr<PropItem>
TypeInState::TakeSetProperty()
{
size_t count = mSetArray.Length();
@@ -221,7 +221,7 @@ TypeInState::TakeSetProperty()
count--; // indices are zero based
PropItem* propItem = mSetArray[count];
mSetArray.RemoveElementAt(count);
- return propItem;
+ return UniquePtr<PropItem>(propItem);
}
/**
diff --git a/editor/libeditor/TypeInState.h b/editor/libeditor/TypeInState.h
index 540b2d9c1..e1b949508 100644
--- a/editor/libeditor/TypeInState.h
+++ b/editor/libeditor/TypeInState.h
@@ -6,6 +6,7 @@
#ifndef TypeInState_h
#define TypeInState_h
+#include "mozilla/UniquePtr.h"
#include "nsCOMPtr.h"
#include "nsCycleCollectionParticipant.h"
#include "nsISelectionListener.h"
@@ -63,13 +64,13 @@ public:
* TakeClearProperty() hands back next property item on the clear list.
* Caller assumes ownership of PropItem and must delete it.
*/
- PropItem* TakeClearProperty();
+ UniquePtr<PropItem> TakeClearProperty();
/**
* TakeSetProperty() hands back next property item on the set list.
* Caller assumes ownership of PropItem and must delete it.
*/
- PropItem* TakeSetProperty();
+ UniquePtr<PropItem> TakeSetProperty();
/**
* TakeRelativeFontSize() hands back relative font value, which is then
diff --git a/editor/libeditor/WSRunObject.cpp b/editor/libeditor/WSRunObject.cpp
index 39ac3fee8..0748f09e5 100644
--- a/editor/libeditor/WSRunObject.cpp
+++ b/editor/libeditor/WSRunObject.cpp
@@ -1315,7 +1315,7 @@ WSRunObject::DeleteChars(nsINode* aStartNode,
if (!range) {
range = new nsRange(aStartNode);
nsresult rv =
- range->Set(aStartNode, aStartOffset, aEndNode, aEndOffset);
+ range->SetStartAndEnd(aStartNode, aStartOffset, aEndNode, aEndOffset);
NS_ENSURE_SUCCESS(rv, rv);
}
bool nodeBefore, nodeAfter;
diff --git a/editor/libeditor/crashtests/1348851.html b/editor/libeditor/crashtests/1348851.html
new file mode 100644
index 000000000..d618f049e
--- /dev/null
+++ b/editor/libeditor/crashtests/1348851.html
@@ -0,0 +1,19 @@
+<!DOCTYPE>
+<html>
+<head>
+<meta charset="UTF-8">
+<script>
+function boom(){
+ document.designMode = "on";
+ document.execCommand("insertlinebreak");
+ document.designMode = "off";
+ document.designMode = "on";
+ document.execCommand("insertunorderedlist");
+}
+addEventListener("DOMContentLoaded", boom);
+</script>
+</head>
+<body style="display:flex;">
+<!--comment-->
+</body>
+</html>
diff --git a/editor/libeditor/crashtests/crashtests.list b/editor/libeditor/crashtests/crashtests.list
index 3fbc6b196..7b1c57dbf 100644
--- a/editor/libeditor/crashtests/crashtests.list
+++ b/editor/libeditor/crashtests/crashtests.list
@@ -68,4 +68,5 @@ load 1158452.html
load 1158651.html
load 1244894.xhtml
load 1272490.html
+load 1348851.html
load 1317704.html
diff --git a/editor/libeditor/nsIAbsorbingTransaction.h b/editor/libeditor/nsIAbsorbingTransaction.h
index e22caed4a..06329f3d4 100644
--- a/editor/libeditor/nsIAbsorbingTransaction.h
+++ b/editor/libeditor/nsIAbsorbingTransaction.h
@@ -23,6 +23,7 @@ class nsIAtom;
namespace mozilla {
class EditorBase;
+class PlaceholderTransaction;
class SelectionState;
} // namespace mozilla
@@ -35,9 +36,6 @@ public:
NS_DECLARE_STATIC_IID_ACCESSOR(NS_IABSORBINGTRANSACTION_IID)
- NS_IMETHOD Init(nsIAtom* aName, mozilla::SelectionState* aSelState,
- mozilla::EditorBase* aEditorBase) = 0;
-
NS_IMETHOD EndPlaceHolderBatch()=0;
NS_IMETHOD GetTxnName(nsIAtom **aName)=0;
@@ -48,6 +46,9 @@ public:
NS_IMETHOD ForwardEndBatchTo(nsIAbsorbingTransaction *aForwardingAddress)=0;
NS_IMETHOD Commit()=0;
+
+ NS_IMETHOD_(mozilla::PlaceholderTransaction*)
+ AsPlaceholderTransaction() = 0;
};
NS_DEFINE_STATIC_IID_ACCESSOR(nsIAbsorbingTransaction,
diff --git a/editor/libeditor/nsIEditRules.h b/editor/libeditor/nsIEditRules.h
index b186895ae..a493145cc 100644
--- a/editor/libeditor/nsIEditRules.h
+++ b/editor/libeditor/nsIEditRules.h
@@ -59,7 +59,7 @@ public:
bool* aHandled) = 0;
NS_IMETHOD DidDoAction(mozilla::dom::Selection* aSelection,
mozilla::RulesInfo* aInfo, nsresult aResult) = 0;
- NS_IMETHOD DocumentIsEmpty(bool* aDocumentIsEmpty) = 0;
+ NS_IMETHOD_(bool) DocumentIsEmpty() = 0;
NS_IMETHOD DocumentModified() = 0;
};