Bug 851353 - Make sure the incoming node's JSObject is up to date. r=bzbarsky

This commit is contained in:
Blake Kaplan 2013-08-15 14:39:28 -07:00
parent 7a213ce34e
commit f804cb2aec
3 changed files with 40 additions and 3 deletions

View File

@ -116,8 +116,8 @@ typedef CallbackObjectHolder<NodeFilter, nsIDOMNodeFilter> NodeFilterHolder;
} // namespace mozilla
#define NS_IDOCUMENT_IID \
{ 0x62cca591, 0xa030, 0x4117, \
{ 0x9b, 0x80, 0xdc, 0xd3, 0x66, 0xbb, 0xb5, 0x9 } }
{ 0x56a350f4, 0xc286, 0x440c, \
{ 0x85, 0xb1, 0xb6, 0x55, 0x77, 0xeb, 0x63, 0xfd } }
// Flag for AddStyleSheet().
#define NS_STYLESHEET_FROM_CATALOG (1 << 0)
@ -655,6 +655,9 @@ public:
*/
nsresult GetSrcdocData(nsAString& aSrcdocData);
bool DidDocumentOpen() {
return mDidDocumentOpen;
}
protected:
virtual Element *GetRootElementInternal() const = 0;
@ -2338,6 +2341,11 @@ protected:
// Whether the document was created by a srcdoc iframe.
bool mIsSrcdocDocument;
// Records whether we've done a document.open. If this is true, it's possible
// for nodes from this document to have outdated wrappers in their wrapper
// caches.
bool mDidDocumentOpen;
// The document's script global object, the object from which the
// document can get its script context and scope. This is the
// *inner* window object.

View File

@ -1324,6 +1324,25 @@ AdoptNodeIntoOwnerDoc(nsINode *aParent, nsINode *aNode)
return NS_OK;
}
static nsresult
CheckForOutdatedParent(nsINode* aParent, nsINode* aNode)
{
if (JSObject* existingObj = aNode->GetWrapper()) {
nsIGlobalObject* global = aParent->OwnerDoc()->GetScopeObject();
MOZ_ASSERT(global);
if (js::GetGlobalForObjectCrossCompartment(existingObj) !=
global->GetGlobalJSObject()) {
AutoJSContext cx;
JS::Rooted<JSObject*> rooted(cx, existingObj);
nsresult rv = ReparentWrapper(cx, rooted);
NS_ENSURE_SUCCESS(rv, rv);
}
}
return NS_OK;
}
nsresult
nsINode::doInsertChildAt(nsIContent* aKid, uint32_t aIndex,
bool aNotify, nsAttrAndChildArray& aChildArray)
@ -1343,6 +1362,9 @@ nsINode::doInsertChildAt(nsIContent* aKid, uint32_t aIndex,
if (OwnerDoc() != aKid->OwnerDoc()) {
rv = AdoptNodeIntoOwnerDoc(this, aKid);
NS_ENSURE_SUCCESS(rv, rv);
} else if (OwnerDoc()->DidDocumentOpen()) {
rv = CheckForOutdatedParent(this, aKid);
NS_ENSURE_SUCCESS(rv, rv);
}
uint32_t childCount = aChildArray.ChildCount();
@ -1953,11 +1975,16 @@ nsINode::ReplaceOrInsertBefore(bool aReplace, nsINode* aNewChild,
// DocumentType nodes are the only nodes that can have a null
// ownerDocument according to the DOM spec, and we need to allow
// inserting them w/o calling AdoptNode().
if (OwnerDoc() != newContent->OwnerDoc()) {
if (doc != newContent->OwnerDoc()) {
aError = AdoptNodeIntoOwnerDoc(this, aNewChild);
if (aError.Failed()) {
return nullptr;
}
} else if (doc->DidDocumentOpen()) {
aError = CheckForOutdatedParent(this, aNewChild);
if (aError.Failed()) {
return nullptr;
}
}
/*

View File

@ -1681,6 +1681,8 @@ nsHTMLDocument::Open(JSContext* cx,
}
}
mDidDocumentOpen = true;
// Call Reset(), this will now do the full reset
Reset(channel, group);
if (baseURI) {