mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 378866, r=peterv,sicking, sr=sicking, a=blocking1.9+
This commit is contained in:
parent
81ab1860c1
commit
045c845b71
@ -98,8 +98,10 @@ enum {
|
||||
NODE_MAY_HAVE_CLASS = 0x00000400U,
|
||||
NODE_MAY_HAVE_STYLE = 0x00000800U,
|
||||
|
||||
NODE_IS_INSERTION_PARENT = 0x00001000U,
|
||||
|
||||
// Four bits for the script-type ID
|
||||
NODE_SCRIPT_TYPE_OFFSET = 12,
|
||||
NODE_SCRIPT_TYPE_OFFSET = 13,
|
||||
|
||||
NODE_SCRIPT_TYPE_SIZE = 4,
|
||||
|
||||
|
@ -87,6 +87,10 @@
|
||||
// = nsAnonymousContentList
|
||||
// ==================================================================
|
||||
|
||||
#define NS_ANONYMOUS_CONTENT_LIST_IID \
|
||||
{ 0xa29df1f8, 0xaeca, 0x4356, \
|
||||
{ 0xa8, 0xc2, 0xa7, 0x24, 0xa2, 0x11, 0x73, 0xac } }
|
||||
|
||||
class nsAnonymousContentList : public nsIDOMNodeList
|
||||
{
|
||||
public:
|
||||
@ -102,11 +106,14 @@ public:
|
||||
|
||||
nsXBLInsertionPoint* GetInsertionPointAt(PRInt32 i) { return static_cast<nsXBLInsertionPoint*>(mElements->ElementAt(i)); }
|
||||
void RemoveInsertionPointAt(PRInt32 i) { mElements->RemoveElementAt(i); }
|
||||
|
||||
NS_DECLARE_STATIC_IID_ACCESSOR(NS_ANONYMOUS_CONTENT_LIST_IID)
|
||||
private:
|
||||
nsInsertionPointList* mElements;
|
||||
};
|
||||
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(nsAnonymousContentList,
|
||||
NS_ANONYMOUS_CONTENT_LIST_IID)
|
||||
|
||||
nsAnonymousContentList::nsAnonymousContentList(nsInsertionPointList* aElements)
|
||||
: mElements(aElements)
|
||||
{
|
||||
@ -129,6 +136,7 @@ NS_IMPL_CYCLE_COLLECTING_RELEASE(nsAnonymousContentList)
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN(nsAnonymousContentList)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIDOMNodeList)
|
||||
NS_INTERFACE_MAP_ENTRY(nsAnonymousContentList)
|
||||
NS_INTERFACE_MAP_ENTRY(nsISupports)
|
||||
NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(NodeList)
|
||||
NS_INTERFACE_MAP_ENTRIES_CYCLE_COLLECTION(nsAnonymousContentList)
|
||||
@ -299,8 +307,17 @@ SetOrRemoveObject(PLDHashTable& table, nsIContent* aKey, nsISupports* aValue)
|
||||
}
|
||||
|
||||
// no value, so remove the key from the table
|
||||
if (table.ops)
|
||||
RemoveObjectEntry(table, aKey);
|
||||
if (table.ops) {
|
||||
ObjectEntry* entry =
|
||||
static_cast<ObjectEntry*>
|
||||
(PL_DHashTableOperate(&table, aKey, PL_DHASH_LOOKUP));
|
||||
if (entry && PL_DHASH_ENTRY_IS_BUSY(entry)) {
|
||||
// Keep key and value alive while removing the entry.
|
||||
nsCOMPtr<nsISupports> key = entry->GetKey();
|
||||
nsCOMPtr<nsISupports> value = entry->GetValue();
|
||||
RemoveObjectEntry(table, aKey);
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -402,12 +419,60 @@ nsBindingManager::~nsBindingManager(void)
|
||||
PL_DHashTableFinish(&mContentListTable);
|
||||
if (mAnonymousNodesTable.ops)
|
||||
PL_DHashTableFinish(&mAnonymousNodesTable);
|
||||
NS_ASSERTION(!mInsertionParentTable.ops || !mInsertionParentTable.entryCount,
|
||||
"Insertion parent table isn't empty!");
|
||||
if (mInsertionParentTable.ops)
|
||||
PL_DHashTableFinish(&mInsertionParentTable);
|
||||
if (mWrapperTable.ops)
|
||||
PL_DHashTableFinish(&mWrapperTable);
|
||||
}
|
||||
|
||||
PLDHashOperator
|
||||
PR_CALLBACK RemoveInsertionParentCB(PLDHashTable* aTable, PLDHashEntryHdr* aEntry,
|
||||
PRUint32 aNumber, void* aArg)
|
||||
{
|
||||
return (static_cast<ObjectEntry*>(aEntry)->GetValue() ==
|
||||
static_cast<nsISupports*>(aArg)) ? PL_DHASH_REMOVE : PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
static void
|
||||
RemoveInsertionParentForNodeList(nsIDOMNodeList* aList, nsIContent* aParent)
|
||||
{
|
||||
nsCOMPtr<nsAnonymousContentList> list = do_QueryInterface(aList);
|
||||
if (list) {
|
||||
PRInt32 count = list->GetInsertionPointCount();
|
||||
for (PRInt32 i = 0; i < count; ++i) {
|
||||
nsRefPtr<nsXBLInsertionPoint> currPoint = list->GetInsertionPointAt(i);
|
||||
nsCOMPtr<nsIContent> defContent = currPoint->GetDefaultContent();
|
||||
if (defContent) {
|
||||
defContent->UnbindFromTree();
|
||||
}
|
||||
#ifdef DEBUG
|
||||
nsCOMPtr<nsIContent> parent = currPoint->GetInsertionParent();
|
||||
NS_ASSERTION(!parent || parent == aParent, "Wrong insertion parent!");
|
||||
#endif
|
||||
currPoint->ClearInsertionParent();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsBindingManager::RemoveInsertionParent(nsIContent* aParent)
|
||||
{
|
||||
nsCOMPtr<nsIDOMNodeList> contentlist;
|
||||
GetContentListFor(aParent, getter_AddRefs(contentlist));
|
||||
RemoveInsertionParentForNodeList(contentlist, aParent);
|
||||
|
||||
nsCOMPtr<nsIDOMNodeList> anonnodes;
|
||||
GetAnonymousNodesFor(aParent, getter_AddRefs(anonnodes));
|
||||
RemoveInsertionParentForNodeList(anonnodes, aParent);
|
||||
|
||||
if (mInsertionParentTable.ops) {
|
||||
PL_DHashTableEnumerate(&mInsertionParentTable, RemoveInsertionParentCB,
|
||||
static_cast<nsISupports*>(aParent));
|
||||
}
|
||||
}
|
||||
|
||||
nsXBLBinding*
|
||||
nsBindingManager::GetBinding(nsIContent* aContent)
|
||||
{
|
||||
@ -433,8 +498,18 @@ nsBindingManager::SetBinding(nsIContent* aContent, nsXBLBinding* aBinding)
|
||||
// constructor twice (if aBinding inherits from it) or firing its constructor
|
||||
// after aContent has been deleted (if aBinding is null and the content node
|
||||
// dies before we process mAttachedStack).
|
||||
nsXBLBinding* oldBinding = mBindingTable.GetWeak(aContent);
|
||||
nsRefPtr<nsXBLBinding> oldBinding = GetBinding(aContent);
|
||||
if (oldBinding) {
|
||||
if (aContent->HasFlag(NODE_IS_INSERTION_PARENT)) {
|
||||
nsRefPtr<nsXBLBinding> parentBinding =
|
||||
GetBinding(aContent->GetBindingParent());
|
||||
// Clear insertion parent only if we don't have a parent binding which
|
||||
// marked content to be an insertion parent. See also ChangeDocumentFor().
|
||||
if (!parentBinding || !parentBinding->HasInsertionParent(aContent)) {
|
||||
RemoveInsertionParent(aContent);
|
||||
aContent->UnsetFlags(NODE_IS_INSERTION_PARENT);
|
||||
}
|
||||
}
|
||||
mAttachedStack.RemoveElement(oldBinding);
|
||||
}
|
||||
|
||||
@ -471,6 +546,8 @@ nsBindingManager::GetInsertionParent(nsIContent* aContent)
|
||||
nsresult
|
||||
nsBindingManager::SetInsertionParent(nsIContent* aContent, nsIContent* aParent)
|
||||
{
|
||||
NS_ASSERTION(!aParent || aParent->HasFlag(NODE_IS_INSERTION_PARENT),
|
||||
"Insertion parent should have NODE_IS_INSERTION_PARENT flag!");
|
||||
return SetOrRemoveObject(mInsertionParentTable, aContent, aParent);
|
||||
}
|
||||
|
||||
@ -505,6 +582,19 @@ nsBindingManager::ChangeDocumentFor(nsIContent* aContent, nsIDocument* aOldDocum
|
||||
// Hold a ref to the binding so it won't die when we remove it from our
|
||||
// table.
|
||||
nsRefPtr<nsXBLBinding> binding = GetBinding(aContent);
|
||||
if (aContent->HasFlag(NODE_IS_INSERTION_PARENT)) {
|
||||
nsRefPtr<nsXBLBinding> parentBinding = GetBinding(aContent->GetBindingParent());
|
||||
if (parentBinding) {
|
||||
parentBinding->RemoveInsertionParent(aContent);
|
||||
// Clear insertion parent only if we don't have a binding which
|
||||
// marked content to be an insertion parent. See also SetBinding().
|
||||
if (!binding || !binding->HasInsertionParent(aContent)) {
|
||||
RemoveInsertionParent(aContent);
|
||||
aContent->UnsetFlags(NODE_IS_INSERTION_PARENT);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (binding) {
|
||||
binding->ChangeDocument(aOldDocument, aNewDocument);
|
||||
SetBinding(aContent, nsnull);
|
||||
|
@ -235,6 +235,7 @@ protected:
|
||||
|
||||
// MEMBER VARIABLES
|
||||
protected:
|
||||
void RemoveInsertionParent(nsIContent* aParent);
|
||||
// A mapping from nsIContent* to the nsXBLBinding* that is
|
||||
// installed on that element.
|
||||
nsRefPtrHashtable<nsISupportsHashKey,nsXBLBinding> mBindingTable;
|
||||
|
@ -442,6 +442,10 @@ BuildContentLists(nsISupports* aKey,
|
||||
// Figure out the relevant content node.
|
||||
nsXBLInsertionPoint* currPoint = aData->ElementAt(0);
|
||||
nsCOMPtr<nsIContent> parent = currPoint->GetInsertionParent();
|
||||
if (!parent) {
|
||||
data->mRv = NS_ERROR_FAILURE;
|
||||
return PL_DHASH_STOP;
|
||||
}
|
||||
PRInt32 currIndex = currPoint->GetInsertionIndex();
|
||||
|
||||
nsCOMPtr<nsIDOMNodeList> nodeList;
|
||||
@ -526,6 +530,10 @@ RealizeDefaultContent(nsISupports* aKey,
|
||||
// actual default content (through cloning).
|
||||
// Clone this insertion point element.
|
||||
nsCOMPtr<nsIContent> insParent = currPoint->GetInsertionParent();
|
||||
if (!insParent) {
|
||||
data->mRv = NS_ERROR_FAILURE;
|
||||
return PL_DHASH_STOP;
|
||||
}
|
||||
nsIDocument *document = insParent->GetOwnerDoc();
|
||||
if (!document) {
|
||||
data->mRv = NS_ERROR_FAILURE;
|
||||
@ -1326,6 +1334,47 @@ nsXBLBinding::AllowScripts()
|
||||
return NS_SUCCEEDED(rv) && canExecute;
|
||||
}
|
||||
|
||||
void
|
||||
nsXBLBinding::RemoveInsertionParent(nsIContent* aParent)
|
||||
{
|
||||
if (mNextBinding) {
|
||||
mNextBinding->RemoveInsertionParent(aParent);
|
||||
}
|
||||
if (mInsertionPointTable) {
|
||||
nsInsertionPointList* list = nsnull;
|
||||
mInsertionPointTable->Get(aParent, &list);
|
||||
if (list) {
|
||||
PRInt32 count = list->Length();
|
||||
for (PRInt32 i = 0; i < count; ++i) {
|
||||
nsRefPtr<nsXBLInsertionPoint> currPoint = list->ElementAt(i);
|
||||
nsCOMPtr<nsIContent> defContent = currPoint->GetDefaultContent();
|
||||
if (defContent) {
|
||||
defContent->UnbindFromTree();
|
||||
}
|
||||
#ifdef DEBUG
|
||||
nsCOMPtr<nsIContent> parent = currPoint->GetInsertionParent();
|
||||
NS_ASSERTION(!parent || parent == aParent, "Wrong insertion parent!");
|
||||
#endif
|
||||
currPoint->ClearInsertionParent();
|
||||
}
|
||||
mInsertionPointTable->Remove(aParent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsXBLBinding::HasInsertionParent(nsIContent* aParent)
|
||||
{
|
||||
if (mInsertionPointTable) {
|
||||
nsInsertionPointList* list = nsnull;
|
||||
mInsertionPointTable->Get(aParent, &list);
|
||||
if (list) {
|
||||
return PR_TRUE;
|
||||
}
|
||||
}
|
||||
return mNextBinding ? mNextBinding->HasInsertionParent(aParent) : PR_FALSE;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsXBLBinding::GetInsertionPointsFor(nsIContent* aParent,
|
||||
nsInsertionPointList** aResult)
|
||||
@ -1349,6 +1398,9 @@ nsXBLBinding::GetInsertionPointsFor(nsIContent* aParent,
|
||||
*aResult = nsnull;
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
if (aParent) {
|
||||
aParent->SetFlags(NODE_IS_INSERTION_PARENT);
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
|
@ -164,6 +164,9 @@ public:
|
||||
|
||||
PRBool AllowScripts(); // XXX make const
|
||||
|
||||
void RemoveInsertionParent(nsIContent* aParent);
|
||||
PRBool HasInsertionParent(nsIContent* aParent);
|
||||
|
||||
// MEMBER VARIABLES
|
||||
protected:
|
||||
nsAutoRefCnt mRefCnt;
|
||||
|
@ -63,6 +63,8 @@ public:
|
||||
NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS(nsXBLInsertionPoint)
|
||||
|
||||
already_AddRefed<nsIContent> GetInsertionParent();
|
||||
void ClearInsertionParent() { mParentElement = nsnull; }
|
||||
|
||||
PRInt32 GetInsertionIndex() { return mIndex; }
|
||||
|
||||
void SetDefaultContent(nsIContent* aDefaultContent) { mDefaultContent = aDefaultContent; }
|
||||
|
Loading…
Reference in New Issue
Block a user