author | Ryan VanderMeulen <ryanvm@gmail.com> |
Fri, 24 Apr 2015 15:42:31 -0400 | |
changeset 241015 | f214df6ac75f0202e40733be62c5b169d7a40b7f |
parent 241014 | 753c674f7c1fa8e5714d8441a85c6d369d04d1ce (current diff) |
parent 240950 | c09eaddb6740b411e91da6615044376e4106f898 (diff) |
child 241016 | d8db346eeac3e943175dee82e25438149d31def0 |
child 241102 | 013f80fd50f1b99d3cc3a6ae3494e49e74fbdc78 |
child 241108 | f21141c84ed0c292f3a15ce233b814c9aefbd760 |
child 241167 | e311030ff4913385b662c13101eaa676fd0dd7b2 |
push id | 58988 |
push user | ryanvm@gmail.com |
push date | Fri, 24 Apr 2015 19:58:56 +0000 |
treeherder | mozilla-inbound@d8db346eeac3 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | merge |
milestone | 40.0a1 |
first release with | nightly linux32
f214df6ac75f
/
40.0a1
/
20150425030208
/
files
nightly linux64
f214df6ac75f
/
40.0a1
/
20150425030208
/
files
nightly mac
f214df6ac75f
/
40.0a1
/
20150425030208
/
files
nightly win32
f214df6ac75f
/
40.0a1
/
20150425030208
/
files
nightly win64
f214df6ac75f
/
40.0a1
/
20150425030208
/
files
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
releases | nightly linux32
40.0a1
/
20150425030208
/
pushlog to previous
nightly linux64
40.0a1
/
20150425030208
/
pushlog to previous
nightly mac
40.0a1
/
20150425030208
/
pushlog to previous
nightly win32
40.0a1
/
20150425030208
/
pushlog to previous
nightly win64
40.0a1
/
20150425030208
/
pushlog to previous
|
dom/ipc/tests/test_NewUnmonitoredThread.html | file | annotate | diff | comparison | revisions |
--- a/b2g/chrome/content/shell.js +++ b/b2g/chrome/content/shell.js @@ -1084,16 +1084,26 @@ window.addEventListener('ContentStart', let stats = volumeService.createOrGetVolumeByPath(path).getStats(); // We must set the size in KB, and keep a bit of free space. let size = Math.floor(stats.totalBytes / 1024) - 1024; Services.prefs.setIntPref("browser.cache.disk.capacity", size); })(); #endif +#ifdef MOZ_WIDGET_GONK +try { + let gmpService = Cc["@mozilla.org/gecko-media-plugin-service;1"] + .getService(Ci.mozIGeckoMediaPluginChromeService); + gmpService.addPluginDirectory("/system/b2g/gmp-clearkey/0.1"); +} catch(e) { + dump("Failed to add clearkey path! " + e + "\n"); +} +#endif + // Calling this observer will cause a shutdown an a profile reset. // Use eg. : Services.obs.notifyObservers(null, 'b2g-reset-profile', null); Services.obs.addObserver(function resetProfile(subject, topic, data) { Services.obs.removeObserver(resetProfile, topic); // Listening for 'profile-before-change2' which is late in the shutdown // sequence, but still has xpcom access. Services.obs.addObserver(function clearProfile(subject, topic, data) {
--- a/b2g/installer/package-manifest.in +++ b/b2g/installer/package-manifest.in @@ -154,16 +154,17 @@ @BINPATH@/components/browser-feeds.xpt @BINPATH@/components/caps.xpt @BINPATH@/components/chardet.xpt @BINPATH@/components/chrome.xpt @BINPATH@/components/commandhandler.xpt @BINPATH@/components/commandlines.xpt @BINPATH@/components/composer.xpt @BINPATH@/components/content_events.xpt +@BINPATH@/components/content_geckomediaplugins.xpt @BINPATH@/components/content_html.xpt @BINPATH@/components/content_xslt.xpt @BINPATH@/components/cookie.xpt @BINPATH@/components/devtools_security.xpt @BINPATH@/components/directory.xpt @BINPATH@/components/diskspacewatcher.xpt @BINPATH@/components/docshell.xpt @BINPATH@/components/dom.xpt
--- a/build/unix/mozconfig.linux +++ b/build/unix/mozconfig.linux @@ -36,8 +36,10 @@ if [ -d "$topsrcdir/gtk3" ]; then export PKG_CONFIG_SYSROOT_DIR="$topsrcdir/gtk3" export PKG_CONFIG_PATH="$topsrcdir/gtk3/usr/local/lib/pkgconfig" export PATH="$topsrcdir/gtk3/usr/local/bin:${PATH}" # Ensure cairo, gdk-pixbuf, etc. are not taken from the system installed packages. LDFLAGS="-L$topsrcdir/gtk3/usr/local/lib" mk_add_options "export LD_LIBRARY_PATH=$topsrcdir/gtk3/usr/local/lib" ac_add_options --enable-default-toolkit=cairo-gtk3 fi + +export SOCORRO_SYMBOL_UPLOAD_TOKEN_FILE=/builds/crash-stats-api.token
--- a/dom/base/nsDOMClassInfo.cpp +++ b/dom/base/nsDOMClassInfo.cpp @@ -2602,11 +2602,10 @@ nsMessageManagerSH<Super>::Enumerate(nsI { JS::Rooted<JSObject*> obj(cx, obj_); *_retval = SystemGlobalEnumerate(cx, obj); NS_ENSURE_TRUE(*_retval, NS_ERROR_FAILURE); // Don't call up to our superclass, since neither nsDOMGenericSH nor // nsEventTargetSH have WANT_ENUMERATE. - MOZ_ASSERT(!(this->GetScriptableFlags() & nsIXPCScriptable::WANT_ENUMERATE)); return NS_OK; }
--- a/dom/base/nsXMLHttpRequest.cpp +++ b/dom/base/nsXMLHttpRequest.cpp @@ -4075,23 +4075,22 @@ ArrayBufferBuilder::mapToFileInPackage(c } // If file was added to the package as stored(uncompressed), map to the // offset of file in zip package. if (!zipItem->Compression()) { uint32_t offset = zip->GetDataOffset(zipItem); uint32_t size = zipItem->RealSize(); mozilla::AutoFDClose pr_fd; - mozilla::ScopedClose fd; rv = aJarFile->OpenNSPRFileDesc(PR_RDONLY, 0, &pr_fd.rwget()); if (NS_FAILED(rv)) { return rv; } - fd.rwget() = PR_FileDesc2NativeHandle(pr_fd); - mMapPtr = JS_CreateMappedArrayBufferContents(fd, offset, size); + mMapPtr = JS_CreateMappedArrayBufferContents(PR_FileDesc2NativeHandle(pr_fd), + offset, size); if (mMapPtr) { mLength = size; return NS_OK; } } return NS_ERROR_FAILURE; #endif }
--- a/dom/bindings/OwningNonNull.h +++ b/dom/bindings/OwningNonNull.h @@ -24,17 +24,17 @@ public: MOZ_IMPLICIT OwningNonNull(T& aValue) { init(&aValue); } template<class U> MOZ_IMPLICIT OwningNonNull(already_AddRefed<U>&& aValue) { - init(aValue.take()); + init(aValue); } // This is no worse than get() in terms of const handling. operator T&() const { MOZ_ASSERT(mInited); MOZ_ASSERT(mPtr, "OwningNonNull<T> was set to null"); return *mPtr; @@ -101,17 +101,17 @@ public: template<typename U> void swap(U& aOther) { mPtr.swap(aOther); } protected: template<typename U> - void init(U aValue) + void init(U&& aValue) { mPtr = aValue; MOZ_ASSERT(mPtr); #ifdef DEBUG mInited = true; #endif }
--- a/dom/ipc/PreallocatedProcessManager.cpp +++ b/dom/ipc/PreallocatedProcessManager.cpp @@ -87,57 +87,16 @@ private: void Enable(); void Disable(); void ObserveProcessShutdown(nsISupports* aSubject); bool mEnabled; bool mShutdown; nsRefPtr<ContentParent> mPreallocatedAppProcess; - -#if defined(MOZ_NUWA_PROCESS) && defined(ENABLE_TESTS) - // For testing NS_NewUnmonitoredThread(). - - void CreateUnmonitoredThread(); - void DestroyUnmonitoredThread(); - - class UnmonitoredThreadRunnable : public nsRunnable - { - public: - UnmonitoredThreadRunnable() - : mMonitor("UnmonitoredThreadRunnable") - , mEnabled(true) - { } - - NS_IMETHODIMP Run() override - { - MonitorAutoLock mon(mMonitor); - while (mEnabled) { - mMonitor.Wait(); - } - return NS_OK; - } - - void Disable() - { - MonitorAutoLock mon(mMonitor); - mEnabled = false; - mMonitor.NotifyAll(); - } - - private: - ~UnmonitoredThreadRunnable() { } - - Monitor mMonitor; - bool mEnabled; - }; - - nsCOMPtr<nsIThread> mUnmonitoredThread; - nsRefPtr<UnmonitoredThreadRunnable> mUnmonitoredThreadRunnable; -#endif }; /* static */ StaticRefPtr<PreallocatedProcessManagerImpl> PreallocatedProcessManagerImpl::sSingleton; /* static */ PreallocatedProcessManagerImpl* PreallocatedProcessManagerImpl::Singleton() { @@ -191,50 +150,16 @@ PreallocatedProcessManagerImpl::Observe( mShutdown = true; } else { MOZ_ASSERT(false); } return NS_OK; } -#if defined(MOZ_NUWA_PROCESS) && defined(ENABLE_TESTS) -void -PreallocatedProcessManagerImpl::CreateUnmonitoredThread() -{ - if (Preferences::GetBool("dom.ipc.newUnmonitoredThread.testMode")) { - // Create an unmonitored thread and dispatch a blocking runnable in test - // case startup. - nsresult rv = NS_NewUnmonitoredThread(getter_AddRefs(mUnmonitoredThread), - nullptr); - NS_ENSURE_SUCCESS_VOID(rv); - - mUnmonitoredThreadRunnable = new UnmonitoredThreadRunnable(); - mUnmonitoredThread->Dispatch(mUnmonitoredThreadRunnable, - NS_DISPATCH_NORMAL); - } -} - -void -PreallocatedProcessManagerImpl::DestroyUnmonitoredThread() -{ - // Cleanup after the test case finishes. - if (mUnmonitoredThreadRunnable) { - mUnmonitoredThreadRunnable->Disable(); - } - - if (mUnmonitoredThread) { - mUnmonitoredThread->Shutdown(); - } - - mUnmonitoredThreadRunnable = nullptr; - mUnmonitoredThread = nullptr; -} -#endif - void PreallocatedProcessManagerImpl::RereadPrefs() { if (Preferences::GetBool("dom.ipc.processPrelaunch.enabled")) { Enable(); } else { Disable(); } @@ -250,21 +175,16 @@ void PreallocatedProcessManagerImpl::Enable() { if (mEnabled) { return; } mEnabled = true; #ifdef MOZ_NUWA_PROCESS -#ifdef ENABLE_TESTS - // For testing New_UnmonitoredThread(). - CreateUnmonitoredThread(); -#endif - ScheduleDelayedNuwaFork(); #else AllocateAfterDelay(); #endif } void PreallocatedProcessManagerImpl::AllocateAfterDelay() @@ -447,21 +367,16 @@ PreallocatedProcessManagerImpl::Disable( { if (!mEnabled) { return; } mEnabled = false; #ifdef MOZ_NUWA_PROCESS -#ifdef ENABLE_TESTS - // Shut down the test-only unmonitored thread. - DestroyUnmonitoredThread(); -#endif - // Cancel pending fork. if (mPreallocateAppProcessTask) { mPreallocateAppProcessTask->Cancel(); mPreallocateAppProcessTask = nullptr; } #endif if (mPreallocatedAppProcess) {
--- a/dom/ipc/tests/mochitest.ini +++ b/dom/ipc/tests/mochitest.ini @@ -12,14 +12,12 @@ skip-if = buildapp == 'b2g' || buildapp # This test is only supposed to run in the main process skip-if = buildapp == 'b2g' || buildapp == 'mulet' || e10s || toolkit == 'android' [test_cpow_cookies.html] skip-if = buildapp == 'b2g' || buildapp == 'mulet' [test_NuwaProcessCreation.html] skip-if = toolkit != 'gonk' [test_NuwaProcessDeadlock.html] skip-if = toolkit != 'gonk' -[test_NewUnmonitoredThread.html] -skip-if = toolkit != 'gonk' [test_child_docshell.html] skip-if = toolkit == 'cocoa' # disabled due to hangs, see changeset 6852e7c47edf [test_CrashService_crash.html] skip-if = !(crashreporter && !e10s && (toolkit == 'gtk2' || toolkit == 'gtk3' || toolkit == 'cocoa' || toolkit == 'windows') && (buildapp != 'b2g' || toolkit == 'gonk') && (buildapp != 'mulet')) # TC: Bug 1144079 - Re-enable Mulet mochitests and reftests taskcluster-specific disables.
deleted file mode 100644 --- a/dom/ipc/tests/test_NewUnmonitoredThread.html +++ /dev/null @@ -1,80 +0,0 @@ -<!DOCTYPE HTML> -<html> -<!-- -Test if Nuwa process created successfully. ---> -<head> - <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> - <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> -</head> -<body onload="setup()"> - -<script type="application/javascript;version=1.7"> -"use strict"; - -function runTest() -{ - info("Launch the Nuwa process"); - let cpmm = SpecialPowers.Cc["@mozilla.org/childprocessmessagemanager;1"] - .getService(SpecialPowers.Ci.nsISyncMessageSender); - let seenNuwaReady = false; - let msgHandler = { - receiveMessage: function receiveMessage(msg) { - msg = SpecialPowers.wrap(msg); - if (msg.name == 'TEST-ONLY:nuwa-ready') { - ok(true, "Got nuwa-ready"); - is(seenNuwaReady, false, "Already received nuwa ready"); - seenNuwaReady = true; - } else if (msg.name == 'TEST-ONLY:nuwa-add-new-process') { - ok(true, "Got nuwa-add-new-process"); - is(seenNuwaReady, true, "Receive nuwa-add-new-process before nuwa-ready"); - shutdown(); - } - } - }; - - function shutdown() { - info("Shut down the test case"); - cpmm.removeMessageListener("TEST-ONLY:nuwa-ready", msgHandler); - cpmm.removeMessageListener("TEST-ONLY:nuwa-add-new-process", msgHandler); - - SimpleTest.finish(); - } - - cpmm.addMessageListener("TEST-ONLY:nuwa-ready", msgHandler); - cpmm.addMessageListener("TEST-ONLY:nuwa-add-new-process", msgHandler); - - - // Setting this pref to true should cause us to prelaunch a process. - SpecialPowers.setBoolPref('dom.ipc.processPrelaunch.enabled', true); -} - -function setup2() -{ - info("Enable the Nuwa process to test the unmonitored thread"); - - SpecialPowers.pushPrefEnv({ - 'set': [ - ['dom.ipc.processPrelaunch.enabled', false], - ['dom.ipc.preallocatedProcessManager.testMode', true] - ] - }, runTest); -} - -function setup() -{ - info("Create an unmonitored thread."); - - SimpleTest.waitForExplicitFinish(); - - SpecialPowers.pushPrefEnv({ - 'set': [ - // For testing NS_NewUnmonitoredThread() - ['dom.ipc.newUnmonitoredThread.testMode', true], - ] - }, setup2); -} - -</script> -</body> -</html>
--- a/editor/libeditor/nsEditor.cpp +++ b/editor/libeditor/nsEditor.cpp @@ -1348,38 +1348,36 @@ already_AddRefed<Element> nsEditor::CreateNode(nsIAtom* aTag, nsINode* aParent, int32_t aPosition) { MOZ_ASSERT(aTag && aParent); nsAutoRules beginRulesSniffing(this, EditAction::createNode, nsIEditor::eNext); - for (int32_t i = 0; i < mActionListeners.Count(); i++) { - mActionListeners[i]->WillCreateNode(nsDependentAtomString(aTag), - GetAsDOMNode(aParent), aPosition); + for (auto& listener : mActionListeners) { + listener->WillCreateNode(nsDependentAtomString(aTag), + GetAsDOMNode(aParent), aPosition); } nsCOMPtr<Element> ret; nsRefPtr<CreateElementTxn> txn = CreateTxnForCreateElement(*aTag, *aParent, aPosition); nsresult res = DoTransaction(txn); if (NS_SUCCEEDED(res)) { ret = txn->GetNewNode(); MOZ_ASSERT(ret); } mRangeUpdater.SelAdjCreateNode(aParent, aPosition); - for (int32_t i = 0; i < mActionListeners.Count(); i++) { - mActionListeners[i]->DidCreateNode(nsDependentAtomString(aTag), - GetAsDOMNode(ret), - GetAsDOMNode(aParent), aPosition, - res); + for (auto& listener : mActionListeners) { + listener->DidCreateNode(nsDependentAtomString(aTag), GetAsDOMNode(ret), + GetAsDOMNode(aParent), aPosition, res); } return ret.forget(); } NS_IMETHODIMP nsEditor::InsertNode(nsIDOMNode* aNode, nsIDOMNode* aParent, int32_t aPosition) @@ -1391,30 +1389,30 @@ nsEditor::InsertNode(nsIDOMNode* aNode, return InsertNode(*node, *parent, aPosition); } nsresult nsEditor::InsertNode(nsIContent& aNode, nsINode& aParent, int32_t aPosition) { nsAutoRules beginRulesSniffing(this, EditAction::insertNode, nsIEditor::eNext); - for (int32_t i = 0; i < mActionListeners.Count(); i++) { - mActionListeners[i]->WillInsertNode(aNode.AsDOMNode(), aParent.AsDOMNode(), - aPosition); + for (auto& listener : mActionListeners) { + listener->WillInsertNode(aNode.AsDOMNode(), aParent.AsDOMNode(), + aPosition); } nsRefPtr<InsertNodeTxn> txn = CreateTxnForInsertNode(aNode, aParent, aPosition); nsresult res = DoTransaction(txn); mRangeUpdater.SelAdjInsertNode(aParent.AsDOMNode(), aPosition); - for (int32_t i = 0; i < mActionListeners.Count(); i++) { - mActionListeners[i]->DidInsertNode(aNode.AsDOMNode(), aParent.AsDOMNode(), - aPosition, res); + for (auto& listener : mActionListeners) { + listener->DidInsertNode(aNode.AsDOMNode(), aParent.AsDOMNode(), aPosition, + res); } return res; } NS_IMETHODIMP nsEditor::SplitNode(nsIDOMNode* aNode, @@ -1430,32 +1428,31 @@ nsEditor::SplitNode(nsIDOMNode* aNode, } nsIContent* nsEditor::SplitNode(nsIContent& aNode, int32_t aOffset, ErrorResult& aResult) { nsAutoRules beginRulesSniffing(this, EditAction::splitNode, nsIEditor::eNext); - for (int32_t i = 0; i < mActionListeners.Count(); i++) { - mActionListeners[i]->WillSplitNode(aNode.AsDOMNode(), aOffset); + for (auto& listener : mActionListeners) { + listener->WillSplitNode(aNode.AsDOMNode(), aOffset); } nsRefPtr<SplitNodeTxn> txn = CreateTxnForSplitNode(aNode, aOffset); aResult = DoTransaction(txn); nsCOMPtr<nsIContent> newNode = aResult.Failed() ? nullptr : txn->GetNewNode(); mRangeUpdater.SelAdjSplitNode(aNode, aOffset, newNode); - for (int32_t i = 0; i < mActionListeners.Count(); i++) { - mActionListeners[i]->DidSplitNode(aNode.AsDOMNode(), aOffset, - GetAsDOMNode(newNode), - aResult.ErrorCode()); + for (auto& listener : mActionListeners) { + listener->DidSplitNode(aNode.AsDOMNode(), aOffset, GetAsDOMNode(newNode), + aResult.ErrorCode()); } return newNode; } NS_IMETHODIMP nsEditor::JoinNodes(nsIDOMNode* aLeftNode, @@ -1478,35 +1475,33 @@ nsEditor::JoinNodes(nsINode& aLeftNode, nsIEditor::ePrevious); // Remember some values; later used for saved selection updating. // Find the offset between the nodes to be joined. int32_t offset = parent->IndexOf(&aRightNode); // Find the number of children of the lefthand node uint32_t oldLeftNodeLen = aLeftNode.Length(); - for (int32_t i = 0; i < mActionListeners.Count(); i++) { - mActionListeners[i]->WillJoinNodes(aLeftNode.AsDOMNode(), - aRightNode.AsDOMNode(), - parent->AsDOMNode()); + for (auto& listener : mActionListeners) { + listener->WillJoinNodes(aLeftNode.AsDOMNode(), aRightNode.AsDOMNode(), + parent->AsDOMNode()); } nsresult result; nsRefPtr<JoinNodeTxn> txn = CreateTxnForJoinNode(aLeftNode, aRightNode); if (txn) { result = DoTransaction(txn); } mRangeUpdater.SelAdjJoinNodes(aLeftNode, aRightNode, *parent, offset, (int32_t)oldLeftNodeLen); - for (int32_t i = 0; i < mActionListeners.Count(); i++) { - mActionListeners[i]->DidJoinNodes(aLeftNode.AsDOMNode(), - aRightNode.AsDOMNode(), - parent->AsDOMNode(), result); + for (auto& listener : mActionListeners) { + listener->DidJoinNodes(aLeftNode.AsDOMNode(), aRightNode.AsDOMNode(), + parent->AsDOMNode(), result); } return result; } NS_IMETHODIMP nsEditor::DeleteNode(nsIDOMNode* aNode) @@ -1517,28 +1512,28 @@ nsEditor::DeleteNode(nsIDOMNode* aNode) } nsresult nsEditor::DeleteNode(nsINode* aNode) { nsAutoRules beginRulesSniffing(this, EditAction::createNode, nsIEditor::ePrevious); // save node location for selection updating code. - for (int32_t i = 0; i < mActionListeners.Count(); i++) { - mActionListeners[i]->WillDeleteNode(aNode->AsDOMNode()); + for (auto& listener : mActionListeners) { + listener->WillDeleteNode(aNode->AsDOMNode()); } nsRefPtr<DeleteNodeTxn> txn; nsresult res = CreateTxnForDeleteNode(aNode, getter_AddRefs(txn)); if (NS_SUCCEEDED(res)) { res = DoTransaction(txn); } - for (int32_t i = 0; i < mActionListeners.Count(); i++) { - mActionListeners[i]->DidDeleteNode(aNode->AsDOMNode(), res); + for (auto& listener : mActionListeners) { + listener->DidDeleteNode(aNode->AsDOMNode(), res); } NS_ENSURE_SUCCESS(res, res); return NS_OK; } /////////////////////////////////////////////////////////////////////////// // ReplaceContainer: replace inNode with a new node (outNode) which is contructed @@ -1733,33 +1728,30 @@ NS_IMETHODIMP nsEditor::AddEditorObserver(nsIEditorObserver *aObserver) { // we don't keep ownership of the observers. They must // remove themselves as observers before they are destroyed. NS_ENSURE_TRUE(aObserver, NS_ERROR_NULL_POINTER); // Make sure the listener isn't already on the list - if (mEditorObservers.IndexOf(aObserver) == -1) - { - if (!mEditorObservers.AppendObject(aObserver)) - return NS_ERROR_FAILURE; + if (!mEditorObservers.Contains(aObserver)) { + mEditorObservers.AppendElement(*aObserver); } return NS_OK; } NS_IMETHODIMP nsEditor::RemoveEditorObserver(nsIEditorObserver *aObserver) { NS_ENSURE_TRUE(aObserver, NS_ERROR_FAILURE); - if (!mEditorObservers.RemoveObject(aObserver)) - return NS_ERROR_FAILURE; + mEditorObservers.RemoveElement(aObserver); return NS_OK; } class EditorInputEventDispatcher : public nsRunnable { public: EditorInputEventDispatcher(nsEditor* aEditor, @@ -1809,36 +1801,36 @@ private: }; void nsEditor::NotifyEditorObservers(NotificationForEditorObservers aNotification) { switch (aNotification) { case eNotifyEditorObserversOfEnd: mIsInEditAction = false; - for (int32_t i = 0; i < mEditorObservers.Count(); i++) { - mEditorObservers[i]->EditAction(); + for (auto& observer : mEditorObservers) { + observer->EditAction(); } if (!mDispatchInputEvent) { return; } FireInputEvent(); break; case eNotifyEditorObserversOfBefore: mIsInEditAction = true; - for (int32_t i = 0; i < mEditorObservers.Count(); i++) { - mEditorObservers[i]->BeforeEditAction(); + for (auto& observer : mEditorObservers) { + observer->BeforeEditAction(); } break; case eNotifyEditorObserversOfCancel: mIsInEditAction = false; - for (int32_t i = 0; i < mEditorObservers.Count(); i++) { - mEditorObservers[i]->CancelEditAction(); + for (auto& observer : mEditorObservers) { + observer->CancelEditAction(); } break; default: MOZ_CRASH("Handle all notifications here"); break; } } @@ -1861,60 +1853,54 @@ nsEditor::FireInputEvent() } NS_IMETHODIMP nsEditor::AddEditActionListener(nsIEditActionListener *aListener) { NS_ENSURE_TRUE(aListener, NS_ERROR_NULL_POINTER); // Make sure the listener isn't already on the list - if (mActionListeners.IndexOf(aListener) == -1) - { - if (!mActionListeners.AppendObject(aListener)) - return NS_ERROR_FAILURE; + if (!mActionListeners.Contains(aListener)) { + mActionListeners.AppendElement(*aListener); } return NS_OK; } NS_IMETHODIMP nsEditor::RemoveEditActionListener(nsIEditActionListener *aListener) { NS_ENSURE_TRUE(aListener, NS_ERROR_FAILURE); - if (!mActionListeners.RemoveObject(aListener)) - return NS_ERROR_FAILURE; + mActionListeners.RemoveElement(aListener); return NS_OK; } NS_IMETHODIMP nsEditor::AddDocumentStateListener(nsIDocumentStateListener *aListener) { NS_ENSURE_TRUE(aListener, NS_ERROR_NULL_POINTER); - if (mDocStateListeners.IndexOf(aListener) == -1) - { - if (!mDocStateListeners.AppendObject(aListener)) - return NS_ERROR_FAILURE; + if (!mDocStateListeners.Contains(aListener)) { + mDocStateListeners.AppendElement(*aListener); } return NS_OK; } NS_IMETHODIMP nsEditor::RemoveDocumentStateListener(nsIDocumentStateListener *aListener) { NS_ENSURE_TRUE(aListener, NS_ERROR_NULL_POINTER); - if (!mDocStateListeners.RemoveObject(aListener)) - return NS_ERROR_FAILURE; + mDocStateListeners.RemoveElement(aListener); return NS_OK; } NS_IMETHODIMP nsEditor::OutputToString(const nsAString& aFormatType, uint32_t aFlags, nsAString& aOutputString) @@ -2387,33 +2373,33 @@ nsEditor::InsertTextIntoTextNodeImpl(con txn = CreateTxnForIMEText(aStringToInsert); isIMETransaction = true; } else { txn = CreateTxnForInsertText(aStringToInsert, aTextNode, aOffset); } // Let listeners know what's up - for (int32_t i = 0; i < mActionListeners.Count(); i++) { - mActionListeners[i]->WillInsertText( + for (auto& listener : mActionListeners) { + listener->WillInsertText( static_cast<nsIDOMCharacterData*>(aTextNode.AsDOMNode()), aOffset, aStringToInsert); } // XXX We may not need these view batches anymore. This is handled at a // higher level now I believe. BeginUpdateViewBatch(); nsresult res = DoTransaction(txn); EndUpdateViewBatch(); mRangeUpdater.SelAdjInsertText(aTextNode, aOffset, aStringToInsert); // let listeners know what happened - for (int32_t i = 0; i < mActionListeners.Count(); i++) { - mActionListeners[i]->DidInsertText( + for (auto& listener : mActionListeners) { + listener->DidInsertText( static_cast<nsIDOMCharacterData*>(aTextNode.AsDOMNode()), aOffset, aStringToInsert, res); } // Added some cruft here for bug 43366. Layout was crashing because we left // an empty text node lying around in the document. So I delete empty text // nodes caused by IME. I have to mark the IME transaction as "fixed", which // means that furure IME txns won't merge with it. This is because we don't @@ -2460,58 +2446,56 @@ nsEditor::GetFirstEditableNode(nsINode* return (node != aRoot) ? node : nullptr; } NS_IMETHODIMP nsEditor::NotifyDocumentListeners(TDocumentListenerNotification aNotificationType) { - int32_t numListeners = mDocStateListeners.Count(); - if (!numListeners) // maybe there just aren't any. + if (!mDocStateListeners.Length()) { + // Maybe there just aren't any. return NS_OK; + } - nsCOMArray<nsIDocumentStateListener> listeners(mDocStateListeners); + nsTArray<OwningNonNull<nsIDocumentStateListener>> + listeners(mDocStateListeners); nsresult rv = NS_OK; - int32_t i; switch (aNotificationType) { case eDocumentCreated: - for (i = 0; i < numListeners;i++) - { - rv = listeners[i]->NotifyDocumentCreated(); + for (auto& listener : listeners) { + rv = listener->NotifyDocumentCreated(); if (NS_FAILED(rv)) break; } break; case eDocumentToBeDestroyed: - for (i = 0; i < numListeners;i++) - { - rv = listeners[i]->NotifyDocumentWillBeDestroyed(); + for (auto& listener : listeners) { + rv = listener->NotifyDocumentWillBeDestroyed(); if (NS_FAILED(rv)) break; } break; case eDocumentStateChanged: { bool docIsDirty; rv = GetDocumentModified(&docIsDirty); NS_ENSURE_SUCCESS(rv, rv); if (static_cast<int8_t>(docIsDirty) == mDocDirtyState) return NS_OK; mDocDirtyState = docIsDirty; - for (i = 0; i < numListeners;i++) - { - rv = listeners[i]->NotifyDocumentStateChanged(mDocDirtyState); + for (auto& listener : listeners) { + rv = listener->NotifyDocumentStateChanged(mDocDirtyState); if (NS_FAILED(rv)) break; } } break; default: NS_NOTREACHED("Unknown notification"); @@ -2537,27 +2521,27 @@ nsEditor::DeleteText(nsGenericDOMDataNod { nsRefPtr<DeleteTextTxn> txn = CreateTxnForDeleteText(aCharData, aOffset, aLength); NS_ENSURE_STATE(txn); nsAutoRules beginRulesSniffing(this, EditAction::deleteText, nsIEditor::ePrevious); // Let listeners know what's up - for (int32_t i = 0; i < mActionListeners.Count(); i++) { - mActionListeners[i]->WillDeleteText( + for (auto& listener : mActionListeners) { + listener->WillDeleteText( static_cast<nsIDOMCharacterData*>(GetAsDOMNode(&aCharData)), aOffset, aLength); } nsresult res = DoTransaction(txn); // Let listeners know what happened - for (int32_t i = 0; i < mActionListeners.Count(); i++) { - mActionListeners[i]->DidDeleteText( + for (auto& listener : mActionListeners) { + listener->DidDeleteText( static_cast<nsIDOMCharacterData*>(GetAsDOMNode(&aCharData)), aOffset, aLength, res); } return res; } @@ -3955,41 +3939,48 @@ nsEditor::DeleteSelectionImpl(EDirection getter_AddRefs(deleteNode), &deleteCharOffset, &deleteCharLength); nsCOMPtr<nsIDOMCharacterData> deleteCharData(do_QueryInterface(deleteNode)); if (NS_SUCCEEDED(res)) { nsAutoRules beginRulesSniffing(this, EditAction::deleteSelection, aAction); - int32_t i; // Notify nsIEditActionListener::WillDelete[Selection|Text|Node] - if (!deleteNode) - for (i = 0; i < mActionListeners.Count(); i++) - mActionListeners[i]->WillDeleteSelection(selection); - else if (deleteCharData) - for (i = 0; i < mActionListeners.Count(); i++) - mActionListeners[i]->WillDeleteText(deleteCharData, deleteCharOffset, 1); - else - for (i = 0; i < mActionListeners.Count(); i++) - mActionListeners[i]->WillDeleteNode(deleteNode->AsDOMNode()); + 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()); + } + } // Delete the specified amount res = DoTransaction(txn); // Notify nsIEditActionListener::DidDelete[Selection|Text|Node] - if (!deleteNode) - for (i = 0; i < mActionListeners.Count(); i++) - mActionListeners[i]->DidDeleteSelection(selection); - else if (deleteCharData) - for (i = 0; i < mActionListeners.Count(); i++) - mActionListeners[i]->DidDeleteText(deleteCharData, deleteCharOffset, 1, res); - else - for (i = 0; i < mActionListeners.Count(); i++) - mActionListeners[i]->DidDeleteNode(deleteNode->AsDOMNode(), res); + if (!deleteNode) { + for (auto& listener : mActionListeners) { + listener->DidDeleteSelection(selection); + } + } else if (deleteCharData) { + for (auto& listener : mActionListeners) { + listener->DidDeleteText(deleteCharData, deleteCharOffset, 1, res); + } + } else { + for (auto& listener : mActionListeners) { + listener->DidDeleteNode(deleteNode->AsDOMNode(), res); + } + } } return res; } already_AddRefed<Element> nsEditor::DeleteSelectionAndCreateElement(nsIAtom& aTag) {
--- a/editor/libeditor/nsEditor.h +++ b/editor/libeditor/nsEditor.h @@ -2,19 +2,19 @@ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef __editor_h__ #define __editor_h__ #include "mozilla/Assertions.h" // for MOZ_ASSERT, etc. +#include "mozilla/dom/OwningNonNull.h" // for OwningNonNull #include "mozilla/dom/Text.h" #include "nsAutoPtr.h" // for nsRefPtr -#include "nsCOMArray.h" // for nsCOMArray #include "nsCOMPtr.h" // for already_AddRefed, nsCOMPtr #include "nsCycleCollectionParticipant.h" #include "nsGkAtoms.h" #include "nsIEditor.h" // for nsIEditor::EDirection, etc #include "nsIEditorIMESupport.h" // for NS_DECL_NSIEDITORIMESUPPORT, etc #include "nsIObserver.h" // for NS_DECL_NSIOBSERVER, etc #include "nsIPhonetic.h" // for NS_DECL_NSIPHONETIC, etc #include "nsIPlaintextEditor.h" // for nsIPlaintextEditor, etc @@ -825,19 +825,22 @@ protected: nsIAtom *mPlaceHolderName; // name of placeholder transaction nsSelectionState *mSelState; // saved selection state for placeholder txn batching nsString *mPhonetic; // IME composition this is not null between compositionstart and // compositionend. nsRefPtr<mozilla::TextComposition> mComposition; // various listeners - nsCOMArray<nsIEditActionListener> mActionListeners; // listens to all low level actions on the doc - nsCOMArray<nsIEditorObserver> mEditorObservers; // just notify once per high level change - nsCOMArray<nsIDocumentStateListener> mDocStateListeners;// listen to overall doc state (dirty or not, just created, etc) + // Listens to all low level actions on the doc + nsTArray<mozilla::dom::OwningNonNull<nsIEditActionListener>> mActionListeners; + // Just notify once per high level change + nsTArray<mozilla::dom::OwningNonNull<nsIEditorObserver>> mEditorObservers; + // Listen to overall doc state (dirty or not, just created, etc) + nsTArray<mozilla::dom::OwningNonNull<nsIDocumentStateListener>> mDocStateListeners; nsSelectionState mSavedSel; // cached selection for nsAutoSelectionReset nsRangeUpdater mRangeUpdater; // utility class object for maintaining preserved ranges uint32_t mModCount; // number of modifications (for undo/redo stack) uint32_t mFlags; // behavior flags. See nsIPlaintextEditor.idl for the flags we use. int32_t mUpdateCount;
--- a/editor/libeditor/nsEditorUtils.cpp +++ b/editor/libeditor/nsEditorUtils.cpp @@ -1,17 +1,17 @@ /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "nsEditorUtils.h" +#include "mozilla/dom/OwningNonNull.h" #include "mozilla/dom/Selection.h" -#include "nsCOMArray.h" #include "nsComponentManagerUtils.h" #include "nsError.h" #include "nsIClipboardDragDropHookList.h" // hooks #include "nsIClipboardDragDropHooks.h" #include "nsIContent.h" #include "nsIContentIterator.h" #include "nsIDOMDocument.h" @@ -61,101 +61,63 @@ nsAutoSelectionReset::Abort() mEd->StopPreservingSelection(); } /****************************************************************************** * some helper classes for iterating the dom tree *****************************************************************************/ -nsDOMIterator::nsDOMIterator() : -mIter(nullptr) +nsDOMIterator::nsDOMIterator(nsRange& aRange) +{ + MOZ_ASSERT(aRange.GetStartParent(), "Invalid range"); + mIter = NS_NewContentIterator(); + DebugOnly<nsresult> res = mIter->Init(&aRange); + MOZ_ASSERT(NS_SUCCEEDED(res)); +} + +nsDOMIterator::nsDOMIterator(nsINode& aNode) +{ + mIter = NS_NewContentIterator(); + DebugOnly<nsresult> res = mIter->Init(&aNode); + MOZ_ASSERT(NS_SUCCEEDED(res)); +} + +nsDOMIterator::nsDOMIterator() { } - + nsDOMIterator::~nsDOMIterator() { } - -nsresult -nsDOMIterator::Init(nsRange* aRange) -{ - nsresult res; - mIter = do_CreateInstance("@mozilla.org/content/post-content-iterator;1", &res); - NS_ENSURE_SUCCESS(res, res); - NS_ENSURE_TRUE(mIter, NS_ERROR_FAILURE); - return mIter->Init(aRange); -} -nsresult -nsDOMIterator::Init(nsIDOMNode* aNode) -{ - nsresult res; - mIter = do_CreateInstance("@mozilla.org/content/post-content-iterator;1", &res); - NS_ENSURE_SUCCESS(res, res); - NS_ENSURE_TRUE(mIter, NS_ERROR_FAILURE); - nsCOMPtr<nsIContent> content = do_QueryInterface(aNode); - return mIter->Init(content); -} - -nsresult -nsDOMIterator::AppendList(nsBoolDomIterFunctor& functor, - nsTArray<nsCOMPtr<nsINode>>& arrayOfNodes) const +void +nsDOMIterator::AppendList(const nsBoolDomIterFunctor& functor, + nsTArray<OwningNonNull<nsINode>>& arrayOfNodes) const { // Iterate through dom and build list - while (!mIter->IsDone()) { + for (; !mIter->IsDone(); mIter->Next()) { nsCOMPtr<nsINode> node = mIter->GetCurrentNode(); - NS_ENSURE_TRUE(node, NS_ERROR_NULL_POINTER); if (functor(node)) { - arrayOfNodes.AppendElement(node); + arrayOfNodes.AppendElement(*node); } - mIter->Next(); } - return NS_OK; } -nsresult -nsDOMIterator::AppendList(nsBoolDomIterFunctor& functor, - nsCOMArray<nsIDOMNode>& arrayOfNodes) const +nsDOMSubtreeIterator::nsDOMSubtreeIterator(nsRange& aRange) { - nsCOMPtr<nsIDOMNode> node; - - // iterate through dom and build list - while (!mIter->IsDone()) - { - node = do_QueryInterface(mIter->GetCurrentNode()); - NS_ENSURE_TRUE(node, NS_ERROR_NULL_POINTER); - - if (functor(node)) - { - arrayOfNodes.AppendObject(node); - } - mIter->Next(); - } - return NS_OK; + mIter = NS_NewContentSubtreeIterator(); + DebugOnly<nsresult> res = mIter->Init(&aRange); + MOZ_ASSERT(NS_SUCCEEDED(res)); } -nsDOMSubtreeIterator::nsDOMSubtreeIterator() -{ -} - nsDOMSubtreeIterator::~nsDOMSubtreeIterator() { } - -nsresult -nsDOMSubtreeIterator::Init(nsRange* aRange) -{ - nsresult res; - mIter = do_CreateInstance("@mozilla.org/content/subtree-content-iterator;1", &res); - NS_ENSURE_SUCCESS(res, res); - NS_ENSURE_TRUE(mIter, NS_ERROR_FAILURE); - return mIter->Init(aRange); -} /****************************************************************************** * some general purpose editor utils *****************************************************************************/ bool nsEditorUtils::IsDescendantOf(nsINode* aNode, nsINode* aParent, int32_t* aOffset) {
--- a/editor/libeditor/nsEditorUtils.h +++ b/editor/libeditor/nsEditorUtils.h @@ -14,19 +14,19 @@ #include "nsIDOMNode.h" #include "nsIEditor.h" #include "nscore.h" class nsIAtom; class nsIContentIterator; class nsIDOMDocument; class nsRange; -template <class E> class nsCOMArray; namespace mozilla { namespace dom { +template <class T> class OwningNonNull; class Selection; } } /*************************************************************************** * stack based helper class for batching a collection of txns inside a * placeholder txn. */ @@ -162,52 +162,47 @@ class MOZ_STACK_CLASS nsAutoUpdateViewBa /****************************************************************************** * some helper classes for iterating the dom tree *****************************************************************************/ class nsBoolDomIterFunctor { public: - virtual bool operator()(nsIDOMNode* aNode)=0; - bool operator()(nsINode* aNode) - { - return operator()(GetAsDOMNode(aNode)); - } + virtual bool operator()(nsINode* aNode) const = 0; }; class MOZ_STACK_CLASS nsDOMIterator { public: - nsDOMIterator(); + explicit nsDOMIterator(nsRange& aRange); + explicit nsDOMIterator(nsINode& aNode); virtual ~nsDOMIterator(); - - nsresult Init(nsRange* aRange); - nsresult Init(nsIDOMNode* aNode); - nsresult AppendList(nsBoolDomIterFunctor& functor, - nsTArray<nsCOMPtr<nsINode>>& arrayOfNodes) const; - nsresult AppendList(nsBoolDomIterFunctor& functor, - nsCOMArray<nsIDOMNode>& arrayOfNodes) const; + + void AppendList(const nsBoolDomIterFunctor& functor, + nsTArray<mozilla::dom::OwningNonNull<nsINode>>& arrayOfNodes) const; protected: nsCOMPtr<nsIContentIterator> mIter; + + // For nsDOMSubtreeIterator + nsDOMIterator(); }; class MOZ_STACK_CLASS nsDOMSubtreeIterator : public nsDOMIterator { public: - nsDOMSubtreeIterator(); + explicit nsDOMSubtreeIterator(nsRange& aRange); virtual ~nsDOMSubtreeIterator(); - - nsresult Init(nsRange* aRange); }; class nsTrivialFunctor : public nsBoolDomIterFunctor { public: - virtual bool operator()(nsIDOMNode* aNode) // used to build list of all nodes iterator covers + // Used to build list of all nodes iterator covers + virtual bool operator()(nsINode* aNode) const { return true; } }; /****************************************************************************** * general dom point utility struct
--- a/editor/libeditor/nsHTMLDataTransfer.cpp +++ b/editor/libeditor/nsHTMLDataTransfer.cpp @@ -2,24 +2,24 @@ /* vim: set ts=2 sw=2 et tw=78: */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include <string.h> #include "mozilla/dom/DocumentFragment.h" +#include "mozilla/dom/OwningNonNull.h" #include "mozilla/ArrayUtils.h" #include "mozilla/Base64.h" #include "mozilla/BasicEvents.h" #include "mozilla/Preferences.h" #include "mozilla/dom/Selection.h" #include "nsAString.h" #include "nsAutoPtr.h" -#include "nsCOMArray.h" #include "nsCOMPtr.h" #include "nsCRT.h" #include "nsCRTGlue.h" #include "nsComponentManagerUtils.h" #include "nsContentUtils.h" #include "nsDebug.h" #include "nsDependentSubstring.h" #include "nsEditRules.h" @@ -97,49 +97,16 @@ using namespace mozilla::dom; // some little helpers static bool FindIntegerAfterString(const char *aLeadingString, nsCString &aCStr, int32_t &foundNumber); static nsresult RemoveFragComments(nsCString &theStr); static void RemoveBodyAndHead(nsIDOMNode *aNode); static nsresult FindTargetNode(nsIDOMNode *aStart, nsCOMPtr<nsIDOMNode> &aResult); -static nsCOMPtr<nsIDOMNode> GetListParent(nsIDOMNode* aNode) -{ - NS_ENSURE_TRUE(aNode, nullptr); - nsCOMPtr<nsIDOMNode> parent, tmp; - aNode->GetParentNode(getter_AddRefs(parent)); - while (parent) - { - if (nsHTMLEditUtils::IsList(parent)) { - return parent; - } - parent->GetParentNode(getter_AddRefs(tmp)); - parent = tmp; - } - return nullptr; -} - -static nsCOMPtr<nsIDOMNode> GetTableParent(nsIDOMNode* aNode) -{ - NS_ENSURE_TRUE(aNode, nullptr); - nsCOMPtr<nsIDOMNode> parent, tmp; - aNode->GetParentNode(getter_AddRefs(parent)); - while (parent) - { - if (nsHTMLEditUtils::IsTable(parent)) { - return parent; - } - parent->GetParentNode(getter_AddRefs(tmp)); - parent = tmp; - } - return nullptr; -} - - nsresult nsHTMLEditor::LoadHTML(const nsAString & aInputString) { NS_ENSURE_TRUE(mRules, NS_ERROR_NOT_INITIALIZED); // force IME commit; set up rules sniffing and batching ForceCompositionEnd(); nsAutoEditBatch beginBatching(this); @@ -316,23 +283,31 @@ nsHTMLEditor::DoInsertHTMLWithContext(co rv = selection->Collapse(targetNode, targetOffset); NS_ENSURE_SUCCESS(rv, rv); } // we need to recalculate various things based on potentially new offsets // this is work to be completed at a later date (probably by jfrancis) // make a list of what nodes in docFrag we need to move - nsCOMArray<nsIDOMNode> nodeList; - rv = CreateListOfNodesToPaste(fragmentAsNode, nodeList, - streamStartParent, streamStartOffset, - streamEndParent, streamEndOffset); - NS_ENSURE_SUCCESS(rv, rv); + nsTArray<OwningNonNull<nsINode>> nodeList; + nsCOMPtr<nsINode> fragmentAsNodeNode = do_QueryInterface(fragmentAsNode); + NS_ENSURE_STATE(fragmentAsNodeNode || !fragmentAsNode); + nsCOMPtr<nsINode> streamStartParentNode = + do_QueryInterface(streamStartParent); + NS_ENSURE_STATE(streamStartParentNode || !streamStartParent); + nsCOMPtr<nsINode> streamEndParentNode = + do_QueryInterface(streamEndParent); + NS_ENSURE_STATE(streamEndParentNode || !streamEndParent); + CreateListOfNodesToPaste(*static_cast<DocumentFragment*>(fragmentAsNodeNode.get()), + nodeList, + streamStartParentNode, streamStartOffset, + streamEndParentNode, streamEndOffset); - if (nodeList.Count() == 0) { + if (nodeList.Length() == 0) { return NS_OK; } // Are there any table elements in the list? // node and offset for insertion nsCOMPtr<nsIDOMNode> parentNode; int32_t offsetOfNewNode; @@ -347,19 +322,19 @@ nsHTMLEditor::DoInsertHTMLWithContext(co if (cellSelectionMode) { // do we have table content to paste? If so, we want to delete // the selected table cells and replace with new table elements; // but if not we want to delete _contents_ of cells and replace // with non-table elements. Use cellSelectionMode bool to // indicate results. - nsIDOMNode* firstNode = nodeList[0]; - if (!nsHTMLEditUtils::IsTableElement(firstNode)) + if (!nsHTMLEditUtils::IsTableElement(nodeList[0])) { cellSelectionMode = false; + } } if (!cellSelectionMode) { rv = DeleteSelectionAndPrepareToCreateNode(); NS_ENSURE_SUCCESS(rv, rv); if (aClearStyle) { @@ -397,17 +372,18 @@ nsHTMLEditor::DoInsertHTMLWithContext(co { // The rules code (WillDoAction above) might have changed the selection. // refresh our memory... rv = GetStartNodeAndOffset(selection, getter_AddRefs(parentNode), &offsetOfNewNode); NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_TRUE(parentNode, NS_ERROR_FAILURE); // Adjust position based on the first node we are going to insert. - NormalizeEOLInsertPosition(nodeList[0], address_of(parentNode), &offsetOfNewNode); + NormalizeEOLInsertPosition(GetAsDOMNode(nodeList[0]), + address_of(parentNode), &offsetOfNewNode); // if there are any invisible br's after our insertion point, remove them. // this is because if there is a br at end of what we paste, it will make // the invisible br visible. nsWSRunObject wsObj(this, parentNode, offsetOfNewNode); if (wsObj.mEndReasonNode && nsTextEditUtils::IsBreak(wsObj.mEndReasonNode) && !IsVisBreak(wsObj.mEndReasonNode)) { @@ -426,70 +402,67 @@ nsHTMLEditor::DoInsertHTMLWithContext(co NS_ENSURE_SUCCESS(rv, rv); rv = parentNode->GetParentNode(getter_AddRefs(temp)); NS_ENSURE_SUCCESS(rv, rv); parentNode = temp; } // build up list of parents of first node in list that are either // lists or tables. First examine front of paste node list. - nsCOMArray<nsIDOMNode> startListAndTableArray; - rv = GetListAndTableParents(false, nodeList, startListAndTableArray); - NS_ENSURE_SUCCESS(rv, rv); + nsTArray<OwningNonNull<Element>> startListAndTableArray; + GetListAndTableParents(StartOrEnd::start, nodeList, + startListAndTableArray); // remember number of lists and tables above us int32_t highWaterMark = -1; - if (startListAndTableArray.Count() > 0) - { - rv = DiscoverPartialListsAndTables(nodeList, startListAndTableArray, &highWaterMark); - NS_ENSURE_SUCCESS(rv, rv); + if (startListAndTableArray.Length() > 0) { + highWaterMark = DiscoverPartialListsAndTables(nodeList, + startListAndTableArray); } // if we have pieces of tables or lists to be inserted, let's force the paste // to deal with table elements right away, so that it doesn't orphan some // table or list contents outside the table or list. if (highWaterMark >= 0) { - rv = ReplaceOrphanedStructure(false, nodeList, startListAndTableArray, highWaterMark); - NS_ENSURE_SUCCESS(rv, rv); + ReplaceOrphanedStructure(StartOrEnd::start, nodeList, + startListAndTableArray, highWaterMark); } // Now go through the same process again for the end of the paste node list. - nsCOMArray<nsIDOMNode> endListAndTableArray; - rv = GetListAndTableParents(true, nodeList, endListAndTableArray); - NS_ENSURE_SUCCESS(rv, rv); + nsTArray<OwningNonNull<Element>> endListAndTableArray; + GetListAndTableParents(StartOrEnd::end, nodeList, endListAndTableArray); highWaterMark = -1; // remember number of lists and tables above us - if (endListAndTableArray.Count() > 0) - { - rv = DiscoverPartialListsAndTables(nodeList, endListAndTableArray, &highWaterMark); - NS_ENSURE_SUCCESS(rv, rv); + if (endListAndTableArray.Length() > 0) { + highWaterMark = DiscoverPartialListsAndTables(nodeList, + endListAndTableArray); } // don't orphan partial list or table structure if (highWaterMark >= 0) { - rv = ReplaceOrphanedStructure(true, nodeList, endListAndTableArray, highWaterMark); - NS_ENSURE_SUCCESS(rv, rv); + ReplaceOrphanedStructure(StartOrEnd::end, nodeList, + endListAndTableArray, highWaterMark); } // Loop over the node list and paste the nodes: nsCOMPtr<nsIDOMNode> parentBlock, lastInsertNode, insertedContextParent; - int32_t listCount = nodeList.Count(); + int32_t listCount = nodeList.Length(); int32_t j; if (IsBlockNode(parentNode)) parentBlock = parentNode; else parentBlock = GetBlockNodeParent(parentNode); for (j=0; j<listCount; j++) { bool bDidInsert = false; - nsCOMPtr<nsIDOMNode> curNode = nodeList[j]; + nsCOMPtr<nsIDOMNode> curNode = nodeList[j]->AsDOMNode(); NS_ENSURE_TRUE(curNode, NS_ERROR_FAILURE); NS_ENSURE_TRUE(curNode != fragmentAsNode, NS_ERROR_FAILURE); NS_ENSURE_TRUE(!nsTextEditUtils::IsBody(curNode), NS_ERROR_FAILURE); if (insertedContextParent) { // if we had to insert something higher up in the paste hierarchy, we want to @@ -716,36 +689,35 @@ nsHTMLEditor::DoInsertHTMLWithContext(co } } } } return mRules->DidDoAction(selection, &ruleInfo, rv); } -nsresult +NS_IMETHODIMP nsHTMLEditor::AddInsertionListener(nsIContentFilter *aListener) { NS_ENSURE_TRUE(aListener, NS_ERROR_NULL_POINTER); // don't let a listener be added more than once - if (mContentFilters.IndexOfObject(aListener) == -1) - { - NS_ENSURE_TRUE(mContentFilters.AppendObject(aListener), NS_ERROR_FAILURE); + if (!mContentFilters.Contains(aListener)) { + mContentFilters.AppendElement(*aListener); } return NS_OK; } -nsresult +NS_IMETHODIMP nsHTMLEditor::RemoveInsertionListener(nsIContentFilter *aListener) { NS_ENSURE_TRUE(aListener, NS_ERROR_FAILURE); - NS_ENSURE_TRUE(mContentFilters.RemoveObject(aListener), NS_ERROR_FAILURE); + mContentFilters.RemoveElement(aListener); return NS_OK; } nsresult nsHTMLEditor::DoContentFilterCallback(const nsAString &aFlavor, nsIDOMDocument *sourceDoc, bool aWillDeleteSelection, @@ -755,27 +727,25 @@ nsHTMLEditor::DoContentFilterCallback(co nsIDOMNode **aFragEndNode, int32_t *aFragEndOffset, nsIDOMNode **aTargetNode, int32_t *aTargetOffset, bool *aDoContinue) { *aDoContinue = true; - int32_t i; - nsIContentFilter *listener; - for (i=0; i < mContentFilters.Count() && *aDoContinue; i++) - { - listener = (nsIContentFilter *)mContentFilters[i]; - if (listener) - listener->NotifyOfInsertion(aFlavor, nullptr, sourceDoc, - aWillDeleteSelection, aFragmentAsNode, - aFragStartNode, aFragStartOffset, - aFragEndNode, aFragEndOffset, - aTargetNode, aTargetOffset, aDoContinue); + for (auto& listener : mContentFilters) { + if (!*aDoContinue) { + break; + } + listener->NotifyOfInsertion(aFlavor, nullptr, sourceDoc, + aWillDeleteSelection, aFragmentAsNode, + aFragStartNode, aFragStartOffset, + aFragEndNode, aFragEndOffset, aTargetNode, + aTargetOffset, aDoContinue); } return NS_OK; } bool nsHTMLEditor::IsInLink(nsIDOMNode *aNode, nsCOMPtr<nsIDOMNode> *outLink) { @@ -2161,224 +2131,175 @@ nsresult nsHTMLEditor::ParseFragment(con nsIParserUtils::SanitizerAllowStyle : nsIParserUtils::SanitizerAllowComments); sanitizer.Sanitize(fragment); } *outNode = fragment.forget(); return rv; } -nsresult nsHTMLEditor::CreateListOfNodesToPaste(nsIDOMNode *aFragmentAsNode, - nsCOMArray<nsIDOMNode>& outNodeList, - nsIDOMNode *aStartNode, - int32_t aStartOffset, - nsIDOMNode *aEndNode, - int32_t aEndOffset) +void +nsHTMLEditor::CreateListOfNodesToPaste(DocumentFragment& aFragment, + nsTArray<OwningNonNull<nsINode>>& outNodeList, + nsINode* aStartNode, + int32_t aStartOffset, + nsINode* aEndNode, + int32_t aEndOffset) { - NS_ENSURE_TRUE(aFragmentAsNode, NS_ERROR_NULL_POINTER); - - nsresult rv; - - // if no info was provided about the boundary between context and stream, + // If no info was provided about the boundary between context and stream, // then assume all is stream. - if (!aStartNode) - { - int32_t fragLen; - rv = GetLengthOfDOMNode(aFragmentAsNode, (uint32_t&)fragLen); - NS_ENSURE_SUCCESS(rv, rv); - - aStartNode = aFragmentAsNode; + if (!aStartNode) { + aStartNode = &aFragment; aStartOffset = 0; - aEndNode = aFragmentAsNode; - aEndOffset = fragLen; + aEndNode = &aFragment; + aEndOffset = aFragment.Length(); } nsRefPtr<nsRange> docFragRange; - rv = nsRange::CreateRange(aStartNode, aStartOffset, aEndNode, aEndOffset, getter_AddRefs(docFragRange)); - NS_ENSURE_SUCCESS(rv, rv); + nsresult rv = nsRange::CreateRange(aStartNode, aStartOffset, + aEndNode, aEndOffset, + getter_AddRefs(docFragRange)); + MOZ_ASSERT(NS_SUCCEEDED(rv)); + NS_ENSURE_SUCCESS(rv, ); - // now use a subtree iterator over the range to create a list of nodes + // Now use a subtree iterator over the range to create a list of nodes nsTrivialFunctor functor; - nsDOMSubtreeIterator iter; - rv = iter.Init(docFragRange); - NS_ENSURE_SUCCESS(rv, rv); - - return iter.AppendList(functor, outNodeList); + nsDOMSubtreeIterator iter(*docFragRange); + iter.AppendList(functor, outNodeList); } -nsresult -nsHTMLEditor::GetListAndTableParents(bool aEnd, - nsCOMArray<nsIDOMNode>& aListOfNodes, - nsCOMArray<nsIDOMNode>& outArray) +void +nsHTMLEditor::GetListAndTableParents(StartOrEnd aStartOrEnd, + nsTArray<OwningNonNull<nsINode>>& aNodeList, + nsTArray<OwningNonNull<Element>>& outArray) { - int32_t listCount = aListOfNodes.Count(); - NS_ENSURE_TRUE(listCount > 0, NS_ERROR_FAILURE); // no empty lists, please - - // build up list of parents of first (or last) node in list - // that are either lists, or tables. - int32_t idx = 0; - if (aEnd) idx = listCount-1; + MOZ_ASSERT(aNodeList.Length()); - nsCOMPtr<nsIDOMNode> pNode = aListOfNodes[idx]; - while (pNode) - { - if (nsHTMLEditUtils::IsList(pNode) || nsHTMLEditUtils::IsTable(pNode)) - { - NS_ENSURE_TRUE(outArray.AppendObject(pNode), NS_ERROR_FAILURE); + // Build up list of parents of first (or last) node in list that are either + // lists, or tables. + int32_t idx = aStartOrEnd == StartOrEnd::end ? aNodeList.Length() - 1 : 0; + + for (nsCOMPtr<nsINode> node = aNodeList[idx]; node; + node = node->GetParentNode()) { + if (nsHTMLEditUtils::IsList(node) || nsHTMLEditUtils::IsTable(node)) { + outArray.AppendElement(*node->AsElement()); } - nsCOMPtr<nsIDOMNode> parent; - pNode->GetParentNode(getter_AddRefs(parent)); - pNode = parent; } - return NS_OK; } -nsresult -nsHTMLEditor::DiscoverPartialListsAndTables(nsCOMArray<nsIDOMNode>& aPasteNodes, - nsCOMArray<nsIDOMNode>& aListsAndTables, - int32_t *outHighWaterMark) +int32_t +nsHTMLEditor::DiscoverPartialListsAndTables(nsTArray<OwningNonNull<nsINode>>& aPasteNodes, + nsTArray<OwningNonNull<Element>>& aListsAndTables) { - NS_ENSURE_TRUE(outHighWaterMark, NS_ERROR_NULL_POINTER); - - *outHighWaterMark = -1; - int32_t listAndTableParents = aListsAndTables.Count(); + int32_t ret = -1; + int32_t listAndTableParents = aListsAndTables.Length(); - // scan insertion list for table elements (other than table). - int32_t listCount = aPasteNodes.Count(); - int32_t j; - for (j=0; j<listCount; j++) - { - nsCOMPtr<nsIDOMNode> curNode = aPasteNodes[j]; - - NS_ENSURE_TRUE(curNode, NS_ERROR_FAILURE); - if (nsHTMLEditUtils::IsTableElement(curNode) && !nsHTMLEditUtils::IsTable(curNode)) - { - nsCOMPtr<nsIDOMNode> theTable = GetTableParent(curNode); - if (theTable) - { - int32_t indexT = aListsAndTables.IndexOf(theTable); - if (indexT >= 0) - { - *outHighWaterMark = indexT; - if (*outHighWaterMark == listAndTableParents-1) break; + // Scan insertion list for table elements (other than table). + for (auto& curNode : aPasteNodes) { + if (nsHTMLEditUtils::IsTableElement(curNode) && + !curNode->IsHTMLElement(nsGkAtoms::table)) { + nsCOMPtr<Element> table = curNode->GetParentElement(); + while (table && !table->IsHTMLElement(nsGkAtoms::table)) { + table = table->GetParentElement(); + } + if (table) { + int32_t idx = aListsAndTables.IndexOf(table); + if (idx == -1) { + return ret; } - else - { - break; + ret = idx; + if (ret == listAndTableParents - 1) { + return ret; } } } - if (nsHTMLEditUtils::IsListItem(curNode)) - { - nsCOMPtr<nsIDOMNode> theList = GetListParent(curNode); - if (theList) - { - int32_t indexL = aListsAndTables.IndexOf(theList); - if (indexL >= 0) - { - *outHighWaterMark = indexL; - if (*outHighWaterMark == listAndTableParents-1) break; + if (nsHTMLEditUtils::IsListItem(curNode)) { + nsCOMPtr<Element> list = curNode->GetParentElement(); + while (list && !nsHTMLEditUtils::IsList(list)) { + list = list->GetParentElement(); + } + if (list) { + int32_t idx = aListsAndTables.IndexOf(list); + if (idx == -1) { + return ret; } - else - { - break; + ret = idx; + if (ret == listAndTableParents - 1) { + return ret; } } } } - return NS_OK; -} - -nsresult -nsHTMLEditor::ScanForListAndTableStructure( bool aEnd, - nsCOMArray<nsIDOMNode>& aNodes, - nsIDOMNode *aListOrTable, - nsCOMPtr<nsIDOMNode> *outReplaceNode) -{ - NS_ENSURE_TRUE(aListOrTable, NS_ERROR_NULL_POINTER); - NS_ENSURE_TRUE(outReplaceNode, NS_ERROR_NULL_POINTER); - - *outReplaceNode = 0; - - // look upward from first/last paste node for a piece of this list/table - int32_t listCount = aNodes.Count(), idx = 0; - if (aEnd) idx = listCount-1; - bool bList = nsHTMLEditUtils::IsList(aListOrTable); - - nsCOMPtr<nsIDOMNode> pNode = aNodes[idx]; - nsCOMPtr<nsIDOMNode> originalNode = pNode; - while (pNode) - { - if ((bList && nsHTMLEditUtils::IsListItem(pNode)) || - (!bList && (nsHTMLEditUtils::IsTableElement(pNode) && !nsHTMLEditUtils::IsTable(pNode)))) - { - nsCOMPtr<nsIDOMNode> structureNode; - if (bList) structureNode = GetListParent(pNode); - else structureNode = GetTableParent(pNode); - if (structureNode == aListOrTable) - { - if (bList) - *outReplaceNode = structureNode; - else - *outReplaceNode = pNode; - break; - } - } - nsCOMPtr<nsIDOMNode> parent; - pNode->GetParentNode(getter_AddRefs(parent)); - pNode = parent; - } - return NS_OK; + return ret; } -nsresult -nsHTMLEditor::ReplaceOrphanedStructure(bool aEnd, - nsCOMArray<nsIDOMNode>& aNodeArray, - nsCOMArray<nsIDOMNode>& aListAndTableArray, +nsINode* +nsHTMLEditor::ScanForListAndTableStructure(StartOrEnd aStartOrEnd, + nsTArray<OwningNonNull<nsINode>>& aNodes, + Element& aListOrTable) +{ + // Look upward from first/last paste node for a piece of this list/table + int32_t idx = aStartOrEnd == StartOrEnd::end ? aNodes.Length() - 1 : 0; + bool isList = nsHTMLEditUtils::IsList(&aListOrTable); + + for (nsCOMPtr<nsINode> node = aNodes[idx]; node; + node = node->GetParentNode()) { + if ((isList && nsHTMLEditUtils::IsListItem(node)) || + (!isList && nsHTMLEditUtils::IsTableElement(node) && + !node->IsHTMLElement(nsGkAtoms::table))) { + nsCOMPtr<Element> structureNode = node->GetParentElement(); + if (isList) { + while (structureNode && !nsHTMLEditUtils::IsList(structureNode)) { + structureNode = structureNode->GetParentElement(); + } + } else { + while (structureNode && + !structureNode->IsHTMLElement(nsGkAtoms::table)) { + structureNode = structureNode->GetParentElement(); + } + } + if (structureNode == &aListOrTable) { + if (isList) { + return structureNode; + } + return node; + } + } + } + return nullptr; +} + +void +nsHTMLEditor::ReplaceOrphanedStructure(StartOrEnd aStartOrEnd, + nsTArray<OwningNonNull<nsINode>>& aNodeArray, + nsTArray<OwningNonNull<Element>>& aListAndTableArray, int32_t aHighWaterMark) { - nsCOMPtr<nsIDOMNode> curNode = aListAndTableArray[aHighWaterMark]; - NS_ENSURE_TRUE(curNode, NS_ERROR_NULL_POINTER); - - nsCOMPtr<nsIDOMNode> replaceNode, originalNode; - - // find substructure of list or table that must be included in paste. - nsresult rv = ScanForListAndTableStructure(aEnd, aNodeArray, - curNode, address_of(replaceNode)); - NS_ENSURE_SUCCESS(rv, rv); + OwningNonNull<Element> curNode = aListAndTableArray[aHighWaterMark]; - // if we found substructure, paste it instead of its descendants - if (replaceNode) - { - // postprocess list to remove any descendants of this node - // so that we don't insert them twice. - nsCOMPtr<nsIDOMNode> endpoint; - do - { - endpoint = GetArrayEndpoint(aEnd, aNodeArray); - if (!endpoint) break; - if (nsEditorUtils::IsDescendantOf(endpoint, replaceNode)) - aNodeArray.RemoveObject(endpoint); - else - break; - } while(endpoint); + // Find substructure of list or table that must be included in paste. + nsCOMPtr<nsINode> replaceNode = + ScanForListAndTableStructure(aStartOrEnd, aNodeArray, curNode); - // now replace the removed nodes with the structural parent - if (aEnd) aNodeArray.AppendObject(replaceNode); - else aNodeArray.InsertObjectAt(replaceNode, 0); - } - return NS_OK; -} - -nsIDOMNode* nsHTMLEditor::GetArrayEndpoint(bool aEnd, - nsCOMArray<nsIDOMNode>& aNodeArray) -{ - int32_t listCount = aNodeArray.Count(); - if (listCount <= 0) { - return nullptr; + if (!replaceNode) { + return; } - if (aEnd) { - return aNodeArray[listCount-1]; + // If we found substructure, paste it instead of its descendants. + // Postprocess list to remove any descendants of this node so that we don't + // insert them twice. + while (aNodeArray.Length()) { + int32_t idx = aStartOrEnd == StartOrEnd::start ? 0 + : aNodeArray.Length() - 1; + OwningNonNull<nsINode> endpoint = aNodeArray[idx]; + if (!nsEditorUtils::IsDescendantOf(endpoint, replaceNode)) { + break; + } + aNodeArray.RemoveElementAt(idx); } - return aNodeArray[0]; + // Now replace the removed nodes with the structural parent + if (aStartOrEnd == StartOrEnd::end) { + aNodeArray.AppendElement(*replaceNode); + } else { + aNodeArray.InsertElementAt(0, *replaceNode); + } }
--- a/editor/libeditor/nsHTMLEditRules.cpp +++ b/editor/libeditor/nsHTMLEditRules.cpp @@ -8,20 +8,20 @@ #include <stdlib.h> #include "mozilla/Assertions.h" #include "mozilla/MathAlgorithms.h" #include "mozilla/Preferences.h" #include "mozilla/dom/Selection.h" #include "mozilla/dom/Element.h" +#include "mozilla/dom/OwningNonNull.h" #include "mozilla/mozalloc.h" #include "nsAString.h" #include "nsAlgorithm.h" -#include "nsCOMArray.h" #include "nsCRT.h" #include "nsCRTGlue.h" #include "nsComponentManagerUtils.h" #include "nsContentUtils.h" #include "nsDebug.h" #include "nsEditor.h" #include "nsEditorUtils.h" #include "nsError.h" @@ -101,61 +101,63 @@ IsStyleCachePreservingAction(EditAction action == EditAction::makeDefListItem || action == EditAction::insertElement || action == EditAction::insertQuotation; } class nsTableCellAndListItemFunctor : public nsBoolDomIterFunctor { public: - virtual bool operator()(nsIDOMNode* aNode) // used to build list of all li's, td's & th's iterator covers + // Used to build list of all li's, td's & th's iterator covers + virtual bool operator()(nsINode* aNode) const { if (nsHTMLEditUtils::IsTableCell(aNode)) return true; if (nsHTMLEditUtils::IsListItem(aNode)) return true; return false; } }; class nsBRNodeFunctor : public nsBoolDomIterFunctor { public: - virtual bool operator()(nsIDOMNode* aNode) + virtual bool operator()(nsINode* aNode) const { - if (nsTextEditUtils::IsBreak(aNode)) return true; + if (aNode->IsHTMLElement(nsGkAtoms::br)) { + return true; + } return false; } }; class nsEmptyEditableFunctor : public nsBoolDomIterFunctor { public: explicit nsEmptyEditableFunctor(nsHTMLEditor* editor) : mHTMLEditor(editor) {} - virtual bool operator()(nsIDOMNode* aNode) + virtual bool operator()(nsINode* aNode) const { if (mHTMLEditor->IsEditable(aNode) && - (nsHTMLEditUtils::IsListItem(aNode) || - nsHTMLEditUtils::IsTableCellOrCaption(aNode))) - { + (nsHTMLEditUtils::IsListItem(aNode) || + nsHTMLEditUtils::IsTableCellOrCaption(GetAsDOMNode(aNode)))) { bool bIsEmptyNode; nsresult res = mHTMLEditor->IsEmptyNode(aNode, &bIsEmptyNode, false, false); NS_ENSURE_SUCCESS(res, false); if (bIsEmptyNode) return true; } return false; } protected: nsHTMLEditor* mHTMLEditor; }; class nsEditableTextFunctor : public nsBoolDomIterFunctor { public: explicit nsEditableTextFunctor(nsHTMLEditor* editor) : mHTMLEditor(editor) {} - virtual bool operator()(nsIDOMNode* aNode) + virtual bool operator()(nsINode* aNode) const { if (nsEditor::IsTextNode(aNode) && mHTMLEditor->IsEditable(aNode)) { return true; } return false; } protected: @@ -269,18 +271,17 @@ nsHTMLEditRules::Init(nsPlaintextEditor nsAutoLockRulesSniffing lockIt((nsTextEditRules*)this); if (!mDocChangeRange) { mDocChangeRange = new nsRange(node); } if (node->IsElement()) { ErrorResult rv; mDocChangeRange->SelectNode(*node, rv); - res = AdjustSpecialBreaks(node); - NS_ENSURE_SUCCESS(res, res); + AdjustSpecialBreaks(); } // add ourselves as a listener to edit actions res = mHTMLEditor->AddEditActionListener(this); return res; } @@ -440,33 +441,31 @@ nsHTMLEditRules::AfterEditInner(EditActi if (bDamagedRange && !((action == EditAction::undo) || (action == EditAction::redo))) { // don't let any txns in here move the selection around behind our back. // Note that this won't prevent explicit selection setting from working. NS_ENSURE_STATE(mHTMLEditor); nsAutoTxnsConserveSelection dontSpazMySelection(mHTMLEditor); // expand the "changed doc range" as needed - res = PromoteRange(mDocChangeRange, action); - NS_ENSURE_SUCCESS(res, res); + PromoteRange(*mDocChangeRange, action); // if we did a ranged deletion or handling backspace key, make sure we have // a place to put caret. // Note we only want to do this if the overall operation was deletion, // not if deletion was done along the way for EditAction::loadHTML, EditAction::insertText, etc. // That's why this is here rather than DidDeleteSelection(). if ((action == EditAction::deleteSelection) && mDidRangedDelete) { res = InsertBRIfNeeded(selection); NS_ENSURE_SUCCESS(res, res); } // add in any needed <br>s, and remove any unneeded ones. - res = AdjustSpecialBreaks(); - NS_ENSURE_SUCCESS(res, res); + AdjustSpecialBreaks(); // merge any adjacent text nodes if ( (action != EditAction::insertText && action != EditAction::insertIMEText) ) { NS_ENSURE_STATE(mHTMLEditor); res = mHTMLEditor->CollapseAdjacentTextNodes(mDocChangeRange); NS_ENSURE_SUCCESS(res, res); @@ -686,43 +685,40 @@ nsHTMLEditRules::GetListState(bool *aMix { NS_ENSURE_TRUE(aMixed && aOL && aUL && aDL, NS_ERROR_NULL_POINTER); *aMixed = false; *aOL = false; *aUL = false; *aDL = false; bool bNonList = false; - nsCOMArray<nsIDOMNode> arrayOfNodes; - nsresult res = GetListActionNodes(arrayOfNodes, false, true); + nsTArray<OwningNonNull<nsINode>> arrayOfNodes; + nsresult res = GetListActionNodes(arrayOfNodes, EntireList::no, + TouchContent::no); NS_ENSURE_SUCCESS(res, res); // Examine list type for nodes in selection. - int32_t listCount = arrayOfNodes.Count(); - for (int32_t i = listCount - 1; i >= 0; --i) { - nsIDOMNode* curDOMNode = arrayOfNodes[i]; - nsCOMPtr<dom::Element> curElement = do_QueryInterface(curDOMNode); - - if (!curElement) { + for (const auto& curNode : arrayOfNodes) { + if (!curNode->IsElement()) { bNonList = true; - } else if (curElement->IsHTMLElement(nsGkAtoms::ul)) { + } else if (curNode->IsHTMLElement(nsGkAtoms::ul)) { *aUL = true; - } else if (curElement->IsHTMLElement(nsGkAtoms::ol)) { + } else if (curNode->IsHTMLElement(nsGkAtoms::ol)) { *aOL = true; - } else if (curElement->IsHTMLElement(nsGkAtoms::li)) { - if (dom::Element* parent = curElement->GetParentElement()) { + } else if (curNode->IsHTMLElement(nsGkAtoms::li)) { + if (dom::Element* parent = curNode->GetParentElement()) { if (parent->IsHTMLElement(nsGkAtoms::ul)) { *aUL = true; } else if (parent->IsHTMLElement(nsGkAtoms::ol)) { *aOL = true; } } - } else if (curElement->IsAnyOfHTMLElements(nsGkAtoms::dl, - nsGkAtoms::dt, - nsGkAtoms::dd)) { + } else if (curNode->IsAnyOfHTMLElements(nsGkAtoms::dl, + nsGkAtoms::dt, + nsGkAtoms::dd)) { *aDL = true; } else { bNonList = true; } } // hokey arithmetic with booleans if ((*aUL + *aOL + *aDL + bNonList) > 1) { @@ -737,39 +733,37 @@ nsHTMLEditRules::GetListItemState(bool * { NS_ENSURE_TRUE(aMixed && aLI && aDT && aDD, NS_ERROR_NULL_POINTER); *aMixed = false; *aLI = false; *aDT = false; *aDD = false; bool bNonList = false; - nsCOMArray<nsIDOMNode> arrayOfNodes; - nsresult res = GetListActionNodes(arrayOfNodes, false, true); + nsTArray<OwningNonNull<nsINode>> arrayOfNodes; + nsresult res = GetListActionNodes(arrayOfNodes, EntireList::no, + TouchContent::no); NS_ENSURE_SUCCESS(res, res); // examine list type for nodes in selection - int32_t listCount = arrayOfNodes.Count(); - for (int32_t i = listCount - 1; i >= 0; --i) { - nsIDOMNode* curNode = arrayOfNodes[i]; - nsCOMPtr<dom::Element> element = do_QueryInterface(curNode); - if (!element) { + for (const auto& node : arrayOfNodes) { + if (!node->IsElement()) { bNonList = true; - } else if (element->IsAnyOfHTMLElements(nsGkAtoms::ul, - nsGkAtoms::ol, - nsGkAtoms::li)) { + } else if (node->IsAnyOfHTMLElements(nsGkAtoms::ul, + nsGkAtoms::ol, + nsGkAtoms::li)) { *aLI = true; - } else if (element->IsHTMLElement(nsGkAtoms::dt)) { + } else if (node->IsHTMLElement(nsGkAtoms::dt)) { *aDT = true; - } else if (element->IsHTMLElement(nsGkAtoms::dd)) { + } else if (node->IsHTMLElement(nsGkAtoms::dd)) { *aDD = true; - } else if (element->IsHTMLElement(nsGkAtoms::dl)) { + } else if (node->IsHTMLElement(nsGkAtoms::dl)) { // need to look inside dl and see which types of items it has bool bDT, bDD; - GetDefinitionListItemTypes(element, &bDT, &bDD); + GetDefinitionListItemTypes(node->AsElement(), &bDT, &bDD); *aDT |= bDT; *aDD |= bDD; } else { bNonList = true; } } // hokey arithmetic with booleans @@ -808,78 +802,75 @@ nsHTMLEditRules::GetAlignment(bool *aMix nsCOMPtr<nsINode> parent = nsEditor::GetNodeLocation(rootElem, &rootOffset); NS_ENSURE_STATE(mHTMLEditor); nsresult res = mHTMLEditor->GetStartNodeAndOffset(selection, getter_AddRefs(parent), &offset); NS_ENSURE_SUCCESS(res, res); // is the selection collapsed? - nsCOMPtr<nsIDOMNode> nodeToExamine; + nsCOMPtr<nsINode> nodeToExamine; if (selection->Collapsed()) { // if it is, we want to look at 'parent' and its ancestors // for divs with alignment on them - nodeToExamine = GetAsDOMNode(parent); + nodeToExamine = parent; } else if (!mHTMLEditor) { return NS_ERROR_UNEXPECTED; } else if (mHTMLEditor->IsTextNode(parent)) { // if we are in a text node, then that is the node of interest - nodeToExamine = GetAsDOMNode(parent); + nodeToExamine = parent; } else if (parent->IsHTMLElement(nsGkAtoms::html) && offset == rootOffset) { // if we have selected the body, let's look at the first editable node NS_ENSURE_STATE(mHTMLEditor); - nodeToExamine = - GetAsDOMNode(mHTMLEditor->GetNextNode(parent, offset, true)); + nodeToExamine = mHTMLEditor->GetNextNode(parent, offset, true); } else { nsTArray<nsRefPtr<nsRange>> arrayOfRanges; - res = GetPromotedRanges(selection, arrayOfRanges, EditAction::align); - NS_ENSURE_SUCCESS(res, res); + GetPromotedRanges(*selection, arrayOfRanges, EditAction::align); // use these ranges to construct a list of nodes to act on. - nsCOMArray<nsIDOMNode> arrayOfNodes; + nsTArray<OwningNonNull<nsINode>> arrayOfNodes; res = GetNodesForOperation(arrayOfRanges, arrayOfNodes, - EditAction::align, true); + EditAction::align, TouchContent::no); NS_ENSURE_SUCCESS(res, res); - nodeToExamine = arrayOfNodes.SafeObjectAt(0); + nodeToExamine = arrayOfNodes.SafeElementAt(0); } NS_ENSURE_TRUE(nodeToExamine, NS_ERROR_NULL_POINTER); NS_NAMED_LITERAL_STRING(typeAttrName, "align"); nsIAtom *dummyProperty = nullptr; - nsCOMPtr<nsIDOMNode> blockParent; + nsCOMPtr<Element> blockParent; NS_ENSURE_STATE(mHTMLEditor); if (mHTMLEditor->IsBlockNode(nodeToExamine)) - blockParent = nodeToExamine; + blockParent = nodeToExamine->AsElement(); else { NS_ENSURE_STATE(mHTMLEditor); blockParent = mHTMLEditor->GetBlockNodeParent(nodeToExamine); } NS_ENSURE_TRUE(blockParent, NS_ERROR_FAILURE); NS_ENSURE_STATE(mHTMLEditor); if (mHTMLEditor->IsCSSEnabled()) { - nsCOMPtr<nsIContent> blockParentContent = do_QueryInterface(blockParent); - NS_ENSURE_STATE(mHTMLEditor); - if (blockParentContent && - mHTMLEditor->mHTMLCSSUtils->IsCSSEditableProperty(blockParentContent, dummyProperty, &typeAttrName)) - { + NS_ENSURE_STATE(mHTMLEditor); + if (mHTMLEditor->mHTMLCSSUtils->IsCSSEditableProperty(blockParent, + dummyProperty, + &typeAttrName)) { // we are in CSS mode and we know how to align this element with CSS nsAutoString value; // let's get the value(s) of text-align or margin-left/margin-right NS_ENSURE_STATE(mHTMLEditor); mHTMLEditor->mHTMLCSSUtils->GetCSSEquivalentToHTMLInlineStyleSet( - blockParentContent, dummyProperty, &typeAttrName, value, + blockParent, dummyProperty, &typeAttrName, value, nsHTMLCSSUtils::eComputed); if (value.EqualsLiteral("center") || value.EqualsLiteral("-moz-center") || value.EqualsLiteral("auto auto")) { *aAlign = nsIHTMLEditor::eCenter; return NS_OK; } @@ -896,29 +887,27 @@ nsHTMLEditRules::GetAlignment(bool *aMix return NS_OK; } *aAlign = nsIHTMLEditor::eLeft; return NS_OK; } } // check up the ladder for divs with alignment - nsCOMPtr<nsIDOMNode> temp = nodeToExamine; bool isFirstNodeToExamine = true; while (nodeToExamine) { if (!isFirstNodeToExamine && nsHTMLEditUtils::IsTable(nodeToExamine)) { // the node to examine is a table and this is not the first node // we examine; let's break here to materialize the 'inline-block' // behaviour of html tables regarding to text alignment return NS_OK; } - if (nsHTMLEditUtils::SupportsAlignAttr(nodeToExamine)) - { + if (nsHTMLEditUtils::SupportsAlignAttr(GetAsDOMNode(nodeToExamine))) { // check for alignment nsCOMPtr<nsIDOMElement> elem = do_QueryInterface(nodeToExamine); if (elem) { nsAutoString typeAttrVal; res = elem->GetAttribute(NS_LITERAL_STRING("align"), typeAttrVal); ToLowerCase(typeAttrVal); if (NS_SUCCEEDED(res) && typeAttrVal.Length()) @@ -931,19 +920,17 @@ nsHTMLEditRules::GetAlignment(bool *aMix *aAlign = nsIHTMLEditor::eJustify; else *aAlign = nsIHTMLEditor::eLeft; return res; } } } isFirstNodeToExamine = false; - res = nodeToExamine->GetParentNode(getter_AddRefs(temp)); - if (NS_FAILED(res)) temp = nullptr; - nodeToExamine = temp; + nodeToExamine = nodeToExamine->GetParentNode(); } return NS_OK; } static nsIAtom* MarginPropertyAtomForIndent(nsHTMLCSSUtils* aHTMLCSSUtils, nsIDOMNode* aNode) { nsCOMPtr<nsINode> node = do_QueryInterface(aNode); NS_ENSURE_TRUE(node || !aNode, nsGkAtoms::marginLeft); @@ -960,33 +947,27 @@ nsHTMLEditRules::GetIndentState(bool *aC *aCanIndent = true; *aCanOutdent = false; // get selection NS_ENSURE_STATE(mHTMLEditor && mHTMLEditor->GetSelection()); OwningNonNull<Selection> selection = *mHTMLEditor->GetSelection(); // contruct a list of nodes to act on. - nsCOMArray<nsIDOMNode> arrayOfNodes; - nsresult res = GetNodesFromSelection(selection, EditAction::indent, - arrayOfNodes, true); + nsTArray<OwningNonNull<nsINode>> arrayOfNodes; + nsresult res = GetNodesFromSelection(*selection, EditAction::indent, + arrayOfNodes, TouchContent::no); NS_ENSURE_SUCCESS(res, res); // examine nodes in selection for blockquotes or list elements; // these we can outdent. Note that we return true for canOutdent // if *any* of the selection is outdentable, rather than all of it. - int32_t listCount = arrayOfNodes.Count(); - int32_t i; NS_ENSURE_STATE(mHTMLEditor); bool useCSS = mHTMLEditor->IsCSSEnabled(); - for (i=listCount-1; i>=0; i--) - { - nsCOMPtr<nsINode> curNode = do_QueryInterface(arrayOfNodes[i]); - NS_ENSURE_STATE(curNode || !arrayOfNodes[i]); - + for (auto& curNode : Reversed(arrayOfNodes)) { if (nsHTMLEditUtils::IsNodeThatCanOutdent(GetAsDOMNode(curNode))) { *aCanOutdent = true; break; } else if (useCSS) { // we are in CSS mode, indentation is done using the margin-left (or margin-right) property NS_ENSURE_STATE(mHTMLEditor); nsIAtom* marginProperty = @@ -1067,80 +1048,71 @@ nsHTMLEditRules::GetParagraphState(bool NS_ENSURE_TRUE(aMixed, NS_ERROR_NULL_POINTER); *aMixed = true; outFormat.Truncate(0); bool bMixed = false; // using "x" as an uninitialized value, since "" is meaningful nsAutoString formatStr(NS_LITERAL_STRING("x")); - nsCOMArray<nsIDOMNode> arrayOfNodes; - nsresult res = GetParagraphFormatNodes(arrayOfNodes, true); + nsTArray<OwningNonNull<nsINode>> arrayOfNodes; + nsresult res = GetParagraphFormatNodes(arrayOfNodes, TouchContent::no); NS_ENSURE_SUCCESS(res, res); // post process list. We need to replace any block nodes that are not format // nodes with their content. This is so we only have to look "up" the hierarchy // to find format nodes, instead of both up and down. - int32_t listCount = arrayOfNodes.Count(); - int32_t i; - for (i=listCount-1; i>=0; i--) - { - nsCOMPtr<nsIDOMNode> curNode = arrayOfNodes[i]; + for (int32_t i = arrayOfNodes.Length() - 1; i >= 0; i--) { + auto& curNode = arrayOfNodes[i]; nsAutoString format; // if it is a known format node we have it easy - if (IsBlockNode(curNode) && !nsHTMLEditUtils::IsFormatNode(curNode)) - { + if (IsBlockNode(GetAsDOMNode(curNode)) && + !nsHTMLEditUtils::IsFormatNode(curNode)) { // arrayOfNodes.RemoveObject(curNode); res = AppendInnerFormatNodes(arrayOfNodes, curNode); NS_ENSURE_SUCCESS(res, res); } } // we might have an empty node list. if so, find selection parent // and put that on the list - listCount = arrayOfNodes.Count(); - if (!listCount) - { - nsCOMPtr<nsIDOMNode> selNode; + if (!arrayOfNodes.Length()) { + nsCOMPtr<nsINode> selNode; int32_t selOffset; NS_ENSURE_STATE(mHTMLEditor); nsRefPtr<Selection> selection = mHTMLEditor->GetSelection(); NS_ENSURE_STATE(selection); NS_ENSURE_STATE(mHTMLEditor); res = mHTMLEditor->GetStartNodeAndOffset(selection, getter_AddRefs(selNode), &selOffset); NS_ENSURE_SUCCESS(res, res); NS_ENSURE_TRUE(selNode, NS_ERROR_NULL_POINTER); - arrayOfNodes.AppendObject(selNode); - listCount = 1; + arrayOfNodes.AppendElement(*selNode); } // remember root node NS_ENSURE_STATE(mHTMLEditor); nsCOMPtr<nsIDOMElement> rootElem = do_QueryInterface(mHTMLEditor->GetRoot()); NS_ENSURE_TRUE(rootElem, NS_ERROR_NULL_POINTER); // loop through the nodes in selection and examine their paragraph format - for (i=listCount-1; i>=0; i--) - { - nsCOMPtr<nsIDOMNode> curNode = arrayOfNodes[i]; + for (auto& curNode : Reversed(arrayOfNodes)) { nsAutoString format; // if it is a known format node we have it easy - if (nsHTMLEditUtils::IsFormatNode(curNode)) - GetFormatString(curNode, format); - else if (IsBlockNode(curNode)) - { + if (nsHTMLEditUtils::IsFormatNode(curNode)) { + GetFormatString(GetAsDOMNode(curNode), format); + } else if (IsBlockNode(GetAsDOMNode(curNode))) { // this is a div or some other non-format block. // we should ignore it. Its children were appended to this list // by AppendInnerFormatNodes() call above. We will get needed // info when we examine them instead. continue; } else { - nsCOMPtr<nsIDOMNode> node, tmp = curNode; + nsCOMPtr<nsIDOMNode> node, tmp = GetAsDOMNode(curNode); tmp->GetParentNode(getter_AddRefs(node)); while (node) { if (node == rootElem) { format.Truncate(0); break; } @@ -1167,27 +1139,17 @@ nsHTMLEditRules::GetParagraphState(bool } *aMixed = bMixed; outFormat = formatStr; return res; } nsresult -nsHTMLEditRules::AppendInnerFormatNodes(nsCOMArray<nsIDOMNode>& aArray, - nsIDOMNode *aNode) -{ - nsCOMPtr<nsINode> node = do_QueryInterface(aNode); - NS_ENSURE_TRUE(node, NS_ERROR_NULL_POINTER); - - return AppendInnerFormatNodes(aArray, node); -} - -nsresult -nsHTMLEditRules::AppendInnerFormatNodes(nsCOMArray<nsIDOMNode>& aArray, +nsHTMLEditRules::AppendInnerFormatNodes(nsTArray<OwningNonNull<nsINode>>& aArray, nsINode* aNode) { MOZ_ASSERT(aNode); // we only need to place any one inline inside this node onto // the list. They are all the same for purposes of determining // paragraph style. We use foundInline to track this as we are // going through the children in the loop below. @@ -1196,21 +1158,21 @@ nsHTMLEditRules::AppendInnerFormatNodes( child; child = child->GetNextSibling()) { bool isBlock = IsBlockNode(child->AsDOMNode()); bool isFormat = nsHTMLEditUtils::IsFormatNode(child); if (isBlock && !isFormat) { // if it's a div, etc, recurse AppendInnerFormatNodes(aArray, child); } else if (isFormat) { - aArray.AppendObject(child->AsDOMNode()); + aArray.AppendElement(*child); } else if (!foundInline) { // if this is the first inline we've found, use it foundInline = true; - aArray.AppendObject(child->AsDOMNode()); + aArray.AppendElement(*child); } } return NS_OK; } nsresult nsHTMLEditRules::GetFormatString(nsIDOMNode *aNode, nsAString &outFormat) { @@ -2432,23 +2394,20 @@ nsHTMLEditRules::WillDeleteSelection(Sel // except table elements. join = true; uint32_t rangeCount = aSelection->RangeCount(); for (uint32_t rangeIdx = 0; rangeIdx < rangeCount; ++rangeIdx) { OwningNonNull<nsRange> range = *aSelection->GetRangeAt(rangeIdx); // Build a list of nodes in the range - nsTArray<nsCOMPtr<nsINode>> arrayOfNodes; + nsTArray<OwningNonNull<nsINode>> arrayOfNodes; nsTrivialFunctor functor; - nsDOMSubtreeIterator iter; - res = iter.Init(range); - NS_ENSURE_SUCCESS(res, res); - res = iter.AppendList(functor, arrayOfNodes); - NS_ENSURE_SUCCESS(res, res); + nsDOMSubtreeIterator iter(*range); + iter.AppendList(functor, arrayOfNodes); // Now that we have the list, delete non-table elements int32_t listCount = arrayOfNodes.Length(); for (int32_t j = 0; j < listCount; j++) { nsCOMPtr<nsINode> somenode = do_QueryInterface(arrayOfNodes[0]); NS_ENSURE_STATE(somenode); DeleteNonTableElements(somenode); arrayOfNodes.RemoveElementAt(0); @@ -2890,40 +2849,35 @@ nsHTMLEditRules::JoinBlocks(nsIDOMNode * * nsIDOMNode *aLeftBlock parent to receive moved content * nsIDOMNode *aRightBlock parent to provide moved content * int32_t aLeftOffset offset in aLeftBlock to move content to * int32_t aRightOffset offset in aRightBlock to move content from */ nsresult nsHTMLEditRules::MoveBlock(nsIDOMNode *aLeftBlock, nsIDOMNode *aRightBlock, int32_t aLeftOffset, int32_t aRightOffset) { - nsCOMArray<nsIDOMNode> arrayOfNodes; - nsCOMPtr<nsISupports> isupports; + nsTArray<OwningNonNull<nsINode>> arrayOfNodes; // GetNodesFromPoint is the workhorse that figures out what we wnat to move. nsresult res = GetNodesFromPoint(::DOMPoint(aRightBlock,aRightOffset), - EditAction::makeList, arrayOfNodes, true); + EditAction::makeList, arrayOfNodes, + TouchContent::no); NS_ENSURE_SUCCESS(res, res); - int32_t listCount = arrayOfNodes.Count(); - int32_t i; - for (i=0; i<listCount; i++) - { + for (auto& curNode : arrayOfNodes) { // get the node to act on - nsIDOMNode* curNode = arrayOfNodes[i]; - if (IsBlockNode(curNode)) - { + if (IsBlockNode(GetAsDOMNode(curNode))) { // For block nodes, move their contents only, then delete block. - res = MoveContents(curNode, aLeftBlock, &aLeftOffset); + res = MoveContents(GetAsDOMNode(curNode), aLeftBlock, &aLeftOffset); NS_ENSURE_SUCCESS(res, res); NS_ENSURE_STATE(mHTMLEditor); res = mHTMLEditor->DeleteNode(curNode); } else { // otherwise move the content as is, checking against the dtd. - res = MoveNodeSmart(curNode, aLeftBlock, &aLeftOffset); + res = MoveNodeSmart(GetAsDOMNode(curNode), aLeftBlock, &aLeftOffset); } } return res; } /***************************************************************************************************** * MoveNodeSmart: this method is used to move node aSource to (aDest,aOffset). * DTD containment rules are followed throughout. aOffset is updated to point _after_ @@ -3089,41 +3043,40 @@ nsHTMLEditRules::WillMakeList(Selection* *aHandled = true; res = NormalizeSelection(aSelection); NS_ENSURE_SUCCESS(res, res); NS_ENSURE_STATE(mHTMLEditor); nsAutoSelectionReset selectionResetter(aSelection, mHTMLEditor); - nsCOMArray<nsIDOMNode> arrayOfNodes; - res = GetListActionNodes(arrayOfNodes, aEntireList); + nsTArray<OwningNonNull<nsINode>> arrayOfNodes; + res = GetListActionNodes(arrayOfNodes, + aEntireList ? EntireList::yes : EntireList::no); NS_ENSURE_SUCCESS(res, res); - int32_t listCount = arrayOfNodes.Count(); - // check if all our nodes are <br>s, or empty inlines bool bOnlyBreaks = true; - for (int32_t j = 0; j < listCount; j++) { - nsIDOMNode* curNode = arrayOfNodes[j]; + for (auto& curNode : arrayOfNodes) { // if curNode is not a Break or empty inline, we're done - if (!nsTextEditUtils::IsBreak(curNode) && !IsEmptyInline(curNode)) { + if (!nsTextEditUtils::IsBreak(curNode) && + !IsEmptyInline(GetAsDOMNode(curNode))) { bOnlyBreaks = false; break; } } // if no nodes, we make empty list. Ditto if the user tried to make a list // of some # of breaks. - if (!listCount || bOnlyBreaks) { + if (!arrayOfNodes.Length() || bOnlyBreaks) { // if only breaks, delete them if (bOnlyBreaks) { - for (int32_t j = 0; j < (int32_t)listCount; j++) { + for (auto& node : arrayOfNodes) { NS_ENSURE_STATE(mHTMLEditor); - res = mHTMLEditor->DeleteNode(arrayOfNodes[j]); + res = mHTMLEditor->DeleteNode(node); NS_ENSURE_SUCCESS(res, res); } } // get selection location NS_ENSURE_STATE(aSelection->RangeCount()); nsCOMPtr<nsINode> parent = aSelection->GetRangeAt(0)->GetStartParent(); int32_t offset = aSelection->GetRangeAt(0)->StartOffset(); @@ -3155,31 +3108,30 @@ nsHTMLEditRules::WillMakeList(Selection* selectionResetter.Abort(); *aHandled = true; return res; } // if there is only one node in the array, and it is a list, div, or // blockquote, then look inside of it until we find inner list or content. - res = LookInsideDivBQandList(arrayOfNodes); - NS_ENSURE_SUCCESS(res, res); + LookInsideDivBQandList(arrayOfNodes); // Ok, now go through all the nodes and put then in the list, // or whatever is approriate. Wohoo! - listCount = arrayOfNodes.Count(); + uint32_t listCount = arrayOfNodes.Length(); nsCOMPtr<nsINode> curParent; nsCOMPtr<Element> curList, prevListItem; - for (int32_t i = 0; i < listCount; i++) { + for (uint32_t i = 0; i < listCount; i++) { // here's where we actually figure out what to do nsCOMPtr<nsIDOMNode> newBlock; - nsCOMPtr<nsIContent> curNode = do_QueryInterface(arrayOfNodes[i]); - NS_ENSURE_STATE(curNode); + NS_ENSURE_STATE(arrayOfNodes[i]->IsContent()); + nsCOMPtr<nsIContent> curNode = arrayOfNodes[i]->AsContent(); int32_t offset; curParent = nsEditor::GetNodeLocation(curNode, &offset); // make sure we don't assemble content that is in different table cells // into the same list. respect table cell boundaries when listifying. if (curList && InDifferentTableElements(curList, curNode)) { curList = nullptr; } @@ -3289,22 +3241,21 @@ nsHTMLEditRules::WillMakeList(Selection* continue; } // if we hit a div clear our prevListItem, insert divs contents // into our node array, and remove the div if (curNode->IsHTMLElement(nsGkAtoms::div)) { prevListItem = nullptr; int32_t j = i + 1; - res = GetInnerContent(curNode->AsDOMNode(), arrayOfNodes, &j); - NS_ENSURE_SUCCESS(res, res); + GetInnerContent(*curNode, arrayOfNodes, &j); NS_ENSURE_STATE(mHTMLEditor); res = mHTMLEditor->RemoveContainer(curNode); NS_ENSURE_SUCCESS(res, res); - listCount = arrayOfNodes.Count(); + listCount = arrayOfNodes.Length(); continue; } // need to make a list to put things in if we haven't already, if (!curList) { res = SplitAsNeeded(listType, curParent, offset); NS_ENSURE_SUCCESS(res, res); NS_ENSURE_STATE(mHTMLEditor); @@ -3372,61 +3323,54 @@ nsHTMLEditRules::WillRemoveList(Selectio *aHandled = true; nsresult res = NormalizeSelection(aSelection); NS_ENSURE_SUCCESS(res, res); NS_ENSURE_STATE(mHTMLEditor); nsAutoSelectionReset selectionResetter(aSelection, mHTMLEditor); nsTArray<nsRefPtr<nsRange>> arrayOfRanges; - res = GetPromotedRanges(aSelection, arrayOfRanges, EditAction::makeList); - NS_ENSURE_SUCCESS(res, res); + GetPromotedRanges(*aSelection, arrayOfRanges, EditAction::makeList); // use these ranges to contruct a list of nodes to act on. - nsCOMArray<nsIDOMNode> arrayOfNodes; - res = GetListActionNodes(arrayOfNodes, false); + nsTArray<OwningNonNull<nsINode>> arrayOfNodes; + res = GetListActionNodes(arrayOfNodes, EntireList::no); NS_ENSURE_SUCCESS(res, res); // Remove all non-editable nodes. Leave them be. - int32_t listCount = arrayOfNodes.Count(); + int32_t listCount = arrayOfNodes.Length(); int32_t i; for (i=listCount-1; i>=0; i--) { - nsIDOMNode* testNode = arrayOfNodes[i]; + OwningNonNull<nsINode> testNode = arrayOfNodes[i]; NS_ENSURE_STATE(mHTMLEditor); if (!mHTMLEditor->IsEditable(testNode)) { - arrayOfNodes.RemoveObjectAt(i); + arrayOfNodes.RemoveElementAt(i); } } // reset list count - listCount = arrayOfNodes.Count(); + listCount = arrayOfNodes.Length(); // Only act on lists or list items in the array - nsCOMPtr<nsIDOMNode> curParent; - for (i=0; i<listCount; i++) - { + for (auto& curNode : arrayOfNodes) { // here's where we actually figure out what to do - nsIDOMNode* curNode = arrayOfNodes[i]; - int32_t offset; - curParent = nsEditor::GetNodeLocation(curNode, &offset); - if (nsHTMLEditUtils::IsListItem(curNode)) // unlist this listitem { bool bOutOfList; do { - res = PopListItem(curNode, &bOutOfList); + res = PopListItem(GetAsDOMNode(curNode), &bOutOfList); NS_ENSURE_SUCCESS(res, res); } while (!bOutOfList); // keep popping it out until it's not in a list anymore } else if (nsHTMLEditUtils::IsList(curNode)) // node is a list, move list items out { - res = RemoveListStructure(curNode); + res = RemoveListStructure(GetAsDOMNode(curNode)); NS_ENSURE_SUCCESS(res, res); } } return res; } nsresult @@ -3463,35 +3407,34 @@ nsHTMLEditRules::WillMakeBasicBlock(Sele NS_ENSURE_STATE(mHTMLEditor); nsAutoSelectionReset selectionResetter(aSelection, mHTMLEditor); NS_ENSURE_STATE(mHTMLEditor); nsAutoTxnsConserveSelection dontSpazMySelection(mHTMLEditor); *aHandled = true; nsString tString(*aBlockType); // contruct a list of nodes to act on. - nsCOMArray<nsIDOMNode> arrayOfNodes; - res = GetNodesFromSelection(aSelection, EditAction::makeBasicBlock, + nsTArray<OwningNonNull<nsINode>> arrayOfNodes; + res = GetNodesFromSelection(*aSelection, EditAction::makeBasicBlock, arrayOfNodes); NS_ENSURE_SUCCESS(res, res); // Remove all non-editable nodes. Leave them be. - int32_t listCount = arrayOfNodes.Count(); + int32_t listCount = arrayOfNodes.Length(); int32_t i; for (i=listCount-1; i>=0; i--) { NS_ENSURE_STATE(mHTMLEditor); - if (!mHTMLEditor->IsEditable(arrayOfNodes[i])) - { - arrayOfNodes.RemoveObjectAt(i); - } - } - + if (!mHTMLEditor->IsEditable(arrayOfNodes[i])) { + arrayOfNodes.RemoveElementAt(i); + } + } + // reset list count - listCount = arrayOfNodes.Count(); + listCount = arrayOfNodes.Length(); // if nothing visible in list, make an empty block if (ListIsEmptyLine(arrayOfNodes)) { nsCOMPtr<nsIDOMNode> theBlock; // get selection location NS_ENSURE_STATE(aSelection->RangeCount()); @@ -3539,66 +3482,64 @@ nsHTMLEditRules::WillMakeBasicBlock(Sele selectionResetter.Abort(); // to prevent selection reseter from overriding us. *aHandled = true; } // else nothing to do! } else // we are making a block { // consume a br, if needed - nsCOMPtr<nsIDOMNode> brNode; NS_ENSURE_STATE(mHTMLEditor); - res = mHTMLEditor->GetNextHTMLNode(parent->AsDOMNode(), offset, - address_of(brNode), true); + nsCOMPtr<nsIContent> brNode = + mHTMLEditor->GetNextHTMLNode(parent, offset, true); NS_ENSURE_SUCCESS(res, res); if (brNode && nsTextEditUtils::IsBreak(brNode)) { NS_ENSURE_STATE(mHTMLEditor); res = mHTMLEditor->DeleteNode(brNode); NS_ENSURE_SUCCESS(res, res); // we don't need to act on this node any more - arrayOfNodes.RemoveObject(brNode); + arrayOfNodes.RemoveElement(brNode); } // make sure we can put a block here res = SplitAsNeeded(blockType, parent, offset); NS_ENSURE_SUCCESS(res, res); NS_ENSURE_STATE(mHTMLEditor); theBlock = dont_AddRef(GetAsDOMNode( mHTMLEditor->CreateNode(blockType, parent, offset).take())); NS_ENSURE_STATE(theBlock); // remember our new block for postprocessing mNewBlock = theBlock; // delete anything that was in the list of nodes - for (int32_t j = arrayOfNodes.Count() - 1; j >= 0; --j) - { - nsCOMPtr<nsIDOMNode> curNode = arrayOfNodes[0]; + while (!arrayOfNodes.IsEmpty()) { + OwningNonNull<nsINode> curNode = arrayOfNodes[0]; NS_ENSURE_STATE(mHTMLEditor); res = mHTMLEditor->DeleteNode(curNode); NS_ENSURE_SUCCESS(res, res); - arrayOfNodes.RemoveObjectAt(0); + arrayOfNodes.RemoveElementAt(0); } // put selection in new block res = aSelection->Collapse(theBlock,0); selectionResetter.Abort(); // to prevent selection reseter from overriding us. *aHandled = true; } return res; } else { // Ok, now go through all the nodes and make the right kind of blocks, // or whatever is approriate. Wohoo! // Note: blockquote is handled a little differently - if (tString.EqualsLiteral("blockquote")) + if (tString.EqualsLiteral("blockquote")) { res = MakeBlockquote(arrayOfNodes); - else if (tString.EqualsLiteral("normal") || - tString.IsEmpty() ) + } else if (tString.EqualsLiteral("normal") || tString.IsEmpty()) { res = RemoveBlockStyle(arrayOfNodes); - else - res = ApplyBlockStyle(arrayOfNodes, aBlockType); + } else { + res = ApplyBlockStyle(arrayOfNodes, *blockType); + } return res; } return res; } nsresult nsHTMLEditRules::DidMakeBasicBlock(Selection* aSelection, nsRulesInfo *aInfo, nsresult aResult) @@ -3645,53 +3586,54 @@ nsHTMLEditRules::WillCSSIndent(Selection // we want to ignore result of WillInsert() *aCancel = false; *aHandled = true; res = NormalizeSelection(aSelection); NS_ENSURE_SUCCESS(res, res); NS_ENSURE_STATE(mHTMLEditor); nsAutoSelectionReset selectionResetter(aSelection, mHTMLEditor); - nsTArray<nsRefPtr<nsRange>> arrayOfRanges; - nsCOMArray<nsIDOMNode> arrayOfNodes; + nsTArray<OwningNonNull<nsRange>> arrayOfRanges; + nsTArray<OwningNonNull<nsINode>> arrayOfNodes; // short circuit: detect case of collapsed selection inside an <li>. // just sublist that <li>. This prevents bug 97797. - nsCOMPtr<nsIDOMNode> liNode; + nsCOMPtr<Element> liNode; if (aSelection->Collapsed()) { - nsCOMPtr<nsIDOMNode> node, block; + nsCOMPtr<nsINode> node; + nsCOMPtr<Element> block; int32_t offset; NS_ENSURE_STATE(mHTMLEditor); nsresult res = mHTMLEditor->GetStartNodeAndOffset(aSelection, getter_AddRefs(node), &offset); NS_ENSURE_SUCCESS(res, res); - if (IsBlockNode(node)) { - block = node; + if (IsBlockNode(GetAsDOMNode(node))) { + block = node->AsElement(); } else { NS_ENSURE_STATE(mHTMLEditor); block = mHTMLEditor->GetBlockNodeParent(node); } if (block && nsHTMLEditUtils::IsListItem(block)) liNode = block; } if (liNode) { - arrayOfNodes.AppendObject(liNode); + arrayOfNodes.AppendElement(*liNode); } else { // convert the selection ranges into "promoted" selection ranges: // this basically just expands the range to include the immediate // block parent, and then further expands to include any ancestors // whose children are all in the range - res = GetNodesFromSelection(aSelection, EditAction::indent, arrayOfNodes); + res = GetNodesFromSelection(*aSelection, EditAction::indent, arrayOfNodes); NS_ENSURE_SUCCESS(res, res); } - + // if nothing visible in list, make an empty block if (ListIsEmptyLine(arrayOfNodes)) { // get selection location NS_ENSURE_STATE(aSelection->RangeCount()); nsCOMPtr<nsINode> parent = aSelection->GetRangeAt(0)->GetStartParent(); int32_t offset = aSelection->GetRangeAt(0)->StartOffset(); NS_ENSURE_STATE(parent); @@ -3702,43 +3644,42 @@ nsHTMLEditRules::WillCSSIndent(Selection NS_ENSURE_STATE(mHTMLEditor); nsCOMPtr<Element> theBlock = mHTMLEditor->CreateNode(nsGkAtoms::div, parent, offset); NS_ENSURE_STATE(theBlock); // remember our new block for postprocessing mNewBlock = theBlock->AsDOMNode(); RelativeChangeIndentationOfElementNode(theBlock->AsDOMNode(), +1); // delete anything that was in the list of nodes - for (int32_t j = arrayOfNodes.Count() - 1; j >= 0; --j) - { - nsCOMPtr<nsIDOMNode> curNode = arrayOfNodes[0]; + while (!arrayOfNodes.IsEmpty()) { + OwningNonNull<nsINode> curNode = arrayOfNodes[0]; NS_ENSURE_STATE(mHTMLEditor); res = mHTMLEditor->DeleteNode(curNode); NS_ENSURE_SUCCESS(res, res); - arrayOfNodes.RemoveObjectAt(0); + arrayOfNodes.RemoveElementAt(0); } // put selection in new block res = aSelection->Collapse(theBlock,0); selectionResetter.Abort(); // to prevent selection reseter from overriding us. *aHandled = true; return res; } // Ok, now go through all the nodes and put them in a blockquote, // or whatever is appropriate. Wohoo! int32_t i; nsCOMPtr<nsINode> curParent; nsCOMPtr<Element> curList, curQuote; nsCOMPtr<nsIContent> sibling; - int32_t listCount = arrayOfNodes.Count(); + int32_t listCount = arrayOfNodes.Length(); for (i=0; i<listCount; i++) { // here's where we actually figure out what to do - nsCOMPtr<nsIContent> curNode = do_QueryInterface(arrayOfNodes[i]); - NS_ENSURE_STATE(!arrayOfNodes[i] || curNode); + NS_ENSURE_STATE(arrayOfNodes[i]->IsContent()); + nsCOMPtr<nsIContent> curNode = arrayOfNodes[i]->AsContent(); // Ignore all non-editable nodes. Leave them be. NS_ENSURE_STATE(mHTMLEditor); if (!mHTMLEditor->IsEditable(curNode)) continue; curParent = curNode->GetParentNode(); int32_t offset = curParent ? curParent->IndexOf(curNode) : -1; @@ -3862,21 +3803,20 @@ nsHTMLEditRules::WillHTMLIndent(Selectio nsAutoSelectionReset selectionResetter(aSelection, mHTMLEditor); // convert the selection ranges into "promoted" selection ranges: // this basically just expands the range to include the immediate // block parent, and then further expands to include any ancestors // whose children are all in the range nsTArray<nsRefPtr<nsRange>> arrayOfRanges; - res = GetPromotedRanges(aSelection, arrayOfRanges, EditAction::indent); - NS_ENSURE_SUCCESS(res, res); + GetPromotedRanges(*aSelection, arrayOfRanges, EditAction::indent); // use these ranges to contruct a list of nodes to act on. - nsCOMArray<nsIDOMNode> arrayOfNodes; + nsTArray<OwningNonNull<nsINode>> arrayOfNodes; res = GetNodesForOperation(arrayOfRanges, arrayOfNodes, EditAction::indent); NS_ENSURE_SUCCESS(res, res); // if nothing visible in list, make an empty block if (ListIsEmptyLine(arrayOfNodes)) { // get selection location NS_ENSURE_STATE(aSelection->RangeCount()); @@ -3889,43 +3829,42 @@ nsHTMLEditRules::WillHTMLIndent(Selectio NS_ENSURE_SUCCESS(res, res); NS_ENSURE_STATE(mHTMLEditor); nsCOMPtr<Element> theBlock = mHTMLEditor->CreateNode(nsGkAtoms::blockquote, parent, offset); NS_ENSURE_STATE(theBlock); // remember our new block for postprocessing mNewBlock = theBlock->AsDOMNode(); // delete anything that was in the list of nodes - for (int32_t j = arrayOfNodes.Count() - 1; j >= 0; --j) - { - nsCOMPtr<nsIDOMNode> curNode = arrayOfNodes[0]; + while (!arrayOfNodes.IsEmpty()) { + OwningNonNull<nsINode> curNode = arrayOfNodes[0]; NS_ENSURE_STATE(mHTMLEditor); res = mHTMLEditor->DeleteNode(curNode); NS_ENSURE_SUCCESS(res, res); - arrayOfNodes.RemoveObjectAt(0); + arrayOfNodes.RemoveElementAt(0); } // put selection in new block res = aSelection->Collapse(theBlock,0); selectionResetter.Abort(); // to prevent selection reseter from overriding us. *aHandled = true; return res; } // Ok, now go through all the nodes and put them in a blockquote, // or whatever is appropriate. Wohoo! int32_t i; nsCOMPtr<nsINode> curParent; nsCOMPtr<nsIContent> sibling; nsCOMPtr<Element> curList, curQuote, indentedLI; - int32_t listCount = arrayOfNodes.Count(); + int32_t listCount = arrayOfNodes.Length(); for (i=0; i<listCount; i++) { // here's where we actually figure out what to do - nsCOMPtr<nsIContent> curNode = do_QueryInterface(arrayOfNodes[i]); - NS_ENSURE_STATE(!arrayOfNodes[i] || curNode); + NS_ENSURE_STATE(arrayOfNodes[i]->IsContent()); + nsCOMPtr<nsIContent> curNode = arrayOfNodes[i]->AsContent(); // Ignore all non-editable nodes. Leave them be. NS_ENSURE_STATE(mHTMLEditor); if (!mHTMLEditor->IsEditable(curNode)) continue; curParent = curNode->GetParentNode(); int32_t offset = curParent ? curParent->IndexOf(curNode) : -1; @@ -4096,74 +4035,68 @@ nsHTMLEditRules::WillOutdent(Selection* { NS_ENSURE_STATE(mHTMLEditor); nsAutoSelectionReset selectionResetter(aSelection, mHTMLEditor); // convert the selection ranges into "promoted" selection ranges: // this basically just expands the range to include the immediate // block parent, and then further expands to include any ancestors // whose children are all in the range - nsCOMArray<nsIDOMNode> arrayOfNodes; - res = GetNodesFromSelection(aSelection, EditAction::outdent, + nsTArray<OwningNonNull<nsINode>> arrayOfNodes; + res = GetNodesFromSelection(*aSelection, EditAction::outdent, arrayOfNodes); NS_ENSURE_SUCCESS(res, res); // Ok, now go through all the nodes and remove a level of blockquoting, // or whatever is appropriate. Wohoo! nsCOMPtr<nsIDOMNode> curBlockQuote, firstBQChild, lastBQChild; bool curBlockQuoteIsIndentedWithCSS = false; - int32_t listCount = arrayOfNodes.Count(); - int32_t i; - for (i=0; i<listCount; i++) - { + for (auto& curNode : arrayOfNodes) { // here's where we actually figure out what to do - nsCOMPtr<nsIDOMNode> curNode = arrayOfNodes[i]; - nsCOMPtr<nsINode> curNode_ = do_QueryInterface(curNode); - NS_ENSURE_STATE(curNode_); - nsCOMPtr<nsINode> curParent = curNode_->GetParentNode(); - int32_t offset = curParent ? curParent->IndexOf(curNode_) : -1; + nsCOMPtr<nsINode> curParent = curNode->GetParentNode(); + int32_t offset = curParent ? curParent->IndexOf(curNode) : -1; // is it a blockquote? - if (nsHTMLEditUtils::IsBlockquote(curNode)) - { + if (curNode->IsHTMLElement(nsGkAtoms::blockquote)) { // if it is a blockquote, remove it. // So we need to finish up dealng with any curBlockQuote first. if (curBlockQuote) { res = OutdentPartOfBlock(curBlockQuote, firstBQChild, lastBQChild, curBlockQuoteIsIndentedWithCSS, address_of(rememberedLeftBQ), address_of(rememberedRightBQ)); NS_ENSURE_SUCCESS(res, res); curBlockQuote = 0; firstBQChild = 0; lastBQChild = 0; curBlockQuoteIsIndentedWithCSS = false; } NS_ENSURE_STATE(mHTMLEditor); - res = mHTMLEditor->RemoveBlockContainer(curNode); + res = mHTMLEditor->RemoveBlockContainer(GetAsDOMNode(curNode)); NS_ENSURE_SUCCESS(res, res); continue; } // is it a block with a 'margin' property? - if (useCSS && IsBlockNode(curNode)) - { + if (useCSS && IsBlockNode(GetAsDOMNode(curNode))) { NS_ENSURE_STATE(mHTMLEditor); - nsIAtom* marginProperty = MarginPropertyAtomForIndent(mHTMLEditor->mHTMLCSSUtils, curNode); + nsIAtom* marginProperty = + MarginPropertyAtomForIndent(mHTMLEditor->mHTMLCSSUtils, + GetAsDOMNode(curNode)); nsAutoString value; NS_ENSURE_STATE(mHTMLEditor); - mHTMLEditor->mHTMLCSSUtils->GetSpecifiedProperty(*curNode_, + mHTMLEditor->mHTMLCSSUtils->GetSpecifiedProperty(*curNode, *marginProperty, value); float f; nsCOMPtr<nsIAtom> unit; NS_ENSURE_STATE(mHTMLEditor); mHTMLEditor->mHTMLCSSUtils->ParseLength(value, &f, getter_AddRefs(unit)); if (f > 0) { - RelativeChangeIndentationOfElementNode(curNode, -1); + RelativeChangeIndentationOfElementNode(GetAsDOMNode(curNode), -1); continue; } } // is it a list item? if (nsHTMLEditUtils::IsListItem(curNode)) { // if it is a list item, that means we are not outdenting whole list. // So we need to finish up dealing with any curBlockQuote, and then @@ -4174,27 +4107,27 @@ nsHTMLEditRules::WillOutdent(Selection* curBlockQuoteIsIndentedWithCSS, address_of(rememberedLeftBQ), address_of(rememberedRightBQ)); NS_ENSURE_SUCCESS(res, res); curBlockQuote = 0; firstBQChild = 0; lastBQChild = 0; curBlockQuoteIsIndentedWithCSS = false; } bool bOutOfList; - res = PopListItem(curNode, &bOutOfList); + res = PopListItem(GetAsDOMNode(curNode), &bOutOfList); NS_ENSURE_SUCCESS(res, res); continue; } // do we have a blockquote that we are already committed to removing? if (curBlockQuote) { // if so, is this node a descendant? - if (nsEditorUtils::IsDescendantOf(curNode, curBlockQuote)) - { - lastBQChild = curNode; + if (nsEditorUtils::IsDescendantOf(GetAsDOMNode(curNode), + curBlockQuote)) { + lastBQChild = GetAsDOMNode(curNode); continue; // then we don't need to do anything different for this node } else { // otherwise, we have progressed beyond end of curBlockQuote, // so lets handle it now. We need to remove the portion of // curBlockQuote that contains [firstBQChild - lastBQChild]. res = OutdentPartOfBlock(curBlockQuote, firstBQChild, lastBQChild, @@ -4204,77 +4137,76 @@ nsHTMLEditRules::WillOutdent(Selection* NS_ENSURE_SUCCESS(res, res); curBlockQuote = 0; firstBQChild = 0; lastBQChild = 0; curBlockQuoteIsIndentedWithCSS = false; // fall out and handle curNode } } // are we inside a blockquote? - nsCOMPtr<nsINode> n = curNode_; + nsCOMPtr<nsINode> n = curNode; curBlockQuoteIsIndentedWithCSS = false; // keep looking up the hierarchy as long as we don't hit the body or the // active editing host or a table element (other than an entire table) while (!n->IsHTMLElement(nsGkAtoms::body) && mHTMLEditor && mHTMLEditor->IsDescendantOfEditorRoot(n) && (n->IsHTMLElement(nsGkAtoms::table) || !nsHTMLEditUtils::IsTableElement(n))) { if (!n->GetParentNode()) { break; } n = n->GetParentNode(); if (n->IsHTMLElement(nsGkAtoms::blockquote)) { // if so, remember it, and remember first node we are taking out of it. curBlockQuote = GetAsDOMNode(n); - firstBQChild = curNode; - lastBQChild = curNode; + firstBQChild = GetAsDOMNode(curNode); + lastBQChild = GetAsDOMNode(curNode); break; } else if (useCSS) { NS_ENSURE_STATE(mHTMLEditor); - nsIAtom* marginProperty = MarginPropertyAtomForIndent(mHTMLEditor->mHTMLCSSUtils, curNode); + nsIAtom* marginProperty = + MarginPropertyAtomForIndent(mHTMLEditor->mHTMLCSSUtils, + GetAsDOMNode(curNode)); nsAutoString value; NS_ENSURE_STATE(mHTMLEditor); mHTMLEditor->mHTMLCSSUtils->GetSpecifiedProperty(*n, *marginProperty, value); float f; nsCOMPtr<nsIAtom> unit; NS_ENSURE_STATE(mHTMLEditor); mHTMLEditor->mHTMLCSSUtils->ParseLength(value, &f, getter_AddRefs(unit)); if (f > 0 && !(nsHTMLEditUtils::IsList(curParent) && nsHTMLEditUtils::IsList(curNode))) { curBlockQuote = GetAsDOMNode(n); - firstBQChild = curNode; - lastBQChild = curNode; + firstBQChild = GetAsDOMNode(curNode); + lastBQChild = GetAsDOMNode(curNode); curBlockQuoteIsIndentedWithCSS = true; break; } } } if (!curBlockQuote) { // could not find an enclosing blockquote for this node. handle list cases. if (nsHTMLEditUtils::IsList(curParent)) // move node out of list { if (nsHTMLEditUtils::IsList(curNode)) // just unwrap this sublist { NS_ENSURE_STATE(mHTMLEditor); - res = mHTMLEditor->RemoveBlockContainer(curNode); + res = mHTMLEditor->RemoveBlockContainer(GetAsDOMNode(curNode)); NS_ENSURE_SUCCESS(res, res); } // handled list item case above } else if (nsHTMLEditUtils::IsList(curNode)) // node is a list, but parent is non-list: move list items out { - nsCOMPtr<nsIDOMNode> childDOM; - curNode->GetLastChild(getter_AddRefs(childDOM)); - nsCOMPtr<nsIContent> child = do_QueryInterface(childDOM); - NS_ENSURE_STATE(!childDOM || child); + nsCOMPtr<nsIContent> child = curNode->GetLastChild(); while (child) { if (nsHTMLEditUtils::IsListItem(child)) { bool bOutOfList; res = PopListItem(GetAsDOMNode(child), &bOutOfList); NS_ENSURE_SUCCESS(res, res); } @@ -4291,23 +4223,21 @@ nsHTMLEditRules::WillOutdent(Selection* } else { // delete any non- list items for now NS_ENSURE_STATE(mHTMLEditor); res = mHTMLEditor->DeleteNode(child); NS_ENSURE_SUCCESS(res, res); } - curNode->GetLastChild(getter_AddRefs(childDOM)); - child = do_QueryInterface(childDOM); - NS_ENSURE_STATE(!childDOM || child); + child = curNode->GetLastChild(); } // delete the now-empty list NS_ENSURE_STATE(mHTMLEditor); - res = mHTMLEditor->RemoveBlockContainer(curNode); + res = mHTMLEditor->RemoveBlockContainer(GetAsDOMNode(curNode)); NS_ENSURE_SUCCESS(res, res); } else if (useCSS) { nsCOMPtr<nsIDOMElement> element; nsCOMPtr<nsIDOMText> textNode = do_QueryInterface(curNode); if (textNode) { // We want to outdent the parent of text nodes nsCOMPtr<nsIDOMNode> parent; @@ -4361,38 +4291,31 @@ nsHTMLEditRules::WillOutdent(Selection* } } return NS_OK; } return res; } -/////////////////////////////////////////////////////////////////////////// -// RemovePartOfBlock: split aBlock and move aStartChild to aEndChild out -// of aBlock. return left side of block (if any) in -// aLeftNode. return right side of block (if any) in -// aRightNode. -// -nsresult -nsHTMLEditRules::RemovePartOfBlock(nsIDOMNode *aBlock, - nsIDOMNode *aStartChild, - nsIDOMNode *aEndChild, - nsCOMPtr<nsIDOMNode> *aLeftNode, - nsCOMPtr<nsIDOMNode> *aRightNode) -{ - nsCOMPtr<nsIDOMNode> middleNode; - nsresult res = SplitBlock(aBlock, aStartChild, aEndChild, - aLeftNode, aRightNode, - address_of(middleNode)); +/////////////////////////////////////////////////////////////////////////////// +// RemovePartOfBlock: Split aBlock and move aStartChild to aEndChild out of +// aBlock. +nsresult +nsHTMLEditRules::RemovePartOfBlock(Element& aBlock, + nsIContent& aStartChild, + nsIContent& aEndChild) +{ + nsresult res = SplitBlock(aBlock.AsDOMNode(), aStartChild.AsDOMNode(), + aEndChild.AsDOMNode()); NS_ENSURE_SUCCESS(res, res); - // get rid of part of blockquote we are outdenting + // Get rid of part of blockquote we are outdenting NS_ENSURE_STATE(mHTMLEditor); - return mHTMLEditor->RemoveBlockContainer(aBlock); + return mHTMLEditor->RemoveBlockContainer(aBlock.AsDOMNode()); } nsresult nsHTMLEditRules::SplitBlock(nsIDOMNode *aBlock, nsIDOMNode *aStartChild, nsIDOMNode *aEndChild, nsCOMPtr<nsIDOMNode> *aLeftNode, nsCOMPtr<nsIDOMNode> *aRightNode, @@ -4635,18 +4558,20 @@ nsHTMLEditRules::CreateStyleForInsertTex res = mHTMLEditor->RelativeFontChangeOnTextNode(dir, nodeAsText, 0, -1); NS_ENSURE_SUCCESS(res, res); } } while (item) { NS_ENSURE_STATE(mHTMLEditor); - res = mHTMLEditor->SetInlinePropertyOnNode(node, item->tag, &item->attr, - &item->value); + nsCOMPtr<nsIContent> content = do_QueryInterface(node); + NS_ENSURE_STATE(content || !node); + res = mHTMLEditor->SetInlinePropertyOnNode(*content, *item->tag, + &item->attr, item->value); NS_ENSURE_SUCCESS(res, res); item = mHTMLEditor->mTypeInState->TakeSetProperty(); } } if (weDidSomething) { return aSelection->Collapse(node, offset); } @@ -4700,31 +4625,30 @@ nsHTMLEditRules::WillAlign(Selection* aS NS_ENSURE_SUCCESS(res, res); nsAutoSelectionReset selectionResetter(aSelection, mHTMLEditor); // convert the selection ranges into "promoted" selection ranges: // this basically just expands the range to include the immediate // block parent, and then further expands to include any ancestors // whose children are all in the range *aHandled = true; - nsCOMArray<nsIDOMNode> arrayOfNodes; - res = GetNodesFromSelection(aSelection, EditAction::align, arrayOfNodes); + nsTArray<OwningNonNull<nsINode>> nodeArray; + res = GetNodesFromSelection(*aSelection, EditAction::align, nodeArray); NS_ENSURE_SUCCESS(res, res); // if we don't have any nodes, or we have only a single br, then we are // creating an empty alignment div. We have to do some different things for these. bool emptyDiv = false; - int32_t listCount = arrayOfNodes.Count(); + int32_t listCount = nodeArray.Length(); if (!listCount) emptyDiv = true; if (listCount == 1) { - nsCOMPtr<nsIDOMNode> theNode = arrayOfNodes[0]; - - if (nsHTMLEditUtils::SupportsAlignAttr(theNode)) - { + OwningNonNull<nsINode> theNode = nodeArray[0]; + + if (nsHTMLEditUtils::SupportsAlignAttr(GetAsDOMNode(theNode))) { // the node is a table element, an horiz rule, a paragraph, a div // or a section header; in HTML 4, it can directly carry the ALIGN // attribute and we don't need to make a div! If we are in CSS mode, // all the work is done in AlignBlock nsCOMPtr<nsIDOMElement> theElem = do_QueryInterface(theNode); res = AlignBlock(theElem, alignType, true); NS_ENSURE_SUCCESS(res, res); return NS_OK; @@ -4735,19 +4659,19 @@ nsHTMLEditRules::WillAlign(Selection* aS // The special case emptyDiv code (below) that consumes BRs can // cause tables to split if the start node of the selection is // not in a table cell or caption, for example parent is a <tr>. // Avoid this unnecessary splitting if possible by leaving emptyDiv // FALSE so that we fall through to the normal case alignment code. // // XXX: It seems a little error prone for the emptyDiv special // case code to assume that the start node of the selection - // is the parent of the single node in the arrayOfNodes, as + // is the parent of the single node in the nodeArray, as // the paragraph above points out. Do we rely on the selection - // start node because of the fact that arrayOfNodes can be empty? + // start node because of the fact that nodeArray can be empty? // We should probably revisit this issue. - kin nsCOMPtr<nsIDOMNode> parent; int32_t offset; NS_ENSURE_STATE(mHTMLEditor); res = mHTMLEditor->GetStartNodeAndOffset(aSelection, getter_AddRefs(parent), &offset); if (!nsHTMLEditUtils::IsTableElement(parent) || nsHTMLEditUtils::IsTableCellOrCaption(parent)) @@ -4806,28 +4730,27 @@ nsHTMLEditRules::WillAlign(Selection* aS selectionResetter.Abort(); // don't reset our selection in this case. return res; } // Next we detect all the transitions in the array, where a transition // means that adjacent nodes in the array don't have the same parent. nsTArray<bool> transitionList; - res = MakeTransitionList(arrayOfNodes, transitionList); - NS_ENSURE_SUCCESS(res, res); + MakeTransitionList(nodeArray, transitionList); // Ok, now go through all the nodes and give them an align attrib or put them in a div, // or whatever is appropriate. Wohoo! nsCOMPtr<nsINode> curParent; nsCOMPtr<Element> curDiv; bool useCSS = mHTMLEditor->IsCSSEnabled(); for (int32_t i = 0; i < listCount; ++i) { // here's where we actually figure out what to do - nsCOMPtr<nsIDOMNode> curNode = arrayOfNodes[i]; + nsCOMPtr<nsIDOMNode> curNode = nodeArray[i]->AsDOMNode(); nsCOMPtr<nsIContent> curContent = do_QueryInterface(curNode); NS_ENSURE_STATE(curContent); // Ignore all non-editable nodes. Leave them be. if (!mHTMLEditor->IsEditable(curNode)) continue; curParent = curContent->GetParentNode(); int32_t offset = curParent ? curParent->IndexOf(curContent) : -1; @@ -4872,17 +4795,17 @@ nsHTMLEditRules::WillAlign(Selection* aS &attrName, alignType, &count, false); curDiv = 0; continue; } else if (nsHTMLEditUtils::IsList(curParent)) { // if we don't use CSS, add a contraint to list element : they have // to be inside another list, ie >= second level of nesting - res = AlignInnerBlocks(curNode, alignType); + res = AlignInnerBlocks(*curContent, alignType); NS_ENSURE_SUCCESS(res, res); curDiv = 0; continue; } // clear out curDiv so that we don't put nodes after this one into it } // need to make a div to put things in if we haven't already, @@ -4915,47 +4838,37 @@ nsHTMLEditRules::WillAlign(Selection* aS res = mHTMLEditor->MoveNode(curContent, curDiv, -1); NS_ENSURE_SUCCESS(res, res); } return res; } -/////////////////////////////////////////////////////////////////////////// -// AlignInnerBlocks: align inside table cells or list items -// +/////////////////////////////////////////////////////////////////////////////// +// AlignInnerBlocks: Align inside table cells or list items +// nsresult -nsHTMLEditRules::AlignInnerBlocks(nsIDOMNode *aNode, const nsAString *alignType) -{ - NS_ENSURE_TRUE(aNode && alignType, NS_ERROR_NULL_POINTER); - nsresult res; - - // gather list of table cells or list items - nsCOMArray<nsIDOMNode> arrayOfNodes; +nsHTMLEditRules::AlignInnerBlocks(nsINode& aNode, const nsAString* alignType) +{ + NS_ENSURE_TRUE(alignType, NS_ERROR_NULL_POINTER); + + // Gather list of table cells or list items + nsTArray<OwningNonNull<nsINode>> nodeArray; nsTableCellAndListItemFunctor functor; - nsDOMIterator iter; - res = iter.Init(aNode); - NS_ENSURE_SUCCESS(res, res); - res = iter.AppendList(functor, arrayOfNodes); - NS_ENSURE_SUCCESS(res, res); - - // now that we have the list, align their contents as requested - int32_t listCount = arrayOfNodes.Count(); - int32_t j; - - for (j = 0; j < listCount; j++) - { - nsIDOMNode* node = arrayOfNodes[0]; - res = AlignBlockContents(node, alignType); + nsDOMIterator iter(aNode); + iter.AppendList(functor, nodeArray); + + // Now that we have the list, align their contents as requested + for (auto& node : nodeArray) { + nsresult res = AlignBlockContents(node->AsDOMNode(), alignType); NS_ENSURE_SUCCESS(res, res); - arrayOfNodes.RemoveObjectAt(0); - } - - return res; + } + + return NS_OK; } /////////////////////////////////////////////////////////////////////////// // AlignBlockContents: align contents of a block element // nsresult nsHTMLEditRules::AlignBlockContents(nsIDOMNode *aNode, const nsAString *alignType) @@ -5153,54 +5066,42 @@ nsHTMLEditRules::CheckForInvisibleBR(nsI *outBRNode = GetAsDOMNode(wsTester.mStartReasonNode); } } return NS_OK; } -/////////////////////////////////////////////////////////////////////////// -// GetInnerContent: aList and aTbl allow the caller to specify what kind -// of content to "look inside". If aTbl is true, look inside -// any table content, and insert the inner content into the -// supplied issupportsarray at offset aIndex. -// Similarly with aList and list content. -// aIndex is updated to point past inserted elements. -// -nsresult -nsHTMLEditRules::GetInnerContent(nsIDOMNode *aNode, nsCOMArray<nsIDOMNode> &outArrayOfNodes, - int32_t *aIndex, bool aList, bool aTbl) -{ - nsCOMPtr<nsINode> aNode_ = do_QueryInterface(aNode); - NS_ENSURE_TRUE(aNode_ && aIndex, NS_ERROR_NULL_POINTER); - - nsCOMPtr<nsIDOMNode> node = - GetAsDOMNode(mHTMLEditor->GetFirstEditableChild(*aNode_)); - nsresult res = NS_OK; - while (NS_SUCCEEDED(res) && node) - { - if ( ( aList && (nsHTMLEditUtils::IsList(node) || - nsHTMLEditUtils::IsListItem(node) ) ) - || ( aTbl && nsHTMLEditUtils::IsTableElement(node) ) ) - { - res = GetInnerContent(node, outArrayOfNodes, aIndex, aList, aTbl); - NS_ENSURE_SUCCESS(res, res); - } - else - { - outArrayOfNodes.InsertObjectAt(node, *aIndex); +//////////////////////////////////////////////////////////////////////////////// +// GetInnerContent: aLists and aTables allow the caller to specify what kind of +// content to "look inside". If aTables is Tables::yes, look +// inside any table content, and insert the inner content into +// the supplied issupportsarray at offset aIndex. Similarly +// with aLists and list content. aIndex is updated to point +// past inserted elements. +// +void +nsHTMLEditRules::GetInnerContent(nsINode& aNode, + nsTArray<OwningNonNull<nsINode>>& aOutArrayOfNodes, + int32_t* aIndex, Lists aLists, Tables aTables) +{ + MOZ_ASSERT(aIndex); + + for (nsCOMPtr<nsIContent> node = mHTMLEditor->GetFirstEditableChild(aNode); + node; node = node->GetNextSibling()) { + if ((aLists == Lists::yes && (nsHTMLEditUtils::IsList(node) || + nsHTMLEditUtils::IsListItem(node))) || + (aTables == Tables::yes && nsHTMLEditUtils::IsTableElement(node))) { + GetInnerContent(*node, aOutArrayOfNodes, aIndex, aLists, aTables); + } else { + aOutArrayOfNodes.InsertElementAt(*aIndex, *node); (*aIndex)++; } - nsCOMPtr<nsIDOMNode> tmp; - res = node->GetNextSibling(getter_AddRefs(tmp)); - node = tmp; - } - - return res; + } } /////////////////////////////////////////////////////////////////////////// // ExpandSelectionForDeletion: this promotes our selection to include blocks // that have all their children selected. // nsresult nsHTMLEditRules::ExpandSelectionForDeletion(Selection* aSelection) @@ -5713,491 +5614,384 @@ nsHTMLEditRules::GetPromotedPoint(RulesE NS_ENSURE_TRUE(mHTMLEditor, /* void */); nearNode = mHTMLEditor->GetNextHTMLNode(node, offset, true); } *outNode = node->AsDOMNode(); *outOffset = offset; } -/////////////////////////////////////////////////////////////////////////// -// GetPromotedRanges: run all the selection range endpoint through +/////////////////////////////////////////////////////////////////////////////// +// GetPromotedRanges: Run all the selection range endpoint through // GetPromotedPoint() -// -nsresult -nsHTMLEditRules::GetPromotedRanges(Selection* inSelection, - nsTArray<nsRefPtr<nsRange>>& outArrayOfRanges, +// +void +nsHTMLEditRules::GetPromotedRanges(Selection& aSelection, + nsTArray<nsRefPtr<nsRange>>& outArrayOfRanges, EditAction inOperationType) { - NS_ENSURE_TRUE(inSelection, NS_ERROR_NULL_POINTER); - - int32_t rangeCount; - nsresult res = inSelection->GetRangeCount(&rangeCount); - NS_ENSURE_SUCCESS(res, res); - - int32_t i; - nsRefPtr<nsRange> selectionRange; - nsRefPtr<nsRange> opRange; - - for (i = 0; i < rangeCount; i++) - { - selectionRange = inSelection->GetRangeAt(i); - NS_ENSURE_STATE(selectionRange); - - // clone range so we don't muck with actual selection ranges - opRange = selectionRange->CloneRange(); - - // make a new adjusted range to represent the appropriate block content. - // The basic idea is to push out the range endpoints - // to truly enclose the blocks that we will affect. - // This call alters opRange. - res = PromoteRange(opRange, inOperationType); - NS_ENSURE_SUCCESS(res, res); - - // stuff new opRange into array + uint32_t rangeCount = aSelection.RangeCount(); + + for (uint32_t i = 0; i < rangeCount; i++) { + nsRefPtr<nsRange> selectionRange = aSelection.GetRangeAt(i); + MOZ_ASSERT(selectionRange); + + // Clone range so we don't muck with actual selection ranges + nsRefPtr<nsRange> opRange = selectionRange->CloneRange(); + + // Make a new adjusted range to represent the appropriate block content. + // The basic idea is to push out the range endpoints to truly enclose the + // blocks that we will affect. This call alters opRange. + PromoteRange(*opRange, inOperationType); + + // Stuff new opRange into array outArrayOfRanges.AppendElement(opRange); } - return res; -} - - -/////////////////////////////////////////////////////////////////////////// -// PromoteRange: expand a range to include any parents for which all -// editable children are already in range. -// -nsresult -nsHTMLEditRules::PromoteRange(nsRange* inRange, EditAction inOperationType) -{ - NS_ENSURE_TRUE(inRange, NS_ERROR_NULL_POINTER); - nsresult res; - nsCOMPtr<nsIDOMNode> startNode, endNode; - int32_t startOffset, endOffset; - - res = inRange->GetStartContainer(getter_AddRefs(startNode)); - NS_ENSURE_SUCCESS(res, res); - res = inRange->GetStartOffset(&startOffset); - NS_ENSURE_SUCCESS(res, res); - res = inRange->GetEndContainer(getter_AddRefs(endNode)); - NS_ENSURE_SUCCESS(res, res); - res = inRange->GetEndOffset(&endOffset); - NS_ENSURE_SUCCESS(res, res); - +} + + +/////////////////////////////////////////////////////////////////////////////// +// PromoteRange: Expand a range to include any parents for which all editable +// children are already in range. +// +void +nsHTMLEditRules::PromoteRange(nsRange& aRange, EditAction aOperationType) +{ + NS_ENSURE_TRUE(mHTMLEditor, ); + nsCOMPtr<nsIEditor> kungFuDeathGrip(mHTMLEditor); + + nsCOMPtr<nsINode> startNode = aRange.GetStartParent(); + nsCOMPtr<nsINode> endNode = aRange.GetEndParent(); + int32_t startOffset = aRange.StartOffset(); + int32_t endOffset = aRange.EndOffset(); + // MOOSE major hack: // GetPromotedPoint doesn't really do the right thing for collapsed ranges // inside block elements that contain nothing but a solo <br>. It's easier // to put a workaround here than to revamp GetPromotedPoint. :-( - if ( (startNode == endNode) && (startOffset == endOffset)) - { - nsCOMPtr<nsIDOMNode> block; - if (IsBlockNode(startNode)) { - block = startNode; + if (startNode == endNode && startOffset == endOffset) { + nsCOMPtr<Element> block; + if (IsBlockNode(GetAsDOMNode(startNode))) { + block = startNode->AsElement(); } else { - NS_ENSURE_STATE(mHTMLEditor); block = mHTMLEditor->GetBlockNodeParent(startNode); } - if (block) - { + if (block) { bool bIsEmptyNode = false; - // check for the editing host - NS_ENSURE_STATE(mHTMLEditor); - nsIContent *rootContent = mHTMLEditor->GetActiveEditingHost(); - nsCOMPtr<nsINode> rootNode = do_QueryInterface(rootContent); - nsCOMPtr<nsINode> blockNode = do_QueryInterface(block); - NS_ENSURE_TRUE(rootNode && blockNode, NS_ERROR_UNEXPECTED); + nsCOMPtr<nsIContent> root = mHTMLEditor->GetActiveEditingHost(); // Make sure we don't go higher than our root element in the content tree - if (!nsContentUtils::ContentIsDescendantOf(rootNode, blockNode)) - { - NS_ENSURE_STATE(mHTMLEditor); - res = mHTMLEditor->IsEmptyNode(block, &bIsEmptyNode, true, false); - } - if (bIsEmptyNode) - { - uint32_t numChildren; - nsEditor::GetLengthOfDOMNode(block, numChildren); + NS_ENSURE_TRUE(root, ); + if (!nsContentUtils::ContentIsDescendantOf(root, block)) { + mHTMLEditor->IsEmptyNode(block, &bIsEmptyNode, true, false); + } + if (bIsEmptyNode) { startNode = block; endNode = block; startOffset = 0; - endOffset = numChildren; - } - } - } - - // make a new adjusted range to represent the appropriate block content. - // this is tricky. the basic idea is to push out the range endpoints - // to truly enclose the blocks that we will affect - + endOffset = block->Length(); + } + } + } + + // Make a new adjusted range to represent the appropriate block content. + // 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; int32_t opStartOffset, opEndOffset; nsRefPtr<nsRange> opRange; - - GetPromotedPoint(kStart, startNode, startOffset, inOperationType, - address_of(opStartNode), &opStartOffset); - GetPromotedPoint(kEnd, endNode, endOffset, inOperationType, + + GetPromotedPoint(kStart, GetAsDOMNode(startNode), startOffset, + aOperationType, address_of(opStartNode), &opStartOffset); + GetPromotedPoint(kEnd, GetAsDOMNode(endNode), endOffset, aOperationType, address_of(opEndNode), &opEndOffset); // Make sure that the new range ends up to be in the editable section. - NS_ENSURE_STATE(mHTMLEditor); - if (!mHTMLEditor->IsDescendantOfEditorRoot(nsEditor::GetNodeAtRangeOffsetPoint(opStartNode, opStartOffset)) || - !mHTMLEditor || // Check again, since it may have gone away - !mHTMLEditor->IsDescendantOfEditorRoot(nsEditor::GetNodeAtRangeOffsetPoint(opEndNode, opEndOffset - 1))) { - NS_ENSURE_STATE(mHTMLEditor); - return NS_OK; - } - - res = inRange->SetStart(opStartNode, opStartOffset); - NS_ENSURE_SUCCESS(res, res); - res = inRange->SetEnd(opEndNode, opEndOffset); - return res; -} + if (!mHTMLEditor->IsDescendantOfEditorRoot( + nsEditor::GetNodeAtRangeOffsetPoint(opStartNode, opStartOffset)) || + !mHTMLEditor->IsDescendantOfEditorRoot( + nsEditor::GetNodeAtRangeOffsetPoint(opEndNode, opEndOffset - 1))) { + return; + } + + DebugOnly<nsresult> res = aRange.SetStart(opStartNode, opStartOffset); + MOZ_ASSERT(NS_SUCCEEDED(res)); + res = aRange.SetEnd(opEndNode, opEndOffset); + MOZ_ASSERT(NS_SUCCEEDED(res)); +} class nsUniqueFunctor : public nsBoolDomIterFunctor { public: - explicit nsUniqueFunctor(nsCOMArray<nsIDOMNode> &aArray) : mArray(aArray) + explicit nsUniqueFunctor(nsTArray<OwningNonNull<nsINode>> &aArray) : mArray(aArray) { } - virtual bool operator()(nsIDOMNode* aNode) // used to build list of all nodes iterator covers + // used to build list of all nodes iterator covers + virtual bool operator()(nsINode* aNode) const { - return mArray.IndexOf(aNode) < 0; + return !mArray.Contains(aNode); } private: - nsCOMArray<nsIDOMNode> &mArray; + nsTArray<OwningNonNull<nsINode>>& mArray; }; -/////////////////////////////////////////////////////////////////////////// -// GetNodesForOperation: run through the ranges in the array and construct -// a new array of nodes to be acted on. -// -nsresult -nsHTMLEditRules::GetNodesForOperation(nsTArray<nsRefPtr<nsRange>>& inArrayOfRanges, - nsCOMArray<nsIDOMNode>& outArrayOfNodes, - EditAction inOperationType, - bool aDontTouchContent) -{ - int32_t rangeCount = inArrayOfRanges.Length(); - - int32_t i; - nsRefPtr<nsRange> opRange; - - nsresult res = NS_OK; - - // bust up any inlines that cross our range endpoints, - // but only if we are allowed to touch content. - - if (!aDontTouchContent) - { - nsTArray<nsRefPtr<nsRangeStore>> rangeItemArray; +/////////////////////////////////////////////////////////////////////////////// +// GetNodesForOperation: Run through the ranges in the array and construct a +// new array of nodes to be acted on. +// +nsresult +nsHTMLEditRules::GetNodesForOperation(nsTArray<nsRefPtr<nsRange>>& aArrayOfRanges, + nsTArray<OwningNonNull<nsINode>>& aOutArrayOfNodes, + EditAction aOperationType, + TouchContent aTouchContent) +{ + NS_ENSURE_STATE(mHTMLEditor); + nsCOMPtr<nsIEditor> kungFuDeathGrip(mHTMLEditor); + + int32_t rangeCount = aArrayOfRanges.Length(); + nsresult res; + + // Bust up any inlines that cross our range endpoints, but only if we are + // allowed to touch content. + + if (aTouchContent == TouchContent::yes) { + nsTArray<OwningNonNull<nsRangeStore>> rangeItemArray; rangeItemArray.AppendElements(rangeCount); - NS_ASSERTION(static_cast<uint32_t>(rangeCount) == rangeItemArray.Length(), - "How did that happen?"); - - // first register ranges for special editor gravity - for (i = 0; i < rangeCount; i++) - { - opRange = inArrayOfRanges[0]; + // First register ranges for special editor gravity + for (int32_t i = 0; i < rangeCount; i++) { rangeItemArray[i] = new nsRangeStore(); - rangeItemArray[i]->StoreRange(opRange); - NS_ENSURE_STATE(mHTMLEditor); + rangeItemArray[i]->StoreRange(aArrayOfRanges[0]); mHTMLEditor->mRangeUpdater.RegisterRangeItem(rangeItemArray[i]); - inArrayOfRanges.RemoveElementAt(0); - } - // now bust up inlines. Safe to start at rangeCount-1, since we - // asserted we have enough items above. - for (i = rangeCount-1; i >= 0 && NS_SUCCEEDED(res); i--) - { - res = BustUpInlinesAtRangeEndpoints(*rangeItemArray[i]); - } - // then unregister the ranges - for (i = 0; i < rangeCount; i++) - { - nsRangeStore* item = rangeItemArray[i]; - NS_ENSURE_STATE(mHTMLEditor); + aArrayOfRanges.RemoveElementAt(0); + } + // Now bust up inlines. + for (auto& item : Reversed(rangeItemArray)) { + res = BustUpInlinesAtRangeEndpoints(*item); + if (NS_FAILED(res)) { + break; + } + } + // Then unregister the ranges + for (auto& item : rangeItemArray) { mHTMLEditor->mRangeUpdater.DropRangeItem(item); - opRange = item->GetRange(); - inArrayOfRanges.AppendElement(opRange); + aArrayOfRanges.AppendElement(item->GetRange()); } NS_ENSURE_SUCCESS(res, res); } - // gather up a list of all the nodes - for (i = 0; i < rangeCount; i++) - { - opRange = inArrayOfRanges[i]; - - nsDOMSubtreeIterator iter; - res = iter.Init(opRange); - NS_ENSURE_SUCCESS(res, res); - if (outArrayOfNodes.Count() == 0) { - nsTrivialFunctor functor; - res = iter.AppendList(functor, outArrayOfNodes); - NS_ENSURE_SUCCESS(res, res); - } - else { - // We don't want duplicates in outArrayOfNodes, so we use an + // Gather up a list of all the nodes + for (auto& range : aArrayOfRanges) { + nsDOMSubtreeIterator iter(*range); + if (aOutArrayOfNodes.Length() == 0) { + iter.AppendList(nsTrivialFunctor(), aOutArrayOfNodes); + } else { + // We don't want duplicates in aOutArrayOfNodes, so we use an // iterator/functor that only return nodes that are not already in - // outArrayOfNodes. - nsCOMArray<nsIDOMNode> nodes; - nsUniqueFunctor functor(outArrayOfNodes); - res = iter.AppendList(functor, nodes); - NS_ENSURE_SUCCESS(res, res); - if (!outArrayOfNodes.AppendObjects(nodes)) - return NS_ERROR_OUT_OF_MEMORY; - } - } - - // certain operations should not act on li's and td's, but rather inside - // them. alter the list as needed - if (inOperationType == EditAction::makeBasicBlock) { - int32_t listCount = outArrayOfNodes.Count(); - for (i=listCount-1; i>=0; i--) - { - nsCOMPtr<nsIDOMNode> node = outArrayOfNodes[i]; - if (nsHTMLEditUtils::IsListItem(node)) - { - int32_t j=i; - outArrayOfNodes.RemoveObjectAt(i); - res = GetInnerContent(node, outArrayOfNodes, &j); - NS_ENSURE_SUCCESS(res, res); - } - } - } - // indent/outdent already do something special for list items, but - // we still need to make sure we don't act on table elements - else if (inOperationType == EditAction::outdent || - inOperationType == EditAction::indent || - inOperationType == EditAction::setAbsolutePosition) { - int32_t listCount = outArrayOfNodes.Count(); - for (i=listCount-1; i>=0; i--) - { - nsCOMPtr<nsIDOMNode> node = outArrayOfNodes[i]; - if (nsHTMLEditUtils::IsTableElementButNotTable(node)) - { - int32_t j=i; - outArrayOfNodes.RemoveObjectAt(i); - res = GetInnerContent(node, outArrayOfNodes, &j); + // aOutArrayOfNodes. + nsTArray<OwningNonNull<nsINode>> nodes; + iter.AppendList(nsUniqueFunctor(aOutArrayOfNodes), nodes); + aOutArrayOfNodes.AppendElements(nodes); + } + } + + // Certain operations should not act on li's and td's, but rather inside + // them. Alter the list as needed. + if (aOperationType == EditAction::makeBasicBlock) { + for (int32_t i = aOutArrayOfNodes.Length() - 1; i >= 0; i--) { + OwningNonNull<nsINode> node = aOutArrayOfNodes[i]; + if (nsHTMLEditUtils::IsListItem(node)) { + int32_t j = i; + aOutArrayOfNodes.RemoveElementAt(i); + GetInnerContent(*node, aOutArrayOfNodes, &j); + } + } + // Indent/outdent already do something special for list items, but we still + // need to make sure we don't act on table elements + } else if (aOperationType == EditAction::outdent || + aOperationType == EditAction::indent || + aOperationType == EditAction::setAbsolutePosition) { + for (int32_t i = aOutArrayOfNodes.Length() - 1; i >= 0; i--) { + OwningNonNull<nsINode> node = aOutArrayOfNodes[i]; + if (nsHTMLEditUtils::IsTableElementButNotTable(node)) { + int32_t j = i; + aOutArrayOfNodes.RemoveElementAt(i); + GetInnerContent(*node, aOutArrayOfNodes, &j); + } + } + } + // Outdent should look inside of divs. + if (aOperationType == EditAction::outdent && + !mHTMLEditor->IsCSSEnabled()) { + for (int32_t i = aOutArrayOfNodes.Length() - 1; i >= 0; i--) { + OwningNonNull<nsINode> node = aOutArrayOfNodes[i]; + if (node->IsHTMLElement(nsGkAtoms::div)) { + int32_t j = i; + aOutArrayOfNodes.RemoveElementAt(i); + GetInnerContent(*node, aOutArrayOfNodes, &j, Lists::no, Tables::no); + } + } + } + + + // Post-process the list to break up inline containers that contain br's, but + // only for operations that might care, like making lists or paragraphs + if (aOperationType == EditAction::makeBasicBlock || + aOperationType == EditAction::makeList || + aOperationType == EditAction::align || + aOperationType == EditAction::setAbsolutePosition || + aOperationType == EditAction::indent || + aOperationType == EditAction::outdent) { + for (int32_t i = aOutArrayOfNodes.Length() - 1; i >= 0; i--) { + OwningNonNull<nsINode> node = aOutArrayOfNodes[i]; + if (aTouchContent == TouchContent::yes && + IsInlineNode(GetAsDOMNode(node)) && mHTMLEditor->IsContainer(node) && + !mHTMLEditor->IsTextNode(node)) { + nsTArray<OwningNonNull<nsINode>> arrayOfInlines; + res = BustUpInlinesAtBRs(*node, arrayOfInlines); NS_ENSURE_SUCCESS(res, res); - } - } - } - // outdent should look inside of divs. - if (inOperationType == EditAction::outdent && - (!mHTMLEditor || !mHTMLEditor->IsCSSEnabled())) { - NS_ENSURE_STATE(mHTMLEditor); - int32_t listCount = outArrayOfNodes.Count(); - for (i=listCount-1; i>=0; i--) - { - nsCOMPtr<nsIDOMNode> node = outArrayOfNodes[i]; - if (nsHTMLEditUtils::IsDiv(node)) - { - int32_t j=i; - outArrayOfNodes.RemoveObjectAt(i); - res = GetInnerContent(node, outArrayOfNodes, &j, false, false); - NS_ENSURE_SUCCESS(res, res); - } - } - } - - - // post process the list to break up inline containers that contain br's. - // but only for operations that might care, like making lists or para's... - if (inOperationType == EditAction::makeBasicBlock || - inOperationType == EditAction::makeList || - inOperationType == EditAction::align || - inOperationType == EditAction::setAbsolutePosition || - inOperationType == EditAction::indent || - inOperationType == EditAction::outdent) { - int32_t listCount = outArrayOfNodes.Count(); - for (i=listCount-1; i>=0; i--) - { - nsCOMPtr<nsIDOMNode> node = outArrayOfNodes[i]; - if (!aDontTouchContent && IsInlineNode(node) && - (!mHTMLEditor || mHTMLEditor->IsContainer(node)) && - (!mHTMLEditor || !mHTMLEditor->IsTextNode(node))) - { - NS_ENSURE_STATE(mHTMLEditor); - nsCOMArray<nsIDOMNode> arrayOfInlines; - res = BustUpInlinesAtBRs(node, arrayOfInlines); - NS_ENSURE_SUCCESS(res, res); - // put these nodes in outArrayOfNodes, replacing the current node - outArrayOfNodes.RemoveObjectAt(i); - outArrayOfNodes.InsertObjectsAt(arrayOfInlines, i); - } - } - } - return res; -} - - - -/////////////////////////////////////////////////////////////////////////// -// GetChildNodesForOperation: -// -nsresult -nsHTMLEditRules::GetChildNodesForOperation(nsIDOMNode *inNode, - nsCOMArray<nsIDOMNode>& outArrayOfNodes) -{ - nsCOMPtr<nsINode> node = do_QueryInterface(inNode); - NS_ENSURE_TRUE(node, NS_ERROR_NULL_POINTER); - - for (nsIContent* child = node->GetFirstChild(); - child; - child = child->GetNextSibling()) { - nsIDOMNode* childNode = child->AsDOMNode(); - if (!outArrayOfNodes.AppendObject(childNode)) { - return NS_ERROR_FAILURE; + + // Put these nodes in aOutArrayOfNodes, replacing the current node + aOutArrayOfNodes.RemoveElementAt(i); + aOutArrayOfNodes.InsertElementsAt(i, arrayOfInlines); + } } } return NS_OK; } - -/////////////////////////////////////////////////////////////////////////// -// GetListActionNodes: -// -nsresult -nsHTMLEditRules::GetListActionNodes(nsCOMArray<nsIDOMNode> &outArrayOfNodes, - bool aEntireList, - bool aDontTouchContent) -{ - nsresult res = NS_OK; - +void +nsHTMLEditRules::GetChildNodesForOperation(nsINode& aNode, + nsTArray<OwningNonNull<nsINode>>& outArrayOfNodes) +{ + for (nsCOMPtr<nsIContent> child = aNode.GetFirstChild(); + child; child = child->GetNextSibling()) { + outArrayOfNodes.AppendElement(*child); + } +} + + +nsresult +nsHTMLEditRules::GetListActionNodes(nsTArray<OwningNonNull<nsINode>>& aOutArrayOfNodes, + EntireList aEntireList, + TouchContent aTouchContent) +{ NS_ENSURE_STATE(mHTMLEditor); + nsCOMPtr<nsIEditor> kungFuDeathGrip(mHTMLEditor); + nsRefPtr<Selection> selection = mHTMLEditor->GetSelection(); NS_ENSURE_TRUE(selection, NS_ERROR_FAILURE); - // added this in so that ui code can ask to change an entire list, even if selection - // is only in part of it. used by list item dialog. - if (aEntireList) - { + + // Added this in so that ui code can ask to change an entire list, even if + // selection is only in part of it. used by list item dialog. + if (aEntireList == EntireList::yes) { uint32_t rangeCount = selection->RangeCount(); for (uint32_t rangeIdx = 0; rangeIdx < rangeCount; ++rangeIdx) { nsRefPtr<nsRange> range = selection->GetRangeAt(rangeIdx); - nsCOMPtr<nsIDOMNode> commonParent, parent, tmp; - range->GetCommonAncestorContainer(getter_AddRefs(commonParent)); - if (commonParent) - { - parent = commonParent; - while (parent) - { - if (nsHTMLEditUtils::IsList(parent)) - { - outArrayOfNodes.AppendObject(parent); - break; - } - parent->GetParentNode(getter_AddRefs(tmp)); - parent = tmp; + for (nsCOMPtr<nsINode> parent = range->GetCommonAncestor(); + parent; parent = parent->GetParentNode()) { + if (nsHTMLEditUtils::IsList(parent)) { + aOutArrayOfNodes.AppendElement(*parent); + break; } } } - // if we didn't find any nodes this way, then try the normal way. perhaps the - // selection spans multiple lists but with no common list parent. - if (outArrayOfNodes.Count()) return NS_OK; + // If we didn't find any nodes this way, then try the normal way. Perhaps + // the selection spans multiple lists but with no common list parent. + if (aOutArrayOfNodes.Length()) { + return NS_OK; + } } { // We don't like other people messing with our selection! - NS_ENSURE_STATE(mHTMLEditor); nsAutoTxnsConserveSelection dontSpazMySelection(mHTMLEditor); // contruct a list of nodes to act on. - res = GetNodesFromSelection(selection, EditAction::makeList, - outArrayOfNodes, aDontTouchContent); + nsresult res = GetNodesFromSelection(*selection, EditAction::makeList, + aOutArrayOfNodes, aTouchContent); NS_ENSURE_SUCCESS(res, res); } - - // pre process our list of nodes... - int32_t listCount = outArrayOfNodes.Count(); - int32_t i; - for (i=listCount-1; i>=0; i--) - { - nsCOMPtr<nsIDOMNode> testNode = outArrayOfNodes[i]; + + // Pre-process our list of nodes + for (int32_t i = aOutArrayOfNodes.Length() - 1; i >= 0; i--) { + OwningNonNull<nsINode> testNode = aOutArrayOfNodes[i]; // Remove all non-editable nodes. Leave them be. - NS_ENSURE_STATE(mHTMLEditor); - if (!mHTMLEditor->IsEditable(testNode)) - { - outArrayOfNodes.RemoveObjectAt(i); - } - - // scan for table elements and divs. If we find table elements other than table, - // replace it with a list of any editable non-table content. - if (nsHTMLEditUtils::IsTableElementButNotTable(testNode)) - { - int32_t j=i; - outArrayOfNodes.RemoveObjectAt(i); - res = GetInnerContent(testNode, outArrayOfNodes, &j, false); - NS_ENSURE_SUCCESS(res, res); - } - } - - // if there is only one node in the array, and it is a list, div, or blockquote, - // then look inside of it until we find inner list or content. - res = LookInsideDivBQandList(outArrayOfNodes); - return res; -} - - -/////////////////////////////////////////////////////////////////////////// -// LookInsideDivBQandList: -// -nsresult -nsHTMLEditRules::LookInsideDivBQandList(nsCOMArray<nsIDOMNode>& aNodeArray) -{ - // if there is only one node in the array, and it is a list, div, or blockquote, - // then look inside of it until we find inner list or content. - int32_t listCount = aNodeArray.Count(); + if (!mHTMLEditor->IsEditable(testNode)) { + aOutArrayOfNodes.RemoveElementAt(i); + continue; + } + + // Scan for table elements and divs. If we find table elements other than + // table, replace it with a list of any editable non-table content. + if (nsHTMLEditUtils::IsTableElementButNotTable(testNode)) { + int32_t j = i; + aOutArrayOfNodes.RemoveElementAt(i); + GetInnerContent(*testNode, aOutArrayOfNodes, &j, Lists::no); + } + } + + // If there is only one node in the array, and it is a list, div, or + // blockquote, then look inside of it until we find inner list or content. + LookInsideDivBQandList(aOutArrayOfNodes); + + return NS_OK; +} + + +void +nsHTMLEditRules::LookInsideDivBQandList(nsTArray<OwningNonNull<nsINode>>& aNodeArray) +{ + NS_ENSURE_TRUE(mHTMLEditor, ); + nsCOMPtr<nsIEditor> kungFuDeathGrip(mHTMLEditor); + + // If there is only one node in the array, and it is a list, div, or + // blockquote, then look inside of it until we find inner list or content. + int32_t listCount = aNodeArray.Length(); if (listCount != 1) { - return NS_OK; - } - - nsCOMPtr<nsINode> curNode = do_QueryInterface(aNodeArray[0]); - NS_ENSURE_STATE(curNode); - - while (curNode->IsElement() && - (curNode->IsHTMLElement(nsGkAtoms::div) || - nsHTMLEditUtils::IsList(curNode) || - curNode->IsHTMLElement(nsGkAtoms::blockquote))) { - // dive as long as there is only one child, and it is a list, div, blockquote - NS_ENSURE_STATE(mHTMLEditor); + return; + } + + OwningNonNull<nsINode> curNode = aNodeArray[0]; + + while (curNode->IsHTMLElement(nsGkAtoms::div) || + nsHTMLEditUtils::IsList(curNode) || + curNode->IsHTMLElement(nsGkAtoms::blockquote)) { + // Dive as long as there's only one child, and it's a list, div, blockquote uint32_t numChildren = mHTMLEditor->CountEditableChildren(curNode); if (numChildren != 1) { break; } - // keep diving - // XXX One would expect to dive into the one editable node. - nsIContent* tmp = curNode->GetFirstChild(); - if (!tmp->IsElement()) { + // Keep diving! XXX One would expect to dive into the one editable node. + nsCOMPtr<nsIContent> child = curNode->GetFirstChild(); + if (!child->IsHTMLElement(nsGkAtoms::div) && + !nsHTMLEditUtils::IsList(child) && + !child->IsHTMLElement(nsGkAtoms::blockquote)) { break; } - dom::Element* element = tmp->AsElement(); - if (!element->IsHTMLElement(nsGkAtoms::div) && - !nsHTMLEditUtils::IsList(element) && - !element->IsHTMLElement(nsGkAtoms::blockquote)) { - break; - } - - // check editablility XXX floppy moose - curNode = tmp; - } - - // we've found innermost list/blockquote/div: - // replace the one node in the array with these nodes - aNodeArray.RemoveObjectAt(0); + // check editability XXX floppy moose + curNode = child; + } + + // We've found innermost list/blockquote/div: replace the one node in the + // array with these nodes + aNodeArray.RemoveElementAt(0); if (curNode->IsAnyOfHTMLElements(nsGkAtoms::div, nsGkAtoms::blockquote)) { int32_t j = 0; - return GetInnerContent(curNode->AsDOMNode(), aNodeArray, &j, false, false); - } - - aNodeArray.AppendObject(curNode->AsDOMNode()); - return NS_OK; + GetInnerContent(*curNode, aNodeArray, &j, Lists::no, Tables::no); + return; + } + + aNodeArray.AppendElement(*curNode); } /////////////////////////////////////////////////////////////////////////// // GetDefinitionListItemTypes: // void nsHTMLEditRules::GetDefinitionListItemTypes(dom::Element* aElement, bool* aDT, bool* aDD) @@ -6214,59 +6008,52 @@ nsHTMLEditRules::GetDefinitionListItemTy if (child->IsHTMLElement(nsGkAtoms::dt)) { *aDT = true; } else if (child->IsHTMLElement(nsGkAtoms::dd)) { *aDD = true; } } } -/////////////////////////////////////////////////////////////////////////// -// GetParagraphFormatNodes: -// -nsresult -nsHTMLEditRules::GetParagraphFormatNodes(nsCOMArray<nsIDOMNode>& outArrayOfNodes, - bool aDontTouchContent) -{ +nsresult +nsHTMLEditRules::GetParagraphFormatNodes(nsTArray<OwningNonNull<nsINode>>& outArrayOfNodes, + TouchContent aTouchContent) +{ NS_ENSURE_STATE(mHTMLEditor); + nsCOMPtr<nsIEditor> kungFuDeathGrip(mHTMLEditor); + nsRefPtr<Selection> selection = mHTMLEditor->GetSelection(); NS_ENSURE_STATE(selection); - // contruct a list of nodes to act on. - nsresult res = GetNodesFromSelection(selection, EditAction::makeBasicBlock, - outArrayOfNodes, aDontTouchContent); + // Contruct a list of nodes to act on. + nsresult res = GetNodesFromSelection(*selection, EditAction::makeBasicBlock, + outArrayOfNodes, aTouchContent); NS_ENSURE_SUCCESS(res, res); - // pre process our list of nodes... - int32_t listCount = outArrayOfNodes.Count(); - int32_t i; - for (i=listCount-1; i>=0; i--) - { - nsCOMPtr<nsIDOMNode> testNode = outArrayOfNodes[i]; + // Pre-process our list of nodes + for (int32_t i = outArrayOfNodes.Length() - 1; i >= 0; i--) { + OwningNonNull<nsINode> testNode = outArrayOfNodes[i]; // Remove all non-editable nodes. Leave them be. - NS_ENSURE_STATE(mHTMLEditor); - if (!mHTMLEditor->IsEditable(testNode)) - { - outArrayOfNodes.RemoveObjectAt(i); - } - - // scan for table elements. If we find table elements other than table, - // replace it with a list of any editable non-table content. Ditto for list elements. + if (!mHTMLEditor->IsEditable(testNode)) { + outArrayOfNodes.RemoveElementAt(i); + } + + // Scan for table elements. If we find table elements other than table, + // replace it with a list of any editable non-table content. Ditto for + // list elements. if (nsHTMLEditUtils::IsTableElement(testNode) || - nsHTMLEditUtils::IsList(testNode) || - nsHTMLEditUtils::IsListItem(testNode) ) - { - int32_t j=i; - outArrayOfNodes.RemoveObjectAt(i); - res = GetInnerContent(testNode, outArrayOfNodes, &j); - NS_ENSURE_SUCCESS(res, res); - } - } - return res; + nsHTMLEditUtils::IsList(testNode) || + nsHTMLEditUtils::IsListItem(testNode)) { + int32_t j = i; + outArrayOfNodes.RemoveElementAt(i); + GetInnerContent(testNode, outArrayOfNodes, &j); + } + } + return NS_OK; } /////////////////////////////////////////////////////////////////////////// // BustUpInlinesAtRangeEndpoints: // nsresult nsHTMLEditRules::BustUpInlinesAtRangeEndpoints(nsRangeStore &item) @@ -6310,91 +6097,77 @@ nsHTMLEditRules::BustUpInlinesAtRangeEnd item.startOffset = resultStartOffset; } return res; } -/////////////////////////////////////////////////////////////////////////// -// BustUpInlinesAtBRs: -// -nsresult -nsHTMLEditRules::BustUpInlinesAtBRs(nsIDOMNode *inNode, - nsCOMArray<nsIDOMNode>& outArrayOfNodes) -{ - nsCOMPtr<nsINode> node = do_QueryInterface(inNode); - NS_ENSURE_TRUE(node, NS_ERROR_NULL_POINTER); - - // first step is to build up a list of all the break nodes inside - // the inline container. - nsCOMArray<nsIDOMNode> arrayOfBreaks; +nsresult +nsHTMLEditRules::BustUpInlinesAtBRs(nsINode& aNode, + nsTArray<OwningNonNull<nsINode>>& aOutArrayOfNodes) +{ + NS_ENSURE_STATE(mHTMLEditor); + nsCOMPtr<nsIEditor> kungFuDeathGrip(mHTMLEditor); + + // First build up a list of all the break nodes inside the inline container. + nsTArray<OwningNonNull<nsINode>> arrayOfBreaks; nsBRNodeFunctor functor; - nsDOMIterator iter; - nsresult res = iter.Init(inNode); - NS_ENSURE_SUCCESS(res, res); - res = iter.AppendList(functor, arrayOfBreaks); - NS_ENSURE_SUCCESS(res, res); - - // if there aren't any breaks, just put inNode itself in the array - int32_t listCount = arrayOfBreaks.Count(); - if (!listCount) - { - if (!outArrayOfNodes.AppendObject(inNode)) - return NS_ERROR_FAILURE; - } - else - { - // else we need to bust up inNode along all the breaks - nsCOMPtr<Element> breakNode; - nsCOMPtr<nsINode> inlineParentNode = node->GetParentNode(); - nsCOMPtr<nsIDOMNode> leftNode; - nsCOMPtr<nsIDOMNode> rightNode; - nsCOMPtr<nsIDOMNode> splitDeepNode = inNode; - nsCOMPtr<nsIDOMNode> splitParentNode; - int32_t splitOffset, resultOffset, i; - - for (i=0; i< listCount; i++) - { - breakNode = do_QueryInterface(arrayOfBreaks[i]); - NS_ENSURE_TRUE(breakNode, NS_ERROR_NULL_POINTER); - NS_ENSURE_TRUE(splitDeepNode, NS_ERROR_NULL_POINTER); - splitParentNode = GetAsDOMNode(nsEditor::GetNodeLocation(breakNode, - &splitOffset)); - NS_ENSURE_STATE(mHTMLEditor); - res = mHTMLEditor->SplitNodeDeep(splitDeepNode, splitParentNode, splitOffset, - &resultOffset, false, address_of(leftNode), address_of(rightNode)); - NS_ENSURE_SUCCESS(res, res); - // put left node in node list - if (leftNode) - { - // might not be a left node. a break might have been at the very - // beginning of inline container, in which case splitnodedeep - // would not actually split anything - if (!outArrayOfNodes.AppendObject(leftNode)) - return NS_ERROR_FAILURE; - } - // move break outside of container and also put in node list - NS_ENSURE_STATE(mHTMLEditor); - res = mHTMLEditor->MoveNode(breakNode, inlineParentNode, resultOffset); - NS_ENSURE_SUCCESS(res, res); - if (!outArrayOfNodes.AppendObject(GetAsDOMNode(breakNode))) - return NS_ERROR_FAILURE; - // now rightNode becomes the new node to split - splitDeepNode = rightNode; - } - // now tack on remaining rightNode, if any, to the list - if (rightNode) - { - if (!outArrayOfNodes.AppendObject(rightNode)) - return NS_ERROR_FAILURE; - } - } - return res; + nsDOMIterator iter(aNode); + iter.AppendList(functor, arrayOfBreaks); + + // If there aren't any breaks, just put inNode itself in the array + if (!arrayOfBreaks.Length()) { + aOutArrayOfNodes.AppendElement(aNode); + return NS_OK; + } + + // Else we need to bust up inNode along all the breaks + nsCOMPtr<nsINode> inlineParentNode = aNode.GetParentNode(); + nsCOMPtr<nsIDOMNode> splitDeepNode = GetAsDOMNode(&aNode); + nsCOMPtr<nsIDOMNode> leftDOMNode, rightDOMNode; + + for (uint32_t i = 0; i < arrayOfBreaks.Length(); i++) { + OwningNonNull<Element> breakNode = *arrayOfBreaks[i]->AsElement(); + NS_ENSURE_TRUE(splitDeepNode, NS_ERROR_NULL_POINTER); + nsCOMPtr<nsINode> splitParentNode = breakNode->GetParentNode(); + int32_t splitOffset = splitParentNode ? + splitParentNode->IndexOf(breakNode) : -1; + + int32_t resultOffset; + nsresult res = mHTMLEditor->SplitNodeDeep(splitDeepNode, + GetAsDOMNode(splitParentNode), splitOffset, &resultOffset, false, + address_of(leftDOMNode), address_of(rightDOMNode)); + NS_ENSURE_SUCCESS(res, res); + + // Put left node in node list + if (leftDOMNode) { + // Might not be a left node. A break might have been at the very + // beginning of inline container, in which case SplitNodeDeep would not + // actually split anything + nsCOMPtr<nsINode> leftNode = do_QueryInterface(leftDOMNode); + NS_ENSURE_STATE(leftNode); + aOutArrayOfNodes.AppendElement(*leftNode); + } + // Move break outside of container and also put in node list + res = mHTMLEditor->MoveNode(breakNode, inlineParentNode, resultOffset); + NS_ENSURE_SUCCESS(res, res); + aOutArrayOfNodes.AppendElement(*breakNode); + + // Now rightNode becomes the new node to split + splitDeepNode = rightDOMNode; + } + // Now tack on remaining rightNode, if any, to the list + if (rightDOMNode) { + nsCOMPtr<nsINode> rightNode = do_QueryInterface(rightDOMNode); + NS_ENSURE_STATE(rightNode); + aOutArrayOfNodes.AppendElement(*rightNode); + } + return NS_OK; } nsCOMPtr<nsIDOMNode> nsHTMLEditRules::GetHighestInlineParent(nsIDOMNode* aNode) { NS_ENSURE_TRUE(aNode, nullptr); if (IsBlockNode(aNode)) return nullptr; @@ -6404,106 +6177,96 @@ nsHTMLEditRules::GetHighestInlineParent( { inlineNode = node; inlineNode->GetParentNode(getter_AddRefs(node)); } return inlineNode; } -/////////////////////////////////////////////////////////////////////////// -// GetNodesFromPoint: given a particular operation, construct a list -// of nodes from a point that will be operated on. -// -nsresult -nsHTMLEditRules::GetNodesFromPoint(::DOMPoint point, - EditAction operation, - nsCOMArray<nsIDOMNode> &arrayOfNodes, - bool dontTouchContent) -{ - NS_ENSURE_STATE(point.node); - nsRefPtr<nsRange> range = new nsRange(point.node); - nsresult res = range->SetStart(point.node, point.offset); - NS_ENSURE_SUCCESS(res, res); - - // expand the range to include adjacent inlines - res = PromoteRange(range, operation); - NS_ENSURE_SUCCESS(res, res); - - // make array of ranges +/////////////////////////////////////////////////////////////////////////////// +// GetNodesFromPoint: Given a particular operation, construct a list of nodes +// from a point that will be operated on. +// +nsresult +nsHTMLEditRules::GetNodesFromPoint(::DOMPoint aPoint, + EditAction aOperation, + nsTArray<OwningNonNull<nsINode>>& outArrayOfNodes, + TouchContent aTouchContent) +{ + NS_ENSURE_STATE(aPoint.node); + nsRefPtr<nsRange> range = new nsRange(aPoint.node); + nsresult res = range->SetStart(aPoint.node, aPoint.offset); + MOZ_ASSERT(NS_SUCCEEDED(res)); + + // Expand the range to include adjacent inlines + PromoteRange(*range, aOperation); + + // Make array of ranges nsTArray<nsRefPtr<nsRange>> arrayOfRanges; - - // stuff new opRange into array + + // Stuff new opRange into array arrayOfRanges.AppendElement(range); - - // use these ranges to contruct a list of nodes to act on. - res = GetNodesForOperation(arrayOfRanges, arrayOfNodes, operation, dontTouchContent); - return res; -} - - -/////////////////////////////////////////////////////////////////////////// -// GetNodesFromSelection: given a particular operation, construct a list -// of nodes from the selection that will be operated on. -// -nsresult -nsHTMLEditRules::GetNodesFromSelection(Selection* selection, - EditAction operation, - nsCOMArray<nsIDOMNode>& arrayOfNodes, - bool dontTouchContent) -{ - NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER); - nsresult res; - - // promote selection ranges - nsTArray<nsRefPtr<nsRange>> arrayOfRanges; - res = GetPromotedRanges(selection, arrayOfRanges, operation); + + // Use these ranges to contruct a list of nodes to act on + res = GetNodesForOperation(arrayOfRanges, outArrayOfNodes, aOperation, + aTouchContent); NS_ENSURE_SUCCESS(res, res); - - // use these ranges to contruct a list of nodes to act on. - res = GetNodesForOperation(arrayOfRanges, arrayOfNodes, operation, dontTouchContent); - return res; -} - - -/////////////////////////////////////////////////////////////////////////// -// MakeTransitionList: detect all the transitions in the array, where a -// transition means that adjacent nodes in the array -// don't have the same parent. -// -nsresult -nsHTMLEditRules::MakeTransitionList(nsCOMArray<nsIDOMNode>& inArrayOfNodes, - nsTArray<bool> &inTransitionArray) -{ - uint32_t listCount = inArrayOfNodes.Count(); - inTransitionArray.EnsureLengthAtLeast(listCount); - uint32_t i; - nsCOMPtr<nsIDOMNode> prevElementParent; - nsCOMPtr<nsIDOMNode> curElementParent; - - for (i=0; i<listCount; i++) - { - nsIDOMNode* transNode = inArrayOfNodes[i]; - transNode->GetParentNode(getter_AddRefs(curElementParent)); - if (curElementParent != prevElementParent) - { - // different parents, or separated by <br>: transition point - inTransitionArray[i] = true; - } - else - { - // same parents: these nodes grew up together - inTransitionArray[i] = false; - } - prevElementParent = curElementParent; - } + + return NS_OK; +} + + +/////////////////////////////////////////////////////////////////////////////// +// GetNodesFromSelection: Given a particular operation, construct a list of +// nodes from the selection that will be operated on. +// +nsresult +nsHTMLEditRules::GetNodesFromSelection(Selection& aSelection, + EditAction aOperation, + nsTArray<OwningNonNull<nsINode>>& outArrayOfNodes, + TouchContent aTouchContent) +{ + // Promote selection ranges + nsTArray<nsRefPtr<nsRange>> arrayOfRanges; + GetPromotedRanges(aSelection, arrayOfRanges, aOperation); + + // Use these ranges to contruct a list of nodes to act on. + nsresult res = GetNodesForOperation(arrayOfRanges, outArrayOfNodes, + aOperation, aTouchContent); + NS_ENSURE_SUCCESS(res, res); + return NS_OK; } +/////////////////////////////////////////////////////////////////////////////// +// MakeTransitionList: Detect all the transitions in the array, where a +// transition means that adjacent nodes in the array don't +// have the same parent. +void +nsHTMLEditRules::MakeTransitionList(nsTArray<OwningNonNull<nsINode>>& aNodeArray, + nsTArray<bool>& aTransitionArray) +{ + nsCOMPtr<nsINode> prevParent; + + aTransitionArray.EnsureLengthAtLeast(aNodeArray.Length()); + for (uint32_t i = 0; i < aNodeArray.Length(); i++) { + if (aNodeArray[i]->GetParentNode() != prevParent) { + // Different parents: transition point + aTransitionArray[i] = true; + } else { + // Same parents: these nodes grew up together + aTransitionArray[i] = false; + } + prevParent = aNodeArray[i]->GetParentNode(); + } +} + + /******************************************************** * main implementation methods ********************************************************/ /////////////////////////////////////////////////////////////////////////// // IsInListItem: if aNode is the descendant of a listitem, return that li. // But table element boundaries are stoppers on the search. @@ -6984,377 +6747,297 @@ nsHTMLEditRules::ReturnInListItem(Select } } } res = aSelection->Collapse(aListItem,0); return res; } -/////////////////////////////////////////////////////////////////////////// -// MakeBlockquote: put the list of nodes into one or more blockquotes. -// -nsresult -nsHTMLEditRules::MakeBlockquote(nsCOMArray<nsIDOMNode>& arrayOfNodes) -{ - // the idea here is to put the nodes into a minimal number of - // blockquotes. When the user blockquotes something, they expect - // one blockquote. That may not be possible (for instance, if they - // have two table cells selected, you need two blockquotes inside the cells). - - nsresult res = NS_OK; - - nsCOMPtr<nsIDOMNode> curNode, newBlock; - nsCOMPtr<nsINode> curParent; +/////////////////////////////////////////////////////////////////////////////// +// MakeBlockquote: Put the list of nodes into one or more blockquotes. +// +nsresult +nsHTMLEditRules::MakeBlockquote(nsTArray<OwningNonNull<nsINode>>& aNodeArray) +{ + // The idea here is to put the nodes into a minimal number of blockquotes. + // When the user blockquotes something, they expect one blockquote. That may + // not be possible (for instance, if they have two table cells selected, you + // need two blockquotes inside the cells). + nsresult res; nsCOMPtr<Element> curBlock; - int32_t offset; - int32_t listCount = arrayOfNodes.Count(); - - nsCOMPtr<nsIDOMNode> prevParent; - - int32_t i; - for (i=0; i<listCount; i++) - { - // get the node to act on, and its location - curNode = arrayOfNodes[i]; - nsCOMPtr<nsIContent> curContent = do_QueryInterface(curNode); - NS_ENSURE_STATE(curContent); - curParent = curContent->GetParentNode(); - offset = curParent ? curParent->IndexOf(curContent) : -1; - - // if the node is a table element or list item, dive inside - if (nsHTMLEditUtils::IsTableElementButNotTable(curNode) || - nsHTMLEditUtils::IsListItem(curNode)) - { - curBlock = 0; // forget any previous block - // recursion time - nsCOMArray<nsIDOMNode> childArray; - res = GetChildNodesForOperation(curNode, childArray); - NS_ENSURE_SUCCESS(res, res); + nsCOMPtr<nsINode> prevParent; + + for (auto& curNode : aNodeArray) { + // Get the node to act on, and its location + NS_ENSURE_STATE(curNode->IsContent()); + + // If the node is a table element or list item, dive inside + if (nsHTMLEditUtils::IsTableElementButNotTable(curNode) || + nsHTMLEditUtils::IsListItem(curNode)) { + // Forget any previous block + curBlock = nullptr; + // Recursion time + nsTArray<OwningNonNull<nsINode>> childArray; + GetChildNodesForOperation(*curNode, childArray); res = MakeBlockquote(childArray); NS_ENSURE_SUCCESS(res, res); } - - // if the node has different parent than previous node, - // further nodes in a new parent - if (prevParent) - { - nsCOMPtr<nsIDOMNode> temp; - curNode->GetParentNode(getter_AddRefs(temp)); - if (temp != prevParent) - { - curBlock = 0; // forget any previous blockquote node we were using - prevParent = temp; - } - } - else - - { - curNode->GetParentNode(getter_AddRefs(prevParent)); - } - - // if no curBlock, make one - if (!curBlock) - { + + // If the node has different parent than previous node, further nodes in a + // new parent + if (prevParent) { + if (prevParent != curNode->GetParentNode()) { + // Forget any previous blockquote node we were using + curBlock = nullptr; + prevParent = curNode->GetParentNode(); + } + } else { + prevParent = curNode->GetParentNode(); + } + + // If no curBlock, make one + if (!curBlock) { + nsCOMPtr<nsINode> curParent = curNode->GetParentNode(); + int32_t offset = curParent ? curParent->IndexOf(curNode) : -1; res = SplitAsNeeded(*nsGkAtoms::blockquote, curParent, offset); NS_ENSURE_SUCCESS(res, res); NS_ENSURE_STATE(mHTMLEditor); curBlock = mHTMLEditor->CreateNode(nsGkAtoms::blockquote, curParent, offset); NS_ENSURE_STATE(curBlock); // remember our new block for postprocessing mNewBlock = curBlock->AsDOMNode(); // note: doesn't matter if we set mNewBlock multiple times. } - - NS_ENSURE_STATE(mHTMLEditor); - res = mHTMLEditor->MoveNode(curContent, curBlock, -1); + + NS_ENSURE_STATE(mHTMLEditor); + res = mHTMLEditor->MoveNode(curNode->AsContent(), curBlock, -1); NS_ENSURE_SUCCESS(res, res); } - return res; -} - - - -/////////////////////////////////////////////////////////////////////////// -// RemoveBlockStyle: make the nodes have no special block type. -// -nsresult -nsHTMLEditRules::RemoveBlockStyle(nsCOMArray<nsIDOMNode>& arrayOfNodes) -{ - // intent of this routine is to be used for converting to/from - // headers, paragraphs, pre, and address. Those blocks - // that pretty much just contain inline things... - - nsresult res = NS_OK; - - nsCOMPtr<nsIDOMNode> curBlock, firstNode, lastNode; - int32_t listCount = arrayOfNodes.Count(); - for (int32_t i = 0; i < listCount; ++i) { - // get the node to act on, and its location - nsCOMPtr<nsIDOMNode> curNode = arrayOfNodes[i]; - - nsCOMPtr<dom::Element> curElement = do_QueryInterface(curNode); - - // if curNode is a address, p, header, address, or pre, remove it - if (curElement && nsHTMLEditUtils::IsFormatNode(curElement)) { - // process any partial progress saved - if (curBlock) - { - res = RemovePartOfBlock(curBlock, firstNode, lastNode); + return NS_OK; +} + + +/////////////////////////////////////////////////////////////////////////////// +// RemoveBlockStyle: Make the nodes have no special block type. +nsresult +nsHTMLEditRules::RemoveBlockStyle(nsTArray<OwningNonNull<nsINode>>& aNodeArray) +{ + NS_ENSURE_STATE(mHTMLEditor); + nsCOMPtr<nsIEditor> kungFuDeathGrip(mHTMLEditor); + + // Intent of this routine is to be used for converting to/from headers, + // paragraphs, pre, and address. Those blocks that pretty much just contain + // inline things... + nsresult res; + + nsCOMPtr<Element> curBlock; + nsCOMPtr<nsIContent> firstNode, lastNode; + for (auto& curNode : aNodeArray) { + // If curNode is a address, p, header, address, or pre, remove it + if (nsHTMLEditUtils::IsFormatNode(curNode)) { + // Process any partial progress saved + if (curBlock) { + res = RemovePartOfBlock(*curBlock, *firstNode, *lastNode); NS_ENSURE_SUCCESS(res, res); - curBlock = 0; firstNode = 0; lastNode = 0; - } - // remove curent block - NS_ENSURE_STATE(mHTMLEditor); - res = mHTMLEditor->RemoveBlockContainer(curNode); + firstNode = lastNode = curBlock = nullptr; + } + // Remove current block + res = mHTMLEditor->RemoveBlockContainer(curNode->AsDOMNode()); NS_ENSURE_SUCCESS(res, res); - } else if (curElement && - (curElement->IsAnyOfHTMLElements(nsGkAtoms::table, - nsGkAtoms::tr, - nsGkAtoms::tbody, - nsGkAtoms::td, - nsGkAtoms::li, - nsGkAtoms::blockquote, - nsGkAtoms::div) || - nsHTMLEditUtils::IsList(curElement))) { - // process any partial progress saved - if (curBlock) - { - res = RemovePartOfBlock(curBlock, firstNode, lastNode); + } else if (curNode->IsAnyOfHTMLElements(nsGkAtoms::table, + nsGkAtoms::tr, + nsGkAtoms::tbody, + nsGkAtoms::td, + nsGkAtoms::li, + nsGkAtoms::blockquote, + nsGkAtoms::div) || + nsHTMLEditUtils::IsList(curNode)) { + // Process any partial progress saved + if (curBlock) { + res = RemovePartOfBlock(*curBlock, *firstNode, *lastNode); NS_ENSURE_SUCCESS(res, res); - curBlock = 0; firstNode = 0; lastNode = 0; - } - // recursion time - nsCOMArray<nsIDOMNode> childArray; - res = GetChildNodesForOperation(curNode, childArray); - NS_ENSURE_SUCCESS(res, res); + firstNode = lastNode = curBlock = nullptr; + } + // Recursion time + nsTArray<OwningNonNull<nsINode>> childArray; + GetChildNodesForOperation(*curNode, childArray); res = RemoveBlockStyle(childArray); NS_ENSURE_SUCCESS(res, res); - } - else if (IsInlineNode(curNode)) - { - if (curBlock) - { - // if so, is this node a descendant? - if (nsEditorUtils::IsDescendantOf(curNode, curBlock)) - { - lastNode = curNode; - continue; // then we don't need to do anything different for this node + } else if (IsInlineNode(GetAsDOMNode(curNode))) { + if (curBlock) { + // If so, is this node a descendant? + if (nsEditorUtils::IsDescendantOf(curNode, curBlock)) { + // Then we don't need to do anything different for this node + lastNode = curNode->AsContent(); + continue; + } else { + // Otherwise, we have progressed beyond end of curBlock, so let's + // handle it now. We need to remove the portion of curBlock that + // contains [firstNode - lastNode]. + res = RemovePartOfBlock(*curBlock, *firstNode, *lastNode); + NS_ENSURE_SUCCESS(res, res); + firstNode = lastNode = curBlock = nullptr; + // Fall out and handle curNode } - else - { - // otherwise, we have progressed beyond end of curBlock, - // so lets handle it now. We need to remove the portion of - // curBlock that contains [firstNode - lastNode]. - res = RemovePartOfBlock(curBlock, firstNode, lastNode); - NS_ENSURE_SUCCESS(res, res); - curBlock = 0; firstNode = 0; lastNode = 0; - // fall out and handle curNode - } - } - NS_ENSURE_STATE(mHTMLEditor); + } curBlock = mHTMLEditor->GetBlockNodeParent(curNode); if (curBlock && nsHTMLEditUtils::IsFormatNode(curBlock)) { - firstNode = curNode; - lastNode = curNode; - } - else - curBlock = 0; // not a block kind that we care about. - } - else - { // some node that is already sans block style. skip over it and - // process any partial progress saved - if (curBlock) - { - res = RemovePartOfBlock(curBlock, firstNode, lastNode); - NS_ENSURE_SUCCESS(res, res); - curBlock = 0; firstNode = 0; lastNode = 0; - } - } - } - // process any partial progress saved - if (curBlock) - { - res = RemovePartOfBlock(curBlock, firstNode, lastNode); + firstNode = lastNode = curNode->AsContent(); + } else { + // Not a block kind that we care about. + curBlock = nullptr; + } + } else if (curBlock) { + // Some node that is already sans block style. Skip over it and process + // any partial progress saved. + res = RemovePartOfBlock(*curBlock, *firstNode, *lastNode); + NS_ENSURE_SUCCESS(res, res); + firstNode = lastNode = curBlock = nullptr; + } + } + // Process any partial progress saved + if (curBlock) { + res = RemovePartOfBlock(*curBlock, *firstNode, *lastNode); NS_ENSURE_SUCCESS(res, res); - curBlock = 0; firstNode = 0; lastNode = 0; - } - return res; -} - - -/////////////////////////////////////////////////////////////////////////// -// ApplyBlockStyle: do whatever it takes to make the list of nodes into -// one or more blocks of type blockTag. -// -nsresult -nsHTMLEditRules::ApplyBlockStyle(nsCOMArray<nsIDOMNode>& arrayOfNodes, const nsAString *aBlockTag) -{ - // intent of this routine is to be used for converting to/from - // headers, paragraphs, pre, and address. Those blocks - // that pretty much just contain inline things... - - NS_ENSURE_TRUE(aBlockTag, NS_ERROR_NULL_POINTER); - nsCOMPtr<nsIAtom> blockTag = do_GetAtom(*aBlockTag); - nsresult res = NS_OK; - - nsCOMPtr<nsINode> curParent; - nsCOMPtr<nsIDOMNode> newBlock; - int32_t offset; - int32_t listCount = arrayOfNodes.Count(); - nsString tString(*aBlockTag);////MJUDGE SCC NEED HELP + firstNode = lastNode = curBlock = nullptr; + } + return NS_OK; +} + + +/////////////////////////////////////////////////////////////////////////////// +// ApplyBlockStyle: Do whatever it takes to make the list of nodes into one or +// more blocks of type aBlockTag. +nsresult +nsHTMLEditRules::ApplyBlockStyle(nsTArray<OwningNonNull<nsINode>>& aNodeArray, + nsIAtom& aBlockTag) +{ + // Intent of this routine is to be used for converting to/from headers, + // paragraphs, pre, and address. Those blocks that pretty much just contain + // inline things... + NS_ENSURE_STATE(mHTMLEditor); + nsCOMPtr<nsIEditor> kungFuDeathGrip(mHTMLEditor); + + nsresult res; // Remove all non-editable nodes. Leave them be. - int32_t j; - for (j=listCount-1; j>=0; j--) - { - NS_ENSURE_STATE(mHTMLEditor); - if (!mHTMLEditor->IsEditable(arrayOfNodes[j])) - { - arrayOfNodes.RemoveObjectAt(j); - } - } - - // reset list count - listCount = arrayOfNodes.Count(); - + for (int32_t i = aNodeArray.Length() - 1; i >= 0; i--) { + if (!mHTMLEditor->IsEditable(aNodeArray[i])) { + aNodeArray.RemoveElementAt(i); + } + } + + nsCOMPtr<Element> newBlock; + nsCOMPtr<Element> curBlock; - int32_t i; - for (i=0; i<listCount; i++) - { - // get the node to act on, and its location - nsCOMPtr<nsIContent> curNode = do_QueryInterface(arrayOfNodes[i]); - NS_ENSURE_STATE(curNode); - curParent = curNode->GetParentNode(); - offset = curParent ? curParent->IndexOf(curNode) : -1; - nsAutoString curNodeTag; - curNode->NodeInfo()->NameAtom()->ToString(curNodeTag); - ToLowerCase(curNodeTag); - - // is it already the right kind of block? - if (curNodeTag == *aBlockTag) - { - curBlock = 0; // forget any previous block used for previous inline nodes - continue; // do nothing to this block - } - - // if curNode is a address, p, header, address, or pre, replace - // it with a new block of correct type. - // xxx floppy moose: pre can't hold everything the others can - if (nsHTMLEditUtils::IsMozDiv(curNode) || - nsHTMLEditUtils::IsFormatNode(curNode)) - { - curBlock = 0; // forget any previous block used for previous inline nodes - NS_ENSURE_STATE(mHTMLEditor); - nsCOMPtr<Element> element = curNode->AsElement(); - newBlock = dont_AddRef(GetAsDOMNode( - mHTMLEditor->ReplaceContainer(element, blockTag, nullptr, nullptr, - nsEditor::eCloneAttributes).take())); + for (auto& curNode : aNodeArray) { + nsCOMPtr<nsINode> curParent = curNode->GetParentNode(); + int32_t offset = curParent ? curParent->IndexOf(curNode) : -1; + + // Is it already the right kind of block? + if (curNode->IsHTMLElement(&aBlockTag)) { + // Forget any previous block used for previous inline nodes + curBlock = nullptr; + // Do nothing to this block + continue; + } + + // If curNode is a address, p, header, address, or pre, replace it with a + // new block of correct type. + // XXX: pre can't hold everything the others can + if (nsHTMLEditUtils::IsMozDiv(curNode) || + nsHTMLEditUtils::IsFormatNode(curNode)) { + // Forget any previous block used for previous inline nodes + curBlock = nullptr; + newBlock = mHTMLEditor->ReplaceContainer(curNode->AsElement(), + &aBlockTag, nullptr, nullptr, + nsEditor::eCloneAttributes); NS_ENSURE_STATE(newBlock); - } - else if (nsHTMLEditUtils::IsTable(curNode) || - (curNodeTag.EqualsLiteral("tbody")) || - (curNodeTag.EqualsLiteral("tr")) || - (curNodeTag.EqualsLiteral("td")) || - nsHTMLEditUtils::IsList(curNode) || - (curNodeTag.EqualsLiteral("li")) || - curNode->IsAnyOfHTMLElements(nsGkAtoms::blockquote, - nsGkAtoms::div)) { - curBlock = 0; // forget any previous block used for previous inline nodes - // recursion time - nsCOMArray<nsIDOMNode> childArray; - res = GetChildNodesForOperation(GetAsDOMNode(curNode), childArray); - NS_ENSURE_SUCCESS(res, res); - int32_t childCount = childArray.Count(); - if (childCount) - { + } else if (nsHTMLEditUtils::IsTable(curNode) || + nsHTMLEditUtils::IsList(curNode) || + curNode->IsAnyOfHTMLElements(nsGkAtoms::tbody, + nsGkAtoms::tr, + nsGkAtoms::td, + nsGkAtoms::li, + nsGkAtoms::blockquote, + nsGkAtoms::div)) { + // Forget any previous block used for previous inline nodes + curBlock = nullptr; + // Recursion time + nsTArray<OwningNonNull<nsINode>> childArray; + GetChildNodesForOperation(*curNode, childArray); + if (childArray.Length()) { res = ApplyBlockStyle(childArray, aBlockTag); NS_ENSURE_SUCCESS(res, res); - } - else - { - // make sure we can put a block here - res = SplitAsNeeded(*blockTag, curParent, offset); + } else { + // Make sure we can put a block here + res = SplitAsNeeded(aBlockTag, curParent, offset); NS_ENSURE_SUCCESS(res, res); - NS_ENSURE_STATE(mHTMLEditor); nsCOMPtr<Element> theBlock = - mHTMLEditor->CreateNode(blockTag, curParent, offset); + mHTMLEditor->CreateNode(&aBlockTag, curParent, offset); NS_ENSURE_STATE(theBlock); - // remember our new block for postprocessing + // Remember our new block for postprocessing mNewBlock = theBlock->AsDOMNode(); } - } - - // if the node is a break, we honor it by putting further nodes in a new parent - else if (curNodeTag.EqualsLiteral("br")) - { - if (curBlock) - { - curBlock = 0; // forget any previous block used for previous inline nodes - NS_ENSURE_STATE(mHTMLEditor); + } else if (curNode->IsHTMLElement(nsGkAtoms::br)) { + // If the node is a break, we honor it by putting further nodes in a new + // parent + if (curBlock) { + // Forget any previous block used for previous inline nodes + curBlock = nullptr; res = mHTMLEditor->DeleteNode(curNode); NS_ENSURE_SUCCESS(res, res); - } - else - { - // the break is the first (or even only) node we encountered. Create a + } else { + // The break is the first (or even only) node we encountered. Create a // block for it. - res = SplitAsNeeded(*blockTag, curParent, offset); + res = SplitAsNeeded(aBlockTag, curParent, offset); NS_ENSURE_SUCCESS(res, res); - NS_ENSURE_STATE(mHTMLEditor); - curBlock = mHTMLEditor->CreateNode(blockTag, curParent, offset); + curBlock = mHTMLEditor->CreateNode(&aBlockTag, curParent, offset); NS_ENSURE_STATE(curBlock); - // remember our new block for postprocessing + // Remember our new block for postprocessing mNewBlock = curBlock->AsDOMNode(); - // note: doesn't matter if we set mNewBlock multiple times. - NS_ENSURE_STATE(mHTMLEditor); - res = mHTMLEditor->MoveNode(curNode, curBlock, -1); + // Note: doesn't matter if we set mNewBlock multiple times. + res = mHTMLEditor->MoveNode(curNode->AsContent(), curBlock, -1); NS_ENSURE_SUCCESS(res, res); } - - - // if curNode is inline, pull it into curBlock - // note: it's assumed that consecutive inline nodes in the - // arrayOfNodes are actually members of the same block parent. - // this happens to be true now as a side effect of how - // arrayOfNodes is contructed, but some additional logic should - // be added here if that should change - } else if (IsInlineNode(GetAsDOMNode(curNode))) { - // if curNode is a non editable, drop it if we are going to <pre> - NS_ENSURE_STATE(mHTMLEditor); - if (tString.LowerCaseEqualsLiteral("pre") - && (!mHTMLEditor->IsEditable(curNode))) - continue; // do nothing to this block - - // if no curBlock, make one - if (!curBlock) - { - res = SplitAsNeeded(*blockTag, curParent, offset); + // If curNode is inline, pull it into curBlock. Note: it's assumed that + // consecutive inline nodes in aNodeArray are actually members of the + // same block parent. This happens to be true now as a side effect of + // how aNodeArray is contructed, but some additional logic should be + // added here if that should change + // + // If curNode is a non editable, drop it if we are going to <pre>. + if (&aBlockTag == nsGkAtoms::pre && !mHTMLEditor->IsEditable(curNode)) { + // Do nothing to this block + continue; + } + + // If no curBlock, make one + if (!curBlock) { + res = SplitAsNeeded(aBlockTag, curParent, offset); NS_ENSURE_SUCCESS(res, res); - NS_ENSURE_STATE(mHTMLEditor); - curBlock = mHTMLEditor->CreateNode(blockTag, curParent, offset); + curBlock = mHTMLEditor->CreateNode(&aBlockTag, curParent, offset); NS_ENSURE_STATE(curBlock); - // remember our new block for postprocessing + // Remember our new block for postprocessing mNewBlock = curBlock->AsDOMNode(); - // note: doesn't matter if we set mNewBlock multiple times. - } - - // if curNode is a Break, replace it with a return if we are going to <pre> - // xxx floppy moose - - // this is a continuation of some inline nodes that belong together in - // the same block item. use curBlock - NS_ENSURE_STATE(mHTMLEditor); - res = mHTMLEditor->MoveNode(curNode, curBlock, -1); + // Note: doesn't matter if we set mNewBlock multiple times. + } + + // XXX If curNode is a br, replace it with a return if going to <pre> + + // This is a continuation of some inline nodes that belong together in + // the same block item. Use curBlock. + res = mHTMLEditor->MoveNode(curNode->AsContent(), curBlock, -1); NS_ENSURE_SUCCESS(res, res); } } - return res; + return NS_OK; } /////////////////////////////////////////////////////////////////////////////// // SplitAsNeeded: Given a tag name, split inOutParent up to the point where we // can insert the tag. Adjust inOutParent and inOutOffset to // point to new location for tag. nsresult @@ -7592,50 +7275,36 @@ nsHTMLEditRules::ClearCachedStyles() // clear the mPresent bits in mCachedStyles array for (uint32_t j = 0; j < SIZE_STYLE_TABLE; j++) { mCachedStyles[j].mPresent = false; mCachedStyles[j].value.Truncate(); } } -nsresult -nsHTMLEditRules::AdjustSpecialBreaks(bool aSafeToAskFrames) -{ - nsCOMArray<nsIDOMNode> arrayOfNodes; - nsCOMPtr<nsISupports> isupports; - int32_t nodeCount,j; - - // gather list of empty nodes - NS_ENSURE_STATE(mHTMLEditor); +void +nsHTMLEditRules::AdjustSpecialBreaks() +{ + NS_ENSURE_TRUE(mHTMLEditor, ); + + // Gather list of empty nodes + nsTArray<OwningNonNull<nsINode>> nodeArray; nsEmptyEditableFunctor functor(mHTMLEditor); - nsDOMIterator iter; - nsresult res = iter.Init(mDocChangeRange); - NS_ENSURE_SUCCESS(res, res); - res = iter.AppendList(functor, arrayOfNodes); - NS_ENSURE_SUCCESS(res, res); - - // put moz-br's into these empty li's and td's - nodeCount = arrayOfNodes.Count(); - for (j = 0; j < nodeCount; j++) - { - // need to put br at END of node. It may have - // empty containers in it and still pass the "IsEmptynode" test, - // and we want the br's to be after them. Also, we want the br - // to be after the selection if the selection is in this node. - uint32_t len; - nsCOMPtr<nsIDOMNode> theNode = arrayOfNodes[0]; - arrayOfNodes.RemoveObjectAt(0); - res = nsEditor::GetLengthOfDOMNode(theNode, len); - NS_ENSURE_SUCCESS(res, res); - res = CreateMozBR(theNode, (int32_t)len); - NS_ENSURE_SUCCESS(res, res); - } - - return res; + nsDOMIterator iter(*mDocChangeRange); + iter.AppendList(functor, nodeArray); + + // Put moz-br's into these empty li's and td's + for (auto& node : nodeArray) { + // Need to put br at END of node. It may have empty containers in it and + // still pass the "IsEmptyNode" test, and we want the br's to be after + // them. Also, we want the br to be after the selection if the selection + // is in this node. + nsresult res = CreateMozBR(node->AsDOMNode(), (int32_t)node->Length()); + NS_ENSURE_SUCCESS(res, ); + } } nsresult nsHTMLEditRules::AdjustWhitespace(Selection* aSelection) { // get selection point nsCOMPtr<nsIDOMNode> selNode; int32_t selOffset; @@ -8031,163 +7700,149 @@ nsHTMLEditRules::InDifferentTableElement while (aNode2 && !nsHTMLEditUtils::IsTableElement(aNode2)) { aNode2 = aNode2->GetParentNode(); } return aNode1 != aNode2; } -nsresult +nsresult nsHTMLEditRules::RemoveEmptyNodes() { - // some general notes on the algorithm used here: the goal is to examine all the - // nodes in mDocChangeRange, and remove the empty ones. We do this by using a - // content iterator to traverse all the nodes in the range, and placing the empty - // nodes into an array. After finishing the iteration, we delete the empty nodes - // in the array. (they cannot be deleted as we find them becasue that would - // invalidate the iterator.) + NS_ENSURE_STATE(mHTMLEditor); + nsCOMPtr<nsIEditor> kungFuDeathGrip(mHTMLEditor); + + // Some general notes on the algorithm used here: the goal is to examine all + // the nodes in mDocChangeRange, and remove the empty ones. We do this by + // using a content iterator to traverse all the nodes in the range, and + // placing the empty nodes into an array. After finishing the iteration, we + // delete the empty nodes in the array. (They cannot be deleted as we find + // them because that would invalidate the iterator.) + // // Since checking to see if a node is empty can be costly for nodes with many - // descendants, there are some optimizations made. I rely on the fact that the - // iterator is post-order: it will visit children of a node before visiting the - // parent node. So if I find that a child node is not empty, I know that its - // parent is not empty without even checking. So I put the parent on a "skipList" - // which is just a voidArray of nodes I can skip the empty check on. If I - // encounter a node on the skiplist, i skip the processing for that node and replace - // its slot in the skiplist with that node's parent. - // An interseting idea is to go ahead and regard parent nodes that are NOT on the - // skiplist as being empty (without even doing the IsEmptyNode check) on the theory - // that if they weren't empty, we would have encountered a non-empty child earlier - // and thus put this parent node on the skiplist. - // Unfortunately I can't use that strategy here, because the range may include - // some children of a node while excluding others. Thus I could find all the - // _examined_ children empty, but still not have an empty parent. - + // descendants, there are some optimizations made. I rely on the fact that + // the iterator is post-order: it will visit children of a node before + // visiting the parent node. So if I find that a child node is not empty, I + // know that its parent is not empty without even checking. So I put the + // parent on a "skipList" which is just a voidArray of nodes I can skip the + // empty check on. If I encounter a node on the skiplist, i skip the + // processing for that node and replace its slot in the skiplist with that + // node's parent. + // + // An interesting idea is to go ahead and regard parent nodes that are NOT on + // the skiplist as being empty (without even doing the IsEmptyNode check) on + // the theory that if they weren't empty, we would have encountered a + // non-empty child earlier and thus put this parent node on the skiplist. + // + // Unfortunately I can't use that strategy here, because the range may + // include some children of a node while excluding others. Thus I could find + // all the _examined_ children empty, but still not have an empty parent. + // need an iterator - nsCOMPtr<nsIContentIterator> iter = - do_CreateInstance("@mozilla.org/content/post-content-iterator;1"); - NS_ENSURE_TRUE(iter, NS_ERROR_NULL_POINTER); - + nsCOMPtr<nsIContentIterator> iter = NS_NewContentIterator(); + nsresult res = iter->Init(mDocChangeRange); NS_ENSURE_SUCCESS(res, res); - - nsCOMArray<nsINode> arrayOfEmptyNodes, arrayOfEmptyCites; - nsTArray<nsCOMPtr<nsINode> > skipList; - - // check for empty nodes + + nsTArray<OwningNonNull<nsINode>> arrayOfEmptyNodes, arrayOfEmptyCites, skipList; + + // Check for empty nodes while (!iter->IsDone()) { - nsINode* node = iter->GetCurrentNode(); - NS_ENSURE_TRUE(node, NS_ERROR_FAILURE); - - nsINode* parent = node->GetParentNode(); + OwningNonNull<nsINode> node = *iter->GetCurrentNode(); + + nsCOMPtr<nsINode> parent = node->GetParentNode(); size_t idx = skipList.IndexOf(node); if (idx != skipList.NoIndex) { - // this node is on our skip list. Skip processing for this node, - // and replace its value in the skip list with the value of its parent + // This node is on our skip list. Skip processing for this node, and + // replace its value in the skip list with the value of its parent skipList[idx] = parent; } else { bool bIsCandidate = false; bool bIsEmptyNode = false; bool bIsMailCite = false; if (node->IsElement()) { - dom::Element* element = node->AsElement(); - if (element->IsHTMLElement(nsGkAtoms::body)) { - // don't delete the body - } else if ((bIsMailCite = nsHTMLEditUtils::IsMailCite(element)) || - element->IsHTMLElement(nsGkAtoms::a) || - nsHTMLEditUtils::IsInlineStyle(element) || - nsHTMLEditUtils::IsList(element) || - element->IsHTMLElement(nsGkAtoms::div)) { - // only consider certain nodes to be empty for purposes of removal + if (node->IsHTMLElement(nsGkAtoms::body)) { + // Don't delete the body + } else if ((bIsMailCite = nsHTMLEditUtils::IsMailCite(node)) || + node->IsHTMLElement(nsGkAtoms::a) || + nsHTMLEditUtils::IsInlineStyle(node) || + nsHTMLEditUtils::IsList(node) || + node->IsHTMLElement(nsGkAtoms::div)) { + // Only consider certain nodes to be empty for purposes of removal bIsCandidate = true; - } else if (nsHTMLEditUtils::IsFormatNode(element) || - nsHTMLEditUtils::IsListItem(element) || - element->IsHTMLElement(nsGkAtoms::blockquote)) { - // these node types are candidates if selection is not in them - // if it is one of these, don't delete if selection inside. - // this is so we can create empty headings, etc, for the - // user to type into. + } else if (nsHTMLEditUtils::IsFormatNode(node) || + nsHTMLEditUtils::IsListItem(node) || + node->IsHTMLElement(nsGkAtoms::blockquote)) { + // These node types are candidates if selection is not in them. If + // it is one of these, don't delete if selection inside. This is so + // we can create empty headings, etc., for the user to type into. bool bIsSelInNode; res = SelectionEndpointInNode(node, &bIsSelInNode); NS_ENSURE_SUCCESS(res, res); - if (!bIsSelInNode) - { + if (!bIsSelInNode) { bIsCandidate = true; } } } - + if (bIsCandidate) { - // we delete mailcites even if they have a solo br in them - // other nodes we require to be empty - NS_ENSURE_STATE(mHTMLEditor); + // We delete mailcites even if they have a solo br in them. Other + // nodes we require to be empty. res = mHTMLEditor->IsEmptyNode(node->AsDOMNode(), &bIsEmptyNode, bIsMailCite, true); NS_ENSURE_SUCCESS(res, res); if (bIsEmptyNode) { if (bIsMailCite) { // mailcites go on a separate list from other empty nodes - arrayOfEmptyCites.AppendObject(node); + arrayOfEmptyCites.AppendElement(*node); } else { - arrayOfEmptyNodes.AppendObject(node); + arrayOfEmptyNodes.AppendElement(*node); } } } - + if (!bIsEmptyNode) { // put parent on skip list - skipList.AppendElement(parent); + skipList.AppendElement(*parent); } } iter->Next(); } - + // now delete the empty nodes - int32_t nodeCount = arrayOfEmptyNodes.Count(); - for (int32_t j = 0; j < nodeCount; j++) { - nsCOMPtr<nsIDOMNode> delNode = arrayOfEmptyNodes[0]->AsDOMNode(); - arrayOfEmptyNodes.RemoveObjectAt(0); - NS_ENSURE_STATE(mHTMLEditor); + for (auto& delNode : arrayOfEmptyNodes) { if (mHTMLEditor->IsModifiableNode(delNode)) { - NS_ENSURE_STATE(mHTMLEditor); res = mHTMLEditor->DeleteNode(delNode); NS_ENSURE_SUCCESS(res, res); } } - - // now delete the empty mailcites - // this is a separate step because we want to pull out any br's and preserve them. - nodeCount = arrayOfEmptyCites.Count(); - for (int32_t j = 0; j < nodeCount; j++) { - nsCOMPtr<nsIDOMNode> delNode = arrayOfEmptyCites[0]->AsDOMNode(); - arrayOfEmptyCites.RemoveObjectAt(0); + + // Now delete the empty mailcites. This is a separate step because we want + // to pull out any br's and preserve them. + for (auto& delNode : arrayOfEmptyCites) { bool bIsEmptyNode; - NS_ENSURE_STATE(mHTMLEditor); res = mHTMLEditor->IsEmptyNode(delNode, &bIsEmptyNode, false, true); NS_ENSURE_SUCCESS(res, res); - if (!bIsEmptyNode) - { - // we are deleting a cite that has just a br. We want to delete cite, + if (!bIsEmptyNode) { + // We are deleting a cite that has just a br. We want to delete cite, // but preserve br. - nsCOMPtr<nsIDOMNode> parent, brNode; - int32_t offset; - parent = nsEditor::GetNodeLocation(delNode, &offset); - NS_ENSURE_STATE(mHTMLEditor); - res = mHTMLEditor->CreateBR(parent, offset, address_of(brNode)); - NS_ENSURE_SUCCESS(res, res); - } - NS_ENSURE_STATE(mHTMLEditor); + nsCOMPtr<nsINode> parent = delNode->GetParentNode(); + int32_t offset = parent ? parent->IndexOf(delNode) : -1; + nsCOMPtr<Element> br = mHTMLEditor->CreateBR(parent, offset); + NS_ENSURE_STATE(br); + } res = mHTMLEditor->DeleteNode(delNode); NS_ENSURE_SUCCESS(res, res); } - - return res; + + return NS_OK; } nsresult nsHTMLEditRules::SelectionEndpointInNode(nsINode* aNode, bool* aResult) { NS_ENSURE_TRUE(aNode && aResult, NS_ERROR_NULL_POINTER); nsIDOMNode* node = aNode->AsDOMNode(); @@ -8245,43 +7900,43 @@ nsHTMLEditRules::IsEmptyInline(nsIDOMNod NS_ENSURE_TRUE(mHTMLEditor, false); mHTMLEditor->IsEmptyNode(aNode, &bEmpty); return bEmpty; } return false; } -bool -nsHTMLEditRules::ListIsEmptyLine(nsCOMArray<nsIDOMNode> &arrayOfNodes) -{ - // we have a list of nodes which we are candidates for being moved - // into a new block. Determine if it's anything more than a blank line. - // Look for editable content above and beyond one single BR. - int32_t listCount = arrayOfNodes.Count(); - NS_ENSURE_TRUE(listCount, true); - nsCOMPtr<nsIDOMNode> somenode; - int32_t j, brCount=0; - for (j = 0; j < listCount; j++) - { - somenode = arrayOfNodes[j]; - NS_ENSURE_TRUE(mHTMLEditor, false); - if (somenode && mHTMLEditor->IsEditable(somenode)) - { - if (nsTextEditUtils::IsBreak(somenode)) - { - // first break doesn't count - if (brCount) return false; - brCount++; - } - else if (IsEmptyInline(somenode)) - { - // empty inline, keep looking - } - else return false; +bool +nsHTMLEditRules::ListIsEmptyLine(nsTArray<OwningNonNull<nsINode>>& aArrayOfNodes) +{ + // We have a list of nodes which we are candidates for being moved into a new + // block. Determine if it's anything more than a blank line. Look for + // editable content above and beyond one single BR. + NS_ENSURE_TRUE(aArrayOfNodes.Length(), true); + + NS_ENSURE_TRUE(mHTMLEditor, false); + nsCOMPtr<nsIEditor> kungFuDeathGrip(mHTMLEditor); + + int32_t brCount = 0; + + for (auto& node : aArrayOfNodes) { + if (!mHTMLEditor->IsEditable(node)) { + continue; + } + if (nsTextEditUtils::IsBreak(node)) { + // First break doesn't count + if (brCount) { + return false; + } + brCount++; + } else if (IsEmptyInline(GetAsDOMNode(node))) { + // Empty inline, keep looking + } else { + return false; } } return true; } nsresult nsHTMLEditRules::PopListItem(nsIDOMNode *aListItem, bool *aOutOfList) @@ -9074,22 +8729,21 @@ nsHTMLEditRules::WillAbsolutePosition(Se nsAutoSelectionReset selectionResetter(aSelection, mHTMLEditor); // convert the selection ranges into "promoted" selection ranges: // this basically just expands the range to include the immediate // block parent, and then further expands to include any ancestors // whose children are all in the range nsTArray<nsRefPtr<nsRange>> arrayOfRanges; - res = GetPromotedRanges(aSelection, arrayOfRanges, - EditAction::setAbsolutePosition); - NS_ENSURE_SUCCESS(res, res); + GetPromotedRanges(*aSelection, arrayOfRanges, + EditAction::setAbsolutePosition); // use these ranges to contruct a list of nodes to act on. - nsCOMArray<nsIDOMNode> arrayOfNodes; + nsTArray<OwningNonNull<nsINode>> arrayOfNodes; res = GetNodesForOperation(arrayOfRanges, arrayOfNodes, EditAction::setAbsolutePosition); NS_ENSURE_SUCCESS(res, res); // if nothing visible in list, make an empty block if (ListIsEmptyLine(arrayOfNodes)) { // get selection location @@ -9103,43 +8757,39 @@ nsHTMLEditRules::WillAbsolutePosition(Se NS_ENSURE_SUCCESS(res, res); NS_ENSURE_STATE(mHTMLEditor); nsCOMPtr<Element> thePositionedDiv = mHTMLEditor->CreateNode(nsGkAtoms::div, parent, offset); NS_ENSURE_STATE(thePositionedDiv); // remember our new block for postprocessing mNewBlock = thePositionedDiv->AsDOMNode(); // delete anything that was in the list of nodes - for (int32_t j = arrayOfNodes.Count() - 1; j >= 0; --j) - { - nsCOMPtr<nsIDOMNode> curNode = arrayOfNodes[0]; + while (!arrayOfNodes.IsEmpty()) { + OwningNonNull<nsINode> curNode = arrayOfNodes[0]; NS_ENSURE_STATE(mHTMLEditor); res = mHTMLEditor->DeleteNode(curNode); NS_ENSURE_SUCCESS(res, res); - arrayOfNodes.RemoveObjectAt(0); + arrayOfNodes.RemoveElementAt(0); } // put selection in new block res = aSelection->Collapse(thePositionedDiv,0); selectionResetter.Abort(); // to prevent selection reseter from overriding us. *aHandled = true; return res; } // Ok, now go through all the nodes and put them in a blockquote, // or whatever is appropriate. Wohoo! - int32_t i; nsCOMPtr<nsINode> curParent; nsCOMPtr<nsIDOMNode> indentedLI, sibling; nsCOMPtr<Element> curList, curPositionedDiv; - int32_t listCount = arrayOfNodes.Count(); - for (i=0; i<listCount; i++) - { + for (uint32_t i = 0; i < arrayOfNodes.Length(); i++) { // here's where we actually figure out what to do - nsCOMPtr<nsIContent> curNode = do_QueryInterface(arrayOfNodes[i]); - NS_ENSURE_STATE(curNode); + NS_ENSURE_STATE(arrayOfNodes[i]->IsContent()); + nsCOMPtr<nsIContent> curNode = arrayOfNodes[i]->AsContent(); // Ignore all non-editable nodes. Leave them be. NS_ENSURE_STATE(mHTMLEditor); if (!mHTMLEditor->IsEditable(curNode)) continue; curParent = curNode->GetParentNode(); int32_t offset = curParent ? curParent->IndexOf(curNode) : -1;
--- a/editor/libeditor/nsHTMLEditRules.h +++ b/editor/libeditor/nsHTMLEditRules.h @@ -32,17 +32,16 @@ class nsRange; class nsRulesInfo; namespace mozilla { namespace dom { class Element; class Selection; } // namespace dom } // namespace mozilla struct DOMPoint; -template <class E> class nsCOMArray; struct StyleCache : public PropItem { bool mPresent; StyleCache() : PropItem(), mPresent(false) { MOZ_COUNT_CTOR(StyleCache); } @@ -186,24 +185,27 @@ protected: const nsAString* aBlockType, bool aEntireList, bool* aCancel, bool* aHandled); nsresult WillMakeBasicBlock(mozilla::dom::Selection* aSelection, const nsAString* aBlockType, bool* aCancel, bool* aHandled); nsresult DidMakeBasicBlock(mozilla::dom::Selection* aSelection, nsRulesInfo* aInfo, nsresult aResult); nsresult DidAbsolutePosition(); - nsresult AlignInnerBlocks(nsIDOMNode *aNode, const nsAString *alignType); + nsresult AlignInnerBlocks(nsINode& aNode, const nsAString* alignType); nsresult AlignBlockContents(nsIDOMNode *aNode, const nsAString *alignType); - nsresult AppendInnerFormatNodes(nsCOMArray<nsIDOMNode>& aArray, + nsresult AppendInnerFormatNodes(nsTArray<mozilla::dom::OwningNonNull<nsINode>>& aArray, nsINode* aNode); - nsresult AppendInnerFormatNodes(nsCOMArray<nsIDOMNode>& aArray, - nsIDOMNode *aNode); nsresult GetFormatString(nsIDOMNode *aNode, nsAString &outFormat); - nsresult GetInnerContent(nsIDOMNode *aNode, nsCOMArray<nsIDOMNode>& outArrayOfNodes, int32_t *aIndex, bool aList = true, bool aTble = true); + enum class Lists { no, yes }; + enum class Tables { no, yes }; + void GetInnerContent(nsINode& aNode, + nsTArray<mozilla::dom::OwningNonNull<nsINode>>& aOutArrayOfNodes, + int32_t* aIndex, Lists aLists = Lists::yes, + Tables aTables = Tables::yes); already_AddRefed<nsIDOMNode> IsInListItem(nsIDOMNode* aNode); mozilla::dom::Element* IsInListItem(nsINode* aNode); nsresult ReturnInHeader(mozilla::dom::Selection* aSelection, nsIDOMNode* aHeader, nsIDOMNode* aTextNode, int32_t aOffset); nsresult ReturnInParagraph(mozilla::dom::Selection* aSelection, nsIDOMNode* aHeader, nsIDOMNode* aTextNode, int32_t aOffset, bool* aCancel, bool* aHandled); @@ -212,21 +214,19 @@ protected: mozilla::dom::Selection* aSelection, nsCOMPtr<nsIDOMNode> *aSelNode, int32_t *aOffset); nsresult ReturnInListItem(mozilla::dom::Selection* aSelection, nsIDOMNode* aHeader, nsIDOMNode* aTextNode, int32_t aOffset); nsresult AfterEditInner(EditAction action, nsIEditor::EDirection aDirection); - nsresult RemovePartOfBlock(nsIDOMNode *aBlock, - nsIDOMNode *aStartChild, - nsIDOMNode *aEndChild, - nsCOMPtr<nsIDOMNode> *aLeftNode = 0, - nsCOMPtr<nsIDOMNode> *aRightNode = 0); + nsresult RemovePartOfBlock(mozilla::dom::Element& aBlock, + nsIContent& aStartChild, + nsIContent& aEndChild); nsresult SplitBlock(nsIDOMNode *aBlock, nsIDOMNode *aStartChild, nsIDOMNode *aEndChild, nsCOMPtr<nsIDOMNode> *aLeftNode = 0, nsCOMPtr<nsIDOMNode> *aRightNode = 0, nsCOMPtr<nsIDOMNode> *aMiddleNode = 0); nsresult OutdentPartOfBlock(nsIDOMNode *aBlock, nsIDOMNode *aStartChild, @@ -258,58 +258,65 @@ protected: nsCOMPtr<nsIDOMNode> *outBRNode, int32_t aOffset=0); nsresult ExpandSelectionForDeletion(mozilla::dom::Selection* aSelection); bool IsFirstNode(nsIDOMNode *aNode); bool IsLastNode(nsIDOMNode *aNode); nsresult NormalizeSelection(mozilla::dom::Selection* aSelection); void GetPromotedPoint(RulesEndpoint aWhere, nsIDOMNode* aNode, int32_t aOffset, EditAction actionID, nsCOMPtr<nsIDOMNode>* outNode, int32_t* outOffset); - nsresult GetPromotedRanges(mozilla::dom::Selection* aSelection, - nsTArray<nsRefPtr<nsRange>>& outArrayOfRanges, - EditAction inOperationType); - nsresult PromoteRange(nsRange* inRange, EditAction inOperationType); - nsresult GetNodesForOperation(nsTArray<nsRefPtr<nsRange>>& inArrayOfRanges, - nsCOMArray<nsIDOMNode>& outArrayOfNodes, - EditAction inOperationType, - bool aDontTouchContent=false); - nsresult GetChildNodesForOperation(nsIDOMNode *inNode, - nsCOMArray<nsIDOMNode>& outArrayOfNodes); - nsresult GetNodesFromPoint(::DOMPoint point, - EditAction operation, - nsCOMArray<nsIDOMNode>& arrayOfNodes, - bool dontTouchContent); - nsresult GetNodesFromSelection(mozilla::dom::Selection* selection, - EditAction operation, - nsCOMArray<nsIDOMNode>& arrayOfNodes, - bool aDontTouchContent=false); - nsresult GetListActionNodes(nsCOMArray<nsIDOMNode> &outArrayOfNodes, bool aEntireList, bool aDontTouchContent=false); + void GetPromotedRanges(mozilla::dom::Selection& aSelection, + nsTArray<nsRefPtr<nsRange>>& outArrayOfRanges, + EditAction inOperationType); + void PromoteRange(nsRange& aRange, EditAction inOperationType); + enum class TouchContent { no, yes }; + nsresult GetNodesForOperation(nsTArray<nsRefPtr<nsRange>>& aArrayOfRanges, + nsTArray<mozilla::dom::OwningNonNull<nsINode>>& aOutArrayOfNodes, + EditAction aOperationType, + TouchContent aTouchContent = TouchContent::yes); + void GetChildNodesForOperation(nsINode& aNode, + nsTArray<mozilla::dom::OwningNonNull<nsINode>>& outArrayOfNodes); + nsresult GetNodesFromPoint(::DOMPoint aPoint, + EditAction aOperation, + nsTArray<mozilla::dom::OwningNonNull<nsINode>>& outArrayOfNodes, + TouchContent aTouchContent); + nsresult GetNodesFromSelection(mozilla::dom::Selection& aSelection, + EditAction aOperation, + nsTArray<mozilla::dom::OwningNonNull<nsINode>>& outArrayOfNodes, + TouchContent aTouchContent = TouchContent::yes); + enum class EntireList { no, yes }; + nsresult GetListActionNodes(nsTArray<mozilla::dom::OwningNonNull<nsINode>>& aOutArrayOfNodes, + EntireList aEntireList, + TouchContent aTouchContent = TouchContent::yes); void GetDefinitionListItemTypes(mozilla::dom::Element* aElement, bool* aDT, bool* aDD); - nsresult GetParagraphFormatNodes(nsCOMArray<nsIDOMNode>& outArrayOfNodes, bool aDontTouchContent=false); - nsresult LookInsideDivBQandList(nsCOMArray<nsIDOMNode>& aNodeArray); + nsresult GetParagraphFormatNodes( + nsTArray<mozilla::dom::OwningNonNull<nsINode>>& outArrayOfNodes, + TouchContent aTouchContent = TouchContent::yes); + void LookInsideDivBQandList(nsTArray<mozilla::dom::OwningNonNull<nsINode>>& aNodeArray); nsresult BustUpInlinesAtRangeEndpoints(nsRangeStore &inRange); - nsresult BustUpInlinesAtBRs(nsIDOMNode *inNode, - nsCOMArray<nsIDOMNode>& outArrayOfNodes); + nsresult BustUpInlinesAtBRs(nsINode& aNode, + nsTArray<mozilla::dom::OwningNonNull<nsINode>>& aOutArrayOfNodes); nsCOMPtr<nsIDOMNode> GetHighestInlineParent(nsIDOMNode* aNode); - nsresult MakeTransitionList(nsCOMArray<nsIDOMNode>& inArrayOfNodes, - nsTArray<bool> &inTransitionArray); - nsresult RemoveBlockStyle(nsCOMArray<nsIDOMNode>& arrayOfNodes); - nsresult ApplyBlockStyle(nsCOMArray<nsIDOMNode>& arrayOfNodes, const nsAString *aBlockTag); - nsresult MakeBlockquote(nsCOMArray<nsIDOMNode>& arrayOfNodes); + void MakeTransitionList(nsTArray<mozilla::dom::OwningNonNull<nsINode>>& aNodeArray, + nsTArray<bool>& aTransitionArray); + nsresult RemoveBlockStyle(nsTArray<mozilla::dom::OwningNonNull<nsINode>>& aNodeArray); + nsresult ApplyBlockStyle(nsTArray<mozilla::dom::OwningNonNull<nsINode>>& aNodeArray, + nsIAtom& aBlockTag); + nsresult MakeBlockquote(nsTArray<mozilla::dom::OwningNonNull<nsINode>>& aNodeArray); nsresult SplitAsNeeded(nsIAtom& aTag, nsCOMPtr<nsINode>& inOutParent, int32_t& inOutOffset); nsresult AddTerminatingBR(nsIDOMNode *aBlock); ::DOMPoint JoinNodesSmart(nsIContent& aNodeLeft, nsIContent& aNodeRight); mozilla::dom::Element* GetTopEnclosingMailCite(nsINode& aNode); nsresult PopListItem(nsIDOMNode *aListItem, bool *aOutOfList); nsresult RemoveListStructure(nsIDOMNode *aList); nsresult CacheInlineStyles(nsIDOMNode *aNode); nsresult ReapplyCachedStyles(); void ClearCachedStyles(); - nsresult AdjustSpecialBreaks(bool aSafeToAskFrames = false); + void AdjustSpecialBreaks(); nsresult AdjustWhitespace(mozilla::dom::Selection* aSelection); nsresult PinSelectionToNewBlock(mozilla::dom::Selection* aSelection); nsresult CheckInterlinePosition(mozilla::dom::Selection* aSelection); nsresult AdjustSelection(mozilla::dom::Selection* aSelection, nsIEditor::EDirection aAction); nsresult FindNearSelectableNode(nsIDOMNode *aSelNode, int32_t aSelOffset, nsIEditor::EDirection &aDirection, @@ -324,17 +331,17 @@ protected: bool InDifferentTableElements(nsIDOMNode* aNode1, nsIDOMNode* aNode2); bool InDifferentTableElements(nsINode* aNode1, nsINode* aNode2); nsresult RemoveEmptyNodes(); nsresult SelectionEndpointInNode(nsINode *aNode, bool *aResult); nsresult UpdateDocChangeRange(nsRange* aRange); nsresult ConfirmSelectionInBody(); nsresult InsertMozBRIfNeeded(nsIDOMNode *aNode); bool IsEmptyInline(nsIDOMNode *aNode); - bool ListIsEmptyLine(nsCOMArray<nsIDOMNode> &arrayOfNodes); + bool ListIsEmptyLine(nsTArray<mozilla::dom::OwningNonNull<nsINode>>& arrayOfNodes); nsresult RemoveAlignment(nsIDOMNode * aNode, const nsAString & aAlignType, bool aChildrenOnly); nsresult MakeSureElemStartsOrEndsOnCR(nsIDOMNode *aNode, bool aStarts); nsresult AlignBlock(nsIDOMElement * aElement, const nsAString * aAlignType, bool aContentsOnly); nsresult RelativeChangeIndentationOfElementNode(nsIDOMNode *aNode, int8_t aRelativeChange); void DocumentModifiedWorker(); // data members protected:
--- a/editor/libeditor/nsHTMLEditor.cpp +++ b/editor/libeditor/nsHTMLEditor.cpp @@ -190,17 +190,17 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_ NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mBottomRightHandle) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mActivatedHandle) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mResizingShadow) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mResizingInfo) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mResizedObject) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMouseMotionListenerP) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSelectionListenerP) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mResizeEventListenerP) - NS_IMPL_CYCLE_COLLECTION_TRAVERSE(objectResizeEventListeners) + NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mObjectResizeEventListeners) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mAbsolutelyPositionedObject) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mGrabber) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPositioningShadow) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mInlineEditedCell) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mAddColumnBeforeButton) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mRemoveColumnButton) @@ -2983,18 +2983,16 @@ nsHTMLEditor::GetStyleSheetForURL(const NS_IMETHODIMP nsHTMLEditor::GetURLForStyleSheet(CSSStyleSheet* aStyleSheet, nsAString &aURL) { // is it already in the list? int32_t foundIndex = mStyleSheets.IndexOf(aStyleSheet); // Don't fail if we don't find it in our list - // Note: mStyleSheets is nsCOMArray, so its IndexOf() method - // returns -1 on failure. if (foundIndex == -1) return NS_OK; // Found it in the list! aURL = mStyleSheetURLs[foundIndex]; return NS_OK; } @@ -4498,206 +4496,166 @@ nsHTMLEditor::SetIsCSSEnabled(bool aIsCS return SetFlags(flags); } // Set the block background color nsresult nsHTMLEditor::SetCSSBackgroundColor(const nsAString& aColor) { - if (!mRules) { return NS_ERROR_NOT_INITIALIZED; } + NS_ENSURE_TRUE(mRules, NS_ERROR_NOT_INITIALIZED); ForceCompositionEnd(); // Protect the edit rules object from dying nsCOMPtr<nsIEditRules> kungFuDeathGrip(mRules); nsRefPtr<Selection> selection = GetSelection(); + NS_ENSURE_STATE(selection); bool isCollapsed = selection->Collapsed(); nsAutoEditBatch batchIt(this); - nsAutoRules beginRulesSniffing(this, EditAction::insertElement, nsIEditor::eNext); + nsAutoRules beginRulesSniffing(this, EditAction::insertElement, + nsIEditor::eNext); nsAutoSelectionReset selectionResetter(selection, this); nsAutoTxnsConserveSelection dontSpazMySelection(this); - + bool cancel, handled; nsTextRulesInfo ruleInfo(EditAction::setTextProperty); nsresult res = mRules->WillDoAction(selection, &ruleInfo, &cancel, &handled); NS_ENSURE_SUCCESS(res, res); - if (!cancel && !handled) - { - // loop thru the ranges in the selection - nsAutoString bgcolor; bgcolor.AssignLiteral("bgcolor"); - uint32_t rangeCount = selection->RangeCount(); - for (uint32_t rangeIdx = 0; rangeIdx < rangeCount; ++rangeIdx) { - nsCOMPtr<nsIDOMNode> cachedBlockParent = nullptr; - nsRefPtr<nsRange> range = selection->GetRangeAt(rangeIdx); + if (!cancel && !handled) { + // Loop through the ranges in the selection + NS_NAMED_LITERAL_STRING(bgcolor, "bgcolor"); + for (uint32_t i = 0; i < selection->RangeCount(); i++) { + nsRefPtr<nsRange> range = selection->GetRangeAt(i); NS_ENSURE_TRUE(range, NS_ERROR_FAILURE); - - // check for easy case: both range endpoints in same text node - nsCOMPtr<nsIDOMNode> startNode, endNode; - int32_t startOffset, endOffset; - res = range->GetStartContainer(getter_AddRefs(startNode)); - NS_ENSURE_SUCCESS(res, res); - res = range->GetEndContainer(getter_AddRefs(endNode)); - NS_ENSURE_SUCCESS(res, res); - res = range->GetStartOffset(&startOffset); - NS_ENSURE_SUCCESS(res, res); - res = range->GetEndOffset(&endOffset); - NS_ENSURE_SUCCESS(res, res); - if ((startNode == endNode) && IsTextNode(startNode)) - { - // let's find the block container of the text node - nsCOMPtr<nsIDOMNode> blockParent; - blockParent = GetBlockNodeParent(startNode); - // and apply the background color to that block container + + nsCOMPtr<Element> cachedBlockParent; + + // Check for easy case: both range endpoints in same text node + nsCOMPtr<nsINode> startNode = range->GetStartParent(); + int32_t startOffset = range->StartOffset(); + nsCOMPtr<nsINode> endNode = range->GetEndParent(); + int32_t endOffset = range->EndOffset(); + if (startNode == endNode && IsTextNode(startNode)) { + // Let's find the block container of the text node + nsCOMPtr<Element> blockParent = GetBlockNodeParent(startNode); + // And apply the background color to that block container if (blockParent && cachedBlockParent != blockParent) { cachedBlockParent = blockParent; - nsCOMPtr<nsIDOMElement> element = do_QueryInterface(blockParent); - int32_t count; - res = mHTMLCSSUtils->SetCSSEquivalentToHTMLStyle(element, nullptr, &bgcolor, &aColor, &count, false); - NS_ENSURE_SUCCESS(res, res); + mHTMLCSSUtils->SetCSSEquivalentToHTMLStyle(blockParent, nullptr, + &bgcolor, &aColor, false); } - } - else if ((startNode == endNode) && nsTextEditUtils::IsBody(startNode) && isCollapsed) - { - // we have no block in the document, let's apply the background to the body - nsCOMPtr<nsIDOMElement> element = do_QueryInterface(startNode); - int32_t count; - res = mHTMLCSSUtils->SetCSSEquivalentToHTMLStyle(element, nullptr, &bgcolor, &aColor, &count, false); - NS_ENSURE_SUCCESS(res, res); - } - else if ((startNode == endNode) && (((endOffset-startOffset) == 1) || (!startOffset && !endOffset))) - { - // a unique node is selected, let's also apply the background color - // to the containing block, possibly the node itself - nsCOMPtr<nsIDOMNode> selectedNode = GetChildAt(startNode, startOffset); - bool isBlock =false; - res = NodeIsBlockStatic(selectedNode, &isBlock); - NS_ENSURE_SUCCESS(res, res); - nsCOMPtr<nsIDOMNode> blockParent = selectedNode; - if (!isBlock) { + } else if (startNode == endNode && + startNode->IsHTMLElement(nsGkAtoms::body) && isCollapsed) { + // No block in the document, let's apply the background to the body + mHTMLCSSUtils->SetCSSEquivalentToHTMLStyle(startNode->AsElement(), + nullptr, &bgcolor, &aColor, + false); + } else if (startNode == endNode && (endOffset - startOffset == 1 || + (!startOffset && !endOffset))) { + // A unique node is selected, let's also apply the background color to + // the containing block, possibly the node itself + nsCOMPtr<nsIContent> selectedNode = startNode->GetChildAt(startOffset); + nsCOMPtr<Element> blockParent; + if (NodeIsBlockStatic(selectedNode)) { + blockParent = selectedNode->AsElement(); + } else { blockParent = GetBlockNodeParent(selectedNode); } if (blockParent && cachedBlockParent != blockParent) { cachedBlockParent = blockParent; - nsCOMPtr<nsIDOMElement> element = do_QueryInterface(blockParent); - int32_t count; - res = mHTMLCSSUtils->SetCSSEquivalentToHTMLStyle(element, nullptr, &bgcolor, &aColor, &count, false); - NS_ENSURE_SUCCESS(res, res); + mHTMLCSSUtils->SetCSSEquivalentToHTMLStyle(blockParent, nullptr, + &bgcolor, &aColor, false); } - } - else - { - // not the easy case. range not contained in single text node. - // there are up to three phases here. There are all the nodes - // reported by the subtree iterator to be processed. And there - // are potentially a starting textnode and an ending textnode - // which are only partially contained by the range. - - // lets handle the nodes reported by the iterator. These nodes - // are entirely contained in the selection range. We build up - // a list of them (since doing operations on the document during - // iteration would perturb the iterator). - - nsCOMPtr<nsIContentIterator> iter = - do_CreateInstance("@mozilla.org/content/subtree-content-iterator;1", &res); - NS_ENSURE_SUCCESS(res, res); - NS_ENSURE_TRUE(iter, NS_ERROR_FAILURE); - - nsCOMArray<nsIDOMNode> arrayOfNodes; - nsCOMPtr<nsIDOMNode> node; - - // iterate range and build up array + } else { + // Not the easy case. Range not contained in single text node. There + // are up to three phases here. There are all the nodes reported by + // the subtree iterator to be processed. And there are potentially a + // starting textnode and an ending textnode which are only partially + // contained by the range. + + // Let's handle the nodes reported by the iterator. These nodes are + // entirely contained in the selection range. We build up a list of + // them (since doing operations on the document during iteration would + // perturb the iterator). + + OwningNonNull<nsIContentIterator> iter = + NS_NewContentSubtreeIterator(); + + nsTArray<OwningNonNull<nsINode>> arrayOfNodes; + nsCOMPtr<nsINode> node; + + // Iterate range and build up array res = iter->Init(range); - // init returns an error if no nodes in range. - // this can easily happen with the subtree - // iterator if the selection doesn't contain - // any *whole* nodes. - if (NS_SUCCEEDED(res)) - { - while (!iter->IsDone()) - { + // Init returns an error if no nodes in range. This can easily happen + // with the subtree iterator if the selection doesn't contain any + // *whole* nodes. + if (NS_SUCCEEDED(res)) { + for (; !iter->IsDone(); iter->Next()) { node = do_QueryInterface(iter->GetCurrentNode()); NS_ENSURE_TRUE(node, NS_ERROR_FAILURE); - if (IsEditable(node)) - { - arrayOfNodes.AppendObject(node); + if (IsEditable(node)) { + arrayOfNodes.AppendElement(*node); } - - iter->Next(); } } - // first check the start parent of the range to see if it needs to - // be separately handled (it does if it's a text node, due to how the + // First check the start parent of the range to see if it needs to be + // separately handled (it does if it's a text node, due to how the // subtree iterator works - it will not have reported it). - if (IsTextNode(startNode) && IsEditable(startNode)) - { - nsCOMPtr<nsIDOMNode> blockParent; - blockParent = GetBlockNodeParent(startNode); + if (IsTextNode(startNode) && IsEditable(startNode)) { + nsCOMPtr<Element> blockParent = GetBlockNodeParent(startNode); if (blockParent && cachedBlockParent != blockParent) { cachedBlockParent = blockParent; - nsCOMPtr<nsIDOMElement> element = do_QueryInterface(blockParent); - int32_t count; - res = mHTMLCSSUtils->SetCSSEquivalentToHTMLStyle(element, nullptr, &bgcolor, &aColor, &count, false); - NS_ENSURE_SUCCESS(res, res); + mHTMLCSSUtils->SetCSSEquivalentToHTMLStyle(blockParent, nullptr, + &bgcolor, &aColor, + false); } } - - // then loop through the list, set the property on each node - int32_t listCount = arrayOfNodes.Count(); - int32_t j; - for (j = 0; j < listCount; j++) - { - node = arrayOfNodes[j]; - // do we have a block here ? - bool isBlock =false; - res = NodeIsBlockStatic(node, &isBlock); - NS_ENSURE_SUCCESS(res, res); - nsCOMPtr<nsIDOMNode> blockParent = node; - if (!isBlock) { - // no we don't, let's find the block ancestor + + // Then loop through the list, set the property on each node + for (auto& node : arrayOfNodes) { + nsCOMPtr<Element> blockParent; + if (NodeIsBlockStatic(node)) { + blockParent = node->AsElement(); + } else { blockParent = GetBlockNodeParent(node); } if (blockParent && cachedBlockParent != blockParent) { cachedBlockParent = blockParent; - nsCOMPtr<nsIDOMElement> element = do_QueryInterface(blockParent); - int32_t count; - // and set the property on it - res = mHTMLCSSUtils->SetCSSEquivalentToHTMLStyle(element, nullptr, &bgcolor, &aColor, &count, false); - NS_ENSURE_SUCCESS(res, res); + mHTMLCSSUtils->SetCSSEquivalentToHTMLStyle(blockParent, nullptr, + &bgcolor, &aColor, + false); } } arrayOfNodes.Clear(); - - // last check the end parent of the range to see if it needs to - // be separately handled (it does if it's a text node, due to how the + + // Last, check the end parent of the range to see if it needs to be + // separately handled (it does if it's a text node, due to how the // subtree iterator works - it will not have reported it). - if (IsTextNode(endNode) && IsEditable(endNode)) - { - nsCOMPtr<nsIDOMNode> blockParent; - blockParent = GetBlockNodeParent(endNode); + if (IsTextNode(endNode) && IsEditable(endNode)) { + nsCOMPtr<Element> blockParent = GetBlockNodeParent(endNode); if (blockParent && cachedBlockParent != blockParent) { cachedBlockParent = blockParent; - nsCOMPtr<nsIDOMElement> element = do_QueryInterface(blockParent); - int32_t count; - res = mHTMLCSSUtils->SetCSSEquivalentToHTMLStyle(element, nullptr, &bgcolor, &aColor, &count, false); - NS_ENSURE_SUCCESS(res, res); + mHTMLCSSUtils->SetCSSEquivalentToHTMLStyle(blockParent, nullptr, + &bgcolor, &aColor, + false); } } } } } - if (!cancel) - { - // post-process + if (!cancel) { + // Post-process res = mRules->DidDoAction(selection, &ruleInfo, res); + NS_ENSURE_SUCCESS(res, res); } - return res; + return NS_OK; } NS_IMETHODIMP nsHTMLEditor::SetBackgroundColor(const nsAString& aColor) { nsresult res; if (IsCSSEnabled()) { // if we are in CSS mode, we have to apply the background color to the
--- a/editor/libeditor/nsHTMLEditor.h +++ b/editor/libeditor/nsHTMLEditor.h @@ -2,17 +2,16 @@ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef nsHTMLEditor_h__ #define nsHTMLEditor_h__ #include "nsCOMPtr.h" -#include "nsCOMArray.h" #include "nsPlaintextEditor.h" #include "nsIEditor.h" #include "nsIHTMLEditor.h" #include "nsITableEditor.h" #include "nsIEditorMailSupport.h" #include "nsIEditorStyleSheets.h" #include "nsEditor.h" @@ -36,28 +35,32 @@ #include "nsTArray.h" #include "nsAutoPtr.h" #include "nsAttrName.h" #include "nsStubMutationObserver.h" #include "mozilla/Attributes.h" #include "mozilla/dom/Element.h" +class nsDocumentFragment; class nsIDOMKeyEvent; class nsITransferable; class nsIClipboard; class TypeInState; class nsIContentFilter; class nsILinkHandler; class nsTableOuterFrame; class nsIDOMRange; class nsRange; struct PropItem; namespace mozilla { +namespace dom { +template<class T> class OwningNonNull; +} namespace widget { struct IMEState; } // namespace widget } // namespace mozilla /** * The HTML editor implementation.<br> * Use to edit HTML document represented as a DOM tree. @@ -586,39 +589,37 @@ protected: nsCOMPtr<nsIDOMNode> *outEndNode, int32_t *outStartOffset, int32_t *outEndOffset, bool aTrustedInput); nsresult ParseFragment(const nsAString & aStr, nsIAtom* aContextLocalName, nsIDocument* aTargetDoc, nsCOMPtr<nsIDOMNode> *outNode, bool aTrustedInput); - nsresult CreateListOfNodesToPaste(nsIDOMNode *aFragmentAsNode, - nsCOMArray<nsIDOMNode>& outNodeList, - nsIDOMNode *aStartNode, + void CreateListOfNodesToPaste(mozilla::dom::DocumentFragment& aFragment, + nsTArray<mozilla::dom::OwningNonNull<nsINode>>& outNodeList, + nsINode* aStartNode, int32_t aStartOffset, - nsIDOMNode *aEndNode, + nsINode* aEndNode, int32_t aEndOffset); nsresult CreateTagStack(nsTArray<nsString> &aTagStack, nsIDOMNode *aNode); - nsresult GetListAndTableParents( bool aEnd, - nsCOMArray<nsIDOMNode>& aListOfNodes, - nsCOMArray<nsIDOMNode>& outArray); - nsresult DiscoverPartialListsAndTables(nsCOMArray<nsIDOMNode>& aPasteNodes, - nsCOMArray<nsIDOMNode>& aListsAndTables, - int32_t *outHighWaterMark); - nsresult ScanForListAndTableStructure(bool aEnd, - nsCOMArray<nsIDOMNode>& aNodes, - nsIDOMNode *aListOrTable, - nsCOMPtr<nsIDOMNode> *outReplaceNode); - nsresult ReplaceOrphanedStructure( bool aEnd, - nsCOMArray<nsIDOMNode>& aNodeArray, - nsCOMArray<nsIDOMNode>& aListAndTableArray, - int32_t aHighWaterMark); - nsIDOMNode* GetArrayEndpoint(bool aEnd, nsCOMArray<nsIDOMNode>& aNodeArray); + enum class StartOrEnd { start, end }; + void GetListAndTableParents(StartOrEnd aStartOrEnd, + nsTArray<mozilla::dom::OwningNonNull<nsINode>>& aNodeList, + nsTArray<mozilla::dom::OwningNonNull<mozilla::dom::Element>>& outArray); + int32_t DiscoverPartialListsAndTables(nsTArray<mozilla::dom::OwningNonNull<nsINode>>& aPasteNodes, + nsTArray<mozilla::dom::OwningNonNull<mozilla::dom::Element>>& aListsAndTables); + nsINode* ScanForListAndTableStructure(StartOrEnd aStartOrEnd, + nsTArray<mozilla::dom::OwningNonNull<nsINode>>& aNodes, + mozilla::dom::Element& aListOrTable); + void ReplaceOrphanedStructure(StartOrEnd aStartOrEnd, + nsTArray<mozilla::dom::OwningNonNull<nsINode>>& aNodeArray, + nsTArray<mozilla::dom::OwningNonNull<mozilla::dom::Element>>& aListAndTableArray, + int32_t aHighWaterMark); /* small utility routine to test if a break node is visible to user */ bool IsVisBreak(nsINode* aNode); bool IsVisBreak(nsIDOMNode *aNode); /* utility routine to possibly adjust the insertion position when inserting a block level element */ void NormalizeEOLInsertPosition(nsIDOMNode *firstNodeToInsert, @@ -628,41 +629,38 @@ protected: /* small utility routine to test the eEditorReadonly bit */ bool IsModifiable(); /* helpers for block transformations */ nsresult MakeDefinitionItem(const nsAString & aItemType); nsresult InsertBasicBlock(const nsAString & aBlockType); /* increase/decrease the font size of selection */ - nsresult RelativeFontChange( int32_t aSizeChange); + enum class FontSize { incr, decr }; + nsresult RelativeFontChange(FontSize aDir); /* helper routines for font size changing */ nsresult RelativeFontChangeOnTextNode( int32_t aSizeChange, nsIDOMCharacterData *aTextNode, int32_t aStartOffset, int32_t aEndOffset); nsresult RelativeFontChangeOnNode(int32_t aSizeChange, nsIContent* aNode); nsresult RelativeFontChangeHelper(int32_t aSizeChange, nsINode* aNode); /* helper routines for inline style */ nsresult SetInlinePropertyOnTextNode(mozilla::dom::Text& aData, int32_t aStartOffset, int32_t aEndOffset, nsIAtom& aProperty, const nsAString* aAttribute, const nsAString& aValue); - nsresult SetInlinePropertyOnNode( nsIDOMNode *aNode, - nsIAtom *aProperty, - const nsAString *aAttribute, - const nsAString *aValue); - nsresult SetInlinePropertyOnNode(nsIContent* aNode, - nsIAtom* aProperty, + nsresult SetInlinePropertyOnNode(nsIContent& aNode, + nsIAtom& aProperty, const nsAString* aAttribute, - const nsAString* aValue); + const nsAString& aValue); nsresult PromoteInlineRange(nsRange* aRange); nsresult PromoteRangeIfStartsOrEndsInNamedAnchor(nsRange* aRange); nsresult SplitStyleAboveRange(nsRange* aRange, nsIAtom *aProperty, const nsAString *aAttribute); nsresult SplitStyleAbovePoint(nsCOMPtr<nsIDOMNode> *aNode, int32_t *aOffset, @@ -753,17 +751,17 @@ protected: bool aClearStyle = true); nsresult ClearStyle(nsCOMPtr<nsIDOMNode>* aNode, int32_t* aOffset, nsIAtom* aProperty, const nsAString* aAttribute); // Data members protected: - nsCOMArray<nsIContentFilter> mContentFilters; + nsTArray<mozilla::dom::OwningNonNull<nsIContentFilter>> mContentFilters; nsRefPtr<TypeInState> mTypeInState; bool mCRInParagraphCreatesParagraph; bool mCSSAware; nsAutoPtr<nsHTMLCSSUtils> mHTMLCSSUtils; @@ -843,17 +841,17 @@ protected: nsCOMPtr<mozilla::dom::Element> mResizingInfo; nsCOMPtr<mozilla::dom::Element> mResizedObject; nsCOMPtr<nsIDOMEventListener> mMouseMotionListenerP; nsCOMPtr<nsISelectionListener> mSelectionListenerP; nsCOMPtr<nsIDOMEventListener> mResizeEventListenerP; - nsCOMArray<nsIHTMLObjectResizeListener> objectResizeEventListeners; + nsTArray<mozilla::dom::OwningNonNull<nsIHTMLObjectResizeListener>> mObjectResizeEventListeners; int32_t mOriginalX; int32_t mOriginalY; int32_t mResizedObjectX; int32_t mResizedObjectY; int32_t mResizedObjectWidth; int32_t mResizedObjectHeight; @@ -954,20 +952,20 @@ friend class nsWSRunObject; friend class nsHTMLEditorEventListener; private: // Helpers bool IsSimpleModifiableNode(nsIContent* aContent, nsIAtom* aProperty, const nsAString* aAttribute, const nsAString* aValue); - nsresult SetInlinePropertyOnNodeImpl(nsIContent* aNode, - nsIAtom* aProperty, + nsresult SetInlinePropertyOnNodeImpl(nsIContent& aNode, + nsIAtom& aProperty, const nsAString* aAttribute, - const nsAString* aValue); + const nsAString& aValue); typedef enum { eInserted, eAppended } InsertedOrAppended; void DoContentInserted(nsIDocument* aDocument, nsIContent* aContainer, nsIContent* aChild, int32_t aIndexInContainer, InsertedOrAppended aInsertedOrAppended); already_AddRefed<mozilla::dom::Element> GetElementOrParentByTagName( const nsAString& aTagName, nsINode* aNode); already_AddRefed<mozilla::dom::Element> CreateElementWithDefaults( const nsAString& aTagName);
--- a/editor/libeditor/nsHTMLEditorStyle.cpp +++ b/editor/libeditor/nsHTMLEditorStyle.cpp @@ -5,17 +5,16 @@ #include "TypeInState.h" #include "mozilla/Assertions.h" #include "mozilla/dom/Selection.h" #include "mozilla/dom/Element.h" #include "mozilla/mozalloc.h" #include "nsAString.h" #include "nsAttrName.h" #include "nsAutoPtr.h" -#include "nsCOMArray.h" #include "nsCOMPtr.h" #include "nsCaseTreatment.h" #include "nsComponentManagerUtils.h" #include "nsDebug.h" #include "nsEditRules.h" #include "nsEditor.h" #include "nsEditorUtils.h" #include "nsError.h" @@ -104,61 +103,57 @@ NS_IMETHODIMP nsHTMLEditor::RemoveAllDef delete mDefaultStyles[j]; } mDefaultStyles.Clear(); return NS_OK; } NS_IMETHODIMP -nsHTMLEditor::SetInlineProperty(nsIAtom *aProperty, +nsHTMLEditor::SetInlineProperty(nsIAtom* aProperty, const nsAString& aAttribute, const nsAString& aValue) { - if (!aProperty) { - return NS_ERROR_NULL_POINTER; - } - if (!mRules) { - return NS_ERROR_NOT_INITIALIZED; - } + NS_ENSURE_TRUE(aProperty, NS_ERROR_NULL_POINTER); + NS_ENSURE_TRUE(mRules, NS_ERROR_NOT_INITIALIZED); + nsCOMPtr<nsIEditRules> kungFuDeathGrip(mRules); ForceCompositionEnd(); nsRefPtr<Selection> selection = GetSelection(); NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER); if (selection->Collapsed()) { - // manipulating text attributes on a collapsed selection only sets state + // Manipulating text attributes on a collapsed selection only sets state // for the next text insertion mTypeInState->SetProp(aProperty, aAttribute, aValue); return NS_OK; } nsAutoEditBatch batchIt(this); nsAutoRules beginRulesSniffing(this, EditAction::insertElement, nsIEditor::eNext); nsAutoSelectionReset selectionResetter(selection, this); nsAutoTxnsConserveSelection dontSpazMySelection(this); bool cancel, handled; nsTextRulesInfo ruleInfo(EditAction::setTextProperty); // Protect the edit rules object from dying - nsCOMPtr<nsIEditRules> kungFuDeathGrip(mRules); nsresult res = mRules->WillDoAction(selection, &ruleInfo, &cancel, &handled); NS_ENSURE_SUCCESS(res, res); if (!cancel && !handled) { - // loop thru the ranges in the selection + // Loop through the ranges in the selection uint32_t rangeCount = selection->RangeCount(); - for (uint32_t rangeIdx = 0; rangeIdx < rangeCount; ++rangeIdx) { + for (uint32_t rangeIdx = 0; rangeIdx < rangeCount; rangeIdx++) { nsRefPtr<nsRange> range = selection->GetRangeAt(rangeIdx); - // adjust range to include any ancestors whose children are entirely + // Adjust range to include any ancestors whose children are entirely // selected res = PromoteInlineRange(range); NS_ENSURE_SUCCESS(res, res); - // check for easy case: both range endpoints in same text node + // Check for easy case: both range endpoints in same text node nsCOMPtr<nsINode> startNode = range->GetStartParent(); nsCOMPtr<nsINode> endNode = range->GetEndParent(); if (startNode && startNode == endNode && startNode->GetAsText()) { res = SetInlinePropertyOnTextNode(*startNode->GetAsText(), range->StartOffset(), range->EndOffset(), *aProperty, &aAttribute, aValue); NS_ENSURE_SUCCESS(res, res); @@ -171,72 +166,64 @@ nsHTMLEditor::SetInlineProperty(nsIAtom // starting textnode and an ending textnode which are only partially // contained by the range. // Let's handle the nodes reported by the iterator. These nodes are // entirely contained in the selection range. We build up a list of them // (since doing operations on the document during iteration would perturb // the iterator). - nsCOMPtr<nsIContentIterator> iter = - do_CreateInstance("@mozilla.org/content/subtree-content-iterator;1", &res); - NS_ENSURE_SUCCESS(res, res); - NS_ENSURE_TRUE(iter, NS_ERROR_FAILURE); + OwningNonNull<nsIContentIterator> iter = NS_NewContentSubtreeIterator(); - nsCOMArray<nsIDOMNode> arrayOfNodes; + nsTArray<OwningNonNull<nsIContent>> arrayOfNodes; - // iterate range and build up array + // Iterate range and build up array res = iter->Init(range); // Init returns an error if there are no nodes in range. This can easily // happen with the subtree iterator if the selection doesn't contain any // *whole* nodes. if (NS_SUCCEEDED(res)) { - nsCOMPtr<nsIDOMNode> node; for (; !iter->IsDone(); iter->Next()) { - node = do_QueryInterface(iter->GetCurrentNode()); - NS_ENSURE_TRUE(node, NS_ERROR_FAILURE); + OwningNonNull<nsINode> node = *iter->GetCurrentNode(); - if (IsEditable(node)) { - arrayOfNodes.AppendObject(node); + if (node->IsContent() && IsEditable(node)) { + arrayOfNodes.AppendElement(*node->AsContent()); } } } - // first check the start parent of the range to see if it needs to - // be separately handled (it does if it's a text node, due to how the + // First check the start parent of the range to see if it needs to be + // separately handled (it does if it's a text node, due to how the // subtree iterator works - it will not have reported it). if (startNode && startNode->GetAsText() && IsEditable(startNode)) { res = SetInlinePropertyOnTextNode(*startNode->GetAsText(), range->StartOffset(), startNode->Length(), *aProperty, &aAttribute, aValue); NS_ENSURE_SUCCESS(res, res); } - // then loop through the list, set the property on each node - int32_t listCount = arrayOfNodes.Count(); - int32_t j; - for (j = 0; j < listCount; j++) { - res = SetInlinePropertyOnNode(arrayOfNodes[j], aProperty, - &aAttribute, &aValue); + // Then loop through the list, set the property on each node + for (auto& node : arrayOfNodes) { + res = SetInlinePropertyOnNode(*node, *aProperty, &aAttribute, aValue); NS_ENSURE_SUCCESS(res, res); } - // last check the end parent of the range to see if it needs to - // be separately handled (it does if it's a text node, due to how the + // Last check the end parent of the range to see if it needs to be + // separately handled (it does if it's a text node, due to how the // subtree iterator works - it will not have reported it). if (endNode && endNode->GetAsText() && IsEditable(endNode)) { res = SetInlinePropertyOnTextNode(*endNode->GetAsText(), 0, range->EndOffset(), *aProperty, &aAttribute, aValue); NS_ENSURE_SUCCESS(res, res); } } } if (!cancel) { - // post-process + // Post-process return mRules->DidDoAction(selection, &ruleInfo, res); } return NS_OK; } // Helper function for SetInlinePropertyOn*: is aNode a simple old <b>, <font>, @@ -371,192 +358,163 @@ nsHTMLEditor::SetInlinePropertyOnTextNod sibling = GetNextHTMLSibling(text); if (IsSimpleModifiableNode(sibling, &aProperty, aAttribute, &aValue)) { // Following sib is already right kind of inline node; slide this over return MoveNode(text, sibling, 0); } } // Reparent the node inside inline node with appropriate {attribute,value} - return SetInlinePropertyOnNode(text, &aProperty, aAttribute, &aValue); + return SetInlinePropertyOnNode(*text, aProperty, aAttribute, aValue); } nsresult -nsHTMLEditor::SetInlinePropertyOnNodeImpl(nsIContent* aNode, - nsIAtom* aProperty, +nsHTMLEditor::SetInlinePropertyOnNodeImpl(nsIContent& aNode, + nsIAtom& aProperty, const nsAString* aAttribute, - const nsAString* aValue) + const nsAString& aValue) { - MOZ_ASSERT(aNode && aProperty); - MOZ_ASSERT(aValue); - nsCOMPtr<nsIAtom> attrAtom = aAttribute ? do_GetAtom(*aAttribute) : nullptr; // If this is an element that can't be contained in a span, we have to // recurse to its children. - if (!TagCanContain(*nsGkAtoms::span, *aNode)) { - if (aNode->HasChildren()) { - nsCOMArray<nsIContent> arrayOfNodes; + if (!TagCanContain(*nsGkAtoms::span, aNode)) { + if (aNode.HasChildren()) { + nsTArray<OwningNonNull<nsIContent>> arrayOfNodes; // Populate the list. - for (nsIContent* child = aNode->GetFirstChild(); + for (nsCOMPtr<nsIContent> child = aNode.GetFirstChild(); child; child = child->GetNextSibling()) { if (IsEditable(child) && !IsEmptyTextNode(this, child)) { - arrayOfNodes.AppendObject(child); + arrayOfNodes.AppendElement(*child); } } // Then loop through the list, set the property on each node. - int32_t listCount = arrayOfNodes.Count(); - for (int32_t j = 0; j < listCount; ++j) { - nsresult rv = SetInlinePropertyOnNode(arrayOfNodes[j], aProperty, - aAttribute, aValue); + for (auto& node : arrayOfNodes) { + nsresult rv = SetInlinePropertyOnNode(node, aProperty, aAttribute, + aValue); NS_ENSURE_SUCCESS(rv, rv); } } return NS_OK; } // First check if there's an adjacent sibling we can put our node into. nsresult res; - nsCOMPtr<nsIContent> previousSibling = GetPriorHTMLSibling(aNode); - nsCOMPtr<nsIContent> nextSibling = GetNextHTMLSibling(aNode); - if (IsSimpleModifiableNode(previousSibling, aProperty, aAttribute, aValue)) { - res = MoveNode(aNode, previousSibling, -1); + nsCOMPtr<nsIContent> previousSibling = GetPriorHTMLSibling(&aNode); + nsCOMPtr<nsIContent> nextSibling = GetNextHTMLSibling(&aNode); + if (IsSimpleModifiableNode(previousSibling, &aProperty, aAttribute, &aValue)) { + res = MoveNode(&aNode, previousSibling, -1); NS_ENSURE_SUCCESS(res, res); - if (IsSimpleModifiableNode(nextSibling, aProperty, aAttribute, aValue)) { + if (IsSimpleModifiableNode(nextSibling, &aProperty, aAttribute, &aValue)) { res = JoinNodes(*previousSibling, *nextSibling); NS_ENSURE_SUCCESS(res, res); } return NS_OK; } - if (IsSimpleModifiableNode(nextSibling, aProperty, aAttribute, aValue)) { - res = MoveNode(aNode, nextSibling, 0); + if (IsSimpleModifiableNode(nextSibling, &aProperty, aAttribute, &aValue)) { + res = MoveNode(&aNode, nextSibling, 0); NS_ENSURE_SUCCESS(res, res); return NS_OK; } - // don't need to do anything if property already set on node - if (mHTMLCSSUtils->IsCSSEditableProperty(aNode, aProperty, aAttribute)) { + // Don't need to do anything if property already set on node + if (mHTMLCSSUtils->IsCSSEditableProperty(&aNode, &aProperty, aAttribute)) { if (mHTMLCSSUtils->IsCSSEquivalentToHTMLInlineStyleSet( - aNode, aProperty, aAttribute, *aValue, nsHTMLCSSUtils::eComputed)) { + &aNode, &aProperty, aAttribute, aValue, nsHTMLCSSUtils::eComputed)) { return NS_OK; } - } else if (IsTextPropertySetByContent(aNode, aProperty, - aAttribute, aValue)) { + } else if (IsTextPropertySetByContent(&aNode, &aProperty, + aAttribute, &aValue)) { return NS_OK; } bool useCSS = (IsCSSEnabled() && - mHTMLCSSUtils->IsCSSEditableProperty(aNode, aProperty, aAttribute)) || + mHTMLCSSUtils->IsCSSEditableProperty(&aNode, &aProperty, aAttribute)) || // bgcolor is always done using CSS aAttribute->EqualsLiteral("bgcolor"); if (useCSS) { nsCOMPtr<dom::Element> tmp; // We only add style="" to <span>s with no attributes (bug 746515). If we // don't have one, we need to make one. - if (aNode->IsHTMLElement(nsGkAtoms::span) && - !aNode->AsElement()->GetAttrCount()) { - tmp = aNode->AsElement(); + if (aNode.IsHTMLElement(nsGkAtoms::span) && + !aNode.AsElement()->GetAttrCount()) { + tmp = aNode.AsElement(); } else { - tmp = InsertContainerAbove(aNode, nsGkAtoms::span); + tmp = InsertContainerAbove(&aNode, nsGkAtoms::span); NS_ENSURE_STATE(tmp); } // Add the CSS styles corresponding to the HTML style request int32_t count; res = mHTMLCSSUtils->SetCSSEquivalentToHTMLStyle(tmp->AsDOMNode(), - aProperty, aAttribute, - aValue, &count, false); + &aProperty, aAttribute, + &aValue, &count, false); NS_ENSURE_SUCCESS(res, res); return NS_OK; } // is it already the right kind of node, but with wrong attribute? - if (aNode->IsHTMLElement(aProperty)) { + if (aNode.IsHTMLElement(&aProperty)) { // Just set the attribute on it. - nsCOMPtr<nsIDOMElement> elem = do_QueryInterface(aNode); - return SetAttribute(elem, *aAttribute, *aValue); + nsCOMPtr<nsIDOMElement> elem = do_QueryInterface(&aNode); + return SetAttribute(elem, *aAttribute, aValue); } // ok, chuck it in its very own container - nsCOMPtr<Element> tmp = InsertContainerAbove(aNode, aProperty, attrAtom, - aValue); + nsCOMPtr<Element> tmp = InsertContainerAbove(&aNode, &aProperty, attrAtom, + &aValue); NS_ENSURE_STATE(tmp); return NS_OK; } nsresult -nsHTMLEditor::SetInlinePropertyOnNode(nsIDOMNode *aNode, - nsIAtom *aProperty, - const nsAString *aAttribute, - const nsAString *aValue) +nsHTMLEditor::SetInlinePropertyOnNode(nsIContent& aNode, + nsIAtom& aProperty, + const nsAString* aAttribute, + const nsAString& aValue) { - // Before setting the property, we remove it if it's already set. - // RemoveStyleInside might remove the node we're looking at or some of its - // descendants, however, in which case we want to set the property on - // whatever wound up in its place. We have to save the original siblings and - // parent to figure this out. - NS_ENSURE_TRUE(aNode && aProperty, NS_ERROR_NULL_POINTER); - - nsCOMPtr<nsIContent> node = do_QueryInterface(aNode); - NS_ENSURE_STATE(node); + nsCOMPtr<nsIContent> previousSibling = aNode.GetPreviousSibling(), + nextSibling = aNode.GetNextSibling(); + NS_ENSURE_STATE(aNode.GetParentNode()); + OwningNonNull<nsINode> parent = *aNode.GetParentNode(); - return SetInlinePropertyOnNode(node, aProperty, aAttribute, aValue); -} - -nsresult -nsHTMLEditor::SetInlinePropertyOnNode(nsIContent* aNode, - nsIAtom* aProperty, - const nsAString* aAttribute, - const nsAString* aValue) -{ - MOZ_ASSERT(aNode); - MOZ_ASSERT(aProperty); - - nsCOMPtr<nsIContent> previousSibling = aNode->GetPreviousSibling(), - nextSibling = aNode->GetNextSibling(); - nsCOMPtr<nsINode> parent = aNode->GetParentNode(); - NS_ENSURE_STATE(parent); - - nsresult res = RemoveStyleInside(aNode->AsDOMNode(), aProperty, aAttribute); + nsresult res = RemoveStyleInside(aNode.AsDOMNode(), &aProperty, aAttribute); NS_ENSURE_SUCCESS(res, res); - if (aNode->GetParentNode()) { + if (aNode.GetParentNode()) { // The node is still where it was return SetInlinePropertyOnNodeImpl(aNode, aProperty, aAttribute, aValue); } // It's vanished. Use the old siblings for reference to construct a // list. But first, verify that the previous/next siblings are still // where we expect them; otherwise we have to give up. if ((previousSibling && previousSibling->GetParentNode() != parent) || (nextSibling && nextSibling->GetParentNode() != parent)) { return NS_ERROR_UNEXPECTED; } - nsCOMArray<nsIContent> nodesToSet; + nsTArray<OwningNonNull<nsIContent>> nodesToSet; nsCOMPtr<nsIContent> cur = previousSibling ? previousSibling->GetNextSibling() : parent->GetFirstChild(); - while (cur && cur != nextSibling) { + for (; cur && cur != nextSibling; cur = cur->GetNextSibling()) { if (IsEditable(cur)) { - nodesToSet.AppendObject(cur); + nodesToSet.AppendElement(*cur); } - cur = cur->GetNextSibling(); } - int32_t nodesToSetCount = nodesToSet.Count(); - for (int32_t k = 0; k < nodesToSetCount; k++) { - res = SetInlinePropertyOnNodeImpl(nodesToSet[k], aProperty, - aAttribute, aValue); + for (auto& node : nodesToSet) { + res = SetInlinePropertyOnNodeImpl(node, aProperty, aAttribute, aValue); NS_ENSURE_SUCCESS(res, res); } return NS_OK; } nsresult @@ -1411,177 +1369,153 @@ nsHTMLEditor::RemoveInlinePropertyImpl(n nsHTMLCSSUtils::eComputed) && // startNode's computed style indicates the CSS equivalence to // the HTML style to remove is applied; but we found no element // in the ancestors of startNode carrying specified styles; // assume it comes from a rule and let's try to insert a span // "inverting" the style mHTMLCSSUtils->IsCSSInvertible(*aProperty, aAttribute)) { NS_NAMED_LITERAL_STRING(value, "-moz-editor-invert-value"); - SetInlinePropertyOnNode(node->AsContent(), aProperty, - aAttribute, &value); + SetInlinePropertyOnNode(*node->AsContent(), *aProperty, + aAttribute, value); } } } } } if (!cancel) { // Post-process res = mRules->DidDoAction(selection, &ruleInfo, res); NS_ENSURE_SUCCESS(res, res); } return NS_OK; } NS_IMETHODIMP nsHTMLEditor::IncreaseFontSize() { - return RelativeFontChange(1); + return RelativeFontChange(FontSize::incr); } NS_IMETHODIMP nsHTMLEditor::DecreaseFontSize() { - return RelativeFontChange(-1); + return RelativeFontChange(FontSize::decr); } nsresult -nsHTMLEditor::RelativeFontChange( int32_t aSizeChange) +nsHTMLEditor::RelativeFontChange(FontSize aDir) { - // Can only change font size by + or - 1 - if ( !( (aSizeChange==1) || (aSizeChange==-1) ) ) - return NS_ERROR_ILLEGAL_VALUE; - ForceCompositionEnd(); - // Get the selection + // Get the selection nsRefPtr<Selection> selection = GetSelection(); NS_ENSURE_TRUE(selection, NS_ERROR_FAILURE); - // Is the selection collapsed? - // if it's collapsed set typing state + // If selection is collapsed, set typing state if (selection->Collapsed()) { - nsCOMPtr<nsIAtom> atom; - if (aSizeChange == 1) { - atom = nsGkAtoms::big; - } else { - atom = nsGkAtoms::small; - } + nsIAtom& atom = aDir == FontSize::incr ? *nsGkAtoms::big : + *nsGkAtoms::small; // Let's see in what kind of element the selection is - int32_t offset; - nsCOMPtr<nsINode> selectedNode; - GetStartNodeAndOffset(selection, getter_AddRefs(selectedNode), &offset); - if (selectedNode && IsTextNode(selectedNode)) { - selectedNode = selectedNode->GetParentNode(); + NS_ENSURE_TRUE(selection->RangeCount() && + selection->GetRangeAt(0)->GetStartParent(), NS_OK); + OwningNonNull<nsINode> selectedNode = + *selection->GetRangeAt(0)->GetStartParent(); + if (IsTextNode(selectedNode)) { + NS_ENSURE_TRUE(selectedNode->GetParentNode(), NS_OK); + selectedNode = *selectedNode->GetParentNode(); } - NS_ENSURE_TRUE(selectedNode, NS_OK); - if (!CanContainTag(*selectedNode, *atom)) { + if (!CanContainTag(selectedNode, atom)) { return NS_OK; } - // manipulating text attributes on a collapsed selection only sets state for the next text insertion - mTypeInState->SetProp(atom, EmptyString(), EmptyString()); + // Manipulating text attributes on a collapsed selection only sets state + // for the next text insertion + mTypeInState->SetProp(&atom, EmptyString(), EmptyString()); return NS_OK; } - - // wrap with txn batching, rules sniffing, and selection preservation code + + // Wrap with txn batching, rules sniffing, and selection preservation code nsAutoEditBatch batchIt(this); - nsAutoRules beginRulesSniffing(this, EditAction::setTextProperty, nsIEditor::eNext); + nsAutoRules beginRulesSniffing(this, EditAction::setTextProperty, + nsIEditor::eNext); nsAutoSelectionReset selectionResetter(selection, this); nsAutoTxnsConserveSelection dontSpazMySelection(this); - // loop thru the ranges in the selection + // Loop through the ranges in the selection uint32_t rangeCount = selection->RangeCount(); for (uint32_t rangeIdx = 0; rangeIdx < rangeCount; ++rangeIdx) { nsRefPtr<nsRange> range = selection->GetRangeAt(rangeIdx); - // adjust range to include any ancestors who's children are entirely selected + // Adjust range to include any ancestors with entirely selected children nsresult res = PromoteInlineRange(range); NS_ENSURE_SUCCESS(res, res); - - // check for easy case: both range endpoints in same text node - nsCOMPtr<nsIDOMNode> startNode, endNode; - res = range->GetStartContainer(getter_AddRefs(startNode)); - NS_ENSURE_SUCCESS(res, res); - res = range->GetEndContainer(getter_AddRefs(endNode)); - NS_ENSURE_SUCCESS(res, res); - if ((startNode == endNode) && IsTextNode(startNode)) - { - int32_t startOffset, endOffset; - range->GetStartOffset(&startOffset); - range->GetEndOffset(&endOffset); - nsCOMPtr<nsIDOMCharacterData> nodeAsText = do_QueryInterface(startNode); - res = RelativeFontChangeOnTextNode(aSizeChange, nodeAsText, startOffset, endOffset); + + // Check for easy case: both range endpoints in same text node + nsCOMPtr<nsINode> startNode = range->GetStartParent(); + nsCOMPtr<nsINode> endNode = range->GetEndParent(); + if (startNode == endNode && IsTextNode(startNode)) { + res = RelativeFontChangeOnTextNode(aDir == FontSize::incr ? +1 : -1, + static_cast<nsIDOMCharacterData*>(startNode->AsDOMNode()), + range->StartOffset(), range->EndOffset()); NS_ENSURE_SUCCESS(res, res); - } - else - { - // not the easy case. range not contained in single text node. - // there are up to three phases here. There are all the nodes - // reported by the subtree iterator to be processed. And there - // are potentially a starting textnode and an ending textnode - // which are only partially contained by the range. - - // lets handle the nodes reported by the iterator. These nodes - // are entirely contained in the selection range. We build up - // a list of them (since doing operations on the document during - // iteration would perturb the iterator). + } else { + // Not the easy case. Range not contained in single text node. There + // are up to three phases here. There are all the nodes reported by the + // subtree iterator to be processed. And there are potentially a + // starting textnode and an ending textnode which are only partially + // contained by the range. - nsCOMPtr<nsIContentIterator> iter = - do_CreateInstance("@mozilla.org/content/subtree-content-iterator;1", &res); - NS_ENSURE_SUCCESS(res, res); - NS_ENSURE_TRUE(iter, NS_ERROR_FAILURE); + // Let's handle the nodes reported by the iterator. These nodes are + // entirely contained in the selection range. We build up a list of them + // (since doing operations on the document during iteration would perturb + // the iterator). - // iterate range and build up array + OwningNonNull<nsIContentIterator> iter = NS_NewContentSubtreeIterator(); + + // Iterate range and build up array res = iter->Init(range); if (NS_SUCCEEDED(res)) { - nsCOMArray<nsIContent> arrayOfNodes; - while (!iter->IsDone()) { + nsTArray<OwningNonNull<nsIContent>> arrayOfNodes; + for (; !iter->IsDone(); iter->Next()) { NS_ENSURE_TRUE(iter->GetCurrentNode()->IsContent(), NS_ERROR_FAILURE); - nsCOMPtr<nsIContent> node = iter->GetCurrentNode()->AsContent(); + OwningNonNull<nsIContent> node = *iter->GetCurrentNode()->AsContent(); if (IsEditable(node)) { - arrayOfNodes.AppendObject(node); + arrayOfNodes.AppendElement(node); } - - iter->Next(); } - - // now that we have the list, do the font size change on each node - int32_t listCount = arrayOfNodes.Count(); - for (int32_t j = 0; j < listCount; ++j) { - nsIContent* node = arrayOfNodes[j]; - res = RelativeFontChangeOnNode(aSizeChange, node); + + // Now that we have the list, do the font size change on each node + for (auto& node : arrayOfNodes) { + res = RelativeFontChangeOnNode(aDir == FontSize::incr ? +1 : -1, + node); NS_ENSURE_SUCCESS(res, res); } - arrayOfNodes.Clear(); } - // now check the start and end parents of the range to see if they need to - // be separately handled (they do if they are text nodes, due to how the - // subtree iterator works - it will not have reported them). - if (IsTextNode(startNode) && IsEditable(startNode)) - { - nsCOMPtr<nsIDOMCharacterData> nodeAsText = do_QueryInterface(startNode); - int32_t startOffset; - uint32_t textLen; - range->GetStartOffset(&startOffset); - nodeAsText->GetLength(&textLen); - res = RelativeFontChangeOnTextNode(aSizeChange, nodeAsText, startOffset, textLen); + // Now check the start and end parents of the range to see if they need + // to be separately handled (they do if they are text nodes, due to how + // the subtree iterator works - it will not have reported them). + if (IsTextNode(startNode) && IsEditable(startNode)) { + res = RelativeFontChangeOnTextNode(aDir == FontSize::incr ? +1 : -1, + static_cast<nsIDOMCharacterData*>(startNode->AsDOMNode()), + range->StartOffset(), startNode->Length()); NS_ENSURE_SUCCESS(res, res); } - if (IsTextNode(endNode) && IsEditable(endNode)) - { + if (IsTextNode(endNode) && IsEditable(endNode)) { nsCOMPtr<nsIDOMCharacterData> nodeAsText = do_QueryInterface(endNode); int32_t endOffset; range->GetEndOffset(&endOffset); - res = RelativeFontChangeOnTextNode(aSizeChange, nodeAsText, 0, endOffset); + res = RelativeFontChangeOnTextNode(aDir == FontSize::incr ? +1 : -1, + static_cast<nsIDOMCharacterData*>(startNode->AsDOMNode()), + 0, range->EndOffset()); NS_ENSURE_SUCCESS(res, res); } } } - - return NS_OK; + + return NS_OK; } nsresult nsHTMLEditor::RelativeFontChangeOnTextNode( int32_t aSizeChange, nsIDOMCharacterData *aTextNode, int32_t aStartOffset, int32_t aEndOffset) {
--- a/editor/libeditor/nsHTMLObjectResizer.cpp +++ b/editor/libeditor/nsHTMLObjectResizer.cpp @@ -8,17 +8,16 @@ #include "mozilla/DebugOnly.h" #include "mozilla/LookAndFeel.h" #include "mozilla/MathAlgorithms.h" #include "mozilla/Preferences.h" #include "mozilla/mozalloc.h" #include "nsAString.h" #include "nsAlgorithm.h" #include "nsAutoPtr.h" -#include "nsCOMArray.h" #include "nsCOMPtr.h" #include "nsDebug.h" #include "nsEditorUtils.h" #include "nsError.h" #include "nsGkAtoms.h" #include "nsHTMLCSSUtils.h" #include "nsHTMLEditUtils.h" #include "nsHTMLEditor.h" @@ -494,24 +493,18 @@ nsHTMLEditor::HideShadowAndInfo() mResizingInfo->SetAttr(kNameSpaceID_None, nsGkAtoms::_class, NS_LITERAL_STRING("hidden"), true); } nsresult nsHTMLEditor::StartResizing(nsIDOMElement *aHandle) { // First notify the listeners if any - int32_t listenersCount = objectResizeEventListeners.Count(); - if (listenersCount) { - nsCOMPtr<nsIHTMLObjectResizeListener> listener; - int32_t index; - for (index = 0; index < listenersCount; index++) { - listener = objectResizeEventListeners[index]; - listener->OnStartResizing(static_cast<nsIDOMElement*>(GetAsDOMNode(mResizedObject))); - } + for (auto& listener : mObjectResizeEventListeners) { + listener->OnStartResizing(static_cast<nsIDOMElement*>(GetAsDOMNode(mResizedObject))); } mIsResizing = true; mActivatedHandle = do_QueryInterface(aHandle); NS_ENSURE_STATE(mActivatedHandle || !aHandle); mActivatedHandle->SetAttr(kNameSpaceID_None, nsGkAtoms::_moz_activated, NS_LITERAL_STRING("true"), true); @@ -971,26 +964,20 @@ nsHTMLEditor::SetFinalSize(int32_t aX, i if (setWidth) mHTMLCSSUtils->RemoveCSSProperty(*resizedObject, *nsGkAtoms::width, EmptyString()); if (setHeight) mHTMLCSSUtils->RemoveCSSProperty(*resizedObject, *nsGkAtoms::height, EmptyString()); } // finally notify the listeners if any - int32_t listenersCount = objectResizeEventListeners.Count(); - if (listenersCount) { - nsCOMPtr<nsIHTMLObjectResizeListener> listener; - int32_t index; - for (index = 0; index < listenersCount; index++) { - listener = objectResizeEventListeners[index]; - listener->OnEndResizing(static_cast<nsIDOMElement*>(GetAsDOMNode(mResizedObject)), - mResizedObjectWidth, mResizedObjectHeight, - width, height); - } + for (auto& listener : mObjectResizeEventListeners) { + listener->OnEndResizing(static_cast<nsIDOMElement*>(GetAsDOMNode(mResizedObject)), + mResizedObjectWidth, mResizedObjectHeight, width, + height); } // keep track of that size mResizedObjectWidth = width; mResizedObjectHeight = height; RefreshResizers(); } @@ -1016,34 +1003,32 @@ nsHTMLEditor::SetObjectResizingEnabled(b mIsObjectResizingEnabled = aObjectResizingEnabled; return NS_OK; } NS_IMETHODIMP nsHTMLEditor::AddObjectResizeEventListener(nsIHTMLObjectResizeListener * aListener) { NS_ENSURE_ARG_POINTER(aListener); - if (objectResizeEventListeners.Count() && - objectResizeEventListeners.IndexOf(aListener) != -1) { + if (mObjectResizeEventListeners.Contains(aListener)) { /* listener already registered */ NS_ASSERTION(false, "trying to register an already registered object resize event listener"); return NS_OK; } - objectResizeEventListeners.AppendObject(aListener); + mObjectResizeEventListeners.AppendElement(*aListener); return NS_OK; } NS_IMETHODIMP nsHTMLEditor::RemoveObjectResizeEventListener(nsIHTMLObjectResizeListener * aListener) { NS_ENSURE_ARG_POINTER(aListener); - if (!objectResizeEventListeners.Count() || - objectResizeEventListeners.IndexOf(aListener) == -1) { + if (!mObjectResizeEventListeners.Contains(aListener)) { /* listener was not registered */ NS_ASSERTION(false, "trying to remove an object resize event listener that was not already registered"); return NS_OK; } - objectResizeEventListeners.RemoveObject(aListener); + mObjectResizeEventListeners.RemoveElement(aListener); return NS_OK; }
--- a/editor/reftests/reftest.list +++ b/editor/reftests/reftest.list @@ -72,17 +72,17 @@ skip-if(B2G||Mulet) fails-if(Android) ne == spellcheck-comma-valid.html spellcheck-comma-valid-ref.html == spellcheck-hyphen-multiple-valid.html spellcheck-hyphen-multiple-valid-ref.html skip-if(B2G||Mulet) fails-if(Android) needs-focus != spellcheck-hyphen-multiple-invalid.html spellcheck-hyphen-multiple-invalid-ref.html # Initial mulet triage: parity with B2G/B2G Desktop == spellcheck-dotafterquote-valid.html spellcheck-dotafterquote-valid-ref.html == spellcheck-url-valid.html spellcheck-url-valid-ref.html == unneeded_scroll.html unneeded_scroll-ref.html skip-if(B2G||Mulet) == caret_on_presshell_reinit.html caret_on_presshell_reinit-ref.html # Initial mulet triage: parity with B2G/B2G Desktop skip-if(B2G||Mulet) == caret_on_presshell_reinit-2.html caret_on_presshell_reinit-ref.html # Initial mulet triage: parity with B2G/B2G Desktop -skip-if(B2G||Mulet) == 642800.html 642800-ref.html # Initial mulet triage: parity with B2G/B2G Desktop +skip-if(B2G||Mulet) fuzzy-if(asyncPanZoom&&!layersGPUAccelerated,102,2824) == 642800.html 642800-ref.html # Initial mulet triage: parity with B2G/B2G Desktop == selection_visibility_after_reframe.html selection_visibility_after_reframe-ref.html != selection_visibility_after_reframe-2.html selection_visibility_after_reframe-ref.html != selection_visibility_after_reframe-3.html selection_visibility_after_reframe-ref.html == 672709.html 672709-ref.html == 338427-1.html 338427-1-ref.html skip-if(Android||B2G||Mulet) needs-focus == 674212-spellcheck.html 674212-spellcheck-ref.html # Initial mulet triage: parity with B2G/B2G Desktop skip-if(Android||B2G||Mulet) needs-focus == 338427-2.html 338427-2-ref.html # Initial mulet triage: parity with B2G/B2G Desktop skip-if(Android||B2G||Mulet) needs-focus == 338427-3.html 338427-3-ref.html # Initial mulet triage: parity with B2G/B2G Desktop
--- a/gfx/layers/d3d11/TextureD3D11.cpp +++ b/gfx/layers/d3d11/TextureD3D11.cpp @@ -1009,16 +1009,20 @@ SyncObjectD3D11::FinalizeFrame() } if (mD3D10SyncedTextures.size()) { RefPtr<IDXGIKeyedMutex> mutex; hr = mD3D10Texture->QueryInterface((IDXGIKeyedMutex**)byRef(mutex)); hr = mutex->AcquireSync(0, 20000); if (hr == WAIT_TIMEOUT) { + if (gfxWindowsPlatform::GetPlatform()->DidRenderingDeviceReset()) { + gfxWarning() << "AcquireSync timed out because of device reset."; + return; + } MOZ_CRASH(); } D3D10_BOX box; box.front = box.top = box.left = 0; box.back = box.bottom = box.right = 1; ID3D10Device* device = gfxWindowsPlatform::GetPlatform()->GetD3D10Device(); @@ -1033,16 +1037,20 @@ SyncObjectD3D11::FinalizeFrame() } if (mD3D11SyncedTextures.size()) { RefPtr<IDXGIKeyedMutex> mutex; hr = mD3D11Texture->QueryInterface((IDXGIKeyedMutex**)byRef(mutex)); hr = mutex->AcquireSync(0, 20000); if (hr == WAIT_TIMEOUT) { + if (gfxWindowsPlatform::GetPlatform()->DidRenderingDeviceReset()) { + gfxWarning() << "AcquireSync timed out because of device reset."; + return; + } MOZ_CRASH(); } D3D11_BOX box; box.front = box.top = box.left = 0; box.back = box.bottom = box.right = 1; ID3D11Device* dev = gfxWindowsPlatform::GetPlatform()->GetD3D11ContentDevice();
--- a/image/src/ProgressTracker.cpp +++ b/image/src/ProgressTracker.cpp @@ -82,26 +82,24 @@ CheckProgressConsistency(Progress aProgr if (aProgress & FLAG_HAS_ERROR) { // No preconditions. } } void ProgressTracker::SetImage(Image* aImage) { - MutexAutoLock lock(mImageMutex); MOZ_ASSERT(aImage, "Setting null image"); MOZ_ASSERT(!mImage, "Setting image when we already have one"); mImage = aImage; } void ProgressTracker::ResetImage() { - MutexAutoLock lock(mImageMutex); MOZ_ASSERT(mImage, "Resetting image when it's already null!"); mImage = nullptr; } uint32_t ProgressTracker::GetImageStatus() const { uint32_t status = imgIRequest::STATUS_NONE; @@ -180,19 +178,18 @@ class AsyncNotifyRunnable : public nsRun }; void ProgressTracker::Notify(IProgressObserver* aObserver) { MOZ_ASSERT(NS_IsMainThread()); #ifdef PR_LOGGING - nsRefPtr<Image> image = GetImage(); - if (image && image->GetURI()) { - nsRefPtr<ImageURL> uri(image->GetURI()); + if (mImage && mImage->GetURI()) { + nsRefPtr<ImageURL> uri(mImage->GetURI()); nsAutoCString spec; uri->GetSpec(spec); LOG_FUNC_WITH_PARAM(GetImgLog(), "ProgressTracker::Notify async", "uri", spec.get()); } else { LOG_FUNC_WITH_PARAM(GetImgLog(), "ProgressTracker::Notify async", "uri", "<unknown>"); } @@ -249,20 +246,19 @@ class AsyncNotifyCurrentStateRunnable : }; void ProgressTracker::NotifyCurrentState(IProgressObserver* aObserver) { MOZ_ASSERT(NS_IsMainThread()); #ifdef PR_LOGGING - nsRefPtr<Image> image = GetImage(); nsAutoCString spec; - if (image && image->GetURI()) { - image->GetURI()->GetSpec(spec); + if (mImage && mImage->GetURI()) { + mImage->GetURI()->GetSpec(spec); } LOG_FUNC_WITH_PARAM(GetImgLog(), "ProgressTracker::NotifyCurrentState", "uri", spec.get()); #endif aObserver->SetNotificationsDeferred(true); nsCOMPtr<nsIRunnable> ev = new AsyncNotifyCurrentStateRunnable(this, @@ -366,51 +362,49 @@ ProgressTracker::SyncNotifyProgress(Prog } // Apply the changes. mProgress |= progress; CheckProgressConsistency(mProgress); // Send notifications. - SyncNotifyInternal(mObservers, HasImage(), progress, aInvalidRect); + SyncNotifyInternal(mObservers, !!mImage, progress, aInvalidRect); if (progress & FLAG_HAS_ERROR) { FireFailureNotification(); } } void ProgressTracker::SyncNotify(IProgressObserver* aObserver) { MOZ_ASSERT(NS_IsMainThread()); - nsRefPtr<Image> image = GetImage(); - #ifdef PR_LOGGING nsAutoCString spec; - if (image && image->GetURI()) { - image->GetURI()->GetSpec(spec); + if (mImage && mImage->GetURI()) { + mImage->GetURI()->GetSpec(spec); } LOG_SCOPE_WITH_PARAM(GetImgLog(), "ProgressTracker::SyncNotify", "uri", spec.get()); #endif nsIntRect rect; - if (image) { - if (NS_FAILED(image->GetWidth(&rect.width)) || - NS_FAILED(image->GetHeight(&rect.height))) { + if (mImage) { + if (NS_FAILED(mImage->GetWidth(&rect.width)) || + NS_FAILED(mImage->GetHeight(&rect.height))) { // Either the image has no intrinsic size, or it has an error. rect = GetMaxSizedIntRect(); } } ObserverArray array; array.AppendElement(aObserver); - SyncNotifyInternal(array, !!image, mProgress, rect); + SyncNotifyInternal(array, !!mImage, mProgress, rect); } void ProgressTracker::EmulateRequestFinished(IProgressObserver* aObserver) { MOZ_ASSERT(NS_IsMainThread(), "SyncNotifyState and mObservers are not threadsafe"); nsRefPtr<IProgressObserver> kungFuDeathGrip(aObserver); @@ -512,22 +506,21 @@ ProgressTracker::OnImageAvailable() void ProgressTracker::FireFailureNotification() { MOZ_ASSERT(NS_IsMainThread()); // Some kind of problem has happened with image decoding. // Report the URI to net:failed-to-process-uri-conent observers. - nsRefPtr<Image> image = GetImage(); - if (image) { + if (mImage) { // Should be on main thread, so ok to create a new nsIURI. nsCOMPtr<nsIURI> uri; { - nsRefPtr<ImageURL> threadsafeUriData = image->GetURI(); + nsRefPtr<ImageURL> threadsafeUriData = mImage->GetURI(); uri = threadsafeUriData ? threadsafeUriData->ToIURI() : nullptr; } if (uri) { nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService(); if (os) { os->NotifyObservers(uri, "net:failed-to-process-uri-content", nullptr); } }
--- a/image/src/ProgressTracker.h +++ b/image/src/ProgressTracker.h @@ -2,17 +2,16 @@ * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef mozilla_image_src_ProgressTracker_h #define mozilla_image_src_ProgressTracker_h -#include "mozilla/Mutex.h" #include "mozilla/RefPtr.h" #include "mozilla/WeakPtr.h" #include "nsCOMPtr.h" #include "nsTObserverArray.h" #include "nsThreadUtils.h" #include "nsRect.h" #include "IProgressObserver.h" @@ -72,25 +71,23 @@ class ProgressTracker : public mozilla:: { virtual ~ProgressTracker() { } public: MOZ_DECLARE_REFCOUNTED_TYPENAME(ProgressTracker) NS_INLINE_DECL_THREADSAFE_REFCOUNTING(ProgressTracker) ProgressTracker() - : mImageMutex("ProgressTracker::mImage") - , mImage(nullptr) + : mImage(nullptr) , mProgress(NoProgress) { } - bool HasImage() const { MutexAutoLock lock(mImageMutex); return mImage; } + bool HasImage() const { return mImage; } already_AddRefed<Image> GetImage() const { - MutexAutoLock lock(mImageMutex); nsRefPtr<Image> image = mImage; return image.forget(); } // Get the current image status (as in imgIRequest). uint32_t GetImageStatus() const; // Get the current Progress. @@ -188,19 +185,17 @@ private: // Main thread only, since notifications are expected on the main thread, and // mObservers is not threadsafe. static void SyncNotifyInternal(ObserverArray& aObservers, bool aHasImage, Progress aProgress, const nsIntRect& aInvalidRect); nsCOMPtr<nsIRunnable> mRunnable; - // mImage is a weak ref; it should be set to null when the image goes out of - // scope. mImageMutex protects mImage. - mutable Mutex mImageMutex; + // This weak ref should be set null when the image goes out of scope. Image* mImage; // List of observers attached to the image. Each observer represents a // consumer using the image. Array and/or individual elements should only be // accessed on the main thread. ObserverArray mObservers; Progress mProgress;
--- a/js/src/gc/Nursery.cpp +++ b/js/src/gc/Nursery.cpp @@ -532,18 +532,38 @@ js::Nursery::collectToFixedPoint(MinorCo } } } MOZ_ALWAYS_INLINE void js::Nursery::traceObject(MinorCollectionTracer* trc, JSObject* obj) { const Class* clasp = obj->getClass(); - if (clasp->trace) + if (clasp->trace) { + if (clasp->trace == InlineTypedObject::obj_trace) { + TypeDescr* descr = &obj->as<InlineTypedObject>().typeDescr(); + if (descr->hasTraceList()) { + markTraceList(trc, descr->traceList(), + obj->as<InlineTypedObject>().inlineTypedMem()); + } + return; + } + if (clasp == &UnboxedPlainObject::class_) { + JSObject** pexpando = obj->as<UnboxedPlainObject>().addressOfExpando(); + if (*pexpando) + markObject(trc, pexpando); + const UnboxedLayout& layout = obj->as<UnboxedPlainObject>().layout(); + if (layout.traceList()) { + markTraceList(trc, layout.traceList(), + obj->as<UnboxedPlainObject>().data()); + } + return; + } clasp->trace(trc, obj); + } MOZ_ASSERT(obj->isNative() == clasp->isNative()); if (!clasp->isNative()) return; NativeObject* nobj = &obj->as<NativeObject>(); // Note: the contents of copy on write elements pointers are filled in // during parsing and cannot contain nursery pointers. @@ -574,26 +594,52 @@ js::Nursery::markSlots(MinorCollectionTr MOZ_ALWAYS_INLINE void js::Nursery::markSlot(MinorCollectionTracer* trc, HeapSlot* slotp) { if (!slotp->isObject()) return; JSObject* obj = &slotp->toObject(); - if (!IsInsideNursery(obj)) - return; - - if (getForwardedPointer(&obj)) { + if (markObject(trc, &obj)) slotp->unsafeGet()->setObject(*obj); - return; - } +} - JSObject* tenured = static_cast<JSObject*>(moveToTenured(trc, obj)); - slotp->unsafeGet()->setObject(*tenured); +MOZ_ALWAYS_INLINE void +js::Nursery::markTraceList(MinorCollectionTracer* trc, const int32_t* traceList, uint8_t* memory) +{ + while (*traceList != -1) { + // Strings are not in the nursery and do not need tracing. + traceList++; + } + traceList++; + while (*traceList != -1) { + JSObject** pobj = reinterpret_cast<JSObject **>(memory + *traceList); + markObject(trc, pobj); + traceList++; + } + traceList++; + while (*traceList != -1) { + HeapSlot* pslot = reinterpret_cast<HeapSlot *>(memory + *traceList); + markSlot(trc, pslot); + traceList++; + } +} + +MOZ_ALWAYS_INLINE bool +js::Nursery::markObject(MinorCollectionTracer* trc, JSObject** pobj) +{ + if (!IsInsideNursery(*pobj)) + return false; + + if (getForwardedPointer(pobj)) + return true; + + *pobj = static_cast<JSObject*>(moveToTenured(trc, *pobj)); + return true; } void* js::Nursery::moveToTenured(MinorCollectionTracer* trc, JSObject* src) { AllocKind dstKind = src->allocKindForTenure(*this); Zone* zone = src->zone();
--- a/js/src/gc/Nursery.h +++ b/js/src/gc/Nursery.h @@ -308,16 +308,19 @@ class Nursery * Move the object at |src| in the Nursery to an already-allocated cell * |dst| in Tenured. */ void collectToFixedPoint(gc::MinorCollectionTracer* trc, TenureCountCache& tenureCounts); MOZ_ALWAYS_INLINE void traceObject(gc::MinorCollectionTracer* trc, JSObject* src); MOZ_ALWAYS_INLINE void markSlots(gc::MinorCollectionTracer* trc, HeapSlot* vp, uint32_t nslots); MOZ_ALWAYS_INLINE void markSlots(gc::MinorCollectionTracer* trc, HeapSlot* vp, HeapSlot* end); MOZ_ALWAYS_INLINE void markSlot(gc::MinorCollectionTracer* trc, HeapSlot* slotp); + MOZ_ALWAYS_INLINE void markTraceList(gc::MinorCollectionTracer* trc, + const int32_t* traceList, uint8_t* memory); + MOZ_ALWAYS_INLINE bool markObject(gc::MinorCollectionTracer* trc, JSObject** pobj); void* moveToTenured(gc::MinorCollectionTracer* trc, JSObject* src); size_t moveObjectToTenured(gc::MinorCollectionTracer* trc, JSObject* dst, JSObject* src, gc::AllocKind dstKind); size_t moveElementsToTenured(NativeObject* dst, NativeObject* src, gc::AllocKind dstKind); size_t moveSlotsToTenured(NativeObject* dst, NativeObject* src, gc::AllocKind dstKind); /* Handle relocation of slots/elements pointers stored in Ion frames. */ void setForwardingPointer(void* oldData, void* newData, bool direct);
--- a/js/src/jit/BaselineIC.cpp +++ b/js/src/jit/BaselineIC.cpp @@ -10125,16 +10125,27 @@ TryAttachStringSplit(JSContext* cx, ICCa RootedString argString(cx, args[0].toString()); RootedArrayObject obj(cx, &res.toObject().as<ArrayObject>()); RootedValue arr(cx); // Copy the array before storing in stub. if (!CopyArray(cx, obj, &arr)) return false; + // Atomize all elements of the array. + RootedArrayObject arrObj(cx, &arr.toObject().as<ArrayObject>()); + uint32_t initLength = arrObj->length(); + for (uint32_t i = 0; i < initLength; i++) { + JSAtom* str = js::AtomizeString(cx, arrObj->getDenseElement(i).toString()); + if (!str) + return false; + + arrObj->setDenseElement(i, StringValue(str)); + } + ICCall_StringSplit::Compiler compiler(cx, stub->fallbackMonitorStub()->firstMonitorStub(), script->pcToOffset(pc), thisString, argString, arr); ICStub* newStub = compiler.getStub(compiler.getStubSpace(script)); if (!newStub) return false; stub->addNewStub(newStub);
--- a/js/src/jit/IonBuilder.cpp +++ b/js/src/jit/IonBuilder.cpp @@ -12868,52 +12868,30 @@ IonBuilder::storeReferenceTypedObjectVal current->add(store); return true; } MConstant* IonBuilder::constant(const Value& v) { - // For performance reason (TLS) and error code handling (AtomizeString), we - // should prefer the specialized frunction constantMaybeAtomize instead of - // constant. MOZ_ASSERT(!v.isString() || v.toString()->isAtom(), - "To handle non-atomized strings, you should use constantMaybeAtomize instead of constant."); - if (v.isString() && MOZ_UNLIKELY(!v.toString()->isAtom())) { - MConstant* cst = constantMaybeAtomize(v); - if (!cst) - js::CrashAtUnhandlableOOM("Use constantMaybeAtomize."); - return cst; - } + "Handle non-atomized strings outside IonBuilder."); MConstant* c = MConstant::New(alloc(), v, constraints()); current->add(c); return c; } MConstant* IonBuilder::constantInt(int32_t i) { return constant(Int32Value(i)); } -MConstant* -IonBuilder::constantMaybeAtomize(const Value& v) -{ - if (!v.isString() || v.toString()->isAtom()) - return constant(v); - - JSContext* cx = GetJitContext()->cx; - JSAtom* atom = js::AtomizeString(cx, v.toString()); - if (!atom) - return nullptr; - return constant(StringValue(atom)); -} - MDefinition* IonBuilder::getCallee() { if (inliningDepth_ == 0) { MInstruction* callee = MCallee::New(alloc()); current->add(callee); return callee; }
--- a/js/src/jit/IonBuilder.h +++ b/js/src/jit/IonBuilder.h @@ -348,19 +348,16 @@ class IonBuilder void rewriteParameters(); bool initScopeChain(MDefinition* callee = nullptr); bool initArgumentsObject(); bool pushConstant(const Value& v); MConstant* constant(const Value& v); MConstant* constantInt(int32_t i); - // Note: This function might return nullptr in case of failure. - MConstant* constantMaybeAtomize(const Value& v); - // Improve the type information at tests bool improveTypesAtTest(MDefinition* ins, bool trueBranch, MTest* test); bool improveTypesAtCompare(MCompare* ins, bool trueBranch, MTest* test); bool improveTypesAtNullOrUndefinedCompare(MCompare* ins, bool trueBranch, MTest* test); bool improveTypesAtTypeOfCompare(MCompare* ins, bool trueBranch, MTest* test); // Used to detect triangular structure at test. bool detectAndOrStructure(MPhi* ins, bool* branchIsTrue);
--- a/js/src/jit/MCallOptimize.cpp +++ b/js/src/jit/MCallOptimize.cpp @@ -1562,24 +1562,21 @@ IonBuilder::inlineConstantStringSplit(Ca if (!key.maybeTypes()->hasType(TypeSet::StringType())) return InliningStatus_NotInlined; uint32_t initLength = templateObject->as<ArrayObject>().length(); if (templateObject->getDenseInitializedLength() != initLength) return InliningStatus_NotInlined; - JSContext* cx = GetJitContext()->cx; Vector<MConstant*, 0, SystemAllocPolicy> arrayValues; for (uint32_t i = 0; i < initLength; i++) { - JSAtom* str = js::AtomizeString(cx, templateObject->getDenseElement(i).toString()); - if (!str) - return InliningStatus_Error; - - MConstant* value = MConstant::New(alloc(), StringValue(str), constraints()); + Value str = templateObject->getDenseElement(i); + MOZ_ASSERT(str.toString()->isAtom()); + MConstant* value = MConstant::New(alloc(), str, constraints()); if (!TypeSetIncludes(key.maybeTypes(), value->type(), value->resultTypeSet())) return InliningStatus_NotInlined; if (!arrayValues.append(value)) return InliningStatus_Error; } callInfo.setImplicitlyUsedUnchecked(); @@ -2767,42 +2764,41 @@ IonBuilder::inlineBoundFunction(CallInfo if (gc::IsInsideNursery(scriptedTarget)) return InliningStatus_NotInlined; for (size_t i = 0; i < target->getBoundFunctionArgumentCount(); i++) { const Value val = target->getBoundFunctionArgument(i); if (val.isObject() && gc::IsInsideNursery(&val.toObject())) return InliningStatus_NotInlined; + if (val.isString() && !val.toString()->isAtom()) + return InliningStatus_NotInlined; } const Value thisVal = target->getBoundFunctionThis(); if (thisVal.isObject() && gc::IsInsideNursery(&thisVal.toObject())) return InliningStatus_NotInlined; + if (thisVal.isString() && !thisVal.toString()->isAtom()) + return InliningStatus_NotInlined; size_t argc = target->getBoundFunctionArgumentCount() + nativeCallInfo.argc(); if (argc > ARGS_LENGTH_MAX) return InliningStatus_NotInlined; nativeCallInfo.thisArg()->setImplicitlyUsedUnchecked(); CallInfo callInfo(alloc(), nativeCallInfo.constructing()); callInfo.setFun(constant(ObjectValue(*scriptedTarget))); - MConstant* thisConst = constantMaybeAtomize(thisVal); - if (!thisConst) - return InliningStatus_Error; - callInfo.setThis(thisConst); + callInfo.setThis(constant(thisVal)); if (!callInfo.argv().reserve(argc)) return InliningStatus_Error; for (size_t i = 0; i < target->getBoundFunctionArgumentCount(); i++) { - MConstant* argConst = constantMaybeAtomize(target->getBoundFunctionArgument(i)); - if (!argConst) - return InliningStatus_Error; + MConstant* argConst = constant(target->getBoundFunctionArgument(i)); callInfo.argv().infallibleAppend(argConst); } for (size_t i = 0; i < nativeCallInfo.argc(); i++) callInfo.argv().infallibleAppend(nativeCallInfo.getArg(i)); if (!makeCall(scriptedTarget, callInfo)) return InliningStatus_Error;
--- a/js/src/vm/TypeInference.cpp +++ b/js/src/vm/TypeInference.cpp @@ -899,17 +899,17 @@ TypeSet::intersectSets(TemporaryTypeSet* if (b->getObject(i)) res->addType(ObjectType(b->getObject(i)), alloc); } return res; } if (b->unknownObject()) { for (size_t i = 0; i < a->getObjectCount(); i++) { - if (b->getObject(i)) + if (a->getObject(i)) res->addType(ObjectType(a->getObject(i)), alloc); } return res; } MOZ_ASSERT(!a->unknownObject() && !b->unknownObject()); for (size_t i = 0; i < a->getObjectCount(); i++) {
--- a/js/src/vm/UnboxedObject.h +++ b/js/src/vm/UnboxedObject.h @@ -228,16 +228,21 @@ class UnboxedPlainObject : public JSObje UnboxedExpandoObject* maybeExpando() const { return expando_; } void initExpando() { expando_ = nullptr; } + // For use during GC. + JSObject** addressOfExpando() { + return reinterpret_cast<JSObject**>(&expando_); + } + bool containsUnboxedOrExpandoProperty(ExclusiveContext* cx, jsid id) const; static UnboxedExpandoObject* ensureExpando(JSContext* cx, Handle<UnboxedPlainObject*> obj); bool setValue(ExclusiveContext* cx, const UnboxedLayout::Property& property, const Value& v); Value getValue(const UnboxedLayout::Property& property); static bool convertToNative(JSContext* cx, JSObject* obj);
--- a/layout/reftests/abs-pos/reftest.list +++ b/layout/reftests/abs-pos/reftest.list @@ -44,19 +44,19 @@ skip-if((B2G&&browserIsRemote)||Mulet) ! == table-footer-group-3.html table-internal-3-ref.html == table-footer-group-4.html table-internal-4-ref.html == table-footer-group-5.html table-internal-5-ref.html == table-footer-group-6.html table-internal-6-ref.html == table-footer-group-7.html table-internal-7-ref.html == continuation-positioned-inline-1.html continuation-positioned-inline-ref.html == continuation-positioned-inline-2.html continuation-positioned-inline-ref.html == scrollframe-1.html scrollframe-1-ref.html -skip-if(B2G||Mulet) fuzzy-if(Android,9,185) == scrollframe-2.html scrollframe-2-ref.html #bug 756530 # Initial mulet triage: parity with B2G/B2G Desktop +skip-if(B2G||Mulet) fuzzy-if(Android,9,185) fuzzy-if(asyncPanZoom&&!layersGPUAccelerated,102,107) == scrollframe-2.html scrollframe-2-ref.html #bug 756530 # Initial mulet triage: parity with B2G/B2G Desktop fuzzy-if(gtk2Widget,1,8) == select-1.html select-1-ref.html fuzzy-if(gtk2Widget,1,8) == select-1-dynamic.html select-1-ref.html == select-2.html select-2-ref.html -fuzzy-if(gtk2Widget,1,19) fuzzy-if(Android||B2G,17,726) == select-3.html select-3-ref.html +fuzzy-if(gtk2Widget,1,19) fuzzy-if(Android||B2G,17,726) fuzzy-if(asyncPanZoom&&!layersGPUAccelerated,102,98) == select-3.html select-3-ref.html == multi-column-1.html multi-column-1-ref.html == button-1.html button-1-ref.html == button-2.html button-2-ref.html == relative-row-animation-1.html relative-row-animation-1-ref.html fuzzy-if(Android&&AndroidVersion>=15,12,50) == fixed-pos-auto-offset-1a.html fixed-pos-auto-offset-1-ref.html fuzzy-if(Android&&AndroidVersion>=15,12,50) == fixed-pos-auto-offset-1b.html fixed-pos-auto-offset-1-ref.html
--- a/layout/reftests/border-image/reftest.list +++ b/layout/reftests/border-image/reftest.list @@ -31,17 +31,17 @@ fails-if(Android||B2G) == center-scaling == border-image-width-1b.html border-image-width-1-ref.html == border-image-width-1c.html border-image-width-1-ref.html == border-image-width-large.html border-image-width-large-ref.html == border-image-outset-1a.html border-image-outset-1-ref.html == border-image-outset-1b.html border-image-outset-1-ref.html == border-image-outset-1c.html border-image-outset-1-ref.html == border-image-nofill-1.html border-image-nofill-1-ref.html == border-image-outset-resize-1.html border-image-outset-resize-1-ref.html -== border-image-outset-move-1.html border-image-outset-move-1-ref.html +fuzzy-if(asyncPanZoom&&!layersGPUAccelerated,102,445) == border-image-outset-move-1.html border-image-outset-move-1-ref.html == border-image-style-none.html border-image-style-none-ref.html == border-image-style-none-length.html border-image-style-none-length-ref.html == border-image-style-none-auto.html border-image-style-none-auto-ref.html # border images with gradients == border-image-linear-gradient.html border-image-linear-gradient-ref.html fuzzy(1,98) == border-image-linear-gradient-slice-1.html border-image-linear-gradient-slice-1-ref.html fuzzy(1,149) fuzzy-if(OSX,1,10595) == border-image-linear-gradient-slice-2.html border-image-linear-gradient-slice-2-ref.html
--- a/layout/reftests/border-radius/reftest.list +++ b/layout/reftests/border-radius/reftest.list @@ -66,17 +66,17 @@ fuzzy-if(true,1,33) fuzzy-if(cocoaWidget # Table elements == table-collapse-1.html table-collapse-1-ref.html # border-radius is ignored on internal table elements # when border-collapse: collapse fuzzy-if(azureQuartz,1,3) skip-if(B2G||Mulet) == invalidate-1a.html invalidate-1-ref.html # Initial mulet triage: parity with B2G/B2G Desktop fuzzy-if(azureQuartz,1,3) skip-if(B2G||Mulet) == invalidate-1b.html invalidate-1-ref.html # Initial mulet triage: parity with B2G/B2G Desktop # test that border-radius is reduced for scrollbars -skip-if(B2G||Mulet) fails-if(Android) == scrollbar-clamping-1.html scrollbar-clamping-1-ref.html # Initial mulet triage: parity with B2G/B2G Desktop +skip-if(B2G||Mulet) fails-if(Android) fuzzy-if(asyncPanZoom&&!layersGPUAccelerated,12,12) == scrollbar-clamping-1.html scrollbar-clamping-1-ref.html # Initial mulet triage: parity with B2G/B2G Desktop skip-if(B2G||Mulet) fails-if(Android) == scrollbar-clamping-2.html scrollbar-clamping-2-ref.html # Initial mulet triage: parity with B2G/B2G Desktop # Test for bad corner joins. fuzzy-if(true,1,1) == corner-joins-1.xhtml corner-joins-1-ref.xhtml skip-if(B2G||Mulet) random-if(winWidget) HTTP(..) == corner-joins-2.xhtml corner-joins-2-ref.xhtml # Initial mulet triage: parity with B2G/B2G Desktop skip-if(B2G||Mulet) fuzzy-if(/^Windows\x20NT\x206\.2/.test(http.oscpu),1,20) fuzzy-if(Android&&browserIsRemote,7,146) fuzzy-if(Android&&!browserIsRemote,166,400) fails-if(Android&&AndroidVersion==15) == scroll-1.html scroll-1-ref.html # see bug 732535 #Bug 959166 # Initial mulet triage: parity with B2G/B2G Desktop
--- a/layout/reftests/bugs/reftest.list +++ b/layout/reftests/bugs/reftest.list @@ -1570,17 +1570,17 @@ random-if(!winWidget) fails-if(winWidget == 577838-1.html 577838-1-ref.html == 577838-2.html 577838-2-ref.html == 579323-1.html 579323-1-ref.html == 579349-1.html 579349-1-ref.html == 579655-1.html 579655-1-ref.html skip-if(!haveTestPlugin) skip-if(B2G||Mulet) fails-if(Android) == 579808-1.html 579808-1-ref.html # Initial mulet triage: parity with B2G/B2G Desktop skip-if(B2G||Mulet) fails-if(Android) random-if(layersGPUAccelerated) == 579985-1.html 579985-1-ref.html # bug 623452 for WinXP; this bug was only for a regression in BasicLayers anyway # Initial mulet triage: parity with B2G/B2G Desktop skip-if(B2G||Mulet) skip-if(Android) == 580160-1.html 580160-1-ref.html # bug 920927 for Android; issues without the test-plugin # Initial mulet triage: parity with B2G/B2G Desktop -HTTP(..) == 580863-1.html 580863-1-ref.html +fuzzy-if(asyncPanZoom&&!layersGPUAccelerated,255,13) HTTP(..) == 580863-1.html 580863-1-ref.html skip-if(B2G||Mulet) fails-if(Android) random-if(layersGPUAccelerated) == 581317-1.html 581317-1-ref.html # Initial mulet triage: parity with B2G/B2G Desktop == 581579-1.html 581579-1-ref.html == 582037-1a.html 582037-1-ref.html == 582037-1b.html 582037-1-ref.html skip-if(B2G||Mulet) fuzzy-if(Android,3,256) == 582037-2a.html 582037-2-ref.html # Initial mulet triage: parity with B2G/B2G Desktop skip-if(B2G||Mulet) fuzzy-if(Android,3,256) == 582037-2b.html 582037-2-ref.html # Initial mulet triage: parity with B2G/B2G Desktop asserts(1-2) == 582146-1.html about:blank skip-if(B2G||Mulet) == 582476-1.svg 582476-1-ref.svg # Initial mulet triage: parity with B2G/B2G Desktop @@ -1666,17 +1666,17 @@ HTTP(..) == 635639-2.html 635639-2-ref.h random == 637597-1.html 637597-1-ref.html # bug 637597 was never really fixed! fuzzy-if(Android&&AndroidVersion>=15,8,500) == 637852-1.html 637852-1-ref.html fuzzy-if(Android&&AndroidVersion>=15,8,500) == 637852-2.html 637852-2-ref.html fuzzy-if(Android&&AndroidVersion>=15,8,500) == 637852-3.html 637852-3-ref.html skip-if(B2G||Mulet) == 641770-1.html 641770-1-ref.html # Initial mulet triage: parity with B2G/B2G Desktop == 641856-1.html 641856-1-ref.html == 645491-1.html 645491-1-ref.html == 645768-1.html 645768-1-ref.html -fails-if(layersGPUAccelerated&&cocoaWidget) fails-if(Android&&AndroidVersion<15&&AndroidVersion!=10) == 650228-1.html 650228-1-ref.html # Quartz alpha blending doesn't match GL alpha blending +fails-if(layersGPUAccelerated&&cocoaWidget) fails-if(Android&&AndroidVersion<15&&AndroidVersion!=10) fuzzy-if(asyncPanZoom&&!layersGPUAccelerated,41,260) == 650228-1.html 650228-1-ref.html # Quartz alpha blending doesn't match GL alpha blending needs-focus == 652301-1a.html 652301-1-ref.html needs-focus == 652301-1b.html 652301-1-ref.html == 652775-1.html 652775-1-ref.html == 653930-1.html 653930-1-ref.html HTTP(..) == 654057-1.html 654057-1-ref.html fails-if(layersGPUAccelerated&&cocoaWidget) fails-if(Android&&AndroidVersion==15) == 654950-1.html 654950-1-ref.html # Quartz alpha blending doesn't match GL alpha blending == 655549-1.html 655549-1-ref.html == 655836-1.html 655836-1-ref.html @@ -1751,17 +1751,17 @@ fuzzy-if(Android,8,608) == 811301-1.html == 814677.html 814677-ref.html skip-if(B2G||Mulet) == 814952-1.html 814952-1-ref.html # Initial mulet triage: parity with B2G/B2G Desktop skip-if(B2G||Mulet) fuzzy-if(Android,4,400) == 815593-1.html 815593-1-ref.html # Initial mulet triage: parity with B2G/B2G Desktop == 816359-1.html 816359-1-ref.html == 816458-1.html 816458-1-ref.html == 816948-1.html 816948-1-ref.html == 817019-1.html about:blank skip-if(B2G||Mulet) == 818276-1.html 818276-1-ref.html # Initial mulet triage: parity with B2G/B2G Desktop -fuzzy-if(asyncPanZoom,190,27) == 825999.html 825999-ref.html +fuzzy-if(asyncPanZoom,190,510) fuzzy-if(asyncPanZoom&&!layersGPUAccelerated,102,510) == 825999.html 825999-ref.html == 827577-1a.html 827577-1-ref.html == 827577-1b.html 827577-1-ref.html == 827799-1.html about:blank == 829958.html 829958-ref.html == 836844-1.html 836844-1-ref.html == 841192-1.html 841192-1-ref.html == 844178.html 844178-ref.html fuzzy-if(OSX,1,364) == 846144-1.html 846144-1-ref.html @@ -1801,17 +1801,17 @@ fuzzy-if(B2G,1,7) == 942672-1.html 94267 == 956513-1.svg 956513-1-ref.svg == 944291-1.html 944291-1-ref.html == 950436-1.html 950436-1-ref.html == 957770-1.svg 957770-1-ref.svg == 960277-1.html 960277-1-ref.html == 961887-1.html 961887-1-ref.html == 961887-2.html 961887-2-ref.html == 961887-3.html 961887-3-ref.html -pref(layout.css.overflow-clip-box.enabled,true) fuzzy(50,145) == 966992-1.html 966992-1-ref.html +pref(layout.css.overflow-clip-box.enabled,true) fuzzy(50,145) fuzzy-if(asyncPanZoom&&!layersGPUAccelerated,102,3712) == 966992-1.html 966992-1-ref.html skip-if(Android) == 966510-1.html 966510-1-ref.html # scrollable elements other than the root probably won't work well on android until bug 776030 is fixed skip-if(Android) == 966510-2.html 966510-2-ref.html # same as above == 978911-1.svg 978911-1-ref.svg == 983084-1.html 983084-1-ref.html == 983084-2.html 983084-2-ref.html == 983084-3.html 983084-1-ref.html == 983691-1.html 983691-ref.html HTTP(..) == 983985-1.html 983985-1-ref.html
--- a/layout/reftests/css-ui-invalid/select/reftest.list +++ b/layout/reftests/css-ui-invalid/select/reftest.list @@ -5,14 +5,14 @@ needs-focus == select-disabled.html sele skip-if(B2G||Mulet) needs-focus == select-dyn-disabled.html select-disabled-ref.html # Initial mulet triage: parity with B2G/B2G Desktop needs-focus == select-dyn-not-disabled.html select-ref.html needs-focus == select-required-invalid-1.html select-required-ref.html needs-focus == select-required-invalid-2.html select-required-ref.html needs-focus == select-required-invalid-changed-1.html select-required-ref.html needs-focus == select-required-invalid-changed-2.html select-required-ref.html needs-focus == select-required-valid.html select-required-ref.html needs-focus == select-required-multiple-invalid.html select-required-multiple-ref.html -needs-focus == select-required-multiple-invalid-changed.html select-required-multiple-ref.html +fuzzy-if(asyncPanZoom&&!layersGPUAccelerated,84,77) needs-focus == select-required-multiple-invalid-changed.html select-required-multiple-ref.html needs-focus == select-required-multiple-valid.html select-required-multiple-ref.html skip-if(B2G||Mulet) fails-if(Android) needs-focus == select-disabled-fieldset-1.html select-fieldset-ref.html # Initial mulet triage: parity with B2G/B2G Desktop skip-if(B2G||Mulet) fails-if(Android) needs-focus == select-disabled-fieldset-2.html select-fieldset-ref.html # Initial mulet triage: parity with B2G/B2G Desktop needs-focus == select-fieldset-legend.html select-fieldset-legend-ref.html needs-focus == select-novalidate.html select-required-ref.html
--- a/layout/reftests/css-ui-valid/select/reftest.list +++ b/layout/reftests/css-ui-valid/select/reftest.list @@ -6,13 +6,13 @@ needs-focus == select-dyn-disabled.html needs-focus == select-dyn-not-disabled.html select-ref.html needs-focus == select-required-invalid.html select-required-ref.html needs-focus == select-required-valid-1.html select-required-ref.html needs-focus == select-required-valid-2.html select-required-ref.html needs-focus == select-required-valid-changed-1.html select-required-ref.html needs-focus == select-required-valid-changed-2.html select-required-ref.html needs-focus == select-required-multiple-invalid.html select-required-multiple-ref.html needs-focus == select-required-multiple-valid.html select-required-multiple-ref.html -fuzzy(64,4) needs-focus == select-required-multiple-valid-changed.html select-required-multiple-ref.html +fuzzy(64,4) fuzzy-if(asyncPanZoom&&layersGPUAccelerated,84,77) needs-focus == select-required-multiple-valid-changed.html select-required-multiple-ref.html fails-if(Android||B2G||Mulet) needs-focus == select-disabled-fieldset-1.html select-fieldset-ref.html # Initial mulet triage: parity with B2G/B2G Desktop fails-if(Android||B2G||Mulet) needs-focus == select-disabled-fieldset-2.html select-fieldset-ref.html # Initial mulet triage: parity with B2G/B2G Desktop needs-focus == select-fieldset-legend.html select-fieldset-legend-ref.html needs-focus == select-novalidate.html select-required-ref.html
--- a/layout/reftests/font-inflation/reftest.list +++ b/layout/reftests/font-inflation/reftest.list @@ -32,17 +32,17 @@ test-pref(font.size.inflation.emPerLine, test-pref(font.size.inflation.emPerLine,15) test-pref(font.size.inflation.forceEnabled,true) test-pref(font.size.inflation.lineThreshold,0) == input-text-2-noheight.html input-text-2-noheight-ref.html test-pref(font.size.inflation.emPerLine,15) test-pref(font.size.inflation.forceEnabled,true) test-pref(font.size.inflation.lineThreshold,0) == input-text-3-height.html input-text-3-height-ref.html test-pref(font.size.inflation.emPerLine,15) test-pref(font.size.inflation.forceEnabled,true) test-pref(font.size.inflation.lineThreshold,0) == input-text-3-noheight.html input-text-3-noheight-ref.html test-pref(font.size.inflation.emPerLine,15) test-pref(font.size.inflation.forceEnabled,true) test-pref(font.size.inflation.lineThreshold,0) == textarea-1.html textarea-1-ref.html test-pref(font.size.inflation.emPerLine,15) test-pref(font.size.inflation.forceEnabled,true) test-pref(font.size.inflation.lineThreshold,0) == textarea-2.html textarea-2-ref.html test-pref(font.size.inflation.emPerLine,15) test-pref(font.size.inflation.forceEnabled,true) test-pref(font.size.inflation.lineThreshold,0) == textarea-3.html textarea-3-ref.html test-pref(font.size.inflation.emPerLine,15) test-pref(font.size.inflation.forceEnabled,true) test-pref(font.size.inflation.lineThreshold,0) == css-transform-1.html css-transform-1-ref.html test-pref(font.size.inflation.emPerLine,15) test-pref(font.size.inflation.forceEnabled,true) test-pref(font.size.inflation.lineThreshold,0) == css-transform-2.html css-transform-2-ref.html -skip-if(B2G||Mulet) test-pref(font.size.inflation.emPerLine,15) test-pref(font.size.inflation.forceEnabled,true) test-pref(font.size.inflation.lineThreshold,0) == container-with-clamping.html container-with-clamping-ref.html # Initial mulet triage: parity with B2G/B2G Desktop +skip-if(B2G||Mulet) fuzzy-if(asyncPanZoom&&!layersGPUAccelerated,102,1764) test-pref(font.size.inflation.emPerLine,15) test-pref(font.size.inflation.forceEnabled,true) test-pref(font.size.inflation.lineThreshold,0) == container-with-clamping.html container-with-clamping-ref.html # Initial mulet triage: parity with B2G/B2G Desktop test-pref(font.size.inflation.emPerLine,15) test-pref(font.size.inflation.forceEnabled,true) test-pref(font.size.inflation.lineThreshold,0) load video-1.html test-pref(font.size.inflation.emPerLine,15) test-pref(font.size.inflation.forceEnabled,true) test-pref(font.size.inflation.lineThreshold,0) HTTP(..) == intrinsic-min-1.html intrinsic-min-1-ref.html skip-if(B2G||Mulet) test-pref(font.size.inflation.emPerLine,15) test-pref(font.size.inflation.forceEnabled,true) test-pref(font.size.inflation.lineThreshold,0) HTTP(..) == intrinsic-max-1.html intrinsic-max-1-ref.html # Initial mulet triage: parity with B2G/B2G Desktop skip-if(B2G||Mulet) test-pref(font.size.inflation.emPerLine,15) test-pref(font.size.inflation.forceEnabled,true) test-pref(font.size.inflation.lineThreshold,0) HTTP(..) == intrinsic-fit-1a.html intrinsic-fit-1a-ref.html # Initial mulet triage: parity with B2G/B2G Desktop skip-if(B2G||Mulet) test-pref(font.size.inflation.emPerLine,15) test-pref(font.size.inflation.forceEnabled,true) test-pref(font.size.inflation.lineThreshold,0) HTTP(..) == intrinsic-fit-1b.html intrinsic-fit-1b-ref.html # Initial mulet triage: parity with B2G/B2G Desktop test-pref(font.size.inflation.emPerLine,15) test-pref(font.size.inflation.forceEnabled,true) test-pref(font.size.inflation.lineThreshold,0) HTTP(..) == intrinsic-fit-1c.html intrinsic-fit-1c-ref.html test-pref(font.size.inflation.emPerLine,15) test-pref(font.size.inflation.forceEnabled,true) test-pref(font.size.inflation.lineThreshold,0) HTTP(..) == intrinsic-fit-2a.html intrinsic-fit-1a-ref.html skip-if(B2G||Mulet) test-pref(font.size.inflation.emPerLine,15) test-pref(font.size.inflation.forceEnabled,true) test-pref(font.size.inflation.lineThreshold,0) HTTP(..) == intrinsic-fit-2b.html intrinsic-fit-1b-ref.html # Initial mulet triage: parity with B2G/B2G Desktop
--- a/layout/reftests/forms/fieldset/reftest.list +++ b/layout/reftests/forms/fieldset/reftest.list @@ -1,14 +1,14 @@ == dynamic-legend-scroll-1.html dynamic-legend-scroll-1-ref.html == fieldset-hidden-1.html fieldset-hidden-1-ref.html == fieldset-intrinsic-width-1.html fieldset-intrinsic-width-1-ref.html == fieldset-percentage-padding-1.html fieldset-percentage-padding-1-ref.html == fieldset-scroll-1.html fieldset-scroll-1-ref.html == fieldset-scrolled-1.html fieldset-scrolled-1-ref.html random-if(B2G||Mulet) == fieldset-overflow-auto-1.html fieldset-overflow-auto-1-ref.html # Initial mulet triage: parity with B2G/B2G Desktop -fuzzy-if(winWidget&&!layersGPUAccelerated,102,205) == positioned-container-1.html positioned-container-1-ref.html +fuzzy-if(winWidget&&!layersGPUAccelerated,102,221) == positioned-container-1.html positioned-container-1-ref.html == relpos-legend-1.html relpos-legend-1-ref.html == relpos-legend-2.html relpos-legend-2-ref.html test-pref(layout.css.sticky.enabled,true) skip-if((B2G&&browserIsRemote)||Mulet) == sticky-legend-1.html sticky-legend-1-ref.html # Initial mulet triage: parity with B2G/B2G Desktop == abs-pos-child-sizing.html abs-pos-child-sizing-ref.html == overflow-hidden.html overflow-hidden-ref.html == legend-rtl.html legend-rtl-ref.html
--- a/layout/reftests/forms/input/text/reftest.list +++ b/layout/reftests/forms/input/text/reftest.list @@ -1,10 +1,10 @@ == bounds-1.html bounds-1-ref.html -== size-1.html size-1-ref.html +fuzzy-if(asyncPanZoom&&!layersGPUAccelerated,102,84) == size-1.html size-1-ref.html skip-if(B2G||Mulet) == size-2.html size-2-ref.html # Initial mulet triage: parity with B2G/B2G Desktop HTTP(..) == baseline-1.html baseline-1-ref.html skip-if((B2G&&browserIsRemote)||Mulet) HTTP(..) == centering-1.xul centering-1-ref.xul # bug 974780 # Initial mulet triage: parity with B2G/B2G Desktop skip-if((B2G&&browserIsRemote)||Mulet) == dynamic-height-1.xul dynamic-height-1-ref.xul # bug 974780 # Initial mulet triage: parity with B2G/B2G Desktop needs-focus == select.html select-ref.html == intrinsic-size.html intrinsic-size-ref.html == line-height-0.5.html line-height-1.0.html != line-height-1.5.html line-height-1.0.html
--- a/layout/reftests/forms/placeholder/reftest.list +++ b/layout/reftests/forms/placeholder/reftest.list @@ -11,17 +11,17 @@ == placeholder-1-text.html placeholder-visible-ref.html == placeholder-1-password.html placeholder-visible-ref.html == placeholder-1-textarea.html placeholder-visible-textarea-ref.html == placeholder-2.html placeholder-visible-ref.html == placeholder-2-textarea.html placeholder-visible-textarea-ref.html == placeholder-3.html placeholder-overridden-ref.html == placeholder-4.html placeholder-overridden-ref.html == placeholder-5.html placeholder-visible-ref.html -fuzzy-if(winWidget,160,7) == placeholder-6.html placeholder-overflow-ref.html +fuzzy-if(winWidget,160,7) fuzzy-if(asyncPanZoom&&!layersGPUAccelerated,146,299) == placeholder-6.html placeholder-overflow-ref.html skip-if(B2G||Mulet) == placeholder-6-textarea.html placeholder-overflow-textarea-ref.html # Initial mulet triage: parity with B2G/B2G Desktop # needs-focus == placeholder-7.html placeholder-focus-ref.html # needs-focus == placeholder-8.html placeholder-focus-ref.html # needs-focus == placeholder-9.html placeholder-focus-ref.html needs-focus == placeholder-10.html placeholder-visible-ref.html == placeholder-11.html placeholder-visible-ref.html == placeholder-12.html placeholder-visible-ref.html == placeholder-13.html placeholder-visible-ref.html
--- a/layout/reftests/forms/textarea/reftest.list +++ b/layout/reftests/forms/textarea/reftest.list @@ -5,10 +5,10 @@ skip-if(B2G||Mulet) fails-if(Android) != skip-if(B2G||Mulet) fails-if(Android) != ltr-scrollbar.html rtl-scrollbar.html # Initial mulet triage: parity with B2G/B2G Desktop skip-if(B2G||Mulet) fails-if(Android) != in-ltr-doc-scrollbar.html in-rtl-doc-scrollbar.html # Initial mulet triage: parity with B2G/B2G Desktop skip-if(B2G||Mulet) fails-if(Android) != ltr.html no-resize.html # Initial mulet triage: parity with B2G/B2G Desktop skip-if(B2G||Mulet) fails-if(Android) fails-if(gtk2Widget) != rtl.html no-resize.html # bug 834724 # Initial mulet triage: parity with B2G/B2G Desktop == rtl.html rtl-dynamic-attr.html == rtl.html rtl-dynamic-style.html == rtl.html in-dynamic-rtl-doc.html == setvalue-framereconstruction-1.html setvalue-framereconstruction-ref.html -== padding-scrollbar-placement.html padding-scrollbar-placement-ref.html +fuzzy-if(asyncPanZoom&&!layersGPUAccelerated,102,4168) == padding-scrollbar-placement.html padding-scrollbar-placement-ref.html == various-cols.html various-cols-ref.html
--- a/layout/reftests/position-dynamic-changes/relative/reftest.list +++ b/layout/reftests/position-dynamic-changes/relative/reftest.list @@ -1,5 +1,5 @@ -fuzzy-if(cocoaWidget,1,2) fuzzy-if(d2d,47,26) == move-right-bottom.html move-right-bottom-ref.html -fuzzy-if(cocoaWidget,1,2) == move-top-left.html move-top-left-ref.html # Bug 688545 -fuzzy-if(cocoaWidget,1,3) == move-right-bottom-table.html move-right-bottom-table-ref.html -fuzzy-if(cocoaWidget,1,3) == move-top-left-table.html move-top-left-table-ref.html # Bug 688545 +fuzzy-if(cocoaWidget,1,2) fuzzy-if(d2d,47,26) fuzzy-if(asyncPanZoom&&!layersGPUAccelerated,102,492) == move-right-bottom.html move-right-bottom-ref.html +fuzzy-if(cocoaWidget,1,2) fuzzy-if(asyncPanZoom&&!layersGPUAccelerated,102,492) == move-top-left.html move-top-left-ref.html # Bug 688545 +fuzzy-if(cocoaWidget,1,3) fuzzy-if(asyncPanZoom&&!layersGPUAccelerated,102,492) == move-right-bottom-table.html move-right-bottom-table-ref.html +fuzzy-if(cocoaWidget,1,3) fuzzy-if(asyncPanZoom&&!layersGPUAccelerated,102,492) == move-top-left-table.html move-top-left-table-ref.html # Bug 688545 == percent.html percent-ref.html
--- a/layout/reftests/scrolling/reftest.list +++ b/layout/reftests/scrolling/reftest.list @@ -22,16 +22,16 @@ skip-if(Android) pref(layout.css.scroll- skip-if((B2G&&browserIsRemote)||Mulet) HTTP == simple-1.html simple-1.html?ref # Initial mulet triage: parity with B2G/B2G Desktop skip-if(B2G||Mulet) HTTP == subpixel-1.html#d subpixel-1-ref.html#d # Initial mulet triage: parity with B2G/B2G Desktop fuzzy-if(Android,4,120) HTTP == text-1.html text-1.html?ref fuzzy-if(Android,4,120) HTTP == text-2.html?up text-2.html?ref skip-if(B2G||Mulet) fuzzy-if(Android&&AndroidVersion<15,251,722) fuzzy-if(d2d,1,4) HTTP == transformed-1.html transformed-1.html?ref # Initial mulet triage: parity with B2G/B2G Desktop HTTP == transformed-1.html?up transformed-1.html?ref fuzzy-if(Android,5,20000) == uncovering-1.html uncovering-1-ref.html fuzzy-if(Android,5,20000) == uncovering-2.html uncovering-2-ref.html -skip-if(B2G||Mulet) == less-than-scrollbar-height.html less-than-scrollbar-height-ref.html # Initial mulet triage: parity with B2G/B2G Desktop +skip-if(B2G||Mulet) fuzzy-if(asyncPanZoom&&!layersGPUAccelerated,102,3721) == less-than-scrollbar-height.html less-than-scrollbar-height-ref.html # Initial mulet triage: parity with B2G/B2G Desktop skip-if(B2G||Mulet) == huge-horizontal-overflow.html huge-horizontal-overflow-ref.html # Initial mulet triage: parity with B2G/B2G Desktop skip-if(B2G||Mulet) == huge-vertical-overflow.html huge-vertical-overflow-ref.html # Initial mulet triage: parity with B2G/B2G Desktop -== iframe-scrolling-attr-1.html iframe-scrolling-attr-ref.html -skip-if((B2G&&browserIsRemote)||Mulet) == iframe-scrolling-attr-2.html iframe-scrolling-attr-ref.html # Initial mulet triage: parity with B2G/B2G Desktop +fuzzy-if(asyncPanZoom&&!layersGPUAccelerated,102,6818) == iframe-scrolling-attr-1.html iframe-scrolling-attr-ref.html +skip-if((B2G&&browserIsRemote)||Mulet) fuzzy-if(asyncPanZoom&&!layersGPUAccelerated,102,6818) == iframe-scrolling-attr-2.html iframe-scrolling-attr-ref.html # Initial mulet triage: parity with B2G/B2G Desktop == frame-scrolling-attr-1.html frame-scrolling-attr-ref.html -== frame-scrolling-attr-2.html frame-scrolling-attr-ref.html +fuzzy-if(asyncPanZoom&&!layersGPUAccelerated,102,2420) == frame-scrolling-attr-2.html frame-scrolling-attr-ref.html == move-item.html move-item-ref.html # bug 1125750
--- a/layout/reftests/text-overflow/reftest.list +++ b/layout/reftests/text-overflow/reftest.list @@ -1,26 +1,26 @@ skip-if(B2G||Mulet) == ellipsis-font-fallback.html ellipsis-font-fallback-ref.html # Initial mulet triage: parity with B2G/B2G Desktop == line-clipping.html line-clipping-ref.html fuzzy-if(Android,16,244) skip-if(B2G||Mulet) HTTP(..) == marker-basic.html marker-basic-ref.html # Bug 1128229 # Initial mulet triage: parity with B2G/B2G Desktop skip-if(B2G||Mulet) HTTP(..) == marker-string.html marker-string-ref.html # Initial mulet triage: parity with B2G/B2G Desktop skip-if(Android||B2G) HTTP(..) == bidi-simple.html bidi-simple-ref.html # Fails on Android due to anti-aliasing skip-if(!gtk2Widget) fuzzy-if(gtk2Widget,1,104) HTTP(..) == bidi-simple-scrolled.html bidi-simple-scrolled-ref.html # Fails on Windows and OSX due to anti-aliasing -skip-if(B2G||Mulet) fuzzy-if(Android&&AndroidVersion<15,9,2545) fuzzy-if(Android&&AndroidVersion>=15,24,4000) fuzzy-if(cocoaWidget,1,40) HTTP(..) == scroll-rounding.html scroll-rounding-ref.html # bug 760264 # Initial mulet triage: parity with B2G/B2G Desktop +skip-if(B2G||Mulet) fuzzy-if(Android&&AndroidVersion<15,9,2545) fuzzy-if(Android&&AndroidVersion>=15,24,4000) fuzzy-if(cocoaWidget,1,40) fuzzy-if(asyncPanZoom&&!layersGPUAccelerated,102,1770) HTTP(..) == scroll-rounding.html scroll-rounding-ref.html # bug 760264 # Initial mulet triage: parity with B2G/B2G Desktop fuzzy-if(OSX==1008,1,1) HTTP(..) == anonymous-block.html anonymous-block-ref.html skip-if(B2G||Mulet) HTTP(..) == false-marker-overlap.html false-marker-overlap-ref.html # Initial mulet triage: parity with B2G/B2G Desktop HTTP(..) == visibility-hidden.html visibility-hidden-ref.html -skip-if(B2G||Mulet) HTTP(..) == block-padding.html block-padding-ref.html # Initial mulet triage: parity with B2G/B2G Desktop +skip-if(B2G||Mulet) fuzzy-if(asyncPanZoom&&!layersGPUAccelerated,102,1724) HTTP(..) == block-padding.html block-padding-ref.html # Initial mulet triage: parity with B2G/B2G Desktop HTTP(..) == quirks-decorations.html quirks-decorations-ref.html HTTP(..) == quirks-line-height.html quirks-line-height-ref.html HTTP(..) == standards-decorations.html standards-decorations-ref.html HTTP(..) == standards-line-height.html standards-line-height-ref.html skip-if(B2G||Mulet) random-if(/^Windows\x20NT\x205\.1/.test(http.oscpu)) HTTP(..) == selection.html selection-ref.html # bug 668849 # Initial mulet triage: parity with B2G/B2G Desktop HTTP(..) == marker-shadow.html marker-shadow-ref.html == aligned-baseline.html aligned-baseline-ref.html skip-if(Android||B2G) == clipped-elements.html clipped-elements-ref.html HTTP(..) == theme-overflow.html theme-overflow-ref.html skip-if(B2G||Mulet) HTTP(..) == table-cell.html table-cell-ref.html # Initial mulet triage: parity with B2G/B2G Desktop skip-if(Mulet) HTTP(..) == two-value-syntax.html two-value-syntax-ref.html # MULET: Bug 1144079: Re-enable Mulet mochitests and reftests taskcluster-specific disables skip-if(B2G||Mulet) HTTP(..) == single-value.html single-value-ref.html # Initial mulet triage: parity with B2G/B2G Desktop skip-if(B2G||Mulet) HTTP(..) == atomic-under-marker.html atomic-under-marker-ref.html # Initial mulet triage: parity with B2G/B2G Desktop -fuzzy(1,702) skip-if(Android||B2G||Mulet) HTTP(..) == xulscroll.html xulscroll-ref.html # Initial mulet triage: parity with B2G/B2G Desktop +fuzzy(1,702) skip-if(Android||B2G||Mulet) fuzzy-if(asyncPanZoom&&!layersGPUAccelerated,102,12352) HTTP(..) == xulscroll.html xulscroll-ref.html # Initial mulet triage: parity with B2G/B2G Desktop HTTP(..) == combobox-zoom.html combobox-zoom-ref.html
--- a/media/libvpx/update.py +++ b/media/libvpx/update.py @@ -323,17 +323,17 @@ platform_files = [ 'vp8_rtcd.h', 'vp9_rtcd.h', 'vpx_config.asm', 'vpx_config.h', 'vpx_scale_rtcd.h', ] def prepare_upstream(prefix, commit=None): - upstream_url = 'https://gerrit.chromium.org/gerrit/webm/libvpx' + upstream_url = 'https://chromium.googlesource.com/webm/libvpx' if os.path.exists(prefix): print "Using existing repo in '%s'" % prefix os.chdir(prefix) subprocess.call(['git', 'fetch', upstream_url, prefix]) else: subprocess.call(['git', 'clone', upstream_url, prefix]) os.chdir(prefix) if commit:
--- a/mozglue/build/WindowsDllBlocklist.cpp +++ b/mozglue/build/WindowsDllBlocklist.cpp @@ -167,16 +167,19 @@ static DllBlockInfo sWindowsDllBlocklist // Flash crashes with RealNetworks RealDownloader, bug 1132663 { "rndlnpshimswf.dll", ALL_VERSIONS }, { "rndlmainbrowserrecordplugin.dll", ALL_VERSIONS }, // Crashes with CyberLink YouCam, bug 1136968 { "ycwebcamerasource.ax", MAKE_VERSION(2, 0, 0, 1611) }, + // Old version of WebcamMax crashes WebRTC, bug 1130061 + { "vwcsource.ax", MAKE_VERSION(1, 5, 0, 0) }, + { nullptr, 0 } }; #ifndef STATUS_DLL_NOT_FOUND #define STATUS_DLL_NOT_FOUND ((DWORD)0xC0000135L) #endif // define this for very verbose dll load debug spew
--- a/testing/marionette/driver.js +++ b/testing/marionette/driver.js @@ -2303,17 +2303,17 @@ GeckoDriver.prototype.getElementRect = f * Reference ID to the element that will be checked. * @param {string} value * Value to send to the element. */ GeckoDriver.prototype.sendKeysToElement = function(cmd, resp) { let {id, value} = cmd.parameters; if (!value) { - throw new IllegalArgumentError(`Expected character sequence: ${value}`); + throw new InvalidArgumentError(`Expected character sequence: ${value}`); } switch (this.context) { case Context.CHROME: let win = this.getCurrentWindow(); let el = this.curBrowser.elementManager.getKnownElement(id, win); utils.sendKeysToElement( win, @@ -2336,17 +2336,17 @@ GeckoDriver.prototype.sendKeysToElement if (el.type == "file") { Cu.importGlobalProperties(["File"]); let fs = Array.prototype.slice.call(el.files); let file; try { file = new File(val); } catch (e) { - err = new IllegalArgumentError(`File not found: ${val}`); + err = new InvalidArgumentError(`File not found: ${val}`); } fs.push(file); el.mozSetFileArray(fs); } else { el.value = val; } }.bind(this);
--- a/testing/marionette/driver/requirements.txt +++ b/testing/marionette/driver/requirements.txt @@ -1,1 +1,2 @@ -marionette-transport == 0.4 \ No newline at end of file +marionette-transport == 0.4 +mozrunner >= 6.2
--- a/testing/marionette/driver/setup.py +++ b/testing/marionette/driver/setup.py @@ -1,11 +1,11 @@ from setuptools import setup, find_packages -version = '0.4' +version = '0.5' # dependencies with open('requirements.txt') as f: deps = f.read().splitlines() setup(name='marionette_driver', version=version, description="Marionette Driver",
--- a/testing/marionette/error.js +++ b/testing/marionette/error.js @@ -6,17 +6,17 @@ const {results: Cr, utils: Cu} = Components; const errors = [ "ElementNotAccessibleError", "ElementNotVisibleError", "FrameSendFailureError", "FrameSendNotInitializedError", - "IllegalArgumentError", + "InvalidArgumentError", "InvalidElementStateError", "InvalidSelectorError", "InvalidSessionIdError", "JavaScriptError", "NoAlertOpenError", "NoSuchElementError", "NoSuchFrameError", "NoSuchWindowError", @@ -166,22 +166,22 @@ this.FrameSendNotInitializedError = func WebDriverError.call(this, this.message); this.name = "FrameSendNotInitializedError"; this.status = "frame send not initialized error"; this.frame = frame; this.errMsg = `${this.message} ${this.frame}; frame has closed.`; }; FrameSendNotInitializedError.prototype = Object.create(WebDriverError.prototype); -this.IllegalArgumentError = function(msg) { +this.InvalidArgumentError = function(msg) { WebDriverError.call(this, msg); - this.name = "IllegalArgumentError"; - this.status = "illegal argument"; + this.name = "InvalidArgumentError"; + this.status = "invalid argument"; }; -IllegalArgumentError.prototype = Object.create(WebDriverError.prototype); +InvalidArgumentError.prototype = Object.create(WebDriverError.prototype); this.InvalidElementStateError = function(msg) { WebDriverError.call(this, msg); this.name = "InvalidElementStateError"; this.status = "invalid element state"; }; InvalidElementStateError.prototype = Object.create(WebDriverError.prototype); @@ -191,17 +191,16 @@ this.InvalidSelectorError = function(msg this.status = "invalid selector"; }; InvalidSelectorError.prototype = Object.create(WebDriverError.prototype); this.InvalidSessionIdError = function(msg) { WebDriverError.call(this, msg); this.name = "InvalidSessionIdError"; this.status = "invalid session id"; - this.code = 13; }; InvalidSessionIdError.prototype = Object.create(WebDriverError.prototype); /** * Creates an error message for a JavaScript error thrown during * executeScript or executeAsyncScript. * * @param {Error} err @@ -302,17 +301,16 @@ this.TimeoutError = function(msg) { this.status = "timeout"; }; TimeoutError.prototype = Object.create(WebDriverError.prototype); this.UnableToSetCookieError = function(msg) { WebDriverError.call(this, msg); this.name = "UnableToSetCookieError"; this.status = "unable to set cookie"; - this.code = 25; }; UnableToSetCookieError.prototype = Object.create(WebDriverError.prototype); this.UnknownCommandError = function(msg) { WebDriverError.call(this, msg); this.name = "UnknownCommandError"; this.status = "unknown command"; };
--- a/testing/marionette/listener.js +++ b/testing/marionette/listener.js @@ -1557,17 +1557,17 @@ function sendKeysToElement(msg) { // // this extra branch can be removed when the e10s bug 1149998 is fixed if (isRemoteBrowser()) { let fs = Array.prototype.slice.call(el.files); let file; try { file = new File(p); } catch (e) { - let err = new IllegalArgumentError(`File not found: ${val}`); + let err = new InvalidArgumentError(`File not found: ${val}`); sendError(err, command_id); return; } fs.push(file); let wel = new SpecialPowers(utils.window).wrap(el); wel.mozSetFileArray(fs); } else {
--- a/widget/gtk/mozgtk/mozgtk.c +++ b/widget/gtk/mozgtk/mozgtk.c @@ -432,16 +432,17 @@ STUB(gtk_widget_has_grab) STUB(gtk_widget_hide) STUB(gtk_widget_is_focus) STUB(gtk_widget_is_toplevel) STUB(gtk_widget_map) STUB(gtk_widget_realize) STUB(gtk_widget_reparent) STUB(gtk_widget_set_allocation) STUB(gtk_widget_set_app_paintable) +STUB(gtk_window_set_auto_startup_notification) STUB(gtk_widget_set_can_focus) STUB(gtk_widget_set_direction) STUB(gtk_widget_set_double_buffered) STUB(gtk_widget_set_has_window) STUB(gtk_widget_set_mapped) STUB(gtk_widget_set_name) STUB(gtk_widget_set_parent) STUB(gtk_widget_set_parent_window)
--- a/xpcom/glue/nsThreadUtils.cpp +++ b/xpcom/glue/nsThreadUtils.cpp @@ -88,77 +88,16 @@ NS_NewThread(nsIThread** aResult, nsIRun } } *aResult = nullptr; thread.swap(*aResult); return NS_OK; } -#if defined(MOZ_NUWA_PROCESS) && !defined(XPCOM_GLUE_AVOID_NSPR) - -namespace { -class IgnoreThreadStatusRunnable : public nsIRunnable -{ -public: - NS_DECL_THREADSAFE_ISUPPORTS - NS_DECL_NSIRUNNABLE - -private: - virtual ~IgnoreThreadStatusRunnable() = default; -}; - -NS_IMPL_ISUPPORTS(IgnoreThreadStatusRunnable, nsIRunnable) - -NS_IMETHODIMP IgnoreThreadStatusRunnable::Run(void) -{ -#ifdef MOZILLA_INTERNAL_API - nsThreadManager::get()->SetIgnoreThreadStatus(); - return NS_OK; -#endif - return NS_ERROR_NOT_IMPLEMENTED; -} - -} // Anonymous namespace. -#endif // defined(MOZ_NUWA_PROCESS) && !defined(XPCOM_GLUE_AVOID_NSPR) - -NS_METHOD -NS_NewUnmonitoredThread(nsIThread** aResult, - nsIRunnable* aEvent, - uint32_t aStackSize) -{ -#if defined(MOZ_NUWA_PROCESS) && !defined(XPCOM_GLUE_AVOID_NSPR) - // Hold a ref while dispatching the initial event to match NS_NewThread() - nsCOMPtr<nsIThread> thread; - nsresult rv = NS_NewThread(getter_AddRefs(thread), nullptr, aStackSize); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - nsCOMPtr<nsIRunnable> ignoreme = new IgnoreThreadStatusRunnable(); - rv = thread->Dispatch(ignoreme, NS_DISPATCH_NORMAL); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - if (aEvent) { - rv = thread->Dispatch(aEvent, NS_DISPATCH_NORMAL); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - } - - *aResult = nullptr; - thread.swap(*aResult); - return rv; -#else - return NS_NewThread(aResult, aEvent, aStackSize); -#endif -} - NS_METHOD NS_GetCurrentThread(nsIThread** aResult) { #ifdef MOZILLA_INTERNAL_API return nsThreadManager::get()->nsThreadManager::GetCurrentThread(aResult); #else nsresult rv; nsCOMPtr<nsIThreadManager> mgr =
--- a/xpcom/glue/nsThreadUtils.h +++ b/xpcom/glue/nsThreadUtils.h @@ -57,27 +57,16 @@ NS_SetThreadName(nsIThread* aThread, con * Indicates that the given name is not unique. */ extern NS_METHOD NS_NewThread(nsIThread** aResult, nsIRunnable* aInitialEvent = nullptr, uint32_t aStackSize = nsIThreadManager::DEFAULT_STACK_SIZE); /** - * Create a new thread that is ignored in thread status monitoring by default on - * platforms with Nuwa process enabled. On non-Nuwa platforms, this function is - * identical to NS_NewThread(). - */ -extern NS_METHOD -NS_NewUnmonitoredThread(nsIThread** aResult, - nsIRunnable* aInitialEvent = nullptr, - uint32_t aStackSize = - nsIThreadManager::DEFAULT_STACK_SIZE); - -/** * Creates a named thread, otherwise the same as NS_NewThread */ template<size_t LEN> inline NS_METHOD NS_NewNamedThread(const char (&aName)[LEN], nsIThread** aResult, nsIRunnable* aInitialEvent = nullptr, uint32_t aStackSize = nsIThreadManager::DEFAULT_STACK_SIZE)