Fixing bug 321299. Make sure XPConnect wrappers get properly reparented when moving nodes from document to document. r=mrbkap@gmail.com, sr=bzbarsky@mit.edu
git-svn-id: svn://10.0.0.236/trunk@194099 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
parent
11741bca71
commit
197612f082
@ -102,7 +102,7 @@ public:
|
||||
// the actual ownerDocument of aContent may not yet be aNewDocument.
|
||||
// XXXbz but then if it gets wrapped after we do this call but before its
|
||||
// ownerDocument actually changes, things will break...
|
||||
static nsresult ReparentContentWrapper(nsIContent *aContent,
|
||||
static nsresult ReparentContentWrapper(nsIContent *aNode,
|
||||
nsIContent *aNewParent,
|
||||
nsIDocument *aNewDocument,
|
||||
nsIDocument *aOldDocument);
|
||||
@ -790,7 +790,7 @@ private:
|
||||
static nsresult doReparentContentWrapper(nsIContent *aChild,
|
||||
JSContext *cx,
|
||||
JSObject *aOldGlobal,
|
||||
JSObject *parent_obj);
|
||||
JSObject *aNewGlobal);
|
||||
|
||||
static nsresult EnsureStringBundle(PropertiesFile aFile);
|
||||
|
||||
|
||||
@ -91,8 +91,9 @@ class nsIDocumentObserver;
|
||||
|
||||
// IID for the nsIDocument interface
|
||||
#define NS_IDOCUMENT_IID \
|
||||
{ 0xb657335d, 0x43db, 0x41f3, \
|
||||
{ 0x8c, 0xc0, 0xe2, 0x29, 0x88, 0xb5, 0x99, 0x69 } }
|
||||
{ 0xfa567fd5, 0x5220, 0x436c, \
|
||||
{ 0xbe, 0x76, 0xdd, 0x1a, 0x78, 0xfb, 0x8c, 0x1a } }
|
||||
|
||||
|
||||
// Flag for AddStyleSheet().
|
||||
#define NS_STYLESHEET_FROM_CATALOG (1 << 0)
|
||||
@ -477,6 +478,14 @@ public:
|
||||
virtual nsIScriptGlobalObject* GetScriptGlobalObject() const = 0;
|
||||
virtual void SetScriptGlobalObject(nsIScriptGlobalObject* aGlobalObject) = 0;
|
||||
|
||||
/**
|
||||
* Get the object that is used as the scope for all of the content
|
||||
* wrappers whose owner document is this document. Unlike the script
|
||||
* global object, this never changes once it's set. Use this object
|
||||
* when you're trying to find a content wrapper in XPConnect.
|
||||
*/
|
||||
virtual nsIScriptGlobalObject* GetScopeObject() = 0;
|
||||
|
||||
/**
|
||||
* Return the window containing the document (the outer window).
|
||||
*/
|
||||
|
||||
@ -811,38 +811,33 @@ nsContentUtils::InProlog(nsIDOMNode *aNode)
|
||||
|
||||
// static
|
||||
nsresult
|
||||
nsContentUtils::doReparentContentWrapper(nsIContent *aChild,
|
||||
nsContentUtils::doReparentContentWrapper(nsIContent *aNode,
|
||||
JSContext *cx,
|
||||
JSObject *aOldGlobal,
|
||||
JSObject *parent_obj)
|
||||
JSObject *aNewGlobal)
|
||||
{
|
||||
nsCOMPtr<nsIXPConnectJSObjectHolder> old_wrapper;
|
||||
|
||||
nsresult rv;
|
||||
|
||||
rv = sXPConnect->ReparentWrappedNativeIfFound(cx, aOldGlobal, parent_obj,
|
||||
aChild,
|
||||
rv = sXPConnect->ReparentWrappedNativeIfFound(cx, aOldGlobal, aNewGlobal,
|
||||
aNode,
|
||||
getter_AddRefs(old_wrapper));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (!old_wrapper) {
|
||||
// If aChild isn't wrapped none of it's children are wrapped so
|
||||
// there's no need to walk into aChild's children.
|
||||
// Whether or not aChild is already wrapped we must iterate through
|
||||
// its descendants since there's no guarantee that a descendant isn't
|
||||
// wrapped even if this child is not wrapped. That used to be true
|
||||
// when every DOM node's JSObject was parented at the DOM node's
|
||||
// parent's JSObject, but that's no longer the case.
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
JSObject *old;
|
||||
rv = old_wrapper->GetJSObject(&old);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
PRUint32 i, count = aChild->GetChildCount();
|
||||
PRUint32 i, count = aNode->GetChildCount();
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
nsIContent *child = aChild->GetChildAt(i);
|
||||
nsIContent *child = aNode->GetChildAt(i);
|
||||
NS_ENSURE_TRUE(child, NS_ERROR_UNEXPECTED);
|
||||
|
||||
rv = doReparentContentWrapper(child, cx, aOldGlobal, old);
|
||||
rv = doReparentContentWrapper(child, cx, aOldGlobal, aNewGlobal);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
@ -852,18 +847,18 @@ nsContentUtils::doReparentContentWrapper(nsIContent *aChild,
|
||||
static JSContext *
|
||||
GetContextFromDocument(nsIDocument *aDocument, JSObject** aGlobalObject)
|
||||
{
|
||||
nsIScriptGlobalObject *sgo = aDocument->GetScriptGlobalObject();
|
||||
|
||||
nsIScriptGlobalObject *sgo = aDocument->GetScopeObject();
|
||||
if (!sgo) {
|
||||
// No script global, no context.
|
||||
|
||||
*aGlobalObject = nsnull;
|
||||
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
*aGlobalObject = sgo->GetGlobalJSObject();
|
||||
|
||||
nsIScriptContext *scx = sgo->GetContext();
|
||||
|
||||
nsIScriptContext *scx = sgo->GetContext();
|
||||
if (!scx) {
|
||||
// No context left in the old scope...
|
||||
|
||||
@ -884,10 +879,13 @@ nsContentUtils::ReparentContentWrapper(nsIContent *aContent,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (!aOldDocument) {
|
||||
// If we can't find our old document we don't know what our old
|
||||
// scope was so there's no way to find the old wrapper
|
||||
nsIScriptGlobalObject *newSGO = aNewDocument->GetScopeObject();
|
||||
JSObject *newScope;
|
||||
|
||||
// If we can't find our old document we don't know what our old
|
||||
// scope was so there's no way to find the old wrapper, and if there
|
||||
// is no new scope there's no reason to reparent.
|
||||
if (!aOldDocument || !newSGO || !(newScope = newSGO->GetGlobalJSObject())) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -906,41 +904,38 @@ nsContentUtils::ReparentContentWrapper(nsIContent *aContent,
|
||||
JSObject *globalObj;
|
||||
JSContext *cx = GetContextFromDocument(aOldDocument, &globalObj);
|
||||
|
||||
if (!cx || !globalObj) {
|
||||
// No JSContext left in the old scope, or no global object around; can't
|
||||
// find the old wrapper w/o the old context or global object
|
||||
if (!globalObj) {
|
||||
// No global object around; can't find the old wrapper w/o the old
|
||||
// global object
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIXPConnectWrappedNative> wrapper;
|
||||
nsresult rv =
|
||||
sXPConnect->GetWrappedNativeOfNativeObject(cx, globalObj, aContent,
|
||||
NS_GET_IID(nsISupports),
|
||||
getter_AddRefs(wrapper));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (!cx) {
|
||||
JSObject *dummy;
|
||||
cx = GetContextFromDocument(aNewDocument, &dummy);
|
||||
|
||||
if (!wrapper) {
|
||||
// aContent is not wrapped (and thus none of its children are
|
||||
// wrapped) so there's no need to reparent anything.
|
||||
if (!cx) {
|
||||
// No context reachable from the old or new document, use the
|
||||
// calling context, or the safe context if no caller can be
|
||||
// found.
|
||||
|
||||
return NS_OK;
|
||||
sThreadJSContextStack->Peek(&cx);
|
||||
|
||||
if (!cx) {
|
||||
sThreadJSContextStack->GetSafeJSContext(&cx);
|
||||
|
||||
if (!cx) {
|
||||
// No safe context reachable, bail.
|
||||
NS_WARNING("No context reachable in ReparentContentWrapper()!");
|
||||
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Wrap the new parent and reparent aContent. Don't bother using globalObj
|
||||
// here, since it's wrong for the new parent anyway... Luckily, WrapNative
|
||||
// will PreCreate and hence get the right scope.
|
||||
nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
|
||||
rv = sXPConnect->WrapNative(cx, ::JS_GetGlobalObject(cx), new_parent,
|
||||
NS_GET_IID(nsISupports),
|
||||
getter_AddRefs(holder));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
JSObject *obj;
|
||||
rv = holder->GetJSObject(&obj);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return doReparentContentWrapper(aContent, cx, globalObj, obj);
|
||||
return doReparentContentWrapper(aContent, cx, globalObj, newScope);
|
||||
}
|
||||
|
||||
nsIDocShell *
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=2 sw=2 et tw=78: */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
@ -2118,6 +2119,13 @@ nsDocument::GetScriptGlobalObject() const
|
||||
return mScriptGlobalObject;
|
||||
}
|
||||
|
||||
nsIScriptGlobalObject*
|
||||
nsDocument::GetScopeObject()
|
||||
{
|
||||
nsCOMPtr<nsIScriptGlobalObject> scope(do_QueryReferent(mScopeObject));
|
||||
return scope;
|
||||
}
|
||||
|
||||
void
|
||||
nsDocument::SetScriptGlobalObject(nsIScriptGlobalObject *aScriptGlobalObject)
|
||||
{
|
||||
@ -2146,6 +2154,20 @@ nsDocument::SetScriptGlobalObject(nsIScriptGlobalObject *aScriptGlobalObject)
|
||||
|
||||
mScriptGlobalObject = aScriptGlobalObject;
|
||||
|
||||
// The scope object is immutable, only set it once.
|
||||
if (!mScopeObject) {
|
||||
mScopeObject = do_GetWeakReference(aScriptGlobalObject);
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
{
|
||||
nsCOMPtr<nsIScriptGlobalObject> scope = do_QueryReferent(mScopeObject);
|
||||
|
||||
NS_ASSERTION(!aScriptGlobalObject || aScriptGlobalObject == scope,
|
||||
"script global and scope mismatch!");
|
||||
}
|
||||
#endif
|
||||
|
||||
if (mScriptGlobalObject) {
|
||||
// Go back to using the docshell for the layout history state
|
||||
mLayoutHistoryState = nsnull;
|
||||
|
||||
@ -443,6 +443,8 @@ public:
|
||||
virtual nsIScriptGlobalObject* GetScriptGlobalObject() const;
|
||||
virtual void SetScriptGlobalObject(nsIScriptGlobalObject* aGlobalObject);
|
||||
|
||||
virtual nsIScriptGlobalObject* GetScopeObject();
|
||||
|
||||
/**
|
||||
* Return the window containing the document (the outer window).
|
||||
*/
|
||||
@ -742,6 +744,11 @@ protected:
|
||||
// *inner* window object.
|
||||
nsCOMPtr<nsIScriptGlobalObject> mScriptGlobalObject;
|
||||
|
||||
// Weak reference to the scope object (aka the script global object)
|
||||
// that, unlike mScriptGlobalObject, is never unset once set. This
|
||||
// is a weak reference to avoid leaks due to circular references.
|
||||
nsWeakPtr mScopeObject;
|
||||
|
||||
nsCOMPtr<nsIEventListenerManager> mListenerManager;
|
||||
nsCOMPtr<nsIDOMStyleSheetList> mDOMStyleSheets;
|
||||
nsCOMPtr<nsIScriptLoader> mScriptLoader;
|
||||
|
||||
@ -698,6 +698,12 @@ nsGenericDOMDataNode::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
|
||||
new_bits |= mParentPtrBits & nsIContent::kParentBitMask;
|
||||
mParentPtrBits = new_bits;
|
||||
|
||||
nsIDocument *oldOwnerDocument = GetOwnerDoc();
|
||||
nsIDocument *newOwnerDocument;
|
||||
nsNodeInfoManager* nodeInfoManager;
|
||||
|
||||
// XXXbz sXBL/XBL2 issue!
|
||||
|
||||
// Set document
|
||||
if (aDocument) {
|
||||
mParentPtrBits |= PARENT_BIT_INDOCUMENT;
|
||||
@ -705,38 +711,43 @@ nsGenericDOMDataNode::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
|
||||
aDocument->SetBidiEnabled(PR_TRUE);
|
||||
}
|
||||
|
||||
nsIDocument *ownerDocument = GetOwnerDoc();
|
||||
if (aDocument != ownerDocument) {
|
||||
if (ownerDocument && CouldHaveProperties()) {
|
||||
// Copy UserData to the new document.
|
||||
ownerDocument->CopyUserData(this, aDocument);
|
||||
newOwnerDocument = aDocument;
|
||||
nodeInfoManager = newOwnerDocument->NodeInfoManager();
|
||||
} else {
|
||||
newOwnerDocument = aParent->GetOwnerDoc();
|
||||
nodeInfoManager = aParent->NodeInfo()->NodeInfoManager();
|
||||
}
|
||||
|
||||
// Remove all properties.
|
||||
ownerDocument->PropertyTable()->DeleteAllPropertiesFor(this);
|
||||
}
|
||||
|
||||
// get a new nodeinfo
|
||||
nsNodeInfoManager *nodeInfoManager = aDocument->NodeInfoManager();
|
||||
nsCOMPtr<nsINodeInfo> newNodeInfo;
|
||||
// optimize common cases
|
||||
nsIAtom* name = mNodeInfo->NameAtom();
|
||||
if (name == nsLayoutAtoms::textTagName) {
|
||||
newNodeInfo = nodeInfoManager->GetTextNodeInfo();
|
||||
NS_ENSURE_TRUE(newNodeInfo, NS_ERROR_OUT_OF_MEMORY);
|
||||
}
|
||||
else if (name == nsLayoutAtoms::commentTagName) {
|
||||
newNodeInfo = nodeInfoManager->GetCommentNodeInfo();
|
||||
NS_ENSURE_TRUE(newNodeInfo, NS_ERROR_OUT_OF_MEMORY);
|
||||
}
|
||||
else {
|
||||
rv = nodeInfoManager->GetNodeInfo(name,
|
||||
mNodeInfo->GetPrefixAtom(),
|
||||
mNodeInfo->NamespaceID(),
|
||||
getter_AddRefs(newNodeInfo));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
mNodeInfo.swap(newNodeInfo);
|
||||
if (oldOwnerDocument) {
|
||||
if (newOwnerDocument && CouldHaveProperties()) {
|
||||
// Copy UserData to the new document.
|
||||
oldOwnerDocument->CopyUserData(this, newOwnerDocument);
|
||||
}
|
||||
|
||||
// Remove all properties.
|
||||
oldOwnerDocument->PropertyTable()->DeleteAllPropertiesFor(this);
|
||||
}
|
||||
|
||||
if (mNodeInfo->NodeInfoManager() != nodeInfoManager) {
|
||||
nsCOMPtr<nsINodeInfo> newNodeInfo;
|
||||
// optimize common cases
|
||||
nsIAtom* name = mNodeInfo->NameAtom();
|
||||
if (name == nsLayoutAtoms::textTagName) {
|
||||
newNodeInfo = nodeInfoManager->GetTextNodeInfo();
|
||||
NS_ENSURE_TRUE(newNodeInfo, NS_ERROR_OUT_OF_MEMORY);
|
||||
}
|
||||
else if (name == nsLayoutAtoms::commentTagName) {
|
||||
newNodeInfo = nodeInfoManager->GetCommentNodeInfo();
|
||||
NS_ENSURE_TRUE(newNodeInfo, NS_ERROR_OUT_OF_MEMORY);
|
||||
}
|
||||
else {
|
||||
rv = nodeInfoManager->GetNodeInfo(name,
|
||||
mNodeInfo->GetPrefixAtom(),
|
||||
mNodeInfo->NamespaceID(),
|
||||
getter_AddRefs(newNodeInfo));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
mNodeInfo.swap(newNodeInfo);
|
||||
}
|
||||
|
||||
NS_POSTCONDITION(aDocument == GetCurrentDoc(), "Bound to wrong document");
|
||||
|
||||
@ -1775,6 +1775,12 @@ nsGenericElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
|
||||
|
||||
nsresult rv;
|
||||
|
||||
nsIDocument *oldOwnerDocument = GetOwnerDoc();
|
||||
nsIDocument *newOwnerDocument;
|
||||
nsNodeInfoManager* nodeInfoManager;
|
||||
|
||||
// XXXbz sXBL/XBL2 issue!
|
||||
|
||||
// Finally, set the document
|
||||
if (aDocument) {
|
||||
// Notify XBL- & nsIAnonymousContentCreator-generated
|
||||
@ -1789,38 +1795,42 @@ nsGenericElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
|
||||
// Being added to a document.
|
||||
mParentPtrBits |= PARENT_BIT_INDOCUMENT;
|
||||
|
||||
// check the document on the nodeinfo to see whether we need a
|
||||
// new nodeinfo
|
||||
// XXXbz sXBL/XBL2 issue!
|
||||
nsIDocument *ownerDocument = GetOwnerDoc();
|
||||
if (aDocument != ownerDocument) {
|
||||
if (ownerDocument && HasProperties()) {
|
||||
// Copy UserData to the new document.
|
||||
ownerDocument->CopyUserData(this, aDocument);
|
||||
newOwnerDocument = aDocument;
|
||||
nodeInfoManager = newOwnerDocument->NodeInfoManager();
|
||||
} else {
|
||||
newOwnerDocument = aParent->GetOwnerDoc();
|
||||
nodeInfoManager = aParent->NodeInfo()->NodeInfoManager();
|
||||
}
|
||||
|
||||
// Remove all properties.
|
||||
ownerDocument->PropertyTable()->DeleteAllPropertiesFor(this);
|
||||
}
|
||||
// Handle a change in our owner document.
|
||||
|
||||
// get a new nodeinfo
|
||||
nsNodeInfoManager* nodeInfoManager = aDocument->NodeInfoManager();
|
||||
if (nodeInfoManager) {
|
||||
nsCOMPtr<nsINodeInfo> newNodeInfo;
|
||||
rv = nodeInfoManager->GetNodeInfo(mNodeInfo->NameAtom(),
|
||||
mNodeInfo->GetPrefixAtom(),
|
||||
mNodeInfo->NamespaceID(),
|
||||
getter_AddRefs(newNodeInfo));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
NS_ASSERTION(newNodeInfo, "GetNodeInfo lies");
|
||||
mNodeInfo.swap(newNodeInfo);
|
||||
}
|
||||
if (oldOwnerDocument) {
|
||||
if (newOwnerDocument && HasProperties()) {
|
||||
// Copy UserData to the new document.
|
||||
oldOwnerDocument->CopyUserData(this, newOwnerDocument);
|
||||
}
|
||||
|
||||
// set a new nodeinfo on attribute nodes
|
||||
nsDOMSlots *slots = GetExistingDOMSlots();
|
||||
if (slots && slots->mAttributeMap) {
|
||||
rv = slots->mAttributeMap->SetOwnerDocument(aDocument);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
// Remove all properties.
|
||||
oldOwnerDocument->PropertyTable()->DeleteAllPropertiesFor(this);
|
||||
}
|
||||
|
||||
if (mNodeInfo->NodeInfoManager() != nodeInfoManager) {
|
||||
nsCOMPtr<nsINodeInfo> newNodeInfo;
|
||||
rv = nodeInfoManager->GetNodeInfo(mNodeInfo->NameAtom(),
|
||||
mNodeInfo->GetPrefixAtom(),
|
||||
mNodeInfo->NamespaceID(),
|
||||
getter_AddRefs(newNodeInfo));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
NS_ASSERTION(newNodeInfo, "GetNodeInfo lies");
|
||||
mNodeInfo.swap(newNodeInfo);
|
||||
}
|
||||
|
||||
if (newOwnerDocument && newOwnerDocument != oldOwnerDocument) {
|
||||
// set a new nodeinfo on attribute nodes
|
||||
nsDOMSlots *slots = GetExistingDOMSlots();
|
||||
if (slots && slots->mAttributeMap) {
|
||||
rv = slots->mAttributeMap->SetOwnerDocument(newOwnerDocument);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2428,7 +2438,7 @@ nsGenericElement::doRemoveChildAt(PRUint32 aIndex, PRBool aNotify,
|
||||
|
||||
NS_PRECONDITION(aKid && aKid->GetParent() == aParent &&
|
||||
aKid == container->GetChildAt(aIndex) &&
|
||||
container->IndexOf(aKid) == aIndex, "Bogus aKid");
|
||||
container->IndexOf(aKid) == (PRInt32)aIndex, "Bogus aKid");
|
||||
|
||||
mozAutoDocUpdate updateBatch(aDocument, UPDATE_CONTENT_MODEL, aNotify);
|
||||
|
||||
@ -3104,9 +3114,8 @@ nsGenericElement::doReplaceOrInsertBefore(PRBool aReplace,
|
||||
|
||||
/* static */
|
||||
nsresult
|
||||
nsGenericElement::doRemoveChild(nsIDOMNode* aOldChild,
|
||||
nsIContent* aParent, nsIDocument* aDocument,
|
||||
nsIDOMNode** aReturn)
|
||||
nsGenericElement::doRemoveChild(nsIDOMNode* aOldChild, nsIContent* aParent,
|
||||
nsIDocument* aDocument, nsIDOMNode** aReturn)
|
||||
{
|
||||
NS_PRECONDITION(aParent || aDocument, "Must have document if no parent!");
|
||||
NS_PRECONDITION(!aParent || aParent->GetCurrentDoc() == aDocument,
|
||||
@ -3776,7 +3785,7 @@ nsGenericElement::List(FILE* out, PRInt32 aIndent) const
|
||||
mNodeInfo->GetQualifiedName(buf);
|
||||
fputs(NS_LossyConvertUTF16toASCII(buf).get(), out);
|
||||
|
||||
fprintf(out, "@%p", this);
|
||||
fprintf(out, "@%p", (void *)this);
|
||||
|
||||
PRUint32 index, attrcount = mAttrsAndChildren.AttrCount();
|
||||
for (index = 0; index < attrcount; index++) {
|
||||
|
||||
@ -800,56 +800,70 @@ nsXULElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
|
||||
new_bits |= mParentPtrBits & nsIContent::kParentBitMask;
|
||||
mParentPtrBits = new_bits;
|
||||
|
||||
nsIDocument *oldOwnerDocument = GetOwnerDoc();
|
||||
nsIDocument *newOwnerDocument;
|
||||
nsNodeInfoManager* nodeInfoManager;
|
||||
|
||||
// XXXbz sXBL/XBL2 issue!
|
||||
|
||||
// Finally, set the document
|
||||
if (aDocument && aDocument != GetCurrentDoc()) {
|
||||
if (aDocument) {
|
||||
// Notify XBL- & nsIAnonymousContentCreator-generated
|
||||
// anonymous content that the document is changing.
|
||||
// XXXbz ordering issues here? Probably not, since ChangeDocumentFor
|
||||
// is just pretty broken anyway.... Need to get it working.
|
||||
// anonymous content that the document is changing. XXXbz
|
||||
// ordering issues here? Probably not, since
|
||||
// ChangeDocumentFor is just pretty broken anyway.... Need to
|
||||
// get it working.
|
||||
|
||||
// XXXbz XBL doesn't handle this (asserts), and we don't really want
|
||||
// to be doing this during parsing anyway... sort this out.
|
||||
// aDocument->BindingManager()->ChangeDocumentFor(this, nsnull,
|
||||
// aDocument);
|
||||
|
||||
|
||||
// Being added to a document.
|
||||
mParentPtrBits |= PARENT_BIT_INDOCUMENT;
|
||||
|
||||
// check the document on the nodeinfo to see whether we need a
|
||||
// new nodeinfo
|
||||
// XXXbz sXBL/XBL2 issue!
|
||||
nsIDocument *ownerDocument = GetOwnerDoc();
|
||||
if (aDocument != ownerDocument) {
|
||||
if (ownerDocument && HasProperties()) {
|
||||
// Copy UserData to the new document.
|
||||
ownerDocument->CopyUserData(this, aDocument);
|
||||
newOwnerDocument = aDocument;
|
||||
nodeInfoManager = newOwnerDocument->NodeInfoManager();
|
||||
} else {
|
||||
newOwnerDocument = aParent->GetOwnerDoc();
|
||||
nodeInfoManager = aParent->NodeInfo()->NodeInfoManager();
|
||||
}
|
||||
|
||||
// Remove all properties.
|
||||
ownerDocument->PropertyTable()->
|
||||
DeleteAllPropertiesFor(NS_STATIC_CAST(nsINode*, this));
|
||||
}
|
||||
// Handle a change in our owner document.
|
||||
|
||||
// get a new nodeinfo
|
||||
nsNodeInfoManager* nodeInfoManager = aDocument->NodeInfoManager();
|
||||
if (nodeInfoManager) {
|
||||
nsCOMPtr<nsINodeInfo> newNodeInfo;
|
||||
nsresult rv =
|
||||
nodeInfoManager->GetNodeInfo(mNodeInfo->NameAtom(),
|
||||
mNodeInfo->GetPrefixAtom(),
|
||||
mNodeInfo->NamespaceID(),
|
||||
getter_AddRefs(newNodeInfo));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
NS_ASSERTION(newNodeInfo, "GetNodeInfo lies");
|
||||
mNodeInfo.swap(newNodeInfo);
|
||||
}
|
||||
|
||||
// set a new nodeinfo on attribute nodes
|
||||
nsDOMSlots *slots = GetExistingDOMSlots();
|
||||
if (slots && slots->mAttributeMap) {
|
||||
rv = slots->mAttributeMap->SetOwnerDocument(aDocument);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
if (oldOwnerDocument) {
|
||||
if (newOwnerDocument && HasProperties()) {
|
||||
// Copy UserData to the new document.
|
||||
oldOwnerDocument->CopyUserData(this, aDocument);
|
||||
}
|
||||
|
||||
// Remove all properties.
|
||||
oldOwnerDocument->PropertyTable()->
|
||||
DeleteAllPropertiesFor(NS_STATIC_CAST(nsINode*, this));
|
||||
}
|
||||
|
||||
if (mNodeInfo->NodeInfoManager() != nodeInfoManager) {
|
||||
nsCOMPtr<nsINodeInfo> newNodeInfo;
|
||||
nsresult rv =
|
||||
nodeInfoManager->GetNodeInfo(mNodeInfo->NameAtom(),
|
||||
mNodeInfo->GetPrefixAtom(),
|
||||
mNodeInfo->NamespaceID(),
|
||||
getter_AddRefs(newNodeInfo));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
NS_ASSERTION(newNodeInfo, "GetNodeInfo lies");
|
||||
mNodeInfo.swap(newNodeInfo);
|
||||
}
|
||||
|
||||
if (newOwnerDocument && newOwnerDocument != oldOwnerDocument) {
|
||||
// set a new nodeinfo on attribute nodes
|
||||
nsDOMSlots *slots = GetExistingDOMSlots();
|
||||
if (slots && slots->mAttributeMap) {
|
||||
rv = slots->mAttributeMap->SetOwnerDocument(newOwnerDocument);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
}
|
||||
|
||||
if (aDocument) {
|
||||
// we need to (re-)initialize several attributes that are dependant on
|
||||
// the document. Do that now.
|
||||
// XXXbz why do we have attributes depending on the current document?
|
||||
|
||||
@ -6419,9 +6419,8 @@ nsNodeSH::PreCreate(nsISupports *nativeObj, JSContext *cx, JSObject *globalObj,
|
||||
// set the parent to be the document's global object, if there
|
||||
// is one
|
||||
|
||||
// Get the script global object from the document.
|
||||
|
||||
native_parent = doc->GetScriptGlobalObject();
|
||||
// Get the scope object from the document.
|
||||
native_parent = doc->GetScopeObject();
|
||||
|
||||
if (!native_parent) {
|
||||
// No global object reachable from this document, use the
|
||||
|
||||
@ -1123,7 +1123,8 @@ XPCWrappedNative::ReparentWrapperIfFound(XPCCallContext& ccx,
|
||||
wrapper->mScriptableInfo = newProto->GetScriptableInfo();
|
||||
}
|
||||
|
||||
NS_ASSERTION(!newMap->Find(wrapper), "wrapper already in new scope!");
|
||||
NS_ASSERTION(!newMap->Find(wrapper->GetIdentityObject()),
|
||||
"wrapper already in new scope!");
|
||||
|
||||
(void) newMap->Add(wrapper);
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user