Merge m-c to b2g-inbound. a=merge

CLOSED TREE

--HG--
extra : amend_source : 2425dc5061db26757ca738a5a739ddc5614947f5
This commit is contained in:
Ryan VanderMeulen 2015-04-24 16:06:05 -04:00
commit f3ed6bc015
56 changed files with 1763 additions and 2552 deletions

View File

@ -1089,6 +1089,16 @@ window.addEventListener('ContentStart', function update_onContentStart() {
})();
#endif
#ifdef MOZ_WIDGET_GONK
try {
let gmpService = Cc["@mozilla.org/gecko-media-plugin-service;1"]
.getService(Ci.mozIGeckoMediaPluginChromeService);
gmpService.addPluginDirectory("/system/b2g/gmp-clearkey/0.1");
} catch(e) {
dump("Failed to add clearkey path! " + e + "\n");
}
#endif
// Calling this observer will cause a shutdown an a profile reset.
// Use eg. : Services.obs.notifyObservers(null, 'b2g-reset-profile', null);
Services.obs.addObserver(function resetProfile(subject, topic, data) {

View File

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

View File

@ -41,3 +41,5 @@ if [ -d "$topsrcdir/gtk3" ]; then
mk_add_options "export LD_LIBRARY_PATH=$topsrcdir/gtk3/usr/local/lib"
ac_add_options --enable-default-toolkit=cairo-gtk3
fi
export SOCORRO_SYMBOL_UPLOAD_TOKEN_FILE=/builds/crash-stats-api.token

View File

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

View File

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

View File

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

View File

@ -92,47 +92,6 @@ private:
bool mEnabled;
bool mShutdown;
nsRefPtr<ContentParent> mPreallocatedAppProcess;
#if defined(MOZ_NUWA_PROCESS) && defined(ENABLE_TESTS)
// For testing NS_NewUnmonitoredThread().
void CreateUnmonitoredThread();
void DestroyUnmonitoredThread();
class UnmonitoredThreadRunnable : public nsRunnable
{
public:
UnmonitoredThreadRunnable()
: mMonitor("UnmonitoredThreadRunnable")
, mEnabled(true)
{ }
NS_IMETHODIMP Run() override
{
MonitorAutoLock mon(mMonitor);
while (mEnabled) {
mMonitor.Wait();
}
return NS_OK;
}
void Disable()
{
MonitorAutoLock mon(mMonitor);
mEnabled = false;
mMonitor.NotifyAll();
}
private:
~UnmonitoredThreadRunnable() { }
Monitor mMonitor;
bool mEnabled;
};
nsCOMPtr<nsIThread> mUnmonitoredThread;
nsRefPtr<UnmonitoredThreadRunnable> mUnmonitoredThreadRunnable;
#endif
};
/* static */ StaticRefPtr<PreallocatedProcessManagerImpl>
@ -196,40 +155,6 @@ PreallocatedProcessManagerImpl::Observe(nsISupports* aSubject,
return NS_OK;
}
#if defined(MOZ_NUWA_PROCESS) && defined(ENABLE_TESTS)
void
PreallocatedProcessManagerImpl::CreateUnmonitoredThread()
{
if (Preferences::GetBool("dom.ipc.newUnmonitoredThread.testMode")) {
// Create an unmonitored thread and dispatch a blocking runnable in test
// case startup.
nsresult rv = NS_NewUnmonitoredThread(getter_AddRefs(mUnmonitoredThread),
nullptr);
NS_ENSURE_SUCCESS_VOID(rv);
mUnmonitoredThreadRunnable = new UnmonitoredThreadRunnable();
mUnmonitoredThread->Dispatch(mUnmonitoredThreadRunnable,
NS_DISPATCH_NORMAL);
}
}
void
PreallocatedProcessManagerImpl::DestroyUnmonitoredThread()
{
// Cleanup after the test case finishes.
if (mUnmonitoredThreadRunnable) {
mUnmonitoredThreadRunnable->Disable();
}
if (mUnmonitoredThread) {
mUnmonitoredThread->Shutdown();
}
mUnmonitoredThreadRunnable = nullptr;
mUnmonitoredThread = nullptr;
}
#endif
void
PreallocatedProcessManagerImpl::RereadPrefs()
{
@ -255,11 +180,6 @@ PreallocatedProcessManagerImpl::Enable()
mEnabled = true;
#ifdef MOZ_NUWA_PROCESS
#ifdef ENABLE_TESTS
// For testing New_UnmonitoredThread().
CreateUnmonitoredThread();
#endif
ScheduleDelayedNuwaFork();
#else
AllocateAfterDelay();
@ -452,11 +372,6 @@ PreallocatedProcessManagerImpl::Disable()
mEnabled = false;
#ifdef MOZ_NUWA_PROCESS
#ifdef ENABLE_TESTS
// Shut down the test-only unmonitored thread.
DestroyUnmonitoredThread();
#endif
// Cancel pending fork.
if (mPreallocateAppProcessTask) {
mPreallocateAppProcessTask->Cancel();

View File

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

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

View File

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

View File

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

View File

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

View File

@ -7,6 +7,7 @@
#include <string.h>
#include "mozilla/dom/DocumentFragment.h"
#include "mozilla/dom/OwningNonNull.h"
#include "mozilla/ArrayUtils.h"
#include "mozilla/Base64.h"
#include "mozilla/BasicEvents.h"
@ -14,7 +15,6 @@
#include "mozilla/dom/Selection.h"
#include "nsAString.h"
#include "nsAutoPtr.h"
#include "nsCOMArray.h"
#include "nsCOMPtr.h"
#include "nsCRT.h"
#include "nsCRTGlue.h"
@ -102,39 +102,6 @@ static nsresult RemoveFragComments(nsCString &theStr);
static void RemoveBodyAndHead(nsIDOMNode *aNode);
static nsresult FindTargetNode(nsIDOMNode *aStart, nsCOMPtr<nsIDOMNode> &aResult);
static nsCOMPtr<nsIDOMNode> GetListParent(nsIDOMNode* aNode)
{
NS_ENSURE_TRUE(aNode, nullptr);
nsCOMPtr<nsIDOMNode> parent, tmp;
aNode->GetParentNode(getter_AddRefs(parent));
while (parent)
{
if (nsHTMLEditUtils::IsList(parent)) {
return parent;
}
parent->GetParentNode(getter_AddRefs(tmp));
parent = tmp;
}
return nullptr;
}
static nsCOMPtr<nsIDOMNode> GetTableParent(nsIDOMNode* aNode)
{
NS_ENSURE_TRUE(aNode, nullptr);
nsCOMPtr<nsIDOMNode> parent, tmp;
aNode->GetParentNode(getter_AddRefs(parent));
while (parent)
{
if (nsHTMLEditUtils::IsTable(parent)) {
return parent;
}
parent->GetParentNode(getter_AddRefs(tmp));
parent = tmp;
}
return nullptr;
}
nsresult
nsHTMLEditor::LoadHTML(const nsAString & aInputString)
{
@ -321,13 +288,21 @@ nsHTMLEditor::DoInsertHTMLWithContext(const nsAString & aInputString,
// this is work to be completed at a later date (probably by jfrancis)
// make a list of what nodes in docFrag we need to move
nsCOMArray<nsIDOMNode> nodeList;
rv = CreateListOfNodesToPaste(fragmentAsNode, nodeList,
streamStartParent, streamStartOffset,
streamEndParent, streamEndOffset);
NS_ENSURE_SUCCESS(rv, rv);
nsTArray<OwningNonNull<nsINode>> nodeList;
nsCOMPtr<nsINode> fragmentAsNodeNode = do_QueryInterface(fragmentAsNode);
NS_ENSURE_STATE(fragmentAsNodeNode || !fragmentAsNode);
nsCOMPtr<nsINode> streamStartParentNode =
do_QueryInterface(streamStartParent);
NS_ENSURE_STATE(streamStartParentNode || !streamStartParent);
nsCOMPtr<nsINode> streamEndParentNode =
do_QueryInterface(streamEndParent);
NS_ENSURE_STATE(streamEndParentNode || !streamEndParent);
CreateListOfNodesToPaste(*static_cast<DocumentFragment*>(fragmentAsNodeNode.get()),
nodeList,
streamStartParentNode, streamStartOffset,
streamEndParentNode, streamEndOffset);
if (nodeList.Count() == 0) {
if (nodeList.Length() == 0) {
return NS_OK;
}
@ -352,9 +327,9 @@ nsHTMLEditor::DoInsertHTMLWithContext(const nsAString & aInputString,
// but if not we want to delete _contents_ of cells and replace
// with non-table elements. Use cellSelectionMode bool to
// indicate results.
nsIDOMNode* firstNode = nodeList[0];
if (!nsHTMLEditUtils::IsTableElement(firstNode))
if (!nsHTMLEditUtils::IsTableElement(nodeList[0])) {
cellSelectionMode = false;
}
}
if (!cellSelectionMode)
@ -402,7 +377,8 @@ nsHTMLEditor::DoInsertHTMLWithContext(const nsAString & aInputString,
NS_ENSURE_TRUE(parentNode, NS_ERROR_FAILURE);
// Adjust position based on the first node we are going to insert.
NormalizeEOLInsertPosition(nodeList[0], address_of(parentNode), &offsetOfNewNode);
NormalizeEOLInsertPosition(GetAsDOMNode(nodeList[0]),
address_of(parentNode), &offsetOfNewNode);
// if there are any invisible br's after our insertion point, remove them.
// this is because if there is a br at end of what we paste, it will make
@ -431,16 +407,15 @@ nsHTMLEditor::DoInsertHTMLWithContext(const nsAString & aInputString,
// build up list of parents of first node in list that are either
// lists or tables. First examine front of paste node list.
nsCOMArray<nsIDOMNode> startListAndTableArray;
rv = GetListAndTableParents(false, nodeList, startListAndTableArray);
NS_ENSURE_SUCCESS(rv, rv);
nsTArray<OwningNonNull<Element>> startListAndTableArray;
GetListAndTableParents(StartOrEnd::start, nodeList,
startListAndTableArray);
// remember number of lists and tables above us
int32_t highWaterMark = -1;
if (startListAndTableArray.Count() > 0)
{
rv = DiscoverPartialListsAndTables(nodeList, startListAndTableArray, &highWaterMark);
NS_ENSURE_SUCCESS(rv, rv);
if (startListAndTableArray.Length() > 0) {
highWaterMark = DiscoverPartialListsAndTables(nodeList,
startListAndTableArray);
}
// if we have pieces of tables or lists to be inserted, let's force the paste
@ -448,33 +423,31 @@ nsHTMLEditor::DoInsertHTMLWithContext(const nsAString & aInputString,
// table or list contents outside the table or list.
if (highWaterMark >= 0)
{
rv = ReplaceOrphanedStructure(false, nodeList, startListAndTableArray, highWaterMark);
NS_ENSURE_SUCCESS(rv, rv);
ReplaceOrphanedStructure(StartOrEnd::start, nodeList,
startListAndTableArray, highWaterMark);
}
// Now go through the same process again for the end of the paste node list.
nsCOMArray<nsIDOMNode> endListAndTableArray;
rv = GetListAndTableParents(true, nodeList, endListAndTableArray);
NS_ENSURE_SUCCESS(rv, rv);
nsTArray<OwningNonNull<Element>> endListAndTableArray;
GetListAndTableParents(StartOrEnd::end, nodeList, endListAndTableArray);
highWaterMark = -1;
// remember number of lists and tables above us
if (endListAndTableArray.Count() > 0)
{
rv = DiscoverPartialListsAndTables(nodeList, endListAndTableArray, &highWaterMark);
NS_ENSURE_SUCCESS(rv, rv);
if (endListAndTableArray.Length() > 0) {
highWaterMark = DiscoverPartialListsAndTables(nodeList,
endListAndTableArray);
}
// don't orphan partial list or table structure
if (highWaterMark >= 0)
{
rv = ReplaceOrphanedStructure(true, nodeList, endListAndTableArray, highWaterMark);
NS_ENSURE_SUCCESS(rv, rv);
ReplaceOrphanedStructure(StartOrEnd::end, nodeList,
endListAndTableArray, highWaterMark);
}
// Loop over the node list and paste the nodes:
nsCOMPtr<nsIDOMNode> parentBlock, lastInsertNode, insertedContextParent;
int32_t listCount = nodeList.Count();
int32_t listCount = nodeList.Length();
int32_t j;
if (IsBlockNode(parentNode))
parentBlock = parentNode;
@ -484,7 +457,7 @@ nsHTMLEditor::DoInsertHTMLWithContext(const nsAString & aInputString,
for (j=0; j<listCount; j++)
{
bool bDidInsert = false;
nsCOMPtr<nsIDOMNode> curNode = nodeList[j];
nsCOMPtr<nsIDOMNode> curNode = nodeList[j]->AsDOMNode();
NS_ENSURE_TRUE(curNode, NS_ERROR_FAILURE);
NS_ENSURE_TRUE(curNode != fragmentAsNode, NS_ERROR_FAILURE);
@ -721,26 +694,25 @@ nsHTMLEditor::DoInsertHTMLWithContext(const nsAString & aInputString,
return mRules->DidDoAction(selection, &ruleInfo, rv);
}
nsresult
NS_IMETHODIMP
nsHTMLEditor::AddInsertionListener(nsIContentFilter *aListener)
{
NS_ENSURE_TRUE(aListener, NS_ERROR_NULL_POINTER);
// don't let a listener be added more than once
if (mContentFilters.IndexOfObject(aListener) == -1)
{
NS_ENSURE_TRUE(mContentFilters.AppendObject(aListener), NS_ERROR_FAILURE);
if (!mContentFilters.Contains(aListener)) {
mContentFilters.AppendElement(*aListener);
}
return NS_OK;
}
nsresult
NS_IMETHODIMP
nsHTMLEditor::RemoveInsertionListener(nsIContentFilter *aListener)
{
NS_ENSURE_TRUE(aListener, NS_ERROR_FAILURE);
NS_ENSURE_TRUE(mContentFilters.RemoveObject(aListener), NS_ERROR_FAILURE);
mContentFilters.RemoveElement(aListener);
return NS_OK;
}
@ -760,17 +732,15 @@ nsHTMLEditor::DoContentFilterCallback(const nsAString &aFlavor,
{
*aDoContinue = true;
int32_t i;
nsIContentFilter *listener;
for (i=0; i < mContentFilters.Count() && *aDoContinue; i++)
{
listener = (nsIContentFilter *)mContentFilters[i];
if (listener)
listener->NotifyOfInsertion(aFlavor, nullptr, sourceDoc,
aWillDeleteSelection, aFragmentAsNode,
aFragStartNode, aFragStartOffset,
aFragEndNode, aFragEndOffset,
aTargetNode, aTargetOffset, aDoContinue);
for (auto& listener : mContentFilters) {
if (!*aDoContinue) {
break;
}
listener->NotifyOfInsertion(aFlavor, nullptr, sourceDoc,
aWillDeleteSelection, aFragmentAsNode,
aFragStartNode, aFragStartOffset,
aFragEndNode, aFragEndOffset, aTargetNode,
aTargetOffset, aDoContinue);
}
return NS_OK;
@ -2166,219 +2136,170 @@ nsresult nsHTMLEditor::ParseFragment(const nsAString & aFragStr,
return rv;
}
nsresult nsHTMLEditor::CreateListOfNodesToPaste(nsIDOMNode *aFragmentAsNode,
nsCOMArray<nsIDOMNode>& outNodeList,
nsIDOMNode *aStartNode,
int32_t aStartOffset,
nsIDOMNode *aEndNode,
int32_t aEndOffset)
void
nsHTMLEditor::CreateListOfNodesToPaste(DocumentFragment& aFragment,
nsTArray<OwningNonNull<nsINode>>& outNodeList,
nsINode* aStartNode,
int32_t aStartOffset,
nsINode* aEndNode,
int32_t aEndOffset)
{
NS_ENSURE_TRUE(aFragmentAsNode, NS_ERROR_NULL_POINTER);
nsresult rv;
// if no info was provided about the boundary between context and stream,
// If no info was provided about the boundary between context and stream,
// then assume all is stream.
if (!aStartNode)
{
int32_t fragLen;
rv = GetLengthOfDOMNode(aFragmentAsNode, (uint32_t&)fragLen);
NS_ENSURE_SUCCESS(rv, rv);
aStartNode = aFragmentAsNode;
if (!aStartNode) {
aStartNode = &aFragment;
aStartOffset = 0;
aEndNode = aFragmentAsNode;
aEndOffset = fragLen;
aEndNode = &aFragment;
aEndOffset = aFragment.Length();
}
nsRefPtr<nsRange> docFragRange;
rv = nsRange::CreateRange(aStartNode, aStartOffset, aEndNode, aEndOffset, getter_AddRefs(docFragRange));
NS_ENSURE_SUCCESS(rv, rv);
nsresult rv = nsRange::CreateRange(aStartNode, aStartOffset,
aEndNode, aEndOffset,
getter_AddRefs(docFragRange));
MOZ_ASSERT(NS_SUCCEEDED(rv));
NS_ENSURE_SUCCESS(rv, );
// now use a subtree iterator over the range to create a list of nodes
// Now use a subtree iterator over the range to create a list of nodes
nsTrivialFunctor functor;
nsDOMSubtreeIterator iter;
rv = iter.Init(docFragRange);
NS_ENSURE_SUCCESS(rv, rv);
return iter.AppendList(functor, outNodeList);
nsDOMSubtreeIterator iter(*docFragRange);
iter.AppendList(functor, outNodeList);
}
nsresult
nsHTMLEditor::GetListAndTableParents(bool aEnd,
nsCOMArray<nsIDOMNode>& aListOfNodes,
nsCOMArray<nsIDOMNode>& outArray)
void
nsHTMLEditor::GetListAndTableParents(StartOrEnd aStartOrEnd,
nsTArray<OwningNonNull<nsINode>>& aNodeList,
nsTArray<OwningNonNull<Element>>& outArray)
{
int32_t listCount = aListOfNodes.Count();
NS_ENSURE_TRUE(listCount > 0, NS_ERROR_FAILURE); // no empty lists, please
MOZ_ASSERT(aNodeList.Length());
// build up list of parents of first (or last) node in list
// that are either lists, or tables.
int32_t idx = 0;
if (aEnd) idx = listCount-1;
// Build up list of parents of first (or last) node in list that are either
// lists, or tables.
int32_t idx = aStartOrEnd == StartOrEnd::end ? aNodeList.Length() - 1 : 0;
nsCOMPtr<nsIDOMNode> pNode = aListOfNodes[idx];
while (pNode)
{
if (nsHTMLEditUtils::IsList(pNode) || nsHTMLEditUtils::IsTable(pNode))
{
NS_ENSURE_TRUE(outArray.AppendObject(pNode), NS_ERROR_FAILURE);
for (nsCOMPtr<nsINode> node = aNodeList[idx]; node;
node = node->GetParentNode()) {
if (nsHTMLEditUtils::IsList(node) || nsHTMLEditUtils::IsTable(node)) {
outArray.AppendElement(*node->AsElement());
}
nsCOMPtr<nsIDOMNode> parent;
pNode->GetParentNode(getter_AddRefs(parent));
pNode = parent;
}
return NS_OK;
}
nsresult
nsHTMLEditor::DiscoverPartialListsAndTables(nsCOMArray<nsIDOMNode>& aPasteNodes,
nsCOMArray<nsIDOMNode>& aListsAndTables,
int32_t *outHighWaterMark)
int32_t
nsHTMLEditor::DiscoverPartialListsAndTables(nsTArray<OwningNonNull<nsINode>>& aPasteNodes,
nsTArray<OwningNonNull<Element>>& aListsAndTables)
{
NS_ENSURE_TRUE(outHighWaterMark, NS_ERROR_NULL_POINTER);
int32_t ret = -1;
int32_t listAndTableParents = aListsAndTables.Length();
*outHighWaterMark = -1;
int32_t listAndTableParents = aListsAndTables.Count();
// scan insertion list for table elements (other than table).
int32_t listCount = aPasteNodes.Count();
int32_t j;
for (j=0; j<listCount; j++)
{
nsCOMPtr<nsIDOMNode> curNode = aPasteNodes[j];
NS_ENSURE_TRUE(curNode, NS_ERROR_FAILURE);
if (nsHTMLEditUtils::IsTableElement(curNode) && !nsHTMLEditUtils::IsTable(curNode))
{
nsCOMPtr<nsIDOMNode> theTable = GetTableParent(curNode);
if (theTable)
{
int32_t indexT = aListsAndTables.IndexOf(theTable);
if (indexT >= 0)
{
*outHighWaterMark = indexT;
if (*outHighWaterMark == listAndTableParents-1) break;
// Scan insertion list for table elements (other than table).
for (auto& curNode : aPasteNodes) {
if (nsHTMLEditUtils::IsTableElement(curNode) &&
!curNode->IsHTMLElement(nsGkAtoms::table)) {
nsCOMPtr<Element> table = curNode->GetParentElement();
while (table && !table->IsHTMLElement(nsGkAtoms::table)) {
table = table->GetParentElement();
}
if (table) {
int32_t idx = aListsAndTables.IndexOf(table);
if (idx == -1) {
return ret;
}
else
{
break;
ret = idx;
if (ret == listAndTableParents - 1) {
return ret;
}
}
}
if (nsHTMLEditUtils::IsListItem(curNode))
{
nsCOMPtr<nsIDOMNode> theList = GetListParent(curNode);
if (theList)
{
int32_t indexL = aListsAndTables.IndexOf(theList);
if (indexL >= 0)
{
*outHighWaterMark = indexL;
if (*outHighWaterMark == listAndTableParents-1) break;
if (nsHTMLEditUtils::IsListItem(curNode)) {
nsCOMPtr<Element> list = curNode->GetParentElement();
while (list && !nsHTMLEditUtils::IsList(list)) {
list = list->GetParentElement();
}
if (list) {
int32_t idx = aListsAndTables.IndexOf(list);
if (idx == -1) {
return ret;
}
else
{
break;
ret = idx;
if (ret == listAndTableParents - 1) {
return ret;
}
}
}
}
return NS_OK;
return ret;
}
nsresult
nsHTMLEditor::ScanForListAndTableStructure( bool aEnd,
nsCOMArray<nsIDOMNode>& aNodes,
nsIDOMNode *aListOrTable,
nsCOMPtr<nsIDOMNode> *outReplaceNode)
nsINode*
nsHTMLEditor::ScanForListAndTableStructure(StartOrEnd aStartOrEnd,
nsTArray<OwningNonNull<nsINode>>& aNodes,
Element& aListOrTable)
{
NS_ENSURE_TRUE(aListOrTable, NS_ERROR_NULL_POINTER);
NS_ENSURE_TRUE(outReplaceNode, NS_ERROR_NULL_POINTER);
*outReplaceNode = 0;
// Look upward from first/last paste node for a piece of this list/table
int32_t idx = aStartOrEnd == StartOrEnd::end ? aNodes.Length() - 1 : 0;
bool isList = nsHTMLEditUtils::IsList(&aListOrTable);
// look upward from first/last paste node for a piece of this list/table
int32_t listCount = aNodes.Count(), idx = 0;
if (aEnd) idx = listCount-1;
bool bList = nsHTMLEditUtils::IsList(aListOrTable);
nsCOMPtr<nsIDOMNode> pNode = aNodes[idx];
nsCOMPtr<nsIDOMNode> originalNode = pNode;
while (pNode)
{
if ((bList && nsHTMLEditUtils::IsListItem(pNode)) ||
(!bList && (nsHTMLEditUtils::IsTableElement(pNode) && !nsHTMLEditUtils::IsTable(pNode))))
{
nsCOMPtr<nsIDOMNode> structureNode;
if (bList) structureNode = GetListParent(pNode);
else structureNode = GetTableParent(pNode);
if (structureNode == aListOrTable)
{
if (bList)
*outReplaceNode = structureNode;
else
*outReplaceNode = pNode;
break;
for (nsCOMPtr<nsINode> node = aNodes[idx]; node;
node = node->GetParentNode()) {
if ((isList && nsHTMLEditUtils::IsListItem(node)) ||
(!isList && nsHTMLEditUtils::IsTableElement(node) &&
!node->IsHTMLElement(nsGkAtoms::table))) {
nsCOMPtr<Element> structureNode = node->GetParentElement();
if (isList) {
while (structureNode && !nsHTMLEditUtils::IsList(structureNode)) {
structureNode = structureNode->GetParentElement();
}
} else {
while (structureNode &&
!structureNode->IsHTMLElement(nsGkAtoms::table)) {
structureNode = structureNode->GetParentElement();
}
}
if (structureNode == &aListOrTable) {
if (isList) {
return structureNode;
}
return node;
}
}
nsCOMPtr<nsIDOMNode> parent;
pNode->GetParentNode(getter_AddRefs(parent));
pNode = parent;
}
return NS_OK;
return nullptr;
}
nsresult
nsHTMLEditor::ReplaceOrphanedStructure(bool aEnd,
nsCOMArray<nsIDOMNode>& aNodeArray,
nsCOMArray<nsIDOMNode>& aListAndTableArray,
void
nsHTMLEditor::ReplaceOrphanedStructure(StartOrEnd aStartOrEnd,
nsTArray<OwningNonNull<nsINode>>& aNodeArray,
nsTArray<OwningNonNull<Element>>& aListAndTableArray,
int32_t aHighWaterMark)
{
nsCOMPtr<nsIDOMNode> curNode = aListAndTableArray[aHighWaterMark];
NS_ENSURE_TRUE(curNode, NS_ERROR_NULL_POINTER);
OwningNonNull<Element> curNode = aListAndTableArray[aHighWaterMark];
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.
nsresult rv = ScanForListAndTableStructure(aEnd, aNodeArray,
curNode, address_of(replaceNode));
NS_ENSURE_SUCCESS(rv, rv);
// if we found substructure, paste it instead of its descendants
if (replaceNode)
{
// postprocess list to remove any descendants of this node
// so that we don't insert them twice.
nsCOMPtr<nsIDOMNode> endpoint;
do
{
endpoint = GetArrayEndpoint(aEnd, aNodeArray);
if (!endpoint) break;
if (nsEditorUtils::IsDescendantOf(endpoint, replaceNode))
aNodeArray.RemoveObject(endpoint);
else
break;
} while(endpoint);
// now replace the removed nodes with the structural parent
if (aEnd) aNodeArray.AppendObject(replaceNode);
else aNodeArray.InsertObjectAt(replaceNode, 0);
if (!replaceNode) {
return;
}
// If we found substructure, paste it instead of its descendants.
// Postprocess list to remove any descendants of this node so that we don't
// insert them twice.
while (aNodeArray.Length()) {
int32_t idx = aStartOrEnd == StartOrEnd::start ? 0
: aNodeArray.Length() - 1;
OwningNonNull<nsINode> endpoint = aNodeArray[idx];
if (!nsEditorUtils::IsDescendantOf(endpoint, replaceNode)) {
break;
}
aNodeArray.RemoveElementAt(idx);
}
// Now replace the removed nodes with the structural parent
if (aStartOrEnd == StartOrEnd::end) {
aNodeArray.AppendElement(*replaceNode);
} else {
aNodeArray.InsertElementAt(0, *replaceNode);
}
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 mozilla
struct DOMPoint;
template <class E> class nsCOMArray;
struct StyleCache : public PropItem
{
@ -191,14 +190,17 @@ protected:
nsresult DidMakeBasicBlock(mozilla::dom::Selection* aSelection,
nsRulesInfo* aInfo, nsresult aResult);
nsresult DidAbsolutePosition();
nsresult AlignInnerBlocks(nsIDOMNode *aNode, const nsAString *alignType);
nsresult AlignInnerBlocks(nsINode& aNode, const nsAString* alignType);
nsresult AlignBlockContents(nsIDOMNode *aNode, const nsAString *alignType);
nsresult AppendInnerFormatNodes(nsCOMArray<nsIDOMNode>& aArray,
nsresult AppendInnerFormatNodes(nsTArray<mozilla::dom::OwningNonNull<nsINode>>& aArray,
nsINode* aNode);
nsresult AppendInnerFormatNodes(nsCOMArray<nsIDOMNode>& aArray,
nsIDOMNode *aNode);
nsresult GetFormatString(nsIDOMNode *aNode, nsAString &outFormat);
nsresult GetInnerContent(nsIDOMNode *aNode, nsCOMArray<nsIDOMNode>& outArrayOfNodes, int32_t *aIndex, bool aList = true, bool aTble = true);
enum class Lists { no, yes };
enum class Tables { no, yes };
void GetInnerContent(nsINode& aNode,
nsTArray<mozilla::dom::OwningNonNull<nsINode>>& aOutArrayOfNodes,
int32_t* aIndex, Lists aLists = Lists::yes,
Tables aTables = Tables::yes);
already_AddRefed<nsIDOMNode> IsInListItem(nsIDOMNode* aNode);
mozilla::dom::Element* IsInListItem(nsINode* aNode);
nsresult ReturnInHeader(mozilla::dom::Selection* aSelection,
@ -217,11 +219,9 @@ protected:
int32_t aOffset);
nsresult AfterEditInner(EditAction action,
nsIEditor::EDirection aDirection);
nsresult RemovePartOfBlock(nsIDOMNode *aBlock,
nsIDOMNode *aStartChild,
nsIDOMNode *aEndChild,
nsCOMPtr<nsIDOMNode> *aLeftNode = 0,
nsCOMPtr<nsIDOMNode> *aRightNode = 0);
nsresult RemovePartOfBlock(mozilla::dom::Element& aBlock,
nsIContent& aStartChild,
nsIContent& aEndChild);
nsresult SplitBlock(nsIDOMNode *aBlock,
nsIDOMNode *aStartChild,
nsIDOMNode *aEndChild,
@ -263,37 +263,44 @@ protected:
void GetPromotedPoint(RulesEndpoint aWhere, nsIDOMNode* aNode,
int32_t aOffset, EditAction actionID,
nsCOMPtr<nsIDOMNode>* outNode, int32_t* outOffset);
nsresult GetPromotedRanges(mozilla::dom::Selection* aSelection,
nsTArray<nsRefPtr<nsRange>>& outArrayOfRanges,
EditAction inOperationType);
nsresult PromoteRange(nsRange* inRange, EditAction inOperationType);
nsresult GetNodesForOperation(nsTArray<nsRefPtr<nsRange>>& inArrayOfRanges,
nsCOMArray<nsIDOMNode>& outArrayOfNodes,
EditAction inOperationType,
bool aDontTouchContent=false);
nsresult GetChildNodesForOperation(nsIDOMNode *inNode,
nsCOMArray<nsIDOMNode>& outArrayOfNodes);
nsresult GetNodesFromPoint(::DOMPoint point,
EditAction operation,
nsCOMArray<nsIDOMNode>& arrayOfNodes,
bool dontTouchContent);
nsresult GetNodesFromSelection(mozilla::dom::Selection* selection,
EditAction operation,
nsCOMArray<nsIDOMNode>& arrayOfNodes,
bool aDontTouchContent=false);
nsresult GetListActionNodes(nsCOMArray<nsIDOMNode> &outArrayOfNodes, bool aEntireList, bool aDontTouchContent=false);
void GetPromotedRanges(mozilla::dom::Selection& aSelection,
nsTArray<nsRefPtr<nsRange>>& outArrayOfRanges,
EditAction inOperationType);
void PromoteRange(nsRange& aRange, EditAction inOperationType);
enum class TouchContent { no, yes };
nsresult GetNodesForOperation(nsTArray<nsRefPtr<nsRange>>& aArrayOfRanges,
nsTArray<mozilla::dom::OwningNonNull<nsINode>>& aOutArrayOfNodes,
EditAction aOperationType,
TouchContent aTouchContent = TouchContent::yes);
void GetChildNodesForOperation(nsINode& aNode,
nsTArray<mozilla::dom::OwningNonNull<nsINode>>& outArrayOfNodes);
nsresult GetNodesFromPoint(::DOMPoint aPoint,
EditAction aOperation,
nsTArray<mozilla::dom::OwningNonNull<nsINode>>& outArrayOfNodes,
TouchContent aTouchContent);
nsresult GetNodesFromSelection(mozilla::dom::Selection& aSelection,
EditAction aOperation,
nsTArray<mozilla::dom::OwningNonNull<nsINode>>& outArrayOfNodes,
TouchContent aTouchContent = TouchContent::yes);
enum class EntireList { no, yes };
nsresult GetListActionNodes(nsTArray<mozilla::dom::OwningNonNull<nsINode>>& aOutArrayOfNodes,
EntireList aEntireList,
TouchContent aTouchContent = TouchContent::yes);
void GetDefinitionListItemTypes(mozilla::dom::Element* aElement, bool* aDT, bool* aDD);
nsresult GetParagraphFormatNodes(nsCOMArray<nsIDOMNode>& outArrayOfNodes, bool aDontTouchContent=false);
nsresult LookInsideDivBQandList(nsCOMArray<nsIDOMNode>& aNodeArray);
nsresult GetParagraphFormatNodes(
nsTArray<mozilla::dom::OwningNonNull<nsINode>>& outArrayOfNodes,
TouchContent aTouchContent = TouchContent::yes);
void LookInsideDivBQandList(nsTArray<mozilla::dom::OwningNonNull<nsINode>>& aNodeArray);
nsresult BustUpInlinesAtRangeEndpoints(nsRangeStore &inRange);
nsresult BustUpInlinesAtBRs(nsIDOMNode *inNode,
nsCOMArray<nsIDOMNode>& outArrayOfNodes);
nsresult BustUpInlinesAtBRs(nsINode& aNode,
nsTArray<mozilla::dom::OwningNonNull<nsINode>>& aOutArrayOfNodes);
nsCOMPtr<nsIDOMNode> GetHighestInlineParent(nsIDOMNode* aNode);
nsresult MakeTransitionList(nsCOMArray<nsIDOMNode>& inArrayOfNodes,
nsTArray<bool> &inTransitionArray);
nsresult RemoveBlockStyle(nsCOMArray<nsIDOMNode>& arrayOfNodes);
nsresult ApplyBlockStyle(nsCOMArray<nsIDOMNode>& arrayOfNodes, const nsAString *aBlockTag);
nsresult MakeBlockquote(nsCOMArray<nsIDOMNode>& arrayOfNodes);
void MakeTransitionList(nsTArray<mozilla::dom::OwningNonNull<nsINode>>& aNodeArray,
nsTArray<bool>& aTransitionArray);
nsresult RemoveBlockStyle(nsTArray<mozilla::dom::OwningNonNull<nsINode>>& aNodeArray);
nsresult ApplyBlockStyle(nsTArray<mozilla::dom::OwningNonNull<nsINode>>& aNodeArray,
nsIAtom& aBlockTag);
nsresult MakeBlockquote(nsTArray<mozilla::dom::OwningNonNull<nsINode>>& aNodeArray);
nsresult SplitAsNeeded(nsIAtom& aTag, nsCOMPtr<nsINode>& inOutParent,
int32_t& inOutOffset);
nsresult AddTerminatingBR(nsIDOMNode *aBlock);
@ -304,7 +311,7 @@ protected:
nsresult CacheInlineStyles(nsIDOMNode *aNode);
nsresult ReapplyCachedStyles();
void ClearCachedStyles();
nsresult AdjustSpecialBreaks(bool aSafeToAskFrames = false);
void AdjustSpecialBreaks();
nsresult AdjustWhitespace(mozilla::dom::Selection* aSelection);
nsresult PinSelectionToNewBlock(mozilla::dom::Selection* aSelection);
nsresult CheckInterlinePosition(mozilla::dom::Selection* aSelection);
@ -329,7 +336,7 @@ protected:
nsresult ConfirmSelectionInBody();
nsresult InsertMozBRIfNeeded(nsIDOMNode *aNode);
bool IsEmptyInline(nsIDOMNode *aNode);
bool ListIsEmptyLine(nsCOMArray<nsIDOMNode> &arrayOfNodes);
bool ListIsEmptyLine(nsTArray<mozilla::dom::OwningNonNull<nsINode>>& arrayOfNodes);
nsresult RemoveAlignment(nsIDOMNode * aNode, const nsAString & aAlignType, bool aChildrenOnly);
nsresult MakeSureElemStartsOrEndsOnCR(nsIDOMNode *aNode, bool aStarts);
nsresult AlignBlock(nsIDOMElement * aElement, const nsAString * aAlignType, bool aContentsOnly);

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

View File

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

View File

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

View File

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

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
skip-if(B2G||Mulet) == caret_on_presshell_reinit.html caret_on_presshell_reinit-ref.html # Initial mulet triage: parity with B2G/B2G Desktop
skip-if(B2G||Mulet) == caret_on_presshell_reinit-2.html caret_on_presshell_reinit-ref.html # Initial mulet triage: parity with B2G/B2G Desktop
skip-if(B2G||Mulet) == 642800.html 642800-ref.html # Initial mulet triage: parity with B2G/B2G Desktop
skip-if(B2G||Mulet) fuzzy-if(asyncPanZoom&&!layersGPUAccelerated,102,2824) == 642800.html 642800-ref.html # Initial mulet triage: parity with B2G/B2G Desktop
== selection_visibility_after_reframe.html selection_visibility_after_reframe-ref.html
!= selection_visibility_after_reframe-2.html selection_visibility_after_reframe-ref.html
!= selection_visibility_after_reframe-3.html selection_visibility_after_reframe-ref.html

View File

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

View File

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

View File

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

View File

@ -537,8 +537,28 @@ MOZ_ALWAYS_INLINE void
js::Nursery::traceObject(MinorCollectionTracer* trc, JSObject* obj)
{
const Class* clasp = obj->getClass();
if (clasp->trace)
if (clasp->trace) {
if (clasp->trace == InlineTypedObject::obj_trace) {
TypeDescr* descr = &obj->as<InlineTypedObject>().typeDescr();
if (descr->hasTraceList()) {
markTraceList(trc, descr->traceList(),
obj->as<InlineTypedObject>().inlineTypedMem());
}
return;
}
if (clasp == &UnboxedPlainObject::class_) {
JSObject** pexpando = obj->as<UnboxedPlainObject>().addressOfExpando();
if (*pexpando)
markObject(trc, pexpando);
const UnboxedLayout& layout = obj->as<UnboxedPlainObject>().layout();
if (layout.traceList()) {
markTraceList(trc, layout.traceList(),
obj->as<UnboxedPlainObject>().data());
}
return;
}
clasp->trace(trc, obj);
}
MOZ_ASSERT(obj->isNative() == clasp->isNative());
if (!clasp->isNative())
@ -579,16 +599,42 @@ js::Nursery::markSlot(MinorCollectionTracer* trc, HeapSlot* slotp)
return;
JSObject* obj = &slotp->toObject();
if (!IsInsideNursery(obj))
return;
if (getForwardedPointer(&obj)) {
if (markObject(trc, &obj))
slotp->unsafeGet()->setObject(*obj);
return;
}
}
JSObject* tenured = static_cast<JSObject*>(moveToTenured(trc, obj));
slotp->unsafeGet()->setObject(*tenured);
MOZ_ALWAYS_INLINE void
js::Nursery::markTraceList(MinorCollectionTracer* trc, const int32_t* traceList, uint8_t* memory)
{
while (*traceList != -1) {
// Strings are not in the nursery and do not need tracing.
traceList++;
}
traceList++;
while (*traceList != -1) {
JSObject** pobj = reinterpret_cast<JSObject **>(memory + *traceList);
markObject(trc, pobj);
traceList++;
}
traceList++;
while (*traceList != -1) {
HeapSlot* pslot = reinterpret_cast<HeapSlot *>(memory + *traceList);
markSlot(trc, pslot);
traceList++;
}
}
MOZ_ALWAYS_INLINE bool
js::Nursery::markObject(MinorCollectionTracer* trc, JSObject** pobj)
{
if (!IsInsideNursery(*pobj))
return false;
if (getForwardedPointer(pobj))
return true;
*pobj = static_cast<JSObject*>(moveToTenured(trc, *pobj));
return true;
}
void*

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, HeapSlot* end);
MOZ_ALWAYS_INLINE void markSlot(gc::MinorCollectionTracer* trc, HeapSlot* slotp);
MOZ_ALWAYS_INLINE void markTraceList(gc::MinorCollectionTracer* trc,
const int32_t* traceList, uint8_t* memory);
MOZ_ALWAYS_INLINE bool markObject(gc::MinorCollectionTracer* trc, JSObject** pobj);
void* moveToTenured(gc::MinorCollectionTracer* trc, JSObject* src);
size_t moveObjectToTenured(gc::MinorCollectionTracer* trc, JSObject* dst, JSObject* src,
gc::AllocKind dstKind);

View File

@ -10130,6 +10130,17 @@ TryAttachStringSplit(JSContext* cx, ICCall_Fallback* stub, HandleScript script,
if (!CopyArray(cx, obj, &arr))
return false;
// Atomize all elements of the array.
RootedArrayObject arrObj(cx, &arr.toObject().as<ArrayObject>());
uint32_t initLength = arrObj->length();
for (uint32_t i = 0; i < initLength; i++) {
JSAtom* str = js::AtomizeString(cx, arrObj->getDenseElement(i).toString());
if (!str)
return false;
arrObj->setDenseElement(i, StringValue(str));
}
ICCall_StringSplit::Compiler compiler(cx, stub->fallbackMonitorStub()->firstMonitorStub(),
script->pcToOffset(pc), thisString, argString,
arr);

View File

@ -12873,17 +12873,8 @@ IonBuilder::storeReferenceTypedObjectValue(MDefinition* typedObj,
MConstant*
IonBuilder::constant(const Value& v)
{
// For performance reason (TLS) and error code handling (AtomizeString), we
// should prefer the specialized frunction constantMaybeAtomize instead of
// constant.
MOZ_ASSERT(!v.isString() || v.toString()->isAtom(),
"To handle non-atomized strings, you should use constantMaybeAtomize instead of constant.");
if (v.isString() && MOZ_UNLIKELY(!v.toString()->isAtom())) {
MConstant* cst = constantMaybeAtomize(v);
if (!cst)
js::CrashAtUnhandlableOOM("Use constantMaybeAtomize.");
return cst;
}
"Handle non-atomized strings outside IonBuilder.");
MConstant* c = MConstant::New(alloc(), v, constraints());
current->add(c);
@ -12896,19 +12887,6 @@ IonBuilder::constantInt(int32_t i)
return constant(Int32Value(i));
}
MConstant*
IonBuilder::constantMaybeAtomize(const Value& v)
{
if (!v.isString() || v.toString()->isAtom())
return constant(v);
JSContext* cx = GetJitContext()->cx;
JSAtom* atom = js::AtomizeString(cx, v.toString());
if (!atom)
return nullptr;
return constant(StringValue(atom));
}
MDefinition*
IonBuilder::getCallee()
{

View File

@ -353,9 +353,6 @@ class IonBuilder
MConstant* constant(const Value& v);
MConstant* constantInt(int32_t i);
// Note: This function might return nullptr in case of failure.
MConstant* constantMaybeAtomize(const Value& v);
// Improve the type information at tests
bool improveTypesAtTest(MDefinition* ins, bool trueBranch, MTest* test);
bool improveTypesAtCompare(MCompare* ins, bool trueBranch, MTest* test);

View File

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

View File

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

View File

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

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-2.html continuation-positioned-inline-ref.html
== scrollframe-1.html scrollframe-1-ref.html
skip-if(B2G||Mulet) fuzzy-if(Android,9,185) == scrollframe-2.html scrollframe-2-ref.html #bug 756530 # Initial mulet triage: parity with B2G/B2G Desktop
skip-if(B2G||Mulet) fuzzy-if(Android,9,185) fuzzy-if(asyncPanZoom&&!layersGPUAccelerated,102,107) == scrollframe-2.html scrollframe-2-ref.html #bug 756530 # Initial mulet triage: parity with B2G/B2G Desktop
fuzzy-if(gtk2Widget,1,8) == select-1.html select-1-ref.html
fuzzy-if(gtk2Widget,1,8) == select-1-dynamic.html select-1-ref.html
== select-2.html select-2-ref.html
fuzzy-if(gtk2Widget,1,19) fuzzy-if(Android||B2G,17,726) == select-3.html select-3-ref.html
fuzzy-if(gtk2Widget,1,19) fuzzy-if(Android||B2G,17,726) fuzzy-if(asyncPanZoom&&!layersGPUAccelerated,102,98) == select-3.html select-3-ref.html
== multi-column-1.html multi-column-1-ref.html
== button-1.html button-1-ref.html
== button-2.html button-2-ref.html

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-nofill-1.html border-image-nofill-1-ref.html
== border-image-outset-resize-1.html border-image-outset-resize-1-ref.html
== border-image-outset-move-1.html border-image-outset-move-1-ref.html
fuzzy-if(asyncPanZoom&&!layersGPUAccelerated,102,445) == border-image-outset-move-1.html border-image-outset-move-1-ref.html
== border-image-style-none.html border-image-style-none-ref.html
== border-image-style-none-length.html border-image-style-none-length-ref.html
== border-image-style-none-auto.html border-image-style-none-auto-ref.html

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
# test that border-radius is reduced for scrollbars
skip-if(B2G||Mulet) fails-if(Android) == scrollbar-clamping-1.html scrollbar-clamping-1-ref.html # Initial mulet triage: parity with B2G/B2G Desktop
skip-if(B2G||Mulet) fails-if(Android) fuzzy-if(asyncPanZoom&&!layersGPUAccelerated,12,12) == scrollbar-clamping-1.html scrollbar-clamping-1-ref.html # Initial mulet triage: parity with B2G/B2G Desktop
skip-if(B2G||Mulet) fails-if(Android) == scrollbar-clamping-2.html scrollbar-clamping-2-ref.html # Initial mulet triage: parity with B2G/B2G Desktop
# Test for bad corner joins.

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(B2G||Mulet) fails-if(Android) random-if(layersGPUAccelerated) == 579985-1.html 579985-1-ref.html # bug 623452 for WinXP; this bug was only for a regression in BasicLayers anyway # Initial mulet triage: parity with B2G/B2G Desktop
skip-if(B2G||Mulet) skip-if(Android) == 580160-1.html 580160-1-ref.html # bug 920927 for Android; issues without the test-plugin # Initial mulet triage: parity with B2G/B2G Desktop
HTTP(..) == 580863-1.html 580863-1-ref.html
fuzzy-if(asyncPanZoom&&!layersGPUAccelerated,255,13) HTTP(..) == 580863-1.html 580863-1-ref.html
skip-if(B2G||Mulet) fails-if(Android) random-if(layersGPUAccelerated) == 581317-1.html 581317-1-ref.html # Initial mulet triage: parity with B2G/B2G Desktop
== 581579-1.html 581579-1-ref.html
== 582037-1a.html 582037-1-ref.html
@ -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
== 645491-1.html 645491-1-ref.html
== 645768-1.html 645768-1-ref.html
fails-if(layersGPUAccelerated&&cocoaWidget) fails-if(Android&&AndroidVersion<15&&AndroidVersion!=10) == 650228-1.html 650228-1-ref.html # Quartz alpha blending doesn't match GL alpha blending
fails-if(layersGPUAccelerated&&cocoaWidget) fails-if(Android&&AndroidVersion<15&&AndroidVersion!=10) fuzzy-if(asyncPanZoom&&!layersGPUAccelerated,41,260) == 650228-1.html 650228-1-ref.html # Quartz alpha blending doesn't match GL alpha blending
needs-focus == 652301-1a.html 652301-1-ref.html
needs-focus == 652301-1b.html 652301-1-ref.html
== 652775-1.html 652775-1-ref.html
@ -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
== 817019-1.html about:blank
skip-if(B2G||Mulet) == 818276-1.html 818276-1-ref.html # Initial mulet triage: parity with B2G/B2G Desktop
fuzzy-if(asyncPanZoom,190,27) == 825999.html 825999-ref.html
fuzzy-if(asyncPanZoom,190,510) fuzzy-if(asyncPanZoom&&!layersGPUAccelerated,102,510) == 825999.html 825999-ref.html
== 827577-1a.html 827577-1-ref.html
== 827577-1b.html 827577-1-ref.html
== 827799-1.html about:blank
@ -1806,7 +1806,7 @@ fuzzy-if(B2G,1,7) == 942672-1.html 942672-1-ref.html
== 961887-1.html 961887-1-ref.html
== 961887-2.html 961887-2-ref.html
== 961887-3.html 961887-3-ref.html
pref(layout.css.overflow-clip-box.enabled,true) fuzzy(50,145) == 966992-1.html 966992-1-ref.html
pref(layout.css.overflow-clip-box.enabled,true) fuzzy(50,145) fuzzy-if(asyncPanZoom&&!layersGPUAccelerated,102,3712) == 966992-1.html 966992-1-ref.html
skip-if(Android) == 966510-1.html 966510-1-ref.html # scrollable elements other than the root probably won't work well on android until bug 776030 is fixed
skip-if(Android) == 966510-2.html 966510-2-ref.html # same as above
== 978911-1.svg 978911-1-ref.svg

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-valid.html select-required-ref.html
needs-focus == select-required-multiple-invalid.html select-required-multiple-ref.html
needs-focus == select-required-multiple-invalid-changed.html select-required-multiple-ref.html
fuzzy-if(asyncPanZoom&&!layersGPUAccelerated,84,77) needs-focus == select-required-multiple-invalid-changed.html select-required-multiple-ref.html
needs-focus == select-required-multiple-valid.html select-required-multiple-ref.html
skip-if(B2G||Mulet) fails-if(Android) needs-focus == select-disabled-fieldset-1.html select-fieldset-ref.html # Initial mulet triage: parity with B2G/B2G Desktop
skip-if(B2G||Mulet) fails-if(Android) needs-focus == select-disabled-fieldset-2.html select-fieldset-ref.html # Initial mulet triage: parity with B2G/B2G Desktop

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-multiple-invalid.html select-required-multiple-ref.html
needs-focus == select-required-multiple-valid.html select-required-multiple-ref.html
fuzzy(64,4) needs-focus == select-required-multiple-valid-changed.html select-required-multiple-ref.html
fuzzy(64,4) fuzzy-if(asyncPanZoom&&layersGPUAccelerated,84,77) needs-focus == select-required-multiple-valid-changed.html select-required-multiple-ref.html
fails-if(Android||B2G||Mulet) needs-focus == select-disabled-fieldset-1.html select-fieldset-ref.html # Initial mulet triage: parity with B2G/B2G Desktop
fails-if(Android||B2G||Mulet) needs-focus == select-disabled-fieldset-2.html select-fieldset-ref.html # Initial mulet triage: parity with B2G/B2G Desktop
needs-focus == select-fieldset-legend.html select-fieldset-legend-ref.html

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) == css-transform-1.html css-transform-1-ref.html
test-pref(font.size.inflation.emPerLine,15) test-pref(font.size.inflation.forceEnabled,true) test-pref(font.size.inflation.lineThreshold,0) == css-transform-2.html css-transform-2-ref.html
skip-if(B2G||Mulet) test-pref(font.size.inflation.emPerLine,15) test-pref(font.size.inflation.forceEnabled,true) test-pref(font.size.inflation.lineThreshold,0) == container-with-clamping.html container-with-clamping-ref.html # Initial mulet triage: parity with B2G/B2G Desktop
skip-if(B2G||Mulet) fuzzy-if(asyncPanZoom&&!layersGPUAccelerated,102,1764) test-pref(font.size.inflation.emPerLine,15) test-pref(font.size.inflation.forceEnabled,true) test-pref(font.size.inflation.lineThreshold,0) == container-with-clamping.html container-with-clamping-ref.html # Initial mulet triage: parity with B2G/B2G Desktop
test-pref(font.size.inflation.emPerLine,15) test-pref(font.size.inflation.forceEnabled,true) test-pref(font.size.inflation.lineThreshold,0) load video-1.html
test-pref(font.size.inflation.emPerLine,15) test-pref(font.size.inflation.forceEnabled,true) test-pref(font.size.inflation.lineThreshold,0) HTTP(..) == intrinsic-min-1.html intrinsic-min-1-ref.html
skip-if(B2G||Mulet) test-pref(font.size.inflation.emPerLine,15) test-pref(font.size.inflation.forceEnabled,true) test-pref(font.size.inflation.lineThreshold,0) HTTP(..) == intrinsic-max-1.html intrinsic-max-1-ref.html # Initial mulet triage: parity with B2G/B2G Desktop

View File

@ -5,7 +5,7 @@
== fieldset-scroll-1.html fieldset-scroll-1-ref.html
== fieldset-scrolled-1.html fieldset-scrolled-1-ref.html
random-if(B2G||Mulet) == fieldset-overflow-auto-1.html fieldset-overflow-auto-1-ref.html # Initial mulet triage: parity with B2G/B2G Desktop
fuzzy-if(winWidget&&!layersGPUAccelerated,102,205) == positioned-container-1.html positioned-container-1-ref.html
fuzzy-if(winWidget&&!layersGPUAccelerated,102,221) == positioned-container-1.html positioned-container-1-ref.html
== relpos-legend-1.html relpos-legend-1-ref.html
== relpos-legend-2.html relpos-legend-2-ref.html
test-pref(layout.css.sticky.enabled,true) skip-if((B2G&&browserIsRemote)||Mulet) == sticky-legend-1.html sticky-legend-1-ref.html # Initial mulet triage: parity with B2G/B2G Desktop

View File

@ -1,5 +1,5 @@
== bounds-1.html bounds-1-ref.html
== size-1.html size-1-ref.html
fuzzy-if(asyncPanZoom&&!layersGPUAccelerated,102,84) == size-1.html size-1-ref.html
skip-if(B2G||Mulet) == size-2.html size-2-ref.html # Initial mulet triage: parity with B2G/B2G Desktop
HTTP(..) == baseline-1.html baseline-1-ref.html
skip-if((B2G&&browserIsRemote)||Mulet) HTTP(..) == centering-1.xul centering-1-ref.xul # bug 974780 # Initial mulet triage: parity with B2G/B2G Desktop

View File

@ -16,7 +16,7 @@
== placeholder-3.html placeholder-overridden-ref.html
== placeholder-4.html placeholder-overridden-ref.html
== placeholder-5.html placeholder-visible-ref.html
fuzzy-if(winWidget,160,7) == placeholder-6.html placeholder-overflow-ref.html
fuzzy-if(winWidget,160,7) fuzzy-if(asyncPanZoom&&!layersGPUAccelerated,146,299) == placeholder-6.html placeholder-overflow-ref.html
skip-if(B2G||Mulet) == placeholder-6-textarea.html placeholder-overflow-textarea-ref.html # Initial mulet triage: parity with B2G/B2G Desktop
# needs-focus == placeholder-7.html placeholder-focus-ref.html
# needs-focus == placeholder-8.html placeholder-focus-ref.html

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 in-dynamic-rtl-doc.html
== setvalue-framereconstruction-1.html setvalue-framereconstruction-ref.html
== padding-scrollbar-placement.html padding-scrollbar-placement-ref.html
fuzzy-if(asyncPanZoom&&!layersGPUAccelerated,102,4168) == padding-scrollbar-placement.html padding-scrollbar-placement-ref.html
== various-cols.html various-cols-ref.html

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) == move-top-left.html move-top-left-ref.html # Bug 688545
fuzzy-if(cocoaWidget,1,3) == move-right-bottom-table.html move-right-bottom-table-ref.html
fuzzy-if(cocoaWidget,1,3) == move-top-left-table.html move-top-left-table-ref.html # Bug 688545
fuzzy-if(cocoaWidget,1,2) fuzzy-if(d2d,47,26) fuzzy-if(asyncPanZoom&&!layersGPUAccelerated,102,492) == move-right-bottom.html move-right-bottom-ref.html
fuzzy-if(cocoaWidget,1,2) fuzzy-if(asyncPanZoom&&!layersGPUAccelerated,102,492) == move-top-left.html move-top-left-ref.html # Bug 688545
fuzzy-if(cocoaWidget,1,3) fuzzy-if(asyncPanZoom&&!layersGPUAccelerated,102,492) == move-right-bottom-table.html move-right-bottom-table-ref.html
fuzzy-if(cocoaWidget,1,3) fuzzy-if(asyncPanZoom&&!layersGPUAccelerated,102,492) == move-top-left-table.html move-top-left-table-ref.html # Bug 688545
== percent.html percent-ref.html

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
fuzzy-if(Android,5,20000) == uncovering-1.html uncovering-1-ref.html
fuzzy-if(Android,5,20000) == uncovering-2.html uncovering-2-ref.html
skip-if(B2G||Mulet) == less-than-scrollbar-height.html less-than-scrollbar-height-ref.html # Initial mulet triage: parity with B2G/B2G Desktop
skip-if(B2G||Mulet) fuzzy-if(asyncPanZoom&&!layersGPUAccelerated,102,3721) == less-than-scrollbar-height.html less-than-scrollbar-height-ref.html # Initial mulet triage: parity with B2G/B2G Desktop
skip-if(B2G||Mulet) == huge-horizontal-overflow.html huge-horizontal-overflow-ref.html # Initial mulet triage: parity with B2G/B2G Desktop
skip-if(B2G||Mulet) == huge-vertical-overflow.html huge-vertical-overflow-ref.html # Initial mulet triage: parity with B2G/B2G Desktop
== iframe-scrolling-attr-1.html iframe-scrolling-attr-ref.html
skip-if((B2G&&browserIsRemote)||Mulet) == iframe-scrolling-attr-2.html iframe-scrolling-attr-ref.html # Initial mulet triage: parity with B2G/B2G Desktop
fuzzy-if(asyncPanZoom&&!layersGPUAccelerated,102,6818) == iframe-scrolling-attr-1.html iframe-scrolling-attr-ref.html
skip-if((B2G&&browserIsRemote)||Mulet) fuzzy-if(asyncPanZoom&&!layersGPUAccelerated,102,6818) == iframe-scrolling-attr-2.html iframe-scrolling-attr-ref.html # Initial mulet triage: parity with B2G/B2G Desktop
== frame-scrolling-attr-1.html frame-scrolling-attr-ref.html
== frame-scrolling-attr-2.html frame-scrolling-attr-ref.html
fuzzy-if(asyncPanZoom&&!layersGPUAccelerated,102,2420) == frame-scrolling-attr-2.html frame-scrolling-attr-ref.html
== move-item.html move-item-ref.html # bug 1125750

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(Android||B2G) HTTP(..) == bidi-simple.html bidi-simple-ref.html # Fails on Android due to anti-aliasing
skip-if(!gtk2Widget) fuzzy-if(gtk2Widget,1,104) HTTP(..) == bidi-simple-scrolled.html bidi-simple-scrolled-ref.html # Fails on Windows and OSX due to anti-aliasing
skip-if(B2G||Mulet) fuzzy-if(Android&&AndroidVersion<15,9,2545) fuzzy-if(Android&&AndroidVersion>=15,24,4000) fuzzy-if(cocoaWidget,1,40) HTTP(..) == scroll-rounding.html scroll-rounding-ref.html # bug 760264 # Initial mulet triage: parity with B2G/B2G Desktop
skip-if(B2G||Mulet) fuzzy-if(Android&&AndroidVersion<15,9,2545) fuzzy-if(Android&&AndroidVersion>=15,24,4000) fuzzy-if(cocoaWidget,1,40) fuzzy-if(asyncPanZoom&&!layersGPUAccelerated,102,1770) HTTP(..) == scroll-rounding.html scroll-rounding-ref.html # bug 760264 # Initial mulet triage: parity with B2G/B2G Desktop
fuzzy-if(OSX==1008,1,1) HTTP(..) == anonymous-block.html anonymous-block-ref.html
skip-if(B2G||Mulet) HTTP(..) == false-marker-overlap.html false-marker-overlap-ref.html # Initial mulet triage: parity with B2G/B2G Desktop
HTTP(..) == visibility-hidden.html visibility-hidden-ref.html
skip-if(B2G||Mulet) HTTP(..) == block-padding.html block-padding-ref.html # Initial mulet triage: parity with B2G/B2G Desktop
skip-if(B2G||Mulet) fuzzy-if(asyncPanZoom&&!layersGPUAccelerated,102,1724) HTTP(..) == block-padding.html block-padding-ref.html # Initial mulet triage: parity with B2G/B2G Desktop
HTTP(..) == quirks-decorations.html quirks-decorations-ref.html
HTTP(..) == quirks-line-height.html quirks-line-height-ref.html
HTTP(..) == standards-decorations.html standards-decorations-ref.html
@ -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(B2G||Mulet) HTTP(..) == single-value.html single-value-ref.html # Initial mulet triage: parity with B2G/B2G Desktop
skip-if(B2G||Mulet) HTTP(..) == atomic-under-marker.html atomic-under-marker-ref.html # Initial mulet triage: parity with B2G/B2G Desktop
fuzzy(1,702) skip-if(Android||B2G||Mulet) HTTP(..) == xulscroll.html xulscroll-ref.html # Initial mulet triage: parity with B2G/B2G Desktop
fuzzy(1,702) skip-if(Android||B2G||Mulet) fuzzy-if(asyncPanZoom&&!layersGPUAccelerated,102,12352) HTTP(..) == xulscroll.html xulscroll-ref.html # Initial mulet triage: parity with B2G/B2G Desktop
HTTP(..) == combobox-zoom.html combobox-zoom-ref.html

View File

@ -328,7 +328,7 @@ platform_files = [
]
def prepare_upstream(prefix, commit=None):
upstream_url = 'https://gerrit.chromium.org/gerrit/webm/libvpx'
upstream_url = 'https://chromium.googlesource.com/webm/libvpx'
if os.path.exists(prefix):
print "Using existing repo in '%s'" % prefix
os.chdir(prefix)

View File

@ -172,6 +172,9 @@ static DllBlockInfo sWindowsDllBlocklist[] = {
// Crashes with CyberLink YouCam, bug 1136968
{ "ycwebcamerasource.ax", MAKE_VERSION(2, 0, 0, 1611) },
// Old version of WebcamMax crashes WebRTC, bug 1130061
{ "vwcsource.ax", MAKE_VERSION(1, 5, 0, 0) },
{ nullptr, 0 }
};

View File

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

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
version = '0.4'
version = '0.5'
# dependencies
with open('requirements.txt') as f:

View File

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

View File

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

View File

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

View File

@ -93,67 +93,6 @@ NS_NewThread(nsIThread** aResult, nsIRunnable* aEvent, uint32_t aStackSize)
return NS_OK;
}
#if defined(MOZ_NUWA_PROCESS) && !defined(XPCOM_GLUE_AVOID_NSPR)
namespace {
class IgnoreThreadStatusRunnable : public nsIRunnable
{
public:
NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_NSIRUNNABLE
private:
virtual ~IgnoreThreadStatusRunnable() = default;
};
NS_IMPL_ISUPPORTS(IgnoreThreadStatusRunnable, nsIRunnable)
NS_IMETHODIMP IgnoreThreadStatusRunnable::Run(void)
{
#ifdef MOZILLA_INTERNAL_API
nsThreadManager::get()->SetIgnoreThreadStatus();
return NS_OK;
#endif
return NS_ERROR_NOT_IMPLEMENTED;
}
} // Anonymous namespace.
#endif // defined(MOZ_NUWA_PROCESS) && !defined(XPCOM_GLUE_AVOID_NSPR)
NS_METHOD
NS_NewUnmonitoredThread(nsIThread** aResult,
nsIRunnable* aEvent,
uint32_t aStackSize)
{
#if defined(MOZ_NUWA_PROCESS) && !defined(XPCOM_GLUE_AVOID_NSPR)
// Hold a ref while dispatching the initial event to match NS_NewThread()
nsCOMPtr<nsIThread> thread;
nsresult rv = NS_NewThread(getter_AddRefs(thread), nullptr, aStackSize);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
nsCOMPtr<nsIRunnable> ignoreme = new IgnoreThreadStatusRunnable();
rv = thread->Dispatch(ignoreme, NS_DISPATCH_NORMAL);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
if (aEvent) {
rv = thread->Dispatch(aEvent, NS_DISPATCH_NORMAL);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
}
*aResult = nullptr;
thread.swap(*aResult);
return rv;
#else
return NS_NewThread(aResult, aEvent, aStackSize);
#endif
}
NS_METHOD
NS_GetCurrentThread(nsIThread** aResult)
{

View File

@ -61,17 +61,6 @@ NS_NewThread(nsIThread** aResult,
nsIRunnable* aInitialEvent = nullptr,
uint32_t aStackSize = nsIThreadManager::DEFAULT_STACK_SIZE);
/**
* Create a new thread that is ignored in thread status monitoring by default on
* platforms with Nuwa process enabled. On non-Nuwa platforms, this function is
* identical to NS_NewThread().
*/
extern NS_METHOD
NS_NewUnmonitoredThread(nsIThread** aResult,
nsIRunnable* aInitialEvent = nullptr,
uint32_t aStackSize =
nsIThreadManager::DEFAULT_STACK_SIZE);
/**
* Creates a named thread, otherwise the same as NS_NewThread
*/