Bug 1466991 - Part 2: Reparent nodes when they start being in the XBL scope.

This commit is contained in:
wolfbeast 2018-09-11 15:38:13 +02:00 committed by Roy Tam
commit 2f2751e46c

View file

@ -27,6 +27,7 @@
#include "mozilla/dom/Element.h"
#include "mozilla/dom/Event.h"
#include "mozilla/dom/ShadowRoot.h"
#include "mozilla/dom/ScriptSettings.h"
#include "nsAttrValueOrString.h"
#include "nsBindingManager.h"
#include "nsCCUncollectableMarker.h"
@ -1569,6 +1570,48 @@ CheckForOutdatedParent(nsINode* aParent, nsINode* aNode)
return NS_OK;
}
static nsresult
ReparentWrappersInSubtree(nsIContent* aRoot)
{
MOZ_ASSERT(ShouldUseXBLScope(aRoot));
// Start off with no global so we don't fire any error events on failure.
AutoJSAPI jsapi;
jsapi.Init();
JSContext* cx = jsapi.cx();
nsIGlobalObject* docGlobal = aRoot->OwnerDoc()->GetScopeObject();
if (NS_WARN_IF(!docGlobal)) {
return NS_ERROR_UNEXPECTED;
}
JS::Rooted<JSObject*> rootedGlobal(cx, docGlobal->GetGlobalJSObject());
if (NS_WARN_IF(!rootedGlobal)) {
return NS_ERROR_UNEXPECTED;
}
rootedGlobal = xpc::GetXBLScope(cx, rootedGlobal);
nsresult rv;
JS::Rooted<JSObject*> reflector(cx);
for (nsIContent* cur = aRoot; cur; cur = cur->GetNextNode(aRoot)) {
if ((reflector = cur->GetWrapper())) {
JSAutoCompartment ac(cx, reflector);
rv = ReparentWrapper(cx, reflector);
if NS_FAILED(rv) {
// We _could_ consider BlastSubtreeToPieces here, but it's not really
// needed. Having some nodes in here accessible to content while others
// are not is probably OK. We just need to fail out of the actual
// insertion, so they're not in the DOM. Returning a failure here will
// do that.
return rv;
}
}
}
return NS_OK;
}
nsresult
nsINode::doInsertChildAt(nsIContent* aKid, uint32_t aIndex,
bool aNotify, nsAttrAndChildArray& aChildArray)
@ -1606,9 +1649,15 @@ nsINode::doInsertChildAt(nsIContent* aKid, uint32_t aIndex,
nsIContent* parent =
IsNodeOfType(eDOCUMENT) ? nullptr : static_cast<nsIContent*>(this);
bool wasInXBLScope = ShouldUseXBLScope(aKid);
rv = aKid->BindToTree(doc, parent,
parent ? parent->GetBindingParent() : nullptr,
true);
if (NS_SUCCEEDED(rv) && !wasInXBLScope && ShouldUseXBLScope(aKid)) {
MOZ_ASSERT(ShouldUseXBLScope(this),
"Why does the kid need to use an XBL scope?");
rv = ReparentWrappersInSubtree(aKid);
}
if (NS_FAILED(rv)) {
if (GetFirstChild() == aKid) {
mFirstChild = aKid->GetNextSibling();