Merge inbound to m-c. a=merge

This commit is contained in:
Ryan VanderMeulen 2015-04-24 15:42:31 -04:00
commit 78196ec059
56 changed files with 1763 additions and 2552 deletions

View File

@ -1089,6 +1089,16 @@ window.addEventListener('ContentStart', function update_onContentStart() {
})(); })();
#endif #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. // Calling this observer will cause a shutdown an a profile reset.
// Use eg. : Services.obs.notifyObservers(null, 'b2g-reset-profile', null); // Use eg. : Services.obs.notifyObservers(null, 'b2g-reset-profile', null);
Services.obs.addObserver(function resetProfile(subject, topic, data) { Services.obs.addObserver(function resetProfile(subject, topic, data) {

View File

@ -159,6 +159,7 @@
@BINPATH@/components/commandlines.xpt @BINPATH@/components/commandlines.xpt
@BINPATH@/components/composer.xpt @BINPATH@/components/composer.xpt
@BINPATH@/components/content_events.xpt @BINPATH@/components/content_events.xpt
@BINPATH@/components/content_geckomediaplugins.xpt
@BINPATH@/components/content_html.xpt @BINPATH@/components/content_html.xpt
@BINPATH@/components/content_xslt.xpt @BINPATH@/components/content_xslt.xpt
@BINPATH@/components/cookie.xpt @BINPATH@/components/cookie.xpt

View File

@ -41,3 +41,5 @@ if [ -d "$topsrcdir/gtk3" ]; then
mk_add_options "export LD_LIBRARY_PATH=$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 ac_add_options --enable-default-toolkit=cairo-gtk3
fi fi
export SOCORRO_SYMBOL_UPLOAD_TOKEN_FILE=/builds/crash-stats-api.token

View File

@ -2607,6 +2607,5 @@ nsMessageManagerSH<Super>::Enumerate(nsIXPConnectWrappedNative* wrapper,
// Don't call up to our superclass, since neither nsDOMGenericSH nor // Don't call up to our superclass, since neither nsDOMGenericSH nor
// nsEventTargetSH have WANT_ENUMERATE. // nsEventTargetSH have WANT_ENUMERATE.
MOZ_ASSERT(!(this->GetScriptableFlags() & nsIXPCScriptable::WANT_ENUMERATE));
return NS_OK; return NS_OK;
} }

View File

@ -4080,13 +4080,12 @@ ArrayBufferBuilder::mapToFileInPackage(const nsCString& aFile,
uint32_t offset = zip->GetDataOffset(zipItem); uint32_t offset = zip->GetDataOffset(zipItem);
uint32_t size = zipItem->RealSize(); uint32_t size = zipItem->RealSize();
mozilla::AutoFDClose pr_fd; mozilla::AutoFDClose pr_fd;
mozilla::ScopedClose fd;
rv = aJarFile->OpenNSPRFileDesc(PR_RDONLY, 0, &pr_fd.rwget()); rv = aJarFile->OpenNSPRFileDesc(PR_RDONLY, 0, &pr_fd.rwget());
if (NS_FAILED(rv)) { if (NS_FAILED(rv)) {
return rv; return rv;
} }
fd.rwget() = PR_FileDesc2NativeHandle(pr_fd); mMapPtr = JS_CreateMappedArrayBufferContents(PR_FileDesc2NativeHandle(pr_fd),
mMapPtr = JS_CreateMappedArrayBufferContents(fd, offset, size); offset, size);
if (mMapPtr) { if (mMapPtr) {
mLength = size; mLength = size;
return NS_OK; return NS_OK;

View File

@ -29,7 +29,7 @@ public:
template<class U> template<class U>
MOZ_IMPLICIT OwningNonNull(already_AddRefed<U>&& aValue) MOZ_IMPLICIT OwningNonNull(already_AddRefed<U>&& aValue)
{ {
init(aValue.take()); init(aValue);
} }
// This is no worse than get() in terms of const handling. // This is no worse than get() in terms of const handling.
@ -106,7 +106,7 @@ public:
protected: protected:
template<typename U> template<typename U>
void init(U aValue) void init(U&& aValue)
{ {
mPtr = aValue; mPtr = aValue;
MOZ_ASSERT(mPtr); MOZ_ASSERT(mPtr);

View File

@ -92,47 +92,6 @@ private:
bool mEnabled; bool mEnabled;
bool mShutdown; bool mShutdown;
nsRefPtr<ContentParent> mPreallocatedAppProcess; 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> /* static */ StaticRefPtr<PreallocatedProcessManagerImpl>
@ -196,40 +155,6 @@ PreallocatedProcessManagerImpl::Observe(nsISupports* aSubject,
return NS_OK; 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 void
PreallocatedProcessManagerImpl::RereadPrefs() PreallocatedProcessManagerImpl::RereadPrefs()
{ {
@ -255,11 +180,6 @@ PreallocatedProcessManagerImpl::Enable()
mEnabled = true; mEnabled = true;
#ifdef MOZ_NUWA_PROCESS #ifdef MOZ_NUWA_PROCESS
#ifdef ENABLE_TESTS
// For testing New_UnmonitoredThread().
CreateUnmonitoredThread();
#endif
ScheduleDelayedNuwaFork(); ScheduleDelayedNuwaFork();
#else #else
AllocateAfterDelay(); AllocateAfterDelay();
@ -452,11 +372,6 @@ PreallocatedProcessManagerImpl::Disable()
mEnabled = false; mEnabled = false;
#ifdef MOZ_NUWA_PROCESS #ifdef MOZ_NUWA_PROCESS
#ifdef ENABLE_TESTS
// Shut down the test-only unmonitored thread.
DestroyUnmonitoredThread();
#endif
// Cancel pending fork. // Cancel pending fork.
if (mPreallocateAppProcessTask) { if (mPreallocateAppProcessTask) {
mPreallocateAppProcessTask->Cancel(); mPreallocateAppProcessTask->Cancel();

View File

@ -17,8 +17,6 @@ skip-if = buildapp == 'b2g' || buildapp == 'mulet'
skip-if = toolkit != 'gonk' skip-if = toolkit != 'gonk'
[test_NuwaProcessDeadlock.html] [test_NuwaProcessDeadlock.html]
skip-if = toolkit != 'gonk' skip-if = toolkit != 'gonk'
[test_NewUnmonitoredThread.html]
skip-if = toolkit != 'gonk'
[test_child_docshell.html] [test_child_docshell.html]
skip-if = toolkit == 'cocoa' # disabled due to hangs, see changeset 6852e7c47edf skip-if = toolkit == 'cocoa' # disabled due to hangs, see changeset 6852e7c47edf
[test_CrashService_crash.html] [test_CrashService_crash.html]

View File

@ -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>

View File

@ -1353,9 +1353,9 @@ nsEditor::CreateNode(nsIAtom* aTag,
nsAutoRules beginRulesSniffing(this, EditAction::createNode, nsIEditor::eNext); nsAutoRules beginRulesSniffing(this, EditAction::createNode, nsIEditor::eNext);
for (int32_t i = 0; i < mActionListeners.Count(); i++) { for (auto& listener : mActionListeners) {
mActionListeners[i]->WillCreateNode(nsDependentAtomString(aTag), listener->WillCreateNode(nsDependentAtomString(aTag),
GetAsDOMNode(aParent), aPosition); GetAsDOMNode(aParent), aPosition);
} }
nsCOMPtr<Element> ret; nsCOMPtr<Element> ret;
@ -1370,11 +1370,9 @@ nsEditor::CreateNode(nsIAtom* aTag,
mRangeUpdater.SelAdjCreateNode(aParent, aPosition); mRangeUpdater.SelAdjCreateNode(aParent, aPosition);
for (int32_t i = 0; i < mActionListeners.Count(); i++) { for (auto& listener : mActionListeners) {
mActionListeners[i]->DidCreateNode(nsDependentAtomString(aTag), listener->DidCreateNode(nsDependentAtomString(aTag), GetAsDOMNode(ret),
GetAsDOMNode(ret), GetAsDOMNode(aParent), aPosition, res);
GetAsDOMNode(aParent), aPosition,
res);
} }
return ret.forget(); return ret.forget();
@ -1396,9 +1394,9 @@ nsEditor::InsertNode(nsIContent& aNode, nsINode& aParent, int32_t aPosition)
{ {
nsAutoRules beginRulesSniffing(this, EditAction::insertNode, nsIEditor::eNext); nsAutoRules beginRulesSniffing(this, EditAction::insertNode, nsIEditor::eNext);
for (int32_t i = 0; i < mActionListeners.Count(); i++) { for (auto& listener : mActionListeners) {
mActionListeners[i]->WillInsertNode(aNode.AsDOMNode(), aParent.AsDOMNode(), listener->WillInsertNode(aNode.AsDOMNode(), aParent.AsDOMNode(),
aPosition); aPosition);
} }
nsRefPtr<InsertNodeTxn> txn = CreateTxnForInsertNode(aNode, aParent, nsRefPtr<InsertNodeTxn> txn = CreateTxnForInsertNode(aNode, aParent,
@ -1407,9 +1405,9 @@ nsEditor::InsertNode(nsIContent& aNode, nsINode& aParent, int32_t aPosition)
mRangeUpdater.SelAdjInsertNode(aParent.AsDOMNode(), aPosition); mRangeUpdater.SelAdjInsertNode(aParent.AsDOMNode(), aPosition);
for (int32_t i = 0; i < mActionListeners.Count(); i++) { for (auto& listener : mActionListeners) {
mActionListeners[i]->DidInsertNode(aNode.AsDOMNode(), aParent.AsDOMNode(), listener->DidInsertNode(aNode.AsDOMNode(), aParent.AsDOMNode(), aPosition,
aPosition, res); res);
} }
return res; return res;
@ -1435,8 +1433,8 @@ nsEditor::SplitNode(nsIContent& aNode, int32_t aOffset, ErrorResult& aResult)
nsAutoRules beginRulesSniffing(this, EditAction::splitNode, nsAutoRules beginRulesSniffing(this, EditAction::splitNode,
nsIEditor::eNext); nsIEditor::eNext);
for (int32_t i = 0; i < mActionListeners.Count(); i++) { for (auto& listener : mActionListeners) {
mActionListeners[i]->WillSplitNode(aNode.AsDOMNode(), aOffset); listener->WillSplitNode(aNode.AsDOMNode(), aOffset);
} }
nsRefPtr<SplitNodeTxn> txn = CreateTxnForSplitNode(aNode, aOffset); nsRefPtr<SplitNodeTxn> txn = CreateTxnForSplitNode(aNode, aOffset);
@ -1447,10 +1445,9 @@ nsEditor::SplitNode(nsIContent& aNode, int32_t aOffset, ErrorResult& aResult)
mRangeUpdater.SelAdjSplitNode(aNode, aOffset, newNode); mRangeUpdater.SelAdjSplitNode(aNode, aOffset, newNode);
for (int32_t i = 0; i < mActionListeners.Count(); i++) { for (auto& listener : mActionListeners) {
mActionListeners[i]->DidSplitNode(aNode.AsDOMNode(), aOffset, listener->DidSplitNode(aNode.AsDOMNode(), aOffset, GetAsDOMNode(newNode),
GetAsDOMNode(newNode), aResult.ErrorCode());
aResult.ErrorCode());
} }
return newNode; return newNode;
@ -1483,10 +1480,9 @@ nsEditor::JoinNodes(nsINode& aLeftNode, nsINode& aRightNode)
// Find the number of children of the lefthand node // Find the number of children of the lefthand node
uint32_t oldLeftNodeLen = aLeftNode.Length(); uint32_t oldLeftNodeLen = aLeftNode.Length();
for (int32_t i = 0; i < mActionListeners.Count(); i++) { for (auto& listener : mActionListeners) {
mActionListeners[i]->WillJoinNodes(aLeftNode.AsDOMNode(), listener->WillJoinNodes(aLeftNode.AsDOMNode(), aRightNode.AsDOMNode(),
aRightNode.AsDOMNode(), parent->AsDOMNode());
parent->AsDOMNode());
} }
nsresult result; nsresult result;
@ -1498,10 +1494,9 @@ nsEditor::JoinNodes(nsINode& aLeftNode, nsINode& aRightNode)
mRangeUpdater.SelAdjJoinNodes(aLeftNode, aRightNode, *parent, offset, mRangeUpdater.SelAdjJoinNodes(aLeftNode, aRightNode, *parent, offset,
(int32_t)oldLeftNodeLen); (int32_t)oldLeftNodeLen);
for (int32_t i = 0; i < mActionListeners.Count(); i++) { for (auto& listener : mActionListeners) {
mActionListeners[i]->DidJoinNodes(aLeftNode.AsDOMNode(), listener->DidJoinNodes(aLeftNode.AsDOMNode(), aRightNode.AsDOMNode(),
aRightNode.AsDOMNode(), parent->AsDOMNode(), result);
parent->AsDOMNode(), result);
} }
return result; return result;
@ -1522,8 +1517,8 @@ nsEditor::DeleteNode(nsINode* aNode)
nsAutoRules beginRulesSniffing(this, EditAction::createNode, nsIEditor::ePrevious); nsAutoRules beginRulesSniffing(this, EditAction::createNode, nsIEditor::ePrevious);
// save node location for selection updating code. // save node location for selection updating code.
for (int32_t i = 0; i < mActionListeners.Count(); i++) { for (auto& listener : mActionListeners) {
mActionListeners[i]->WillDeleteNode(aNode->AsDOMNode()); listener->WillDeleteNode(aNode->AsDOMNode());
} }
nsRefPtr<DeleteNodeTxn> txn; nsRefPtr<DeleteNodeTxn> txn;
@ -1532,8 +1527,8 @@ nsEditor::DeleteNode(nsINode* aNode)
res = DoTransaction(txn); res = DoTransaction(txn);
} }
for (int32_t i = 0; i < mActionListeners.Count(); i++) { for (auto& listener : mActionListeners) {
mActionListeners[i]->DidDeleteNode(aNode->AsDOMNode(), res); listener->DidDeleteNode(aNode->AsDOMNode(), res);
} }
NS_ENSURE_SUCCESS(res, res); NS_ENSURE_SUCCESS(res, res);
@ -1738,10 +1733,8 @@ nsEditor::AddEditorObserver(nsIEditorObserver *aObserver)
NS_ENSURE_TRUE(aObserver, NS_ERROR_NULL_POINTER); NS_ENSURE_TRUE(aObserver, NS_ERROR_NULL_POINTER);
// Make sure the listener isn't already on the list // Make sure the listener isn't already on the list
if (mEditorObservers.IndexOf(aObserver) == -1) if (!mEditorObservers.Contains(aObserver)) {
{ mEditorObservers.AppendElement(*aObserver);
if (!mEditorObservers.AppendObject(aObserver))
return NS_ERROR_FAILURE;
} }
return NS_OK; return NS_OK;
@ -1753,8 +1746,7 @@ nsEditor::RemoveEditorObserver(nsIEditorObserver *aObserver)
{ {
NS_ENSURE_TRUE(aObserver, NS_ERROR_FAILURE); NS_ENSURE_TRUE(aObserver, NS_ERROR_FAILURE);
if (!mEditorObservers.RemoveObject(aObserver)) mEditorObservers.RemoveElement(aObserver);
return NS_ERROR_FAILURE;
return NS_OK; return NS_OK;
} }
@ -1814,8 +1806,8 @@ nsEditor::NotifyEditorObservers(NotificationForEditorObservers aNotification)
switch (aNotification) { switch (aNotification) {
case eNotifyEditorObserversOfEnd: case eNotifyEditorObserversOfEnd:
mIsInEditAction = false; mIsInEditAction = false;
for (int32_t i = 0; i < mEditorObservers.Count(); i++) { for (auto& observer : mEditorObservers) {
mEditorObservers[i]->EditAction(); observer->EditAction();
} }
if (!mDispatchInputEvent) { if (!mDispatchInputEvent) {
@ -1826,14 +1818,14 @@ nsEditor::NotifyEditorObservers(NotificationForEditorObservers aNotification)
break; break;
case eNotifyEditorObserversOfBefore: case eNotifyEditorObserversOfBefore:
mIsInEditAction = true; mIsInEditAction = true;
for (int32_t i = 0; i < mEditorObservers.Count(); i++) { for (auto& observer : mEditorObservers) {
mEditorObservers[i]->BeforeEditAction(); observer->BeforeEditAction();
} }
break; break;
case eNotifyEditorObserversOfCancel: case eNotifyEditorObserversOfCancel:
mIsInEditAction = false; mIsInEditAction = false;
for (int32_t i = 0; i < mEditorObservers.Count(); i++) { for (auto& observer : mEditorObservers) {
mEditorObservers[i]->CancelEditAction(); observer->CancelEditAction();
} }
break; break;
default: default:
@ -1866,10 +1858,8 @@ nsEditor::AddEditActionListener(nsIEditActionListener *aListener)
NS_ENSURE_TRUE(aListener, NS_ERROR_NULL_POINTER); NS_ENSURE_TRUE(aListener, NS_ERROR_NULL_POINTER);
// Make sure the listener isn't already on the list // Make sure the listener isn't already on the list
if (mActionListeners.IndexOf(aListener) == -1) if (!mActionListeners.Contains(aListener)) {
{ mActionListeners.AppendElement(*aListener);
if (!mActionListeners.AppendObject(aListener))
return NS_ERROR_FAILURE;
} }
return NS_OK; return NS_OK;
@ -1881,8 +1871,7 @@ nsEditor::RemoveEditActionListener(nsIEditActionListener *aListener)
{ {
NS_ENSURE_TRUE(aListener, NS_ERROR_FAILURE); NS_ENSURE_TRUE(aListener, NS_ERROR_FAILURE);
if (!mActionListeners.RemoveObject(aListener)) mActionListeners.RemoveElement(aListener);
return NS_ERROR_FAILURE;
return NS_OK; return NS_OK;
} }
@ -1893,10 +1882,8 @@ nsEditor::AddDocumentStateListener(nsIDocumentStateListener *aListener)
{ {
NS_ENSURE_TRUE(aListener, NS_ERROR_NULL_POINTER); NS_ENSURE_TRUE(aListener, NS_ERROR_NULL_POINTER);
if (mDocStateListeners.IndexOf(aListener) == -1) if (!mDocStateListeners.Contains(aListener)) {
{ mDocStateListeners.AppendElement(*aListener);
if (!mDocStateListeners.AppendObject(aListener))
return NS_ERROR_FAILURE;
} }
return NS_OK; return NS_OK;
@ -1908,8 +1895,7 @@ nsEditor::RemoveDocumentStateListener(nsIDocumentStateListener *aListener)
{ {
NS_ENSURE_TRUE(aListener, NS_ERROR_NULL_POINTER); NS_ENSURE_TRUE(aListener, NS_ERROR_NULL_POINTER);
if (!mDocStateListeners.RemoveObject(aListener)) mDocStateListeners.RemoveElement(aListener);
return NS_ERROR_FAILURE;
return NS_OK; return NS_OK;
} }
@ -2392,8 +2378,8 @@ nsEditor::InsertTextIntoTextNodeImpl(const nsAString& aStringToInsert,
} }
// Let listeners know what's up // Let listeners know what's up
for (int32_t i = 0; i < mActionListeners.Count(); i++) { for (auto& listener : mActionListeners) {
mActionListeners[i]->WillInsertText( listener->WillInsertText(
static_cast<nsIDOMCharacterData*>(aTextNode.AsDOMNode()), aOffset, static_cast<nsIDOMCharacterData*>(aTextNode.AsDOMNode()), aOffset,
aStringToInsert); aStringToInsert);
} }
@ -2407,8 +2393,8 @@ nsEditor::InsertTextIntoTextNodeImpl(const nsAString& aStringToInsert,
mRangeUpdater.SelAdjInsertText(aTextNode, aOffset, aStringToInsert); mRangeUpdater.SelAdjInsertText(aTextNode, aOffset, aStringToInsert);
// let listeners know what happened // let listeners know what happened
for (int32_t i = 0; i < mActionListeners.Count(); i++) { for (auto& listener : mActionListeners) {
mActionListeners[i]->DidInsertText( listener->DidInsertText(
static_cast<nsIDOMCharacterData*>(aTextNode.AsDOMNode()), static_cast<nsIDOMCharacterData*>(aTextNode.AsDOMNode()),
aOffset, aStringToInsert, res); aOffset, aStringToInsert, res);
} }
@ -2465,29 +2451,28 @@ nsEditor::GetFirstEditableNode(nsINode* aRoot)
NS_IMETHODIMP NS_IMETHODIMP
nsEditor::NotifyDocumentListeners(TDocumentListenerNotification aNotificationType) nsEditor::NotifyDocumentListeners(TDocumentListenerNotification aNotificationType)
{ {
int32_t numListeners = mDocStateListeners.Count(); if (!mDocStateListeners.Length()) {
if (!numListeners) // maybe there just aren't any. // Maybe there just aren't any.
return NS_OK; return NS_OK;
}
nsCOMArray<nsIDocumentStateListener> listeners(mDocStateListeners); nsTArray<OwningNonNull<nsIDocumentStateListener>>
listeners(mDocStateListeners);
nsresult rv = NS_OK; nsresult rv = NS_OK;
int32_t i;
switch (aNotificationType) switch (aNotificationType)
{ {
case eDocumentCreated: case eDocumentCreated:
for (i = 0; i < numListeners;i++) for (auto& listener : listeners) {
{ rv = listener->NotifyDocumentCreated();
rv = listeners[i]->NotifyDocumentCreated();
if (NS_FAILED(rv)) if (NS_FAILED(rv))
break; break;
} }
break; break;
case eDocumentToBeDestroyed: case eDocumentToBeDestroyed:
for (i = 0; i < numListeners;i++) for (auto& listener : listeners) {
{ rv = listener->NotifyDocumentWillBeDestroyed();
rv = listeners[i]->NotifyDocumentWillBeDestroyed();
if (NS_FAILED(rv)) if (NS_FAILED(rv))
break; break;
} }
@ -2504,9 +2489,8 @@ nsEditor::NotifyDocumentListeners(TDocumentListenerNotification aNotificationTyp
mDocDirtyState = docIsDirty; mDocDirtyState = docIsDirty;
for (i = 0; i < numListeners;i++) for (auto& listener : listeners) {
{ rv = listener->NotifyDocumentStateChanged(mDocDirtyState);
rv = listeners[i]->NotifyDocumentStateChanged(mDocDirtyState);
if (NS_FAILED(rv)) if (NS_FAILED(rv))
break; break;
} }
@ -2542,8 +2526,8 @@ nsEditor::DeleteText(nsGenericDOMDataNode& aCharData, uint32_t aOffset,
nsAutoRules beginRulesSniffing(this, EditAction::deleteText, nsIEditor::ePrevious); nsAutoRules beginRulesSniffing(this, EditAction::deleteText, nsIEditor::ePrevious);
// Let listeners know what's up // Let listeners know what's up
for (int32_t i = 0; i < mActionListeners.Count(); i++) { for (auto& listener : mActionListeners) {
mActionListeners[i]->WillDeleteText( listener->WillDeleteText(
static_cast<nsIDOMCharacterData*>(GetAsDOMNode(&aCharData)), aOffset, static_cast<nsIDOMCharacterData*>(GetAsDOMNode(&aCharData)), aOffset,
aLength); aLength);
} }
@ -2551,8 +2535,8 @@ nsEditor::DeleteText(nsGenericDOMDataNode& aCharData, uint32_t aOffset,
nsresult res = DoTransaction(txn); nsresult res = DoTransaction(txn);
// Let listeners know what happened // Let listeners know what happened
for (int32_t i = 0; i < mActionListeners.Count(); i++) { for (auto& listener : mActionListeners) {
mActionListeners[i]->DidDeleteText( listener->DidDeleteText(
static_cast<nsIDOMCharacterData*>(GetAsDOMNode(&aCharData)), aOffset, static_cast<nsIDOMCharacterData*>(GetAsDOMNode(&aCharData)), aOffset,
aLength, res); aLength, res);
} }
@ -3960,31 +3944,38 @@ nsEditor::DeleteSelectionImpl(EDirection aAction,
if (NS_SUCCEEDED(res)) if (NS_SUCCEEDED(res))
{ {
nsAutoRules beginRulesSniffing(this, EditAction::deleteSelection, aAction); nsAutoRules beginRulesSniffing(this, EditAction::deleteSelection, aAction);
int32_t i;
// Notify nsIEditActionListener::WillDelete[Selection|Text|Node] // Notify nsIEditActionListener::WillDelete[Selection|Text|Node]
if (!deleteNode) if (!deleteNode) {
for (i = 0; i < mActionListeners.Count(); i++) for (auto& listener : mActionListeners) {
mActionListeners[i]->WillDeleteSelection(selection); listener->WillDeleteSelection(selection);
else if (deleteCharData) }
for (i = 0; i < mActionListeners.Count(); i++) } else if (deleteCharData) {
mActionListeners[i]->WillDeleteText(deleteCharData, deleteCharOffset, 1); for (auto& listener : mActionListeners) {
else listener->WillDeleteText(deleteCharData, deleteCharOffset, 1);
for (i = 0; i < mActionListeners.Count(); i++) }
mActionListeners[i]->WillDeleteNode(deleteNode->AsDOMNode()); } else {
for (auto& listener : mActionListeners) {
listener->WillDeleteNode(deleteNode->AsDOMNode());
}
}
// Delete the specified amount // Delete the specified amount
res = DoTransaction(txn); res = DoTransaction(txn);
// Notify nsIEditActionListener::DidDelete[Selection|Text|Node] // Notify nsIEditActionListener::DidDelete[Selection|Text|Node]
if (!deleteNode) if (!deleteNode) {
for (i = 0; i < mActionListeners.Count(); i++) for (auto& listener : mActionListeners) {
mActionListeners[i]->DidDeleteSelection(selection); listener->DidDeleteSelection(selection);
else if (deleteCharData) }
for (i = 0; i < mActionListeners.Count(); i++) } else if (deleteCharData) {
mActionListeners[i]->DidDeleteText(deleteCharData, deleteCharOffset, 1, res); for (auto& listener : mActionListeners) {
else listener->DidDeleteText(deleteCharData, deleteCharOffset, 1, res);
for (i = 0; i < mActionListeners.Count(); i++) }
mActionListeners[i]->DidDeleteNode(deleteNode->AsDOMNode(), res); } else {
for (auto& listener : mActionListeners) {
listener->DidDeleteNode(deleteNode->AsDOMNode(), res);
}
}
} }
return res; return res;

View File

@ -7,9 +7,9 @@
#define __editor_h__ #define __editor_h__
#include "mozilla/Assertions.h" // for MOZ_ASSERT, etc. #include "mozilla/Assertions.h" // for MOZ_ASSERT, etc.
#include "mozilla/dom/OwningNonNull.h" // for OwningNonNull
#include "mozilla/dom/Text.h" #include "mozilla/dom/Text.h"
#include "nsAutoPtr.h" // for nsRefPtr #include "nsAutoPtr.h" // for nsRefPtr
#include "nsCOMArray.h" // for nsCOMArray
#include "nsCOMPtr.h" // for already_AddRefed, nsCOMPtr #include "nsCOMPtr.h" // for already_AddRefed, nsCOMPtr
#include "nsCycleCollectionParticipant.h" #include "nsCycleCollectionParticipant.h"
#include "nsGkAtoms.h" #include "nsGkAtoms.h"
@ -830,9 +830,12 @@ protected:
nsRefPtr<mozilla::TextComposition> mComposition; nsRefPtr<mozilla::TextComposition> mComposition;
// various listeners // various listeners
nsCOMArray<nsIEditActionListener> mActionListeners; // listens to all low level actions on the doc // Listens to all low level actions on the doc
nsCOMArray<nsIEditorObserver> mEditorObservers; // just notify once per high level change nsTArray<mozilla::dom::OwningNonNull<nsIEditActionListener>> mActionListeners;
nsCOMArray<nsIDocumentStateListener> mDocStateListeners;// listen to overall doc state (dirty or not, just created, etc) // 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 nsSelectionState mSavedSel; // cached selection for nsAutoSelectionReset
nsRangeUpdater mRangeUpdater; // utility class object for maintaining preserved ranges nsRangeUpdater mRangeUpdater; // utility class object for maintaining preserved ranges

View File

@ -5,8 +5,8 @@
#include "nsEditorUtils.h" #include "nsEditorUtils.h"
#include "mozilla/dom/OwningNonNull.h"
#include "mozilla/dom/Selection.h" #include "mozilla/dom/Selection.h"
#include "nsCOMArray.h"
#include "nsComponentManagerUtils.h" #include "nsComponentManagerUtils.h"
#include "nsError.h" #include "nsError.h"
#include "nsIClipboardDragDropHookList.h" #include "nsIClipboardDragDropHookList.h"
@ -66,91 +66,53 @@ nsAutoSelectionReset::Abort()
* some helper classes for iterating the dom tree * some helper classes for iterating the dom tree
*****************************************************************************/ *****************************************************************************/
nsDOMIterator::nsDOMIterator() : nsDOMIterator::nsDOMIterator(nsRange& aRange)
mIter(nullptr) {
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() 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 void
nsDOMIterator::Init(nsIDOMNode* aNode) nsDOMIterator::AppendList(const nsBoolDomIterFunctor& functor,
{ nsTArray<OwningNonNull<nsINode>>& arrayOfNodes) const
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
{ {
// Iterate through dom and build list // Iterate through dom and build list
while (!mIter->IsDone()) { for (; !mIter->IsDone(); mIter->Next()) {
nsCOMPtr<nsINode> node = mIter->GetCurrentNode(); nsCOMPtr<nsINode> node = mIter->GetCurrentNode();
NS_ENSURE_TRUE(node, NS_ERROR_NULL_POINTER);
if (functor(node)) { if (functor(node)) {
arrayOfNodes.AppendElement(node); arrayOfNodes.AppendElement(*node);
} }
mIter->Next();
} }
return NS_OK;
} }
nsresult nsDOMSubtreeIterator::nsDOMSubtreeIterator(nsRange& aRange)
nsDOMIterator::AppendList(nsBoolDomIterFunctor& functor,
nsCOMArray<nsIDOMNode>& arrayOfNodes) const
{ {
nsCOMPtr<nsIDOMNode> node; mIter = NS_NewContentSubtreeIterator();
DebugOnly<nsresult> res = mIter->Init(&aRange);
// iterate through dom and build list MOZ_ASSERT(NS_SUCCEEDED(res));
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;
} }
nsDOMSubtreeIterator::nsDOMSubtreeIterator()
{
}
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 * some general purpose editor utils

View File

@ -19,9 +19,9 @@ class nsIAtom;
class nsIContentIterator; class nsIContentIterator;
class nsIDOMDocument; class nsIDOMDocument;
class nsRange; class nsRange;
template <class E> class nsCOMArray;
namespace mozilla { namespace mozilla {
namespace dom { namespace dom {
template <class T> class OwningNonNull;
class Selection; class Selection;
} }
} }
@ -167,42 +167,37 @@ class MOZ_STACK_CLASS nsAutoUpdateViewBatch
class nsBoolDomIterFunctor class nsBoolDomIterFunctor
{ {
public: public:
virtual bool operator()(nsIDOMNode* aNode)=0; virtual bool operator()(nsINode* aNode) const = 0;
bool operator()(nsINode* aNode)
{
return operator()(GetAsDOMNode(aNode));
}
}; };
class MOZ_STACK_CLASS nsDOMIterator class MOZ_STACK_CLASS nsDOMIterator
{ {
public: public:
nsDOMIterator(); explicit nsDOMIterator(nsRange& aRange);
explicit nsDOMIterator(nsINode& aNode);
virtual ~nsDOMIterator(); virtual ~nsDOMIterator();
nsresult Init(nsRange* aRange); void AppendList(const nsBoolDomIterFunctor& functor,
nsresult Init(nsIDOMNode* aNode); nsTArray<mozilla::dom::OwningNonNull<nsINode>>& arrayOfNodes) const;
nsresult AppendList(nsBoolDomIterFunctor& functor,
nsTArray<nsCOMPtr<nsINode>>& arrayOfNodes) const;
nsresult AppendList(nsBoolDomIterFunctor& functor,
nsCOMArray<nsIDOMNode>& arrayOfNodes) const;
protected: protected:
nsCOMPtr<nsIContentIterator> mIter; nsCOMPtr<nsIContentIterator> mIter;
// For nsDOMSubtreeIterator
nsDOMIterator();
}; };
class MOZ_STACK_CLASS nsDOMSubtreeIterator : public nsDOMIterator class MOZ_STACK_CLASS nsDOMSubtreeIterator : public nsDOMIterator
{ {
public: public:
nsDOMSubtreeIterator(); explicit nsDOMSubtreeIterator(nsRange& aRange);
virtual ~nsDOMSubtreeIterator(); virtual ~nsDOMSubtreeIterator();
nsresult Init(nsRange* aRange);
}; };
class nsTrivialFunctor : public nsBoolDomIterFunctor class nsTrivialFunctor : public nsBoolDomIterFunctor
{ {
public: 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; return true;
} }

View File

@ -7,6 +7,7 @@
#include <string.h> #include <string.h>
#include "mozilla/dom/DocumentFragment.h" #include "mozilla/dom/DocumentFragment.h"
#include "mozilla/dom/OwningNonNull.h"
#include "mozilla/ArrayUtils.h" #include "mozilla/ArrayUtils.h"
#include "mozilla/Base64.h" #include "mozilla/Base64.h"
#include "mozilla/BasicEvents.h" #include "mozilla/BasicEvents.h"
@ -14,7 +15,6 @@
#include "mozilla/dom/Selection.h" #include "mozilla/dom/Selection.h"
#include "nsAString.h" #include "nsAString.h"
#include "nsAutoPtr.h" #include "nsAutoPtr.h"
#include "nsCOMArray.h"
#include "nsCOMPtr.h" #include "nsCOMPtr.h"
#include "nsCRT.h" #include "nsCRT.h"
#include "nsCRTGlue.h" #include "nsCRTGlue.h"
@ -102,39 +102,6 @@ static nsresult RemoveFragComments(nsCString &theStr);
static void RemoveBodyAndHead(nsIDOMNode *aNode); static void RemoveBodyAndHead(nsIDOMNode *aNode);
static nsresult FindTargetNode(nsIDOMNode *aStart, nsCOMPtr<nsIDOMNode> &aResult); 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 nsresult
nsHTMLEditor::LoadHTML(const nsAString & aInputString) nsHTMLEditor::LoadHTML(const nsAString & aInputString)
{ {
@ -321,13 +288,21 @@ nsHTMLEditor::DoInsertHTMLWithContext(const nsAString & aInputString,
// this is work to be completed at a later date (probably by jfrancis) // 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 // make a list of what nodes in docFrag we need to move
nsCOMArray<nsIDOMNode> nodeList; nsTArray<OwningNonNull<nsINode>> nodeList;
rv = CreateListOfNodesToPaste(fragmentAsNode, nodeList, nsCOMPtr<nsINode> fragmentAsNodeNode = do_QueryInterface(fragmentAsNode);
streamStartParent, streamStartOffset, NS_ENSURE_STATE(fragmentAsNodeNode || !fragmentAsNode);
streamEndParent, streamEndOffset); nsCOMPtr<nsINode> streamStartParentNode =
NS_ENSURE_SUCCESS(rv, rv); 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; return NS_OK;
} }
@ -352,9 +327,9 @@ nsHTMLEditor::DoInsertHTMLWithContext(const nsAString & aInputString,
// but if not we want to delete _contents_ of cells and replace // but if not we want to delete _contents_ of cells and replace
// with non-table elements. Use cellSelectionMode bool to // with non-table elements. Use cellSelectionMode bool to
// indicate results. // indicate results.
nsIDOMNode* firstNode = nodeList[0]; if (!nsHTMLEditUtils::IsTableElement(nodeList[0])) {
if (!nsHTMLEditUtils::IsTableElement(firstNode))
cellSelectionMode = false; cellSelectionMode = false;
}
} }
if (!cellSelectionMode) if (!cellSelectionMode)
@ -402,7 +377,8 @@ nsHTMLEditor::DoInsertHTMLWithContext(const nsAString & aInputString,
NS_ENSURE_TRUE(parentNode, NS_ERROR_FAILURE); NS_ENSURE_TRUE(parentNode, NS_ERROR_FAILURE);
// Adjust position based on the first node we are going to insert. // 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. // 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 // this is because if there is a br at end of what we paste, it will make
@ -431,16 +407,15 @@ nsHTMLEditor::DoInsertHTMLWithContext(const nsAString & aInputString,
// build up list of parents of first node in list that are either // build up list of parents of first node in list that are either
// lists or tables. First examine front of paste node list. // lists or tables. First examine front of paste node list.
nsCOMArray<nsIDOMNode> startListAndTableArray; nsTArray<OwningNonNull<Element>> startListAndTableArray;
rv = GetListAndTableParents(false, nodeList, startListAndTableArray); GetListAndTableParents(StartOrEnd::start, nodeList,
NS_ENSURE_SUCCESS(rv, rv); startListAndTableArray);
// remember number of lists and tables above us // remember number of lists and tables above us
int32_t highWaterMark = -1; int32_t highWaterMark = -1;
if (startListAndTableArray.Count() > 0) if (startListAndTableArray.Length() > 0) {
{ highWaterMark = DiscoverPartialListsAndTables(nodeList,
rv = DiscoverPartialListsAndTables(nodeList, startListAndTableArray, &highWaterMark); startListAndTableArray);
NS_ENSURE_SUCCESS(rv, rv);
} }
// if we have pieces of tables or lists to be inserted, let's force the paste // if we have pieces of tables or lists to be inserted, let's force the paste
@ -448,33 +423,31 @@ nsHTMLEditor::DoInsertHTMLWithContext(const nsAString & aInputString,
// table or list contents outside the table or list. // table or list contents outside the table or list.
if (highWaterMark >= 0) if (highWaterMark >= 0)
{ {
rv = ReplaceOrphanedStructure(false, nodeList, startListAndTableArray, highWaterMark); ReplaceOrphanedStructure(StartOrEnd::start, nodeList,
NS_ENSURE_SUCCESS(rv, rv); startListAndTableArray, highWaterMark);
} }
// Now go through the same process again for the end of the paste node list. // Now go through the same process again for the end of the paste node list.
nsCOMArray<nsIDOMNode> endListAndTableArray; nsTArray<OwningNonNull<Element>> endListAndTableArray;
rv = GetListAndTableParents(true, nodeList, endListAndTableArray); GetListAndTableParents(StartOrEnd::end, nodeList, endListAndTableArray);
NS_ENSURE_SUCCESS(rv, rv);
highWaterMark = -1; highWaterMark = -1;
// remember number of lists and tables above us // remember number of lists and tables above us
if (endListAndTableArray.Count() > 0) if (endListAndTableArray.Length() > 0) {
{ highWaterMark = DiscoverPartialListsAndTables(nodeList,
rv = DiscoverPartialListsAndTables(nodeList, endListAndTableArray, &highWaterMark); endListAndTableArray);
NS_ENSURE_SUCCESS(rv, rv);
} }
// don't orphan partial list or table structure // don't orphan partial list or table structure
if (highWaterMark >= 0) if (highWaterMark >= 0)
{ {
rv = ReplaceOrphanedStructure(true, nodeList, endListAndTableArray, highWaterMark); ReplaceOrphanedStructure(StartOrEnd::end, nodeList,
NS_ENSURE_SUCCESS(rv, rv); endListAndTableArray, highWaterMark);
} }
// Loop over the node list and paste the nodes: // Loop over the node list and paste the nodes:
nsCOMPtr<nsIDOMNode> parentBlock, lastInsertNode, insertedContextParent; nsCOMPtr<nsIDOMNode> parentBlock, lastInsertNode, insertedContextParent;
int32_t listCount = nodeList.Count(); int32_t listCount = nodeList.Length();
int32_t j; int32_t j;
if (IsBlockNode(parentNode)) if (IsBlockNode(parentNode))
parentBlock = parentNode; parentBlock = parentNode;
@ -484,7 +457,7 @@ nsHTMLEditor::DoInsertHTMLWithContext(const nsAString & aInputString,
for (j=0; j<listCount; j++) for (j=0; j<listCount; j++)
{ {
bool bDidInsert = false; 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, NS_ERROR_FAILURE);
NS_ENSURE_TRUE(curNode != fragmentAsNode, NS_ERROR_FAILURE); NS_ENSURE_TRUE(curNode != fragmentAsNode, NS_ERROR_FAILURE);
@ -721,26 +694,25 @@ nsHTMLEditor::DoInsertHTMLWithContext(const nsAString & aInputString,
return mRules->DidDoAction(selection, &ruleInfo, rv); return mRules->DidDoAction(selection, &ruleInfo, rv);
} }
nsresult NS_IMETHODIMP
nsHTMLEditor::AddInsertionListener(nsIContentFilter *aListener) nsHTMLEditor::AddInsertionListener(nsIContentFilter *aListener)
{ {
NS_ENSURE_TRUE(aListener, NS_ERROR_NULL_POINTER); NS_ENSURE_TRUE(aListener, NS_ERROR_NULL_POINTER);
// don't let a listener be added more than once // don't let a listener be added more than once
if (mContentFilters.IndexOfObject(aListener) == -1) if (!mContentFilters.Contains(aListener)) {
{ mContentFilters.AppendElement(*aListener);
NS_ENSURE_TRUE(mContentFilters.AppendObject(aListener), NS_ERROR_FAILURE);
} }
return NS_OK; return NS_OK;
} }
nsresult NS_IMETHODIMP
nsHTMLEditor::RemoveInsertionListener(nsIContentFilter *aListener) nsHTMLEditor::RemoveInsertionListener(nsIContentFilter *aListener)
{ {
NS_ENSURE_TRUE(aListener, NS_ERROR_FAILURE); NS_ENSURE_TRUE(aListener, NS_ERROR_FAILURE);
NS_ENSURE_TRUE(mContentFilters.RemoveObject(aListener), NS_ERROR_FAILURE); mContentFilters.RemoveElement(aListener);
return NS_OK; return NS_OK;
} }
@ -760,17 +732,15 @@ nsHTMLEditor::DoContentFilterCallback(const nsAString &aFlavor,
{ {
*aDoContinue = true; *aDoContinue = true;
int32_t i; for (auto& listener : mContentFilters) {
nsIContentFilter *listener; if (!*aDoContinue) {
for (i=0; i < mContentFilters.Count() && *aDoContinue; i++) break;
{ }
listener = (nsIContentFilter *)mContentFilters[i]; listener->NotifyOfInsertion(aFlavor, nullptr, sourceDoc,
if (listener) aWillDeleteSelection, aFragmentAsNode,
listener->NotifyOfInsertion(aFlavor, nullptr, sourceDoc, aFragStartNode, aFragStartOffset,
aWillDeleteSelection, aFragmentAsNode, aFragEndNode, aFragEndOffset, aTargetNode,
aFragStartNode, aFragStartOffset, aTargetOffset, aDoContinue);
aFragEndNode, aFragEndOffset,
aTargetNode, aTargetOffset, aDoContinue);
} }
return NS_OK; return NS_OK;
@ -2166,219 +2136,170 @@ nsresult nsHTMLEditor::ParseFragment(const nsAString & aFragStr,
return rv; return rv;
} }
nsresult nsHTMLEditor::CreateListOfNodesToPaste(nsIDOMNode *aFragmentAsNode, void
nsCOMArray<nsIDOMNode>& outNodeList, nsHTMLEditor::CreateListOfNodesToPaste(DocumentFragment& aFragment,
nsIDOMNode *aStartNode, nsTArray<OwningNonNull<nsINode>>& outNodeList,
int32_t aStartOffset, nsINode* aStartNode,
nsIDOMNode *aEndNode, int32_t aStartOffset,
int32_t aEndOffset) nsINode* aEndNode,
int32_t aEndOffset)
{ {
NS_ENSURE_TRUE(aFragmentAsNode, NS_ERROR_NULL_POINTER); // If no info was provided about the boundary between context and stream,
nsresult rv;
// if no info was provided about the boundary between context and stream,
// then assume all is stream. // then assume all is stream.
if (!aStartNode) if (!aStartNode) {
{ aStartNode = &aFragment;
int32_t fragLen;
rv = GetLengthOfDOMNode(aFragmentAsNode, (uint32_t&)fragLen);
NS_ENSURE_SUCCESS(rv, rv);
aStartNode = aFragmentAsNode;
aStartOffset = 0; aStartOffset = 0;
aEndNode = aFragmentAsNode; aEndNode = &aFragment;
aEndOffset = fragLen; aEndOffset = aFragment.Length();
} }
nsRefPtr<nsRange> docFragRange; nsRefPtr<nsRange> docFragRange;
rv = nsRange::CreateRange(aStartNode, aStartOffset, aEndNode, aEndOffset, getter_AddRefs(docFragRange)); nsresult rv = nsRange::CreateRange(aStartNode, aStartOffset,
NS_ENSURE_SUCCESS(rv, rv); 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; nsTrivialFunctor functor;
nsDOMSubtreeIterator iter; nsDOMSubtreeIterator iter(*docFragRange);
rv = iter.Init(docFragRange); iter.AppendList(functor, outNodeList);
NS_ENSURE_SUCCESS(rv, rv);
return iter.AppendList(functor, outNodeList);
} }
nsresult void
nsHTMLEditor::GetListAndTableParents(bool aEnd, nsHTMLEditor::GetListAndTableParents(StartOrEnd aStartOrEnd,
nsCOMArray<nsIDOMNode>& aListOfNodes, nsTArray<OwningNonNull<nsINode>>& aNodeList,
nsCOMArray<nsIDOMNode>& outArray) nsTArray<OwningNonNull<Element>>& outArray)
{ {
int32_t listCount = aListOfNodes.Count(); MOZ_ASSERT(aNodeList.Length());
NS_ENSURE_TRUE(listCount > 0, NS_ERROR_FAILURE); // no empty lists, please
// build up list of parents of first (or last) node in list // Build up list of parents of first (or last) node in list that are either
// that are either lists, or tables. // lists, or tables.
int32_t idx = 0; int32_t idx = aStartOrEnd == StartOrEnd::end ? aNodeList.Length() - 1 : 0;
if (aEnd) idx = listCount-1;
nsCOMPtr<nsIDOMNode> pNode = aListOfNodes[idx]; for (nsCOMPtr<nsINode> node = aNodeList[idx]; node;
while (pNode) node = node->GetParentNode()) {
{ if (nsHTMLEditUtils::IsList(node) || nsHTMLEditUtils::IsTable(node)) {
if (nsHTMLEditUtils::IsList(pNode) || nsHTMLEditUtils::IsTable(pNode)) outArray.AppendElement(*node->AsElement());
{
NS_ENSURE_TRUE(outArray.AppendObject(pNode), NS_ERROR_FAILURE);
} }
nsCOMPtr<nsIDOMNode> parent;
pNode->GetParentNode(getter_AddRefs(parent));
pNode = parent;
} }
return NS_OK;
} }
nsresult int32_t
nsHTMLEditor::DiscoverPartialListsAndTables(nsCOMArray<nsIDOMNode>& aPasteNodes, nsHTMLEditor::DiscoverPartialListsAndTables(nsTArray<OwningNonNull<nsINode>>& aPasteNodes,
nsCOMArray<nsIDOMNode>& aListsAndTables, nsTArray<OwningNonNull<Element>>& aListsAndTables)
int32_t *outHighWaterMark)
{ {
NS_ENSURE_TRUE(outHighWaterMark, NS_ERROR_NULL_POINTER); int32_t ret = -1;
int32_t listAndTableParents = aListsAndTables.Length();
*outHighWaterMark = -1; // Scan insertion list for table elements (other than table).
int32_t listAndTableParents = aListsAndTables.Count(); for (auto& curNode : aPasteNodes) {
if (nsHTMLEditUtils::IsTableElement(curNode) &&
// scan insertion list for table elements (other than table). !curNode->IsHTMLElement(nsGkAtoms::table)) {
int32_t listCount = aPasteNodes.Count(); nsCOMPtr<Element> table = curNode->GetParentElement();
int32_t j; while (table && !table->IsHTMLElement(nsGkAtoms::table)) {
for (j=0; j<listCount; j++) table = table->GetParentElement();
{ }
nsCOMPtr<nsIDOMNode> curNode = aPasteNodes[j]; if (table) {
int32_t idx = aListsAndTables.IndexOf(table);
NS_ENSURE_TRUE(curNode, NS_ERROR_FAILURE); if (idx == -1) {
if (nsHTMLEditUtils::IsTableElement(curNode) && !nsHTMLEditUtils::IsTable(curNode)) return ret;
{
nsCOMPtr<nsIDOMNode> theTable = GetTableParent(curNode);
if (theTable)
{
int32_t indexT = aListsAndTables.IndexOf(theTable);
if (indexT >= 0)
{
*outHighWaterMark = indexT;
if (*outHighWaterMark == listAndTableParents-1) break;
} }
else ret = idx;
{ if (ret == listAndTableParents - 1) {
break; return ret;
} }
} }
} }
if (nsHTMLEditUtils::IsListItem(curNode)) if (nsHTMLEditUtils::IsListItem(curNode)) {
{ nsCOMPtr<Element> list = curNode->GetParentElement();
nsCOMPtr<nsIDOMNode> theList = GetListParent(curNode); while (list && !nsHTMLEditUtils::IsList(list)) {
if (theList) list = list->GetParentElement();
{ }
int32_t indexL = aListsAndTables.IndexOf(theList); if (list) {
if (indexL >= 0) int32_t idx = aListsAndTables.IndexOf(list);
{ if (idx == -1) {
*outHighWaterMark = indexL; return ret;
if (*outHighWaterMark == listAndTableParents-1) break;
} }
else ret = idx;
{ if (ret == listAndTableParents - 1) {
break; return ret;
} }
} }
} }
} }
return NS_OK; return ret;
} }
nsresult nsINode*
nsHTMLEditor::ScanForListAndTableStructure( bool aEnd, nsHTMLEditor::ScanForListAndTableStructure(StartOrEnd aStartOrEnd,
nsCOMArray<nsIDOMNode>& aNodes, nsTArray<OwningNonNull<nsINode>>& aNodes,
nsIDOMNode *aListOrTable, Element& aListOrTable)
nsCOMPtr<nsIDOMNode> *outReplaceNode)
{ {
NS_ENSURE_TRUE(aListOrTable, NS_ERROR_NULL_POINTER); // Look upward from first/last paste node for a piece of this list/table
NS_ENSURE_TRUE(outReplaceNode, NS_ERROR_NULL_POINTER); int32_t idx = aStartOrEnd == StartOrEnd::end ? aNodes.Length() - 1 : 0;
bool isList = nsHTMLEditUtils::IsList(&aListOrTable);
*outReplaceNode = 0;
// look upward from first/last paste node for a piece of this list/table for (nsCOMPtr<nsINode> node = aNodes[idx]; node;
int32_t listCount = aNodes.Count(), idx = 0; node = node->GetParentNode()) {
if (aEnd) idx = listCount-1; if ((isList && nsHTMLEditUtils::IsListItem(node)) ||
bool bList = nsHTMLEditUtils::IsList(aListOrTable); (!isList && nsHTMLEditUtils::IsTableElement(node) &&
!node->IsHTMLElement(nsGkAtoms::table))) {
nsCOMPtr<nsIDOMNode> pNode = aNodes[idx]; nsCOMPtr<Element> structureNode = node->GetParentElement();
nsCOMPtr<nsIDOMNode> originalNode = pNode; if (isList) {
while (pNode) while (structureNode && !nsHTMLEditUtils::IsList(structureNode)) {
{ structureNode = structureNode->GetParentElement();
if ((bList && nsHTMLEditUtils::IsListItem(pNode)) || }
(!bList && (nsHTMLEditUtils::IsTableElement(pNode) && !nsHTMLEditUtils::IsTable(pNode)))) } else {
{ while (structureNode &&
nsCOMPtr<nsIDOMNode> structureNode; !structureNode->IsHTMLElement(nsGkAtoms::table)) {
if (bList) structureNode = GetListParent(pNode); structureNode = structureNode->GetParentElement();
else structureNode = GetTableParent(pNode); }
if (structureNode == aListOrTable) }
{ if (structureNode == &aListOrTable) {
if (bList) if (isList) {
*outReplaceNode = structureNode; return structureNode;
else }
*outReplaceNode = pNode; return node;
break;
} }
} }
nsCOMPtr<nsIDOMNode> parent;
pNode->GetParentNode(getter_AddRefs(parent));
pNode = parent;
} }
return NS_OK; return nullptr;
} }
nsresult void
nsHTMLEditor::ReplaceOrphanedStructure(bool aEnd, nsHTMLEditor::ReplaceOrphanedStructure(StartOrEnd aStartOrEnd,
nsCOMArray<nsIDOMNode>& aNodeArray, nsTArray<OwningNonNull<nsINode>>& aNodeArray,
nsCOMArray<nsIDOMNode>& aListAndTableArray, nsTArray<OwningNonNull<Element>>& aListAndTableArray,
int32_t aHighWaterMark) int32_t aHighWaterMark)
{ {
nsCOMPtr<nsIDOMNode> curNode = aListAndTableArray[aHighWaterMark]; OwningNonNull<Element> 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.
nsCOMPtr<nsINode> replaceNode =
ScanForListAndTableStructure(aStartOrEnd, aNodeArray, curNode);
// find substructure of list or table that must be included in paste. if (!replaceNode) {
nsresult rv = ScanForListAndTableStructure(aEnd, aNodeArray, return;
curNode, address_of(replaceNode)); }
NS_ENSURE_SUCCESS(rv, rv);
// If we found substructure, paste it instead of its descendants.
// if we found substructure, paste it instead of its descendants // Postprocess list to remove any descendants of this node so that we don't
if (replaceNode) // insert them twice.
{ while (aNodeArray.Length()) {
// postprocess list to remove any descendants of this node int32_t idx = aStartOrEnd == StartOrEnd::start ? 0
// so that we don't insert them twice. : aNodeArray.Length() - 1;
nsCOMPtr<nsIDOMNode> endpoint; OwningNonNull<nsINode> endpoint = aNodeArray[idx];
do if (!nsEditorUtils::IsDescendantOf(endpoint, replaceNode)) {
{ break;
endpoint = GetArrayEndpoint(aEnd, aNodeArray); }
if (!endpoint) break; aNodeArray.RemoveElementAt(idx);
if (nsEditorUtils::IsDescendantOf(endpoint, replaceNode)) }
aNodeArray.RemoveObject(endpoint);
else // Now replace the removed nodes with the structural parent
break; if (aStartOrEnd == StartOrEnd::end) {
} while(endpoint); aNodeArray.AppendElement(*replaceNode);
} else {
// now replace the removed nodes with the structural parent aNodeArray.InsertElementAt(0, *replaceNode);
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 (aEnd) {
return aNodeArray[listCount-1];
}
return aNodeArray[0];
} }

File diff suppressed because it is too large Load Diff

View File

@ -37,7 +37,6 @@ class Selection;
} // namespace dom } // namespace dom
} // namespace mozilla } // namespace mozilla
struct DOMPoint; struct DOMPoint;
template <class E> class nsCOMArray;
struct StyleCache : public PropItem struct StyleCache : public PropItem
{ {
@ -191,14 +190,17 @@ protected:
nsresult DidMakeBasicBlock(mozilla::dom::Selection* aSelection, nsresult DidMakeBasicBlock(mozilla::dom::Selection* aSelection,
nsRulesInfo* aInfo, nsresult aResult); nsRulesInfo* aInfo, nsresult aResult);
nsresult DidAbsolutePosition(); nsresult DidAbsolutePosition();
nsresult AlignInnerBlocks(nsIDOMNode *aNode, const nsAString *alignType); nsresult AlignInnerBlocks(nsINode& aNode, const nsAString* alignType);
nsresult AlignBlockContents(nsIDOMNode *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); nsINode* aNode);
nsresult AppendInnerFormatNodes(nsCOMArray<nsIDOMNode>& aArray,
nsIDOMNode *aNode);
nsresult GetFormatString(nsIDOMNode *aNode, nsAString &outFormat); 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); already_AddRefed<nsIDOMNode> IsInListItem(nsIDOMNode* aNode);
mozilla::dom::Element* IsInListItem(nsINode* aNode); mozilla::dom::Element* IsInListItem(nsINode* aNode);
nsresult ReturnInHeader(mozilla::dom::Selection* aSelection, nsresult ReturnInHeader(mozilla::dom::Selection* aSelection,
@ -217,11 +219,9 @@ protected:
int32_t aOffset); int32_t aOffset);
nsresult AfterEditInner(EditAction action, nsresult AfterEditInner(EditAction action,
nsIEditor::EDirection aDirection); nsIEditor::EDirection aDirection);
nsresult RemovePartOfBlock(nsIDOMNode *aBlock, nsresult RemovePartOfBlock(mozilla::dom::Element& aBlock,
nsIDOMNode *aStartChild, nsIContent& aStartChild,
nsIDOMNode *aEndChild, nsIContent& aEndChild);
nsCOMPtr<nsIDOMNode> *aLeftNode = 0,
nsCOMPtr<nsIDOMNode> *aRightNode = 0);
nsresult SplitBlock(nsIDOMNode *aBlock, nsresult SplitBlock(nsIDOMNode *aBlock,
nsIDOMNode *aStartChild, nsIDOMNode *aStartChild,
nsIDOMNode *aEndChild, nsIDOMNode *aEndChild,
@ -263,37 +263,44 @@ protected:
void GetPromotedPoint(RulesEndpoint aWhere, nsIDOMNode* aNode, void GetPromotedPoint(RulesEndpoint aWhere, nsIDOMNode* aNode,
int32_t aOffset, EditAction actionID, int32_t aOffset, EditAction actionID,
nsCOMPtr<nsIDOMNode>* outNode, int32_t* outOffset); nsCOMPtr<nsIDOMNode>* outNode, int32_t* outOffset);
nsresult GetPromotedRanges(mozilla::dom::Selection* aSelection, void GetPromotedRanges(mozilla::dom::Selection& aSelection,
nsTArray<nsRefPtr<nsRange>>& outArrayOfRanges, nsTArray<nsRefPtr<nsRange>>& outArrayOfRanges,
EditAction inOperationType); EditAction inOperationType);
nsresult PromoteRange(nsRange* inRange, EditAction inOperationType); void PromoteRange(nsRange& aRange, EditAction inOperationType);
nsresult GetNodesForOperation(nsTArray<nsRefPtr<nsRange>>& inArrayOfRanges, enum class TouchContent { no, yes };
nsCOMArray<nsIDOMNode>& outArrayOfNodes, nsresult GetNodesForOperation(nsTArray<nsRefPtr<nsRange>>& aArrayOfRanges,
EditAction inOperationType, nsTArray<mozilla::dom::OwningNonNull<nsINode>>& aOutArrayOfNodes,
bool aDontTouchContent=false); EditAction aOperationType,
nsresult GetChildNodesForOperation(nsIDOMNode *inNode, TouchContent aTouchContent = TouchContent::yes);
nsCOMArray<nsIDOMNode>& outArrayOfNodes); void GetChildNodesForOperation(nsINode& aNode,
nsresult GetNodesFromPoint(::DOMPoint point, nsTArray<mozilla::dom::OwningNonNull<nsINode>>& outArrayOfNodes);
EditAction operation, nsresult GetNodesFromPoint(::DOMPoint aPoint,
nsCOMArray<nsIDOMNode>& arrayOfNodes, EditAction aOperation,
bool dontTouchContent); nsTArray<mozilla::dom::OwningNonNull<nsINode>>& outArrayOfNodes,
nsresult GetNodesFromSelection(mozilla::dom::Selection* selection, TouchContent aTouchContent);
EditAction operation, nsresult GetNodesFromSelection(mozilla::dom::Selection& aSelection,
nsCOMArray<nsIDOMNode>& arrayOfNodes, EditAction aOperation,
bool aDontTouchContent=false); nsTArray<mozilla::dom::OwningNonNull<nsINode>>& outArrayOfNodes,
nsresult GetListActionNodes(nsCOMArray<nsIDOMNode> &outArrayOfNodes, bool aEntireList, bool aDontTouchContent=false); 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); void GetDefinitionListItemTypes(mozilla::dom::Element* aElement, bool* aDT, bool* aDD);
nsresult GetParagraphFormatNodes(nsCOMArray<nsIDOMNode>& outArrayOfNodes, bool aDontTouchContent=false); nsresult GetParagraphFormatNodes(
nsresult LookInsideDivBQandList(nsCOMArray<nsIDOMNode>& aNodeArray); nsTArray<mozilla::dom::OwningNonNull<nsINode>>& outArrayOfNodes,
TouchContent aTouchContent = TouchContent::yes);
void LookInsideDivBQandList(nsTArray<mozilla::dom::OwningNonNull<nsINode>>& aNodeArray);
nsresult BustUpInlinesAtRangeEndpoints(nsRangeStore &inRange); nsresult BustUpInlinesAtRangeEndpoints(nsRangeStore &inRange);
nsresult BustUpInlinesAtBRs(nsIDOMNode *inNode, nsresult BustUpInlinesAtBRs(nsINode& aNode,
nsCOMArray<nsIDOMNode>& outArrayOfNodes); nsTArray<mozilla::dom::OwningNonNull<nsINode>>& aOutArrayOfNodes);
nsCOMPtr<nsIDOMNode> GetHighestInlineParent(nsIDOMNode* aNode); nsCOMPtr<nsIDOMNode> GetHighestInlineParent(nsIDOMNode* aNode);
nsresult MakeTransitionList(nsCOMArray<nsIDOMNode>& inArrayOfNodes, void MakeTransitionList(nsTArray<mozilla::dom::OwningNonNull<nsINode>>& aNodeArray,
nsTArray<bool> &inTransitionArray); nsTArray<bool>& aTransitionArray);
nsresult RemoveBlockStyle(nsCOMArray<nsIDOMNode>& arrayOfNodes); nsresult RemoveBlockStyle(nsTArray<mozilla::dom::OwningNonNull<nsINode>>& aNodeArray);
nsresult ApplyBlockStyle(nsCOMArray<nsIDOMNode>& arrayOfNodes, const nsAString *aBlockTag); nsresult ApplyBlockStyle(nsTArray<mozilla::dom::OwningNonNull<nsINode>>& aNodeArray,
nsresult MakeBlockquote(nsCOMArray<nsIDOMNode>& arrayOfNodes); nsIAtom& aBlockTag);
nsresult MakeBlockquote(nsTArray<mozilla::dom::OwningNonNull<nsINode>>& aNodeArray);
nsresult SplitAsNeeded(nsIAtom& aTag, nsCOMPtr<nsINode>& inOutParent, nsresult SplitAsNeeded(nsIAtom& aTag, nsCOMPtr<nsINode>& inOutParent,
int32_t& inOutOffset); int32_t& inOutOffset);
nsresult AddTerminatingBR(nsIDOMNode *aBlock); nsresult AddTerminatingBR(nsIDOMNode *aBlock);
@ -304,7 +311,7 @@ protected:
nsresult CacheInlineStyles(nsIDOMNode *aNode); nsresult CacheInlineStyles(nsIDOMNode *aNode);
nsresult ReapplyCachedStyles(); nsresult ReapplyCachedStyles();
void ClearCachedStyles(); void ClearCachedStyles();
nsresult AdjustSpecialBreaks(bool aSafeToAskFrames = false); void AdjustSpecialBreaks();
nsresult AdjustWhitespace(mozilla::dom::Selection* aSelection); nsresult AdjustWhitespace(mozilla::dom::Selection* aSelection);
nsresult PinSelectionToNewBlock(mozilla::dom::Selection* aSelection); nsresult PinSelectionToNewBlock(mozilla::dom::Selection* aSelection);
nsresult CheckInterlinePosition(mozilla::dom::Selection* aSelection); nsresult CheckInterlinePosition(mozilla::dom::Selection* aSelection);
@ -329,7 +336,7 @@ protected:
nsresult ConfirmSelectionInBody(); nsresult ConfirmSelectionInBody();
nsresult InsertMozBRIfNeeded(nsIDOMNode *aNode); nsresult InsertMozBRIfNeeded(nsIDOMNode *aNode);
bool IsEmptyInline(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 RemoveAlignment(nsIDOMNode * aNode, const nsAString & aAlignType, bool aChildrenOnly);
nsresult MakeSureElemStartsOrEndsOnCR(nsIDOMNode *aNode, bool aStarts); nsresult MakeSureElemStartsOrEndsOnCR(nsIDOMNode *aNode, bool aStarts);
nsresult AlignBlock(nsIDOMElement * aElement, const nsAString * aAlignType, bool aContentsOnly); nsresult AlignBlock(nsIDOMElement * aElement, const nsAString * aAlignType, bool aContentsOnly);

View File

@ -195,7 +195,7 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsHTMLEditor, nsPlaintextEdito
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMouseMotionListenerP) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMouseMotionListenerP)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSelectionListenerP) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSelectionListenerP)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mResizeEventListenerP) 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(mAbsolutelyPositionedObject)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mGrabber) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mGrabber)
@ -2988,8 +2988,6 @@ nsHTMLEditor::GetURLForStyleSheet(CSSStyleSheet* aStyleSheet,
int32_t foundIndex = mStyleSheets.IndexOf(aStyleSheet); int32_t foundIndex = mStyleSheets.IndexOf(aStyleSheet);
// Don't fail if we don't find it in our list // 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) if (foundIndex == -1)
return NS_OK; return NS_OK;
@ -4503,196 +4501,156 @@ nsHTMLEditor::SetIsCSSEnabled(bool aIsCSSPrefChecked)
nsresult nsresult
nsHTMLEditor::SetCSSBackgroundColor(const nsAString& aColor) nsHTMLEditor::SetCSSBackgroundColor(const nsAString& aColor)
{ {
if (!mRules) { return NS_ERROR_NOT_INITIALIZED; } NS_ENSURE_TRUE(mRules, NS_ERROR_NOT_INITIALIZED);
ForceCompositionEnd(); ForceCompositionEnd();
// Protect the edit rules object from dying // Protect the edit rules object from dying
nsCOMPtr<nsIEditRules> kungFuDeathGrip(mRules); nsCOMPtr<nsIEditRules> kungFuDeathGrip(mRules);
nsRefPtr<Selection> selection = GetSelection(); nsRefPtr<Selection> selection = GetSelection();
NS_ENSURE_STATE(selection);
bool isCollapsed = selection->Collapsed(); bool isCollapsed = selection->Collapsed();
nsAutoEditBatch batchIt(this); nsAutoEditBatch batchIt(this);
nsAutoRules beginRulesSniffing(this, EditAction::insertElement, nsIEditor::eNext); nsAutoRules beginRulesSniffing(this, EditAction::insertElement,
nsIEditor::eNext);
nsAutoSelectionReset selectionResetter(selection, this); nsAutoSelectionReset selectionResetter(selection, this);
nsAutoTxnsConserveSelection dontSpazMySelection(this); nsAutoTxnsConserveSelection dontSpazMySelection(this);
bool cancel, handled; bool cancel, handled;
nsTextRulesInfo ruleInfo(EditAction::setTextProperty); nsTextRulesInfo ruleInfo(EditAction::setTextProperty);
nsresult res = mRules->WillDoAction(selection, &ruleInfo, &cancel, &handled); nsresult res = mRules->WillDoAction(selection, &ruleInfo, &cancel, &handled);
NS_ENSURE_SUCCESS(res, res); NS_ENSURE_SUCCESS(res, res);
if (!cancel && !handled) if (!cancel && !handled) {
{ // Loop through the ranges in the selection
// loop thru the ranges in the selection NS_NAMED_LITERAL_STRING(bgcolor, "bgcolor");
nsAutoString bgcolor; bgcolor.AssignLiteral("bgcolor"); for (uint32_t i = 0; i < selection->RangeCount(); i++) {
uint32_t rangeCount = selection->RangeCount(); nsRefPtr<nsRange> range = selection->GetRangeAt(i);
for (uint32_t rangeIdx = 0; rangeIdx < rangeCount; ++rangeIdx) {
nsCOMPtr<nsIDOMNode> cachedBlockParent = nullptr;
nsRefPtr<nsRange> range = selection->GetRangeAt(rangeIdx);
NS_ENSURE_TRUE(range, NS_ERROR_FAILURE); NS_ENSURE_TRUE(range, NS_ERROR_FAILURE);
// check for easy case: both range endpoints in same text node nsCOMPtr<Element> cachedBlockParent;
nsCOMPtr<nsIDOMNode> startNode, endNode;
int32_t startOffset, endOffset; // Check for easy case: both range endpoints in same text node
res = range->GetStartContainer(getter_AddRefs(startNode)); nsCOMPtr<nsINode> startNode = range->GetStartParent();
NS_ENSURE_SUCCESS(res, res); int32_t startOffset = range->StartOffset();
res = range->GetEndContainer(getter_AddRefs(endNode)); nsCOMPtr<nsINode> endNode = range->GetEndParent();
NS_ENSURE_SUCCESS(res, res); int32_t endOffset = range->EndOffset();
res = range->GetStartOffset(&startOffset); if (startNode == endNode && IsTextNode(startNode)) {
NS_ENSURE_SUCCESS(res, res); // Let's find the block container of the text node
res = range->GetEndOffset(&endOffset); nsCOMPtr<Element> blockParent = GetBlockNodeParent(startNode);
NS_ENSURE_SUCCESS(res, res); // And apply the background color to that block container
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
if (blockParent && cachedBlockParent != blockParent) { if (blockParent && cachedBlockParent != blockParent) {
cachedBlockParent = blockParent; cachedBlockParent = blockParent;
nsCOMPtr<nsIDOMElement> element = do_QueryInterface(blockParent); mHTMLCSSUtils->SetCSSEquivalentToHTMLStyle(blockParent, nullptr,
int32_t count; &bgcolor, &aColor, false);
res = mHTMLCSSUtils->SetCSSEquivalentToHTMLStyle(element, nullptr, &bgcolor, &aColor, &count, false);
NS_ENSURE_SUCCESS(res, res);
} }
} } else if (startNode == endNode &&
else if ((startNode == endNode) && nsTextEditUtils::IsBody(startNode) && isCollapsed) startNode->IsHTMLElement(nsGkAtoms::body) && isCollapsed) {
{ // No block in the document, let's apply the background to the body
// we have no block in the document, let's apply the background to the body mHTMLCSSUtils->SetCSSEquivalentToHTMLStyle(startNode->AsElement(),
nsCOMPtr<nsIDOMElement> element = do_QueryInterface(startNode); nullptr, &bgcolor, &aColor,
int32_t count; false);
res = mHTMLCSSUtils->SetCSSEquivalentToHTMLStyle(element, nullptr, &bgcolor, &aColor, &count, false); } else if (startNode == endNode && (endOffset - startOffset == 1 ||
NS_ENSURE_SUCCESS(res, res); (!startOffset && !endOffset))) {
} // A unique node is selected, let's also apply the background color to
else if ((startNode == endNode) && (((endOffset-startOffset) == 1) || (!startOffset && !endOffset))) // the containing block, possibly the node itself
{ nsCOMPtr<nsIContent> selectedNode = startNode->GetChildAt(startOffset);
// a unique node is selected, let's also apply the background color nsCOMPtr<Element> blockParent;
// to the containing block, possibly the node itself if (NodeIsBlockStatic(selectedNode)) {
nsCOMPtr<nsIDOMNode> selectedNode = GetChildAt(startNode, startOffset); blockParent = selectedNode->AsElement();
bool isBlock =false; } else {
res = NodeIsBlockStatic(selectedNode, &isBlock);
NS_ENSURE_SUCCESS(res, res);
nsCOMPtr<nsIDOMNode> blockParent = selectedNode;
if (!isBlock) {
blockParent = GetBlockNodeParent(selectedNode); blockParent = GetBlockNodeParent(selectedNode);
} }
if (blockParent && cachedBlockParent != blockParent) { if (blockParent && cachedBlockParent != blockParent) {
cachedBlockParent = blockParent; cachedBlockParent = blockParent;
nsCOMPtr<nsIDOMElement> element = do_QueryInterface(blockParent); mHTMLCSSUtils->SetCSSEquivalentToHTMLStyle(blockParent, nullptr,
int32_t count; &bgcolor, &aColor, false);
res = mHTMLCSSUtils->SetCSSEquivalentToHTMLStyle(element, nullptr, &bgcolor, &aColor, &count, false);
NS_ENSURE_SUCCESS(res, res);
} }
} } else {
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
// not the easy case. range not contained in single text node. // the subtree iterator to be processed. And there are potentially a
// there are up to three phases here. There are all the nodes // starting textnode and an ending textnode which are only partially
// reported by the subtree iterator to be processed. And there // contained by the range.
// 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 = // Let's handle the nodes reported by the iterator. These nodes are
do_CreateInstance("@mozilla.org/content/subtree-content-iterator;1", &res); // entirely contained in the selection range. We build up a list of
NS_ENSURE_SUCCESS(res, res); // them (since doing operations on the document during iteration would
NS_ENSURE_TRUE(iter, NS_ERROR_FAILURE); // perturb the iterator).
nsCOMArray<nsIDOMNode> arrayOfNodes; OwningNonNull<nsIContentIterator> iter =
nsCOMPtr<nsIDOMNode> node; NS_NewContentSubtreeIterator();
// iterate range and build up array nsTArray<OwningNonNull<nsINode>> arrayOfNodes;
nsCOMPtr<nsINode> node;
// Iterate range and build up array
res = iter->Init(range); res = iter->Init(range);
// init returns an error if no nodes in range. // Init returns an error if no nodes in range. This can easily happen
// this can easily happen with the subtree // with the subtree iterator if the selection doesn't contain any
// iterator if the selection doesn't contain // *whole* nodes.
// any *whole* nodes. if (NS_SUCCEEDED(res)) {
if (NS_SUCCEEDED(res)) for (; !iter->IsDone(); iter->Next()) {
{
while (!iter->IsDone())
{
node = do_QueryInterface(iter->GetCurrentNode()); node = do_QueryInterface(iter->GetCurrentNode());
NS_ENSURE_TRUE(node, NS_ERROR_FAILURE); NS_ENSURE_TRUE(node, NS_ERROR_FAILURE);
if (IsEditable(node)) if (IsEditable(node)) {
{ arrayOfNodes.AppendElement(*node);
arrayOfNodes.AppendObject(node);
} }
iter->Next();
} }
} }
// first check the start parent of the range to see if it needs to // First check the start parent of the range to see if it needs to be
// be separately handled (it does if it's a text node, due to how the // separately handled (it does if it's a text node, due to how the
// subtree iterator works - it will not have reported it). // subtree iterator works - it will not have reported it).
if (IsTextNode(startNode) && IsEditable(startNode)) if (IsTextNode(startNode) && IsEditable(startNode)) {
{ nsCOMPtr<Element> blockParent = GetBlockNodeParent(startNode);
nsCOMPtr<nsIDOMNode> blockParent;
blockParent = GetBlockNodeParent(startNode);
if (blockParent && cachedBlockParent != blockParent) { if (blockParent && cachedBlockParent != blockParent) {
cachedBlockParent = blockParent; cachedBlockParent = blockParent;
nsCOMPtr<nsIDOMElement> element = do_QueryInterface(blockParent); mHTMLCSSUtils->SetCSSEquivalentToHTMLStyle(blockParent, nullptr,
int32_t count; &bgcolor, &aColor,
res = mHTMLCSSUtils->SetCSSEquivalentToHTMLStyle(element, nullptr, &bgcolor, &aColor, &count, false); false);
NS_ENSURE_SUCCESS(res, res);
} }
} }
// then loop through the list, set the property on each node // Then loop through the list, set the property on each node
int32_t listCount = arrayOfNodes.Count(); for (auto& node : arrayOfNodes) {
int32_t j; nsCOMPtr<Element> blockParent;
for (j = 0; j < listCount; j++) if (NodeIsBlockStatic(node)) {
{ blockParent = node->AsElement();
node = arrayOfNodes[j]; } else {
// 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
blockParent = GetBlockNodeParent(node); blockParent = GetBlockNodeParent(node);
} }
if (blockParent && cachedBlockParent != blockParent) { if (blockParent && cachedBlockParent != blockParent) {
cachedBlockParent = blockParent; cachedBlockParent = blockParent;
nsCOMPtr<nsIDOMElement> element = do_QueryInterface(blockParent); mHTMLCSSUtils->SetCSSEquivalentToHTMLStyle(blockParent, nullptr,
int32_t count; &bgcolor, &aColor,
// and set the property on it false);
res = mHTMLCSSUtils->SetCSSEquivalentToHTMLStyle(element, nullptr, &bgcolor, &aColor, &count, false);
NS_ENSURE_SUCCESS(res, res);
} }
} }
arrayOfNodes.Clear(); arrayOfNodes.Clear();
// last check the end parent of the range to see if it needs to // Last, check the end parent of the range to see if it needs to be
// be separately handled (it does if it's a text node, due to how the // separately handled (it does if it's a text node, due to how the
// subtree iterator works - it will not have reported it). // subtree iterator works - it will not have reported it).
if (IsTextNode(endNode) && IsEditable(endNode)) if (IsTextNode(endNode) && IsEditable(endNode)) {
{ nsCOMPtr<Element> blockParent = GetBlockNodeParent(endNode);
nsCOMPtr<nsIDOMNode> blockParent;
blockParent = GetBlockNodeParent(endNode);
if (blockParent && cachedBlockParent != blockParent) { if (blockParent && cachedBlockParent != blockParent) {
cachedBlockParent = blockParent; cachedBlockParent = blockParent;
nsCOMPtr<nsIDOMElement> element = do_QueryInterface(blockParent); mHTMLCSSUtils->SetCSSEquivalentToHTMLStyle(blockParent, nullptr,
int32_t count; &bgcolor, &aColor,
res = mHTMLCSSUtils->SetCSSEquivalentToHTMLStyle(element, nullptr, &bgcolor, &aColor, &count, false); false);
NS_ENSURE_SUCCESS(res, res);
} }
} }
} }
} }
} }
if (!cancel) if (!cancel) {
{ // Post-process
// post-process
res = mRules->DidDoAction(selection, &ruleInfo, res); res = mRules->DidDoAction(selection, &ruleInfo, res);
NS_ENSURE_SUCCESS(res, res);
} }
return res; return NS_OK;
} }
NS_IMETHODIMP NS_IMETHODIMP

View File

@ -7,7 +7,6 @@
#define nsHTMLEditor_h__ #define nsHTMLEditor_h__
#include "nsCOMPtr.h" #include "nsCOMPtr.h"
#include "nsCOMArray.h"
#include "nsPlaintextEditor.h" #include "nsPlaintextEditor.h"
#include "nsIEditor.h" #include "nsIEditor.h"
#include "nsIHTMLEditor.h" #include "nsIHTMLEditor.h"
@ -41,6 +40,7 @@
#include "mozilla/Attributes.h" #include "mozilla/Attributes.h"
#include "mozilla/dom/Element.h" #include "mozilla/dom/Element.h"
class nsDocumentFragment;
class nsIDOMKeyEvent; class nsIDOMKeyEvent;
class nsITransferable; class nsITransferable;
class nsIClipboard; class nsIClipboard;
@ -53,6 +53,9 @@ class nsRange;
struct PropItem; struct PropItem;
namespace mozilla { namespace mozilla {
namespace dom {
template<class T> class OwningNonNull;
}
namespace widget { namespace widget {
struct IMEState; struct IMEState;
} // namespace widget } // namespace widget
@ -591,29 +594,27 @@ protected:
nsIDocument* aTargetDoc, nsIDocument* aTargetDoc,
nsCOMPtr<nsIDOMNode> *outNode, nsCOMPtr<nsIDOMNode> *outNode,
bool aTrustedInput); bool aTrustedInput);
nsresult CreateListOfNodesToPaste(nsIDOMNode *aFragmentAsNode, void CreateListOfNodesToPaste(mozilla::dom::DocumentFragment& aFragment,
nsCOMArray<nsIDOMNode>& outNodeList, nsTArray<mozilla::dom::OwningNonNull<nsINode>>& outNodeList,
nsIDOMNode *aStartNode, nsINode* aStartNode,
int32_t aStartOffset, int32_t aStartOffset,
nsIDOMNode *aEndNode, nsINode* aEndNode,
int32_t aEndOffset); int32_t aEndOffset);
nsresult CreateTagStack(nsTArray<nsString> &aTagStack, nsresult CreateTagStack(nsTArray<nsString> &aTagStack,
nsIDOMNode *aNode); nsIDOMNode *aNode);
nsresult GetListAndTableParents( bool aEnd, enum class StartOrEnd { start, end };
nsCOMArray<nsIDOMNode>& aListOfNodes, void GetListAndTableParents(StartOrEnd aStartOrEnd,
nsCOMArray<nsIDOMNode>& outArray); nsTArray<mozilla::dom::OwningNonNull<nsINode>>& aNodeList,
nsresult DiscoverPartialListsAndTables(nsCOMArray<nsIDOMNode>& aPasteNodes, nsTArray<mozilla::dom::OwningNonNull<mozilla::dom::Element>>& outArray);
nsCOMArray<nsIDOMNode>& aListsAndTables, int32_t DiscoverPartialListsAndTables(nsTArray<mozilla::dom::OwningNonNull<nsINode>>& aPasteNodes,
int32_t *outHighWaterMark); nsTArray<mozilla::dom::OwningNonNull<mozilla::dom::Element>>& aListsAndTables);
nsresult ScanForListAndTableStructure(bool aEnd, nsINode* ScanForListAndTableStructure(StartOrEnd aStartOrEnd,
nsCOMArray<nsIDOMNode>& aNodes, nsTArray<mozilla::dom::OwningNonNull<nsINode>>& aNodes,
nsIDOMNode *aListOrTable, mozilla::dom::Element& aListOrTable);
nsCOMPtr<nsIDOMNode> *outReplaceNode); void ReplaceOrphanedStructure(StartOrEnd aStartOrEnd,
nsresult ReplaceOrphanedStructure( bool aEnd, nsTArray<mozilla::dom::OwningNonNull<nsINode>>& aNodeArray,
nsCOMArray<nsIDOMNode>& aNodeArray, nsTArray<mozilla::dom::OwningNonNull<mozilla::dom::Element>>& aListAndTableArray,
nsCOMArray<nsIDOMNode>& aListAndTableArray, int32_t aHighWaterMark);
int32_t aHighWaterMark);
nsIDOMNode* GetArrayEndpoint(bool aEnd, nsCOMArray<nsIDOMNode>& aNodeArray);
/* small utility routine to test if a break node is visible to user */ /* small utility routine to test if a break node is visible to user */
bool IsVisBreak(nsINode* aNode); bool IsVisBreak(nsINode* aNode);
@ -633,7 +634,8 @@ protected:
nsresult InsertBasicBlock(const nsAString & aBlockType); nsresult InsertBasicBlock(const nsAString & aBlockType);
/* increase/decrease the font size of selection */ /* 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 */ /* helper routines for font size changing */
nsresult RelativeFontChangeOnTextNode( int32_t aSizeChange, nsresult RelativeFontChangeOnTextNode( int32_t aSizeChange,
@ -650,14 +652,10 @@ protected:
nsIAtom& aProperty, nsIAtom& aProperty,
const nsAString* aAttribute, const nsAString* aAttribute,
const nsAString& aValue); const nsAString& aValue);
nsresult SetInlinePropertyOnNode( nsIDOMNode *aNode, nsresult SetInlinePropertyOnNode(nsIContent& aNode,
nsIAtom *aProperty, nsIAtom& aProperty,
const nsAString *aAttribute,
const nsAString *aValue);
nsresult SetInlinePropertyOnNode(nsIContent* aNode,
nsIAtom* aProperty,
const nsAString* aAttribute, const nsAString* aAttribute,
const nsAString* aValue); const nsAString& aValue);
nsresult PromoteInlineRange(nsRange* aRange); nsresult PromoteInlineRange(nsRange* aRange);
nsresult PromoteRangeIfStartsOrEndsInNamedAnchor(nsRange* aRange); nsresult PromoteRangeIfStartsOrEndsInNamedAnchor(nsRange* aRange);
@ -758,7 +756,7 @@ protected:
// Data members // Data members
protected: protected:
nsCOMArray<nsIContentFilter> mContentFilters; nsTArray<mozilla::dom::OwningNonNull<nsIContentFilter>> mContentFilters;
nsRefPtr<TypeInState> mTypeInState; nsRefPtr<TypeInState> mTypeInState;
@ -848,7 +846,7 @@ protected:
nsCOMPtr<nsISelectionListener> mSelectionListenerP; nsCOMPtr<nsISelectionListener> mSelectionListenerP;
nsCOMPtr<nsIDOMEventListener> mResizeEventListenerP; nsCOMPtr<nsIDOMEventListener> mResizeEventListenerP;
nsCOMArray<nsIHTMLObjectResizeListener> objectResizeEventListeners; nsTArray<mozilla::dom::OwningNonNull<nsIHTMLObjectResizeListener>> mObjectResizeEventListeners;
int32_t mOriginalX; int32_t mOriginalX;
int32_t mOriginalY; int32_t mOriginalY;
@ -959,10 +957,10 @@ private:
nsIAtom* aProperty, nsIAtom* aProperty,
const nsAString* aAttribute, const nsAString* aAttribute,
const nsAString* aValue); const nsAString* aValue);
nsresult SetInlinePropertyOnNodeImpl(nsIContent* aNode, nsresult SetInlinePropertyOnNodeImpl(nsIContent& aNode,
nsIAtom* aProperty, nsIAtom& aProperty,
const nsAString* aAttribute, const nsAString* aAttribute,
const nsAString* aValue); const nsAString& aValue);
typedef enum { eInserted, eAppended } InsertedOrAppended; typedef enum { eInserted, eAppended } InsertedOrAppended;
void DoContentInserted(nsIDocument* aDocument, nsIContent* aContainer, void DoContentInserted(nsIDocument* aDocument, nsIContent* aContainer,
nsIContent* aChild, int32_t aIndexInContainer, nsIContent* aChild, int32_t aIndexInContainer,

View File

@ -10,7 +10,6 @@
#include "nsAString.h" #include "nsAString.h"
#include "nsAttrName.h" #include "nsAttrName.h"
#include "nsAutoPtr.h" #include "nsAutoPtr.h"
#include "nsCOMArray.h"
#include "nsCOMPtr.h" #include "nsCOMPtr.h"
#include "nsCaseTreatment.h" #include "nsCaseTreatment.h"
#include "nsComponentManagerUtils.h" #include "nsComponentManagerUtils.h"
@ -109,23 +108,20 @@ NS_IMETHODIMP nsHTMLEditor::RemoveAllDefaultProperties()
NS_IMETHODIMP NS_IMETHODIMP
nsHTMLEditor::SetInlineProperty(nsIAtom *aProperty, nsHTMLEditor::SetInlineProperty(nsIAtom* aProperty,
const nsAString& aAttribute, const nsAString& aAttribute,
const nsAString& aValue) const nsAString& aValue)
{ {
if (!aProperty) { NS_ENSURE_TRUE(aProperty, NS_ERROR_NULL_POINTER);
return NS_ERROR_NULL_POINTER; NS_ENSURE_TRUE(mRules, NS_ERROR_NOT_INITIALIZED);
} nsCOMPtr<nsIEditRules> kungFuDeathGrip(mRules);
if (!mRules) {
return NS_ERROR_NOT_INITIALIZED;
}
ForceCompositionEnd(); ForceCompositionEnd();
nsRefPtr<Selection> selection = GetSelection(); nsRefPtr<Selection> selection = GetSelection();
NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER); NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);
if (selection->Collapsed()) { 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 // for the next text insertion
mTypeInState->SetProp(aProperty, aAttribute, aValue); mTypeInState->SetProp(aProperty, aAttribute, aValue);
return NS_OK; return NS_OK;
@ -139,21 +135,20 @@ nsHTMLEditor::SetInlineProperty(nsIAtom *aProperty,
bool cancel, handled; bool cancel, handled;
nsTextRulesInfo ruleInfo(EditAction::setTextProperty); nsTextRulesInfo ruleInfo(EditAction::setTextProperty);
// Protect the edit rules object from dying // Protect the edit rules object from dying
nsCOMPtr<nsIEditRules> kungFuDeathGrip(mRules);
nsresult res = mRules->WillDoAction(selection, &ruleInfo, &cancel, &handled); nsresult res = mRules->WillDoAction(selection, &ruleInfo, &cancel, &handled);
NS_ENSURE_SUCCESS(res, res); NS_ENSURE_SUCCESS(res, res);
if (!cancel && !handled) { if (!cancel && !handled) {
// loop thru the ranges in the selection // Loop through the ranges in the selection
uint32_t rangeCount = selection->RangeCount(); 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); 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 // selected
res = PromoteInlineRange(range); res = PromoteInlineRange(range);
NS_ENSURE_SUCCESS(res, res); 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> startNode = range->GetStartParent();
nsCOMPtr<nsINode> endNode = range->GetEndParent(); nsCOMPtr<nsINode> endNode = range->GetEndParent();
if (startNode && startNode == endNode && startNode->GetAsText()) { if (startNode && startNode == endNode && startNode->GetAsText()) {
@ -176,31 +171,26 @@ nsHTMLEditor::SetInlineProperty(nsIAtom *aProperty,
// (since doing operations on the document during iteration would perturb // (since doing operations on the document during iteration would perturb
// the iterator). // the iterator).
nsCOMPtr<nsIContentIterator> iter = OwningNonNull<nsIContentIterator> iter = NS_NewContentSubtreeIterator();
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; nsTArray<OwningNonNull<nsIContent>> arrayOfNodes;
// iterate range and build up array // Iterate range and build up array
res = iter->Init(range); res = iter->Init(range);
// Init returns an error if there are no nodes in range. This can easily // 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 // happen with the subtree iterator if the selection doesn't contain any
// *whole* nodes. // *whole* nodes.
if (NS_SUCCEEDED(res)) { if (NS_SUCCEEDED(res)) {
nsCOMPtr<nsIDOMNode> node;
for (; !iter->IsDone(); iter->Next()) { for (; !iter->IsDone(); iter->Next()) {
node = do_QueryInterface(iter->GetCurrentNode()); OwningNonNull<nsINode> node = *iter->GetCurrentNode();
NS_ENSURE_TRUE(node, NS_ERROR_FAILURE);
if (IsEditable(node)) { if (node->IsContent() && IsEditable(node)) {
arrayOfNodes.AppendObject(node); arrayOfNodes.AppendElement(*node->AsContent());
} }
} }
} }
// first check the start parent of the range to see if it needs to // First check the start parent of the range to see if it needs to be
// be separately handled (it does if it's a text node, due to how the // separately handled (it does if it's a text node, due to how the
// subtree iterator works - it will not have reported it). // subtree iterator works - it will not have reported it).
if (startNode && startNode->GetAsText() && IsEditable(startNode)) { if (startNode && startNode->GetAsText() && IsEditable(startNode)) {
res = SetInlinePropertyOnTextNode(*startNode->GetAsText(), res = SetInlinePropertyOnTextNode(*startNode->GetAsText(),
@ -210,17 +200,14 @@ nsHTMLEditor::SetInlineProperty(nsIAtom *aProperty,
NS_ENSURE_SUCCESS(res, res); NS_ENSURE_SUCCESS(res, res);
} }
// then loop through the list, set the property on each node // Then loop through the list, set the property on each node
int32_t listCount = arrayOfNodes.Count(); for (auto& node : arrayOfNodes) {
int32_t j; res = SetInlinePropertyOnNode(*node, *aProperty, &aAttribute, aValue);
for (j = 0; j < listCount; j++) {
res = SetInlinePropertyOnNode(arrayOfNodes[j], aProperty,
&aAttribute, &aValue);
NS_ENSURE_SUCCESS(res, res); NS_ENSURE_SUCCESS(res, res);
} }
// last check the end parent of the range to see if it needs to // Last check the end parent of the range to see if it needs to be
// be separately handled (it does if it's a text node, due to how the // separately handled (it does if it's a text node, due to how the
// subtree iterator works - it will not have reported it). // subtree iterator works - it will not have reported it).
if (endNode && endNode->GetAsText() && IsEditable(endNode)) { if (endNode && endNode->GetAsText() && IsEditable(endNode)) {
res = SetInlinePropertyOnTextNode(*endNode->GetAsText(), 0, res = SetInlinePropertyOnTextNode(*endNode->GetAsText(), 0,
@ -231,7 +218,7 @@ nsHTMLEditor::SetInlineProperty(nsIAtom *aProperty,
} }
} }
if (!cancel) { if (!cancel) {
// post-process // Post-process
return mRules->DidDoAction(selection, &ruleInfo, res); return mRules->DidDoAction(selection, &ruleInfo, res);
} }
return NS_OK; return NS_OK;
@ -376,41 +363,37 @@ nsHTMLEditor::SetInlinePropertyOnTextNode(Text& aText,
} }
// Reparent the node inside inline node with appropriate {attribute,value} // Reparent the node inside inline node with appropriate {attribute,value}
return SetInlinePropertyOnNode(text, &aProperty, aAttribute, &aValue); return SetInlinePropertyOnNode(*text, aProperty, aAttribute, aValue);
} }
nsresult nsresult
nsHTMLEditor::SetInlinePropertyOnNodeImpl(nsIContent* aNode, nsHTMLEditor::SetInlinePropertyOnNodeImpl(nsIContent& aNode,
nsIAtom* aProperty, nsIAtom& aProperty,
const nsAString* aAttribute, const nsAString* aAttribute,
const nsAString* aValue) const nsAString& aValue)
{ {
MOZ_ASSERT(aNode && aProperty);
MOZ_ASSERT(aValue);
nsCOMPtr<nsIAtom> attrAtom = aAttribute ? do_GetAtom(*aAttribute) : nullptr; nsCOMPtr<nsIAtom> attrAtom = aAttribute ? do_GetAtom(*aAttribute) : nullptr;
// If this is an element that can't be contained in a span, we have to // If this is an element that can't be contained in a span, we have to
// recurse to its children. // recurse to its children.
if (!TagCanContain(*nsGkAtoms::span, *aNode)) { if (!TagCanContain(*nsGkAtoms::span, aNode)) {
if (aNode->HasChildren()) { if (aNode.HasChildren()) {
nsCOMArray<nsIContent> arrayOfNodes; nsTArray<OwningNonNull<nsIContent>> arrayOfNodes;
// Populate the list. // Populate the list.
for (nsIContent* child = aNode->GetFirstChild(); for (nsCOMPtr<nsIContent> child = aNode.GetFirstChild();
child; child;
child = child->GetNextSibling()) { child = child->GetNextSibling()) {
if (IsEditable(child) && !IsEmptyTextNode(this, child)) { if (IsEditable(child) && !IsEmptyTextNode(this, child)) {
arrayOfNodes.AppendObject(child); arrayOfNodes.AppendElement(*child);
} }
} }
// Then loop through the list, set the property on each node. // Then loop through the list, set the property on each node.
int32_t listCount = arrayOfNodes.Count(); for (auto& node : arrayOfNodes) {
for (int32_t j = 0; j < listCount; ++j) { nsresult rv = SetInlinePropertyOnNode(node, aProperty, aAttribute,
nsresult rv = SetInlinePropertyOnNode(arrayOfNodes[j], aProperty, aValue);
aAttribute, aValue);
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
} }
} }
@ -419,36 +402,36 @@ nsHTMLEditor::SetInlinePropertyOnNodeImpl(nsIContent* aNode,
// First check if there's an adjacent sibling we can put our node into. // First check if there's an adjacent sibling we can put our node into.
nsresult res; nsresult res;
nsCOMPtr<nsIContent> previousSibling = GetPriorHTMLSibling(aNode); nsCOMPtr<nsIContent> previousSibling = GetPriorHTMLSibling(&aNode);
nsCOMPtr<nsIContent> nextSibling = GetNextHTMLSibling(aNode); nsCOMPtr<nsIContent> nextSibling = GetNextHTMLSibling(&aNode);
if (IsSimpleModifiableNode(previousSibling, aProperty, aAttribute, aValue)) { if (IsSimpleModifiableNode(previousSibling, &aProperty, aAttribute, &aValue)) {
res = MoveNode(aNode, previousSibling, -1); res = MoveNode(&aNode, previousSibling, -1);
NS_ENSURE_SUCCESS(res, res); NS_ENSURE_SUCCESS(res, res);
if (IsSimpleModifiableNode(nextSibling, aProperty, aAttribute, aValue)) { if (IsSimpleModifiableNode(nextSibling, &aProperty, aAttribute, &aValue)) {
res = JoinNodes(*previousSibling, *nextSibling); res = JoinNodes(*previousSibling, *nextSibling);
NS_ENSURE_SUCCESS(res, res); NS_ENSURE_SUCCESS(res, res);
} }
return NS_OK; return NS_OK;
} }
if (IsSimpleModifiableNode(nextSibling, aProperty, aAttribute, aValue)) { if (IsSimpleModifiableNode(nextSibling, &aProperty, aAttribute, &aValue)) {
res = MoveNode(aNode, nextSibling, 0); res = MoveNode(&aNode, nextSibling, 0);
NS_ENSURE_SUCCESS(res, res); NS_ENSURE_SUCCESS(res, res);
return NS_OK; return NS_OK;
} }
// don't need to do anything if property already set on node // Don't need to do anything if property already set on node
if (mHTMLCSSUtils->IsCSSEditableProperty(aNode, aProperty, aAttribute)) { if (mHTMLCSSUtils->IsCSSEditableProperty(&aNode, &aProperty, aAttribute)) {
if (mHTMLCSSUtils->IsCSSEquivalentToHTMLInlineStyleSet( if (mHTMLCSSUtils->IsCSSEquivalentToHTMLInlineStyleSet(
aNode, aProperty, aAttribute, *aValue, nsHTMLCSSUtils::eComputed)) { &aNode, &aProperty, aAttribute, aValue, nsHTMLCSSUtils::eComputed)) {
return NS_OK; return NS_OK;
} }
} else if (IsTextPropertySetByContent(aNode, aProperty, } else if (IsTextPropertySetByContent(&aNode, &aProperty,
aAttribute, aValue)) { aAttribute, &aValue)) {
return NS_OK; return NS_OK;
} }
bool useCSS = (IsCSSEnabled() && bool useCSS = (IsCSSEnabled() &&
mHTMLCSSUtils->IsCSSEditableProperty(aNode, aProperty, aAttribute)) || mHTMLCSSUtils->IsCSSEditableProperty(&aNode, &aProperty, aAttribute)) ||
// bgcolor is always done using CSS // bgcolor is always done using CSS
aAttribute->EqualsLiteral("bgcolor"); aAttribute->EqualsLiteral("bgcolor");
@ -456,33 +439,33 @@ nsHTMLEditor::SetInlinePropertyOnNodeImpl(nsIContent* aNode,
nsCOMPtr<dom::Element> tmp; nsCOMPtr<dom::Element> tmp;
// We only add style="" to <span>s with no attributes (bug 746515). If we // We only add style="" to <span>s with no attributes (bug 746515). If we
// don't have one, we need to make one. // don't have one, we need to make one.
if (aNode->IsHTMLElement(nsGkAtoms::span) && if (aNode.IsHTMLElement(nsGkAtoms::span) &&
!aNode->AsElement()->GetAttrCount()) { !aNode.AsElement()->GetAttrCount()) {
tmp = aNode->AsElement(); tmp = aNode.AsElement();
} else { } else {
tmp = InsertContainerAbove(aNode, nsGkAtoms::span); tmp = InsertContainerAbove(&aNode, nsGkAtoms::span);
NS_ENSURE_STATE(tmp); NS_ENSURE_STATE(tmp);
} }
// Add the CSS styles corresponding to the HTML style request // Add the CSS styles corresponding to the HTML style request
int32_t count; int32_t count;
res = mHTMLCSSUtils->SetCSSEquivalentToHTMLStyle(tmp->AsDOMNode(), res = mHTMLCSSUtils->SetCSSEquivalentToHTMLStyle(tmp->AsDOMNode(),
aProperty, aAttribute, &aProperty, aAttribute,
aValue, &count, false); &aValue, &count, false);
NS_ENSURE_SUCCESS(res, res); NS_ENSURE_SUCCESS(res, res);
return NS_OK; return NS_OK;
} }
// is it already the right kind of node, but with wrong attribute? // 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. // Just set the attribute on it.
nsCOMPtr<nsIDOMElement> elem = do_QueryInterface(aNode); nsCOMPtr<nsIDOMElement> elem = do_QueryInterface(&aNode);
return SetAttribute(elem, *aAttribute, *aValue); return SetAttribute(elem, *aAttribute, aValue);
} }
// ok, chuck it in its very own container // ok, chuck it in its very own container
nsCOMPtr<Element> tmp = InsertContainerAbove(aNode, aProperty, attrAtom, nsCOMPtr<Element> tmp = InsertContainerAbove(&aNode, &aProperty, attrAtom,
aValue); &aValue);
NS_ENSURE_STATE(tmp); NS_ENSURE_STATE(tmp);
return NS_OK; return NS_OK;
@ -490,42 +473,20 @@ nsHTMLEditor::SetInlinePropertyOnNodeImpl(nsIContent* aNode,
nsresult nsresult
nsHTMLEditor::SetInlinePropertyOnNode(nsIDOMNode *aNode, nsHTMLEditor::SetInlinePropertyOnNode(nsIContent& aNode,
nsIAtom *aProperty, 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);
return SetInlinePropertyOnNode(node, aProperty, aAttribute, aValue);
}
nsresult
nsHTMLEditor::SetInlinePropertyOnNode(nsIContent* aNode,
nsIAtom* aProperty,
const nsAString* aAttribute, const nsAString* aAttribute,
const nsAString* aValue) const nsAString& aValue)
{ {
MOZ_ASSERT(aNode); nsCOMPtr<nsIContent> previousSibling = aNode.GetPreviousSibling(),
MOZ_ASSERT(aProperty); nextSibling = aNode.GetNextSibling();
NS_ENSURE_STATE(aNode.GetParentNode());
OwningNonNull<nsINode> parent = *aNode.GetParentNode();
nsCOMPtr<nsIContent> previousSibling = aNode->GetPreviousSibling(), nsresult res = RemoveStyleInside(aNode.AsDOMNode(), &aProperty, aAttribute);
nextSibling = aNode->GetNextSibling();
nsCOMPtr<nsINode> parent = aNode->GetParentNode();
NS_ENSURE_STATE(parent);
nsresult res = RemoveStyleInside(aNode->AsDOMNode(), aProperty, aAttribute);
NS_ENSURE_SUCCESS(res, res); NS_ENSURE_SUCCESS(res, res);
if (aNode->GetParentNode()) { if (aNode.GetParentNode()) {
// The node is still where it was // The node is still where it was
return SetInlinePropertyOnNodeImpl(aNode, aProperty, return SetInlinePropertyOnNodeImpl(aNode, aProperty,
aAttribute, aValue); aAttribute, aValue);
@ -538,20 +499,17 @@ nsHTMLEditor::SetInlinePropertyOnNode(nsIContent* aNode,
(nextSibling && nextSibling->GetParentNode() != parent)) { (nextSibling && nextSibling->GetParentNode() != parent)) {
return NS_ERROR_UNEXPECTED; return NS_ERROR_UNEXPECTED;
} }
nsCOMArray<nsIContent> nodesToSet; nsTArray<OwningNonNull<nsIContent>> nodesToSet;
nsCOMPtr<nsIContent> cur = previousSibling nsCOMPtr<nsIContent> cur = previousSibling
? previousSibling->GetNextSibling() : parent->GetFirstChild(); ? previousSibling->GetNextSibling() : parent->GetFirstChild();
while (cur && cur != nextSibling) { for (; cur && cur != nextSibling; cur = cur->GetNextSibling()) {
if (IsEditable(cur)) { if (IsEditable(cur)) {
nodesToSet.AppendObject(cur); nodesToSet.AppendElement(*cur);
} }
cur = cur->GetNextSibling();
} }
int32_t nodesToSetCount = nodesToSet.Count(); for (auto& node : nodesToSet) {
for (int32_t k = 0; k < nodesToSetCount; k++) { res = SetInlinePropertyOnNodeImpl(node, aProperty, aAttribute, aValue);
res = SetInlinePropertyOnNodeImpl(nodesToSet[k], aProperty,
aAttribute, aValue);
NS_ENSURE_SUCCESS(res, res); NS_ENSURE_SUCCESS(res, res);
} }
@ -1416,8 +1374,8 @@ nsHTMLEditor::RemoveInlinePropertyImpl(nsIAtom* aProperty,
// "inverting" the style // "inverting" the style
mHTMLCSSUtils->IsCSSInvertible(*aProperty, aAttribute)) { mHTMLCSSUtils->IsCSSInvertible(*aProperty, aAttribute)) {
NS_NAMED_LITERAL_STRING(value, "-moz-editor-invert-value"); NS_NAMED_LITERAL_STRING(value, "-moz-editor-invert-value");
SetInlinePropertyOnNode(node->AsContent(), aProperty, SetInlinePropertyOnNode(*node->AsContent(), *aProperty,
aAttribute, &value); aAttribute, value);
} }
} }
} }
@ -1433,150 +1391,126 @@ nsHTMLEditor::RemoveInlinePropertyImpl(nsIAtom* aProperty,
NS_IMETHODIMP nsHTMLEditor::IncreaseFontSize() NS_IMETHODIMP nsHTMLEditor::IncreaseFontSize()
{ {
return RelativeFontChange(1); return RelativeFontChange(FontSize::incr);
} }
NS_IMETHODIMP nsHTMLEditor::DecreaseFontSize() NS_IMETHODIMP nsHTMLEditor::DecreaseFontSize()
{ {
return RelativeFontChange(-1); return RelativeFontChange(FontSize::decr);
} }
nsresult 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(); ForceCompositionEnd();
// Get the selection // Get the selection
nsRefPtr<Selection> selection = GetSelection(); nsRefPtr<Selection> selection = GetSelection();
NS_ENSURE_TRUE(selection, NS_ERROR_FAILURE); NS_ENSURE_TRUE(selection, NS_ERROR_FAILURE);
// Is the selection collapsed? // If selection is collapsed, set typing state
// if it's collapsed set typing state
if (selection->Collapsed()) { if (selection->Collapsed()) {
nsCOMPtr<nsIAtom> atom; nsIAtom& atom = aDir == FontSize::incr ? *nsGkAtoms::big :
if (aSizeChange == 1) { *nsGkAtoms::small;
atom = nsGkAtoms::big;
} else {
atom = nsGkAtoms::small;
}
// Let's see in what kind of element the selection is // Let's see in what kind of element the selection is
int32_t offset; NS_ENSURE_TRUE(selection->RangeCount() &&
nsCOMPtr<nsINode> selectedNode; selection->GetRangeAt(0)->GetStartParent(), NS_OK);
GetStartNodeAndOffset(selection, getter_AddRefs(selectedNode), &offset); OwningNonNull<nsINode> selectedNode =
if (selectedNode && IsTextNode(selectedNode)) { *selection->GetRangeAt(0)->GetStartParent();
selectedNode = selectedNode->GetParentNode(); 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; return NS_OK;
} }
// manipulating text attributes on a collapsed selection only sets state for the next text insertion // Manipulating text attributes on a collapsed selection only sets state
mTypeInState->SetProp(atom, EmptyString(), EmptyString()); // for the next text insertion
mTypeInState->SetProp(&atom, EmptyString(), EmptyString());
return NS_OK; 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); nsAutoEditBatch batchIt(this);
nsAutoRules beginRulesSniffing(this, EditAction::setTextProperty, nsIEditor::eNext); nsAutoRules beginRulesSniffing(this, EditAction::setTextProperty,
nsIEditor::eNext);
nsAutoSelectionReset selectionResetter(selection, this); nsAutoSelectionReset selectionResetter(selection, this);
nsAutoTxnsConserveSelection dontSpazMySelection(this); nsAutoTxnsConserveSelection dontSpazMySelection(this);
// loop thru the ranges in the selection // Loop through the ranges in the selection
uint32_t rangeCount = selection->RangeCount(); 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); 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); nsresult res = PromoteInlineRange(range);
NS_ENSURE_SUCCESS(res, res); 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);
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).
nsCOMPtr<nsIContentIterator> iter = // Check for easy case: both range endpoints in same text node
do_CreateInstance("@mozilla.org/content/subtree-content-iterator;1", &res); 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); NS_ENSURE_SUCCESS(res, res);
NS_ENSURE_TRUE(iter, NS_ERROR_FAILURE); } 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.
// iterate range and build up array // 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();
// Iterate range and build up array
res = iter->Init(range); res = iter->Init(range);
if (NS_SUCCEEDED(res)) { if (NS_SUCCEEDED(res)) {
nsCOMArray<nsIContent> arrayOfNodes; nsTArray<OwningNonNull<nsIContent>> arrayOfNodes;
while (!iter->IsDone()) { for (; !iter->IsDone(); iter->Next()) {
NS_ENSURE_TRUE(iter->GetCurrentNode()->IsContent(), NS_ERROR_FAILURE); NS_ENSURE_TRUE(iter->GetCurrentNode()->IsContent(), NS_ERROR_FAILURE);
nsCOMPtr<nsIContent> node = iter->GetCurrentNode()->AsContent(); OwningNonNull<nsIContent> node = *iter->GetCurrentNode()->AsContent();
if (IsEditable(node)) { 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 // Now that we have the list, do the font size change on each node
int32_t listCount = arrayOfNodes.Count(); for (auto& node : arrayOfNodes) {
for (int32_t j = 0; j < listCount; ++j) { res = RelativeFontChangeOnNode(aDir == FontSize::incr ? +1 : -1,
nsIContent* node = arrayOfNodes[j]; node);
res = RelativeFontChangeOnNode(aSizeChange, node);
NS_ENSURE_SUCCESS(res, res); NS_ENSURE_SUCCESS(res, res);
} }
arrayOfNodes.Clear();
} }
// now check the start and end parents of the range to see if they need to // Now check the start and end parents of the range to see if they need
// be separately handled (they do if they are text nodes, due to how the // to be separately handled (they do if they are text nodes, due to how
// subtree iterator works - it will not have reported them). // the subtree iterator works - it will not have reported them).
if (IsTextNode(startNode) && IsEditable(startNode)) if (IsTextNode(startNode) && IsEditable(startNode)) {
{ res = RelativeFontChangeOnTextNode(aDir == FontSize::incr ? +1 : -1,
nsCOMPtr<nsIDOMCharacterData> nodeAsText = do_QueryInterface(startNode); static_cast<nsIDOMCharacterData*>(startNode->AsDOMNode()),
int32_t startOffset; range->StartOffset(), startNode->Length());
uint32_t textLen;
range->GetStartOffset(&startOffset);
nodeAsText->GetLength(&textLen);
res = RelativeFontChangeOnTextNode(aSizeChange, nodeAsText, startOffset, textLen);
NS_ENSURE_SUCCESS(res, res); NS_ENSURE_SUCCESS(res, res);
} }
if (IsTextNode(endNode) && IsEditable(endNode)) if (IsTextNode(endNode) && IsEditable(endNode)) {
{
nsCOMPtr<nsIDOMCharacterData> nodeAsText = do_QueryInterface(endNode); nsCOMPtr<nsIDOMCharacterData> nodeAsText = do_QueryInterface(endNode);
int32_t endOffset; int32_t endOffset;
range->GetEndOffset(&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); NS_ENSURE_SUCCESS(res, res);
} }
} }
} }
return NS_OK; return NS_OK;
} }
nsresult nsresult

View File

@ -13,7 +13,6 @@
#include "nsAString.h" #include "nsAString.h"
#include "nsAlgorithm.h" #include "nsAlgorithm.h"
#include "nsAutoPtr.h" #include "nsAutoPtr.h"
#include "nsCOMArray.h"
#include "nsCOMPtr.h" #include "nsCOMPtr.h"
#include "nsDebug.h" #include "nsDebug.h"
#include "nsEditorUtils.h" #include "nsEditorUtils.h"
@ -499,14 +498,8 @@ nsresult
nsHTMLEditor::StartResizing(nsIDOMElement *aHandle) nsHTMLEditor::StartResizing(nsIDOMElement *aHandle)
{ {
// First notify the listeners if any // First notify the listeners if any
int32_t listenersCount = objectResizeEventListeners.Count(); for (auto& listener : mObjectResizeEventListeners) {
if (listenersCount) { listener->OnStartResizing(static_cast<nsIDOMElement*>(GetAsDOMNode(mResizedObject)));
nsCOMPtr<nsIHTMLObjectResizeListener> listener;
int32_t index;
for (index = 0; index < listenersCount; index++) {
listener = objectResizeEventListeners[index];
listener->OnStartResizing(static_cast<nsIDOMElement*>(GetAsDOMNode(mResizedObject)));
}
} }
mIsResizing = true; mIsResizing = true;
@ -976,16 +969,10 @@ nsHTMLEditor::SetFinalSize(int32_t aX, int32_t aY)
EmptyString()); EmptyString());
} }
// finally notify the listeners if any // finally notify the listeners if any
int32_t listenersCount = objectResizeEventListeners.Count(); for (auto& listener : mObjectResizeEventListeners) {
if (listenersCount) { listener->OnEndResizing(static_cast<nsIDOMElement*>(GetAsDOMNode(mResizedObject)),
nsCOMPtr<nsIHTMLObjectResizeListener> listener; mResizedObjectWidth, mResizedObjectHeight, width,
int32_t index; height);
for (index = 0; index < listenersCount; index++) {
listener = objectResizeEventListeners[index];
listener->OnEndResizing(static_cast<nsIDOMElement*>(GetAsDOMNode(mResizedObject)),
mResizedObjectWidth, mResizedObjectHeight,
width, height);
}
} }
// keep track of that size // keep track of that size
@ -1021,14 +1008,13 @@ NS_IMETHODIMP
nsHTMLEditor::AddObjectResizeEventListener(nsIHTMLObjectResizeListener * aListener) nsHTMLEditor::AddObjectResizeEventListener(nsIHTMLObjectResizeListener * aListener)
{ {
NS_ENSURE_ARG_POINTER(aListener); NS_ENSURE_ARG_POINTER(aListener);
if (objectResizeEventListeners.Count() && if (mObjectResizeEventListeners.Contains(aListener)) {
objectResizeEventListeners.IndexOf(aListener) != -1) {
/* listener already registered */ /* listener already registered */
NS_ASSERTION(false, NS_ASSERTION(false,
"trying to register an already registered object resize event listener"); "trying to register an already registered object resize event listener");
return NS_OK; return NS_OK;
} }
objectResizeEventListeners.AppendObject(aListener); mObjectResizeEventListeners.AppendElement(*aListener);
return NS_OK; return NS_OK;
} }
@ -1036,14 +1022,13 @@ NS_IMETHODIMP
nsHTMLEditor::RemoveObjectResizeEventListener(nsIHTMLObjectResizeListener * aListener) nsHTMLEditor::RemoveObjectResizeEventListener(nsIHTMLObjectResizeListener * aListener)
{ {
NS_ENSURE_ARG_POINTER(aListener); NS_ENSURE_ARG_POINTER(aListener);
if (!objectResizeEventListeners.Count() || if (!mObjectResizeEventListeners.Contains(aListener)) {
objectResizeEventListeners.IndexOf(aListener) == -1) {
/* listener was not registered */ /* listener was not registered */
NS_ASSERTION(false, NS_ASSERTION(false,
"trying to remove an object resize event listener that was not already registered"); "trying to remove an object resize event listener that was not already registered");
return NS_OK; return NS_OK;
} }
objectResizeEventListeners.RemoveObject(aListener); mObjectResizeEventListeners.RemoveElement(aListener);
return NS_OK; return NS_OK;
} }

View File

@ -77,7 +77,7 @@ skip-if(B2G||Mulet) fails-if(Android) needs-focus != spellcheck-hyphen-multiple-
== unneeded_scroll.html unneeded_scroll-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.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) == 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.html selection_visibility_after_reframe-ref.html
!= selection_visibility_after_reframe-2.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 != selection_visibility_after_reframe-3.html selection_visibility_after_reframe-ref.html

View File

@ -1014,6 +1014,10 @@ SyncObjectD3D11::FinalizeFrame()
hr = mutex->AcquireSync(0, 20000); hr = mutex->AcquireSync(0, 20000);
if (hr == WAIT_TIMEOUT) { if (hr == WAIT_TIMEOUT) {
if (gfxWindowsPlatform::GetPlatform()->DidRenderingDeviceReset()) {
gfxWarning() << "AcquireSync timed out because of device reset.";
return;
}
MOZ_CRASH(); MOZ_CRASH();
} }
@ -1038,6 +1042,10 @@ SyncObjectD3D11::FinalizeFrame()
hr = mutex->AcquireSync(0, 20000); hr = mutex->AcquireSync(0, 20000);
if (hr == WAIT_TIMEOUT) { if (hr == WAIT_TIMEOUT) {
if (gfxWindowsPlatform::GetPlatform()->DidRenderingDeviceReset()) {
gfxWarning() << "AcquireSync timed out because of device reset.";
return;
}
MOZ_CRASH(); MOZ_CRASH();
} }

View File

@ -87,7 +87,6 @@ CheckProgressConsistency(Progress aProgress)
void void
ProgressTracker::SetImage(Image* aImage) ProgressTracker::SetImage(Image* aImage)
{ {
MutexAutoLock lock(mImageMutex);
MOZ_ASSERT(aImage, "Setting null image"); MOZ_ASSERT(aImage, "Setting null image");
MOZ_ASSERT(!mImage, "Setting image when we already have one"); MOZ_ASSERT(!mImage, "Setting image when we already have one");
mImage = aImage; mImage = aImage;
@ -96,7 +95,6 @@ ProgressTracker::SetImage(Image* aImage)
void void
ProgressTracker::ResetImage() ProgressTracker::ResetImage()
{ {
MutexAutoLock lock(mImageMutex);
MOZ_ASSERT(mImage, "Resetting image when it's already null!"); MOZ_ASSERT(mImage, "Resetting image when it's already null!");
mImage = nullptr; mImage = nullptr;
} }
@ -185,9 +183,8 @@ ProgressTracker::Notify(IProgressObserver* aObserver)
MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(NS_IsMainThread());
#ifdef PR_LOGGING #ifdef PR_LOGGING
nsRefPtr<Image> image = GetImage(); if (mImage && mImage->GetURI()) {
if (image && image->GetURI()) { nsRefPtr<ImageURL> uri(mImage->GetURI());
nsRefPtr<ImageURL> uri(image->GetURI());
nsAutoCString spec; nsAutoCString spec;
uri->GetSpec(spec); uri->GetSpec(spec);
LOG_FUNC_WITH_PARAM(GetImgLog(), LOG_FUNC_WITH_PARAM(GetImgLog(),
@ -254,10 +251,9 @@ ProgressTracker::NotifyCurrentState(IProgressObserver* aObserver)
MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(NS_IsMainThread());
#ifdef PR_LOGGING #ifdef PR_LOGGING
nsRefPtr<Image> image = GetImage();
nsAutoCString spec; nsAutoCString spec;
if (image && image->GetURI()) { if (mImage && mImage->GetURI()) {
image->GetURI()->GetSpec(spec); mImage->GetURI()->GetSpec(spec);
} }
LOG_FUNC_WITH_PARAM(GetImgLog(), LOG_FUNC_WITH_PARAM(GetImgLog(),
"ProgressTracker::NotifyCurrentState", "uri", spec.get()); "ProgressTracker::NotifyCurrentState", "uri", spec.get());
@ -371,7 +367,7 @@ ProgressTracker::SyncNotifyProgress(Progress aProgress,
CheckProgressConsistency(mProgress); CheckProgressConsistency(mProgress);
// Send notifications. // Send notifications.
SyncNotifyInternal(mObservers, HasImage(), progress, aInvalidRect); SyncNotifyInternal(mObservers, !!mImage, progress, aInvalidRect);
if (progress & FLAG_HAS_ERROR) { if (progress & FLAG_HAS_ERROR) {
FireFailureNotification(); FireFailureNotification();
@ -383,21 +379,19 @@ ProgressTracker::SyncNotify(IProgressObserver* aObserver)
{ {
MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(NS_IsMainThread());
nsRefPtr<Image> image = GetImage();
#ifdef PR_LOGGING #ifdef PR_LOGGING
nsAutoCString spec; nsAutoCString spec;
if (image && image->GetURI()) { if (mImage && mImage->GetURI()) {
image->GetURI()->GetSpec(spec); mImage->GetURI()->GetSpec(spec);
} }
LOG_SCOPE_WITH_PARAM(GetImgLog(), LOG_SCOPE_WITH_PARAM(GetImgLog(),
"ProgressTracker::SyncNotify", "uri", spec.get()); "ProgressTracker::SyncNotify", "uri", spec.get());
#endif #endif
nsIntRect rect; nsIntRect rect;
if (image) { if (mImage) {
if (NS_FAILED(image->GetWidth(&rect.width)) || if (NS_FAILED(mImage->GetWidth(&rect.width)) ||
NS_FAILED(image->GetHeight(&rect.height))) { NS_FAILED(mImage->GetHeight(&rect.height))) {
// Either the image has no intrinsic size, or it has an error. // Either the image has no intrinsic size, or it has an error.
rect = GetMaxSizedIntRect(); rect = GetMaxSizedIntRect();
} }
@ -405,7 +399,7 @@ ProgressTracker::SyncNotify(IProgressObserver* aObserver)
ObserverArray array; ObserverArray array;
array.AppendElement(aObserver); array.AppendElement(aObserver);
SyncNotifyInternal(array, !!image, mProgress, rect); SyncNotifyInternal(array, !!mImage, mProgress, rect);
} }
void void
@ -517,12 +511,11 @@ ProgressTracker::FireFailureNotification()
// Some kind of problem has happened with image decoding. // Some kind of problem has happened with image decoding.
// Report the URI to net:failed-to-process-uri-conent observers. // Report the URI to net:failed-to-process-uri-conent observers.
nsRefPtr<Image> image = GetImage(); if (mImage) {
if (image) {
// Should be on main thread, so ok to create a new nsIURI. // Should be on main thread, so ok to create a new nsIURI.
nsCOMPtr<nsIURI> uri; nsCOMPtr<nsIURI> uri;
{ {
nsRefPtr<ImageURL> threadsafeUriData = image->GetURI(); nsRefPtr<ImageURL> threadsafeUriData = mImage->GetURI();
uri = threadsafeUriData ? threadsafeUriData->ToIURI() : nullptr; uri = threadsafeUriData ? threadsafeUriData->ToIURI() : nullptr;
} }
if (uri) { if (uri) {

View File

@ -7,7 +7,6 @@
#ifndef mozilla_image_src_ProgressTracker_h #ifndef mozilla_image_src_ProgressTracker_h
#define mozilla_image_src_ProgressTracker_h #define mozilla_image_src_ProgressTracker_h
#include "mozilla/Mutex.h"
#include "mozilla/RefPtr.h" #include "mozilla/RefPtr.h"
#include "mozilla/WeakPtr.h" #include "mozilla/WeakPtr.h"
#include "nsCOMPtr.h" #include "nsCOMPtr.h"
@ -77,15 +76,13 @@ public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(ProgressTracker) NS_INLINE_DECL_THREADSAFE_REFCOUNTING(ProgressTracker)
ProgressTracker() ProgressTracker()
: mImageMutex("ProgressTracker::mImage") : mImage(nullptr)
, mImage(nullptr)
, mProgress(NoProgress) , mProgress(NoProgress)
{ } { }
bool HasImage() const { MutexAutoLock lock(mImageMutex); return mImage; } bool HasImage() const { return mImage; }
already_AddRefed<Image> GetImage() const already_AddRefed<Image> GetImage() const
{ {
MutexAutoLock lock(mImageMutex);
nsRefPtr<Image> image = mImage; nsRefPtr<Image> image = mImage;
return image.forget(); return image.forget();
} }
@ -193,9 +190,7 @@ private:
nsCOMPtr<nsIRunnable> mRunnable; nsCOMPtr<nsIRunnable> mRunnable;
// mImage is a weak ref; it should be set to null when the image goes out of // This weak ref should be set null when the image goes out of scope.
// scope. mImageMutex protects mImage.
mutable Mutex mImageMutex;
Image* mImage; Image* mImage;
// List of observers attached to the image. Each observer represents a // List of observers attached to the image. Each observer represents a

View File

@ -537,8 +537,28 @@ MOZ_ALWAYS_INLINE void
js::Nursery::traceObject(MinorCollectionTracer* trc, JSObject* obj) js::Nursery::traceObject(MinorCollectionTracer* trc, JSObject* obj)
{ {
const Class* clasp = obj->getClass(); 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); clasp->trace(trc, obj);
}
MOZ_ASSERT(obj->isNative() == clasp->isNative()); MOZ_ASSERT(obj->isNative() == clasp->isNative());
if (!clasp->isNative()) if (!clasp->isNative())
@ -579,16 +599,42 @@ js::Nursery::markSlot(MinorCollectionTracer* trc, HeapSlot* slotp)
return; return;
JSObject* obj = &slotp->toObject(); JSObject* obj = &slotp->toObject();
if (!IsInsideNursery(obj)) if (markObject(trc, &obj))
return;
if (getForwardedPointer(&obj)) {
slotp->unsafeGet()->setObject(*obj); slotp->unsafeGet()->setObject(*obj);
return; }
}
JSObject* tenured = static_cast<JSObject*>(moveToTenured(trc, obj)); MOZ_ALWAYS_INLINE void
slotp->unsafeGet()->setObject(*tenured); 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* void*

View File

@ -313,6 +313,9 @@ class Nursery
MOZ_ALWAYS_INLINE void markSlots(gc::MinorCollectionTracer* trc, HeapSlot* vp, uint32_t nslots); 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 markSlots(gc::MinorCollectionTracer* trc, HeapSlot* vp, HeapSlot* end);
MOZ_ALWAYS_INLINE void markSlot(gc::MinorCollectionTracer* trc, HeapSlot* slotp); 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); void* moveToTenured(gc::MinorCollectionTracer* trc, JSObject* src);
size_t moveObjectToTenured(gc::MinorCollectionTracer* trc, JSObject* dst, JSObject* src, size_t moveObjectToTenured(gc::MinorCollectionTracer* trc, JSObject* dst, JSObject* src,
gc::AllocKind dstKind); gc::AllocKind dstKind);

View File

@ -10130,6 +10130,17 @@ TryAttachStringSplit(JSContext* cx, ICCall_Fallback* stub, HandleScript script,
if (!CopyArray(cx, obj, &arr)) if (!CopyArray(cx, obj, &arr))
return false; 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(), ICCall_StringSplit::Compiler compiler(cx, stub->fallbackMonitorStub()->firstMonitorStub(),
script->pcToOffset(pc), thisString, argString, script->pcToOffset(pc), thisString, argString,
arr); arr);

View File

@ -12873,17 +12873,8 @@ IonBuilder::storeReferenceTypedObjectValue(MDefinition* typedObj,
MConstant* MConstant*
IonBuilder::constant(const Value& v) 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(), MOZ_ASSERT(!v.isString() || v.toString()->isAtom(),
"To handle non-atomized strings, you should use constantMaybeAtomize instead of constant."); "Handle non-atomized strings outside IonBuilder.");
if (v.isString() && MOZ_UNLIKELY(!v.toString()->isAtom())) {
MConstant* cst = constantMaybeAtomize(v);
if (!cst)
js::CrashAtUnhandlableOOM("Use constantMaybeAtomize.");
return cst;
}
MConstant* c = MConstant::New(alloc(), v, constraints()); MConstant* c = MConstant::New(alloc(), v, constraints());
current->add(c); current->add(c);
@ -12896,19 +12887,6 @@ IonBuilder::constantInt(int32_t i)
return constant(Int32Value(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* MDefinition*
IonBuilder::getCallee() IonBuilder::getCallee()
{ {

View File

@ -353,9 +353,6 @@ class IonBuilder
MConstant* constant(const Value& v); MConstant* constant(const Value& v);
MConstant* constantInt(int32_t i); 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 // Improve the type information at tests
bool improveTypesAtTest(MDefinition* ins, bool trueBranch, MTest* test); bool improveTypesAtTest(MDefinition* ins, bool trueBranch, MTest* test);
bool improveTypesAtCompare(MCompare* ins, bool trueBranch, MTest* test); bool improveTypesAtCompare(MCompare* ins, bool trueBranch, MTest* test);

View File

@ -1567,14 +1567,11 @@ IonBuilder::inlineConstantStringSplit(CallInfo& callInfo)
if (templateObject->getDenseInitializedLength() != initLength) if (templateObject->getDenseInitializedLength() != initLength)
return InliningStatus_NotInlined; return InliningStatus_NotInlined;
JSContext* cx = GetJitContext()->cx;
Vector<MConstant*, 0, SystemAllocPolicy> arrayValues; Vector<MConstant*, 0, SystemAllocPolicy> arrayValues;
for (uint32_t i = 0; i < initLength; i++) { for (uint32_t i = 0; i < initLength; i++) {
JSAtom* str = js::AtomizeString(cx, templateObject->getDenseElement(i).toString()); Value str = templateObject->getDenseElement(i);
if (!str) MOZ_ASSERT(str.toString()->isAtom());
return InliningStatus_Error; MConstant* value = MConstant::New(alloc(), str, constraints());
MConstant* value = MConstant::New(alloc(), StringValue(str), constraints());
if (!TypeSetIncludes(key.maybeTypes(), value->type(), value->resultTypeSet())) if (!TypeSetIncludes(key.maybeTypes(), value->type(), value->resultTypeSet()))
return InliningStatus_NotInlined; return InliningStatus_NotInlined;
@ -2772,11 +2769,15 @@ IonBuilder::inlineBoundFunction(CallInfo& nativeCallInfo, JSFunction* target)
const Value val = target->getBoundFunctionArgument(i); const Value val = target->getBoundFunctionArgument(i);
if (val.isObject() && gc::IsInsideNursery(&val.toObject())) if (val.isObject() && gc::IsInsideNursery(&val.toObject()))
return InliningStatus_NotInlined; return InliningStatus_NotInlined;
if (val.isString() && !val.toString()->isAtom())
return InliningStatus_NotInlined;
} }
const Value thisVal = target->getBoundFunctionThis(); const Value thisVal = target->getBoundFunctionThis();
if (thisVal.isObject() && gc::IsInsideNursery(&thisVal.toObject())) if (thisVal.isObject() && gc::IsInsideNursery(&thisVal.toObject()))
return InliningStatus_NotInlined; return InliningStatus_NotInlined;
if (thisVal.isString() && !thisVal.toString()->isAtom())
return InliningStatus_NotInlined;
size_t argc = target->getBoundFunctionArgumentCount() + nativeCallInfo.argc(); size_t argc = target->getBoundFunctionArgumentCount() + nativeCallInfo.argc();
if (argc > ARGS_LENGTH_MAX) if (argc > ARGS_LENGTH_MAX)
@ -2786,18 +2787,13 @@ IonBuilder::inlineBoundFunction(CallInfo& nativeCallInfo, JSFunction* target)
CallInfo callInfo(alloc(), nativeCallInfo.constructing()); CallInfo callInfo(alloc(), nativeCallInfo.constructing());
callInfo.setFun(constant(ObjectValue(*scriptedTarget))); callInfo.setFun(constant(ObjectValue(*scriptedTarget)));
MConstant* thisConst = constantMaybeAtomize(thisVal); callInfo.setThis(constant(thisVal));
if (!thisConst)
return InliningStatus_Error;
callInfo.setThis(thisConst);
if (!callInfo.argv().reserve(argc)) if (!callInfo.argv().reserve(argc))
return InliningStatus_Error; return InliningStatus_Error;
for (size_t i = 0; i < target->getBoundFunctionArgumentCount(); i++) { for (size_t i = 0; i < target->getBoundFunctionArgumentCount(); i++) {
MConstant* argConst = constantMaybeAtomize(target->getBoundFunctionArgument(i)); MConstant* argConst = constant(target->getBoundFunctionArgument(i));
if (!argConst)
return InliningStatus_Error;
callInfo.argv().infallibleAppend(argConst); callInfo.argv().infallibleAppend(argConst);
} }
for (size_t i = 0; i < nativeCallInfo.argc(); i++) for (size_t i = 0; i < nativeCallInfo.argc(); i++)

View File

@ -904,7 +904,7 @@ TypeSet::intersectSets(TemporaryTypeSet* a, TemporaryTypeSet* b, LifoAlloc* allo
if (b->unknownObject()) { if (b->unknownObject()) {
for (size_t i = 0; i < a->getObjectCount(); i++) { for (size_t i = 0; i < a->getObjectCount(); i++) {
if (b->getObject(i)) if (a->getObject(i))
res->addType(ObjectType(a->getObject(i)), alloc); res->addType(ObjectType(a->getObject(i)), alloc);
} }
return res; return res;

View File

@ -233,6 +233,11 @@ class UnboxedPlainObject : public JSObject
expando_ = nullptr; expando_ = nullptr;
} }
// For use during GC.
JSObject** addressOfExpando() {
return reinterpret_cast<JSObject**>(&expando_);
}
bool containsUnboxedOrExpandoProperty(ExclusiveContext* cx, jsid id) const; bool containsUnboxedOrExpandoProperty(ExclusiveContext* cx, jsid id) const;
static UnboxedExpandoObject* ensureExpando(JSContext* cx, Handle<UnboxedPlainObject*> obj); static UnboxedExpandoObject* ensureExpando(JSContext* cx, Handle<UnboxedPlainObject*> obj);

View File

@ -49,11 +49,11 @@ skip-if((B2G&&browserIsRemote)||Mulet) != table-cell-8.html table-print-1-ref.ht
== continuation-positioned-inline-1.html continuation-positioned-inline-ref.html == continuation-positioned-inline-1.html continuation-positioned-inline-ref.html
== continuation-positioned-inline-2.html continuation-positioned-inline-ref.html == continuation-positioned-inline-2.html continuation-positioned-inline-ref.html
== scrollframe-1.html scrollframe-1-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.html select-1-ref.html
fuzzy-if(gtk2Widget,1,8) == select-1-dynamic.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 == 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 == multi-column-1.html multi-column-1-ref.html
== button-1.html button-1-ref.html == button-1.html button-1-ref.html
== button-2.html button-2-ref.html == button-2.html button-2-ref.html

View File

@ -36,7 +36,7 @@ fails-if(Android||B2G) == center-scaling-3.html center-scaling-3-ref.html # Andr
== border-image-outset-1c.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-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-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.html border-image-style-none-ref.html
== border-image-style-none-length.html border-image-style-none-length-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-image-style-none-auto.html border-image-style-none-auto-ref.html

View File

@ -71,7 +71,7 @@ fuzzy-if(azureQuartz,1,3) skip-if(B2G||Mulet) == invalidate-1a.html invalidate-1
fuzzy-if(azureQuartz,1,3) skip-if(B2G||Mulet) == invalidate-1b.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 # 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 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. # Test for bad corner joins.

View File

@ -1575,7 +1575,7 @@ random-if(!winWidget) fails-if(winWidget&&!d2d) random-if(winWidget&&d2d) != 574
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(!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) 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 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 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 == 581579-1.html 581579-1-ref.html
== 582037-1a.html 582037-1-ref.html == 582037-1a.html 582037-1-ref.html
@ -1671,7 +1671,7 @@ skip-if(B2G||Mulet) == 641770-1.html 641770-1-ref.html # Initial mulet triage: p
== 641856-1.html 641856-1-ref.html == 641856-1.html 641856-1-ref.html
== 645491-1.html 645491-1-ref.html == 645491-1.html 645491-1-ref.html
== 645768-1.html 645768-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-1a.html 652301-1-ref.html
needs-focus == 652301-1b.html 652301-1-ref.html needs-focus == 652301-1b.html 652301-1-ref.html
== 652775-1.html 652775-1-ref.html == 652775-1.html 652775-1-ref.html
@ -1756,7 +1756,7 @@ skip-if(B2G||Mulet) fuzzy-if(Android,4,400) == 815593-1.html 815593-1-ref.html #
== 816948-1.html 816948-1-ref.html == 816948-1.html 816948-1-ref.html
== 817019-1.html about:blank == 817019-1.html about:blank
skip-if(B2G||Mulet) == 818276-1.html 818276-1-ref.html # Initial mulet triage: parity with B2G/B2G Desktop 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-1a.html 827577-1-ref.html
== 827577-1b.html 827577-1-ref.html == 827577-1b.html 827577-1-ref.html
== 827799-1.html about:blank == 827799-1.html about:blank
@ -1806,7 +1806,7 @@ fuzzy-if(B2G,1,7) == 942672-1.html 942672-1-ref.html
== 961887-1.html 961887-1-ref.html == 961887-1.html 961887-1-ref.html
== 961887-2.html 961887-2-ref.html == 961887-2.html 961887-2-ref.html
== 961887-3.html 961887-3-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-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 skip-if(Android) == 966510-2.html 966510-2-ref.html # same as above
== 978911-1.svg 978911-1-ref.svg == 978911-1.svg 978911-1-ref.svg

View File

@ -10,7 +10,7 @@ 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-invalid-changed-2.html select-required-ref.html
needs-focus == select-required-valid.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.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 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-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 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

View File

@ -11,7 +11,7 @@ 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-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-invalid.html select-required-multiple-ref.html
needs-focus == select-required-multiple-valid.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-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 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-fieldset-legend.html select-fieldset-legend-ref.html

View File

@ -37,7 +37,7 @@ test-pref(font.size.inflation.emPerLine,15) test-pref(font.size.inflation.forceE
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) == 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-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 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) 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 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-max-1.html intrinsic-max-1-ref.html # Initial mulet triage: parity with B2G/B2G Desktop

View File

@ -5,7 +5,7 @@
== fieldset-scroll-1.html fieldset-scroll-1-ref.html == fieldset-scroll-1.html fieldset-scroll-1-ref.html
== fieldset-scrolled-1.html fieldset-scrolled-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 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-1.html relpos-legend-1-ref.html
== relpos-legend-2.html relpos-legend-2-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 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

View File

@ -1,5 +1,5 @@
== bounds-1.html bounds-1-ref.html == 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 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 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) HTTP(..) == centering-1.xul centering-1-ref.xul # bug 974780 # Initial mulet triage: parity with B2G/B2G Desktop

View File

@ -16,7 +16,7 @@
== placeholder-3.html placeholder-overridden-ref.html == placeholder-3.html placeholder-overridden-ref.html
== placeholder-4.html placeholder-overridden-ref.html == placeholder-4.html placeholder-overridden-ref.html
== placeholder-5.html placeholder-visible-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 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-7.html placeholder-focus-ref.html
# needs-focus == placeholder-8.html placeholder-focus-ref.html # needs-focus == placeholder-8.html placeholder-focus-ref.html

View File

@ -10,5 +10,5 @@ skip-if(B2G||Mulet) fails-if(Android) fails-if(gtk2Widget) != rtl.html no-resize
== rtl.html rtl-dynamic-style.html == rtl.html rtl-dynamic-style.html
== rtl.html in-dynamic-rtl-doc.html == rtl.html in-dynamic-rtl-doc.html
== setvalue-framereconstruction-1.html setvalue-framereconstruction-ref.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 == various-cols.html various-cols-ref.html

View File

@ -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) 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) == move-top-left.html move-top-left-ref.html # Bug 688545 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) == move-right-bottom-table.html move-right-bottom-table-ref.html 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) == move-top-left-table.html move-top-left-table-ref.html # Bug 688545 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 == percent.html percent-ref.html

View File

@ -27,11 +27,11 @@ skip-if(B2G||Mulet) fuzzy-if(Android&&AndroidVersion<15,251,722) fuzzy-if(d2d,1,
HTTP == transformed-1.html?up transformed-1.html?ref 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-1.html uncovering-1-ref.html
fuzzy-if(Android,5,20000) == uncovering-2.html uncovering-2-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-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 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 fuzzy-if(asyncPanZoom&&!layersGPUAccelerated,102,6818) == 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 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-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 == move-item.html move-item-ref.html # bug 1125750

View File

@ -4,11 +4,11 @@ fuzzy-if(Android,16,244) skip-if(B2G||Mulet) HTTP(..) == marker-basic.html marke
skip-if(B2G||Mulet) HTTP(..) == marker-string.html marker-string-ref.html # 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(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(!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 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 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 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-decorations.html quirks-decorations-ref.html
HTTP(..) == quirks-line-height.html quirks-line-height-ref.html HTTP(..) == quirks-line-height.html quirks-line-height-ref.html
HTTP(..) == standards-decorations.html standards-decorations-ref.html HTTP(..) == standards-decorations.html standards-decorations-ref.html
@ -22,5 +22,5 @@ skip-if(B2G||Mulet) HTTP(..) == table-cell.html table-cell-ref.html # Initial mu
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(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(..) == 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 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 HTTP(..) == combobox-zoom.html combobox-zoom-ref.html

View File

@ -328,7 +328,7 @@ platform_files = [
] ]
def prepare_upstream(prefix, commit=None): 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): if os.path.exists(prefix):
print "Using existing repo in '%s'" % prefix print "Using existing repo in '%s'" % prefix
os.chdir(prefix) os.chdir(prefix)

View File

@ -172,6 +172,9 @@ static DllBlockInfo sWindowsDllBlocklist[] = {
// Crashes with CyberLink YouCam, bug 1136968 // Crashes with CyberLink YouCam, bug 1136968
{ "ycwebcamerasource.ax", MAKE_VERSION(2, 0, 0, 1611) }, { "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 } { nullptr, 0 }
}; };

View File

@ -2308,7 +2308,7 @@ GeckoDriver.prototype.sendKeysToElement = function(cmd, resp) {
let {id, value} = cmd.parameters; let {id, value} = cmd.parameters;
if (!value) { if (!value) {
throw new IllegalArgumentError(`Expected character sequence: ${value}`); throw new InvalidArgumentError(`Expected character sequence: ${value}`);
} }
switch (this.context) { switch (this.context) {
@ -2341,7 +2341,7 @@ GeckoDriver.prototype.sendKeysToElement = function(cmd, resp) {
try { try {
file = new File(val); file = new File(val);
} catch (e) { } catch (e) {
err = new IllegalArgumentError(`File not found: ${val}`); err = new InvalidArgumentError(`File not found: ${val}`);
} }
fs.push(file); fs.push(file);
el.mozSetFileArray(fs); el.mozSetFileArray(fs);

View File

@ -1 +1,2 @@
marionette-transport == 0.4 marionette-transport == 0.4
mozrunner >= 6.2

View File

@ -1,6 +1,6 @@
from setuptools import setup, find_packages from setuptools import setup, find_packages
version = '0.4' version = '0.5'
# dependencies # dependencies
with open('requirements.txt') as f: with open('requirements.txt') as f:

View File

@ -11,7 +11,7 @@ const errors = [
"ElementNotVisibleError", "ElementNotVisibleError",
"FrameSendFailureError", "FrameSendFailureError",
"FrameSendNotInitializedError", "FrameSendNotInitializedError",
"IllegalArgumentError", "InvalidArgumentError",
"InvalidElementStateError", "InvalidElementStateError",
"InvalidSelectorError", "InvalidSelectorError",
"InvalidSessionIdError", "InvalidSessionIdError",
@ -171,12 +171,12 @@ this.FrameSendNotInitializedError = function(frame) {
}; };
FrameSendNotInitializedError.prototype = Object.create(WebDriverError.prototype); FrameSendNotInitializedError.prototype = Object.create(WebDriverError.prototype);
this.IllegalArgumentError = function(msg) { this.InvalidArgumentError = function(msg) {
WebDriverError.call(this, msg); WebDriverError.call(this, msg);
this.name = "IllegalArgumentError"; this.name = "InvalidArgumentError";
this.status = "illegal argument"; this.status = "invalid argument";
}; };
IllegalArgumentError.prototype = Object.create(WebDriverError.prototype); InvalidArgumentError.prototype = Object.create(WebDriverError.prototype);
this.InvalidElementStateError = function(msg) { this.InvalidElementStateError = function(msg) {
WebDriverError.call(this, msg); WebDriverError.call(this, msg);
@ -196,7 +196,6 @@ this.InvalidSessionIdError = function(msg) {
WebDriverError.call(this, msg); WebDriverError.call(this, msg);
this.name = "InvalidSessionIdError"; this.name = "InvalidSessionIdError";
this.status = "invalid session id"; this.status = "invalid session id";
this.code = 13;
}; };
InvalidSessionIdError.prototype = Object.create(WebDriverError.prototype); InvalidSessionIdError.prototype = Object.create(WebDriverError.prototype);
@ -307,7 +306,6 @@ this.UnableToSetCookieError = function(msg) {
WebDriverError.call(this, msg); WebDriverError.call(this, msg);
this.name = "UnableToSetCookieError"; this.name = "UnableToSetCookieError";
this.status = "unable to set cookie"; this.status = "unable to set cookie";
this.code = 25;
}; };
UnableToSetCookieError.prototype = Object.create(WebDriverError.prototype); UnableToSetCookieError.prototype = Object.create(WebDriverError.prototype);

View File

@ -1562,7 +1562,7 @@ function sendKeysToElement(msg) {
try { try {
file = new File(p); file = new File(p);
} catch (e) { } catch (e) {
let err = new IllegalArgumentError(`File not found: ${val}`); let err = new InvalidArgumentError(`File not found: ${val}`);
sendError(err, command_id); sendError(err, command_id);
return; return;
} }

View File

@ -437,6 +437,7 @@ STUB(gtk_widget_realize)
STUB(gtk_widget_reparent) STUB(gtk_widget_reparent)
STUB(gtk_widget_set_allocation) STUB(gtk_widget_set_allocation)
STUB(gtk_widget_set_app_paintable) STUB(gtk_widget_set_app_paintable)
STUB(gtk_window_set_auto_startup_notification)
STUB(gtk_widget_set_can_focus) STUB(gtk_widget_set_can_focus)
STUB(gtk_widget_set_direction) STUB(gtk_widget_set_direction)
STUB(gtk_widget_set_double_buffered) STUB(gtk_widget_set_double_buffered)

View File

@ -93,67 +93,6 @@ NS_NewThread(nsIThread** aResult, nsIRunnable* aEvent, uint32_t aStackSize)
return NS_OK; 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_METHOD
NS_GetCurrentThread(nsIThread** aResult) NS_GetCurrentThread(nsIThread** aResult)
{ {

View File

@ -61,17 +61,6 @@ NS_NewThread(nsIThread** aResult,
nsIRunnable* aInitialEvent = nullptr, nsIRunnable* aInitialEvent = nullptr,
uint32_t aStackSize = nsIThreadManager::DEFAULT_STACK_SIZE); 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 * Creates a named thread, otherwise the same as NS_NewThread
*/ */