mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-18 15:55:36 +00:00
Bug 1404107 - Fix cloning expando chains when reparenting DOM objects. r=bz,r=mrbkap
--HG-- extra : rebase_source : fac045a54af8fba9e3ac46012aaf3b8a4b7b480c extra : source : 53838f13462feb5db5542ee6d5bc7e24172fb51f
This commit is contained in:
parent
49b9ec94b3
commit
f719f95f29
@ -2259,19 +2259,10 @@ ReparentWrapper(JSContext* aCx, JS::Handle<JSObject*> aObjArg, ErrorResult& aErr
|
||||
propertyHolder = nullptr;
|
||||
}
|
||||
|
||||
// Expandos from other compartments are attached to the target JS object.
|
||||
// Copy them over, and let the old ones die a natural death.
|
||||
|
||||
// Note that at this point the DOM_OBJECT_SLOT for |newobj| has not been set.
|
||||
// CloneExpandoChain() will use this property of |newobj| when it calls
|
||||
// preserveWrapper() via attachExpandoObject() if |aObj| has expandos set, and
|
||||
// preserveWrapper() will not do anything in this case. This is safe because
|
||||
// if expandos are present then the wrapper will already have been preserved
|
||||
// for this native.
|
||||
if (!xpc::XrayUtils::CloneExpandoChain(aCx, newobj, aObj)) {
|
||||
aError.StealExceptionFromJSContext(aCx);
|
||||
return;
|
||||
}
|
||||
// Grab a reference to the chain of objects that carry aObj's Xray expando
|
||||
// properties (from all compartments). Transplanting will blow this away;
|
||||
// we'll restore it manually afterwards.
|
||||
JS::Rooted<JSObject*> expandoChain(aCx, xpc::XrayUtils::GetExpandoChain(aObj));
|
||||
|
||||
// We've set up |newobj|, so we make it own the native by setting its reserved
|
||||
// slot and nulling out the reserved slot of |obj|.
|
||||
@ -2288,6 +2279,14 @@ ReparentWrapper(JSContext* aCx, JS::Handle<JSObject*> aObjArg, ErrorResult& aErr
|
||||
MOZ_CRASH();
|
||||
}
|
||||
|
||||
// Copy Xray expando properties to the new wrapper.
|
||||
if (!xpc::XrayUtils::CloneExpandoChain(aCx, aObj, expandoChain)) {
|
||||
// Failure here means some expandos were not copied over. The object graph
|
||||
// and the Xray machinery are left in a consistent state, but mysteriously
|
||||
// losing these expandos is too weird to allow.
|
||||
MOZ_CRASH();
|
||||
}
|
||||
|
||||
nsWrapperCache* cache = nullptr;
|
||||
CallQueryInterface(native, &cache);
|
||||
bool preserving = cache->PreservingWrapper();
|
||||
|
@ -1241,30 +1241,12 @@ XrayTraits::ensureExpandoObject(JSContext* cx, HandleObject wrapper,
|
||||
}
|
||||
|
||||
bool
|
||||
XrayTraits::cloneExpandoChain(JSContext* cx, HandleObject dst, HandleObject src)
|
||||
XrayTraits::cloneExpandoChain(JSContext* cx, HandleObject dst, HandleObject srcChain)
|
||||
{
|
||||
MOZ_ASSERT(js::IsObjectInContextCompartment(dst, cx));
|
||||
MOZ_ASSERT(getExpandoChain(dst) == nullptr);
|
||||
|
||||
RootedObject oldHead(cx, getExpandoChain(src));
|
||||
|
||||
#ifdef DEBUG
|
||||
// When this is called from dom::ReparentWrapper() there will be no native
|
||||
// set for |dst|. Eventually it will be set to that of |src|. This will
|
||||
// prevent attachExpandoObject() from preserving the wrapper, but this is
|
||||
// not a problem because in this case the wrapper will already have been
|
||||
// preserved when expandos were originally added to |src|. Assert the
|
||||
// wrapper for |src| has been preserved if it has expandos set.
|
||||
if (oldHead) {
|
||||
nsISupports* identity = mozilla::dom::UnwrapDOMObjectToISupports(src);
|
||||
if (identity) {
|
||||
nsWrapperCache* cache = nullptr;
|
||||
CallQueryInterface(identity, &cache);
|
||||
MOZ_ASSERT_IF(cache, cache->PreservingWrapper());
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
RootedObject oldHead(cx, srcChain);
|
||||
while (oldHead) {
|
||||
RootedObject exclusive(cx, JS_GetReservedSlot(oldHead,
|
||||
JSSLOT_EXPANDO_EXCLUSIVE_GLOBAL)
|
||||
@ -1318,11 +1300,14 @@ XrayTraits::getExpandoClass(JSContext* cx, HandleObject target) const
|
||||
}
|
||||
|
||||
namespace XrayUtils {
|
||||
bool CloneExpandoChain(JSContext* cx, JSObject* dstArg, JSObject* srcArg)
|
||||
JSObject* GetExpandoChain(HandleObject target)
|
||||
{
|
||||
RootedObject dst(cx, dstArg);
|
||||
RootedObject src(cx, srcArg);
|
||||
return GetXrayTraits(src)->cloneExpandoChain(cx, dst, src);
|
||||
return GetXrayTraits(target)->getExpandoChain(target);
|
||||
}
|
||||
|
||||
bool CloneExpandoChain(JSContext* cx, HandleObject dst, HandleObject srcChain)
|
||||
{
|
||||
return GetXrayTraits(dst)->cloneExpandoChain(cx, dst, srcChain);
|
||||
}
|
||||
} // namespace XrayUtils
|
||||
|
||||
|
@ -35,9 +35,14 @@ namespace xpc {
|
||||
|
||||
namespace XrayUtils {
|
||||
|
||||
bool IsXPCWNHolderClass(const JSClass* clasp);
|
||||
bool
|
||||
IsXPCWNHolderClass(const JSClass* clasp);
|
||||
|
||||
bool CloneExpandoChain(JSContext* cx, JSObject* src, JSObject* dst);
|
||||
JSObject*
|
||||
GetExpandoChain(JS::HandleObject target);
|
||||
|
||||
bool
|
||||
CloneExpandoChain(JSContext* cx, JS::HandleObject dst, JS::HandleObject srcChain);
|
||||
|
||||
bool
|
||||
IsTransparent(JSContext* cx, JS::HandleObject wrapper, JS::HandleId id);
|
||||
@ -114,7 +119,7 @@ public:
|
||||
|
||||
JSObject* getExpandoChain(JS::HandleObject obj);
|
||||
bool setExpandoChain(JSContext* cx, JS::HandleObject obj, JS::HandleObject chain);
|
||||
bool cloneExpandoChain(JSContext* cx, JS::HandleObject dst, JS::HandleObject src);
|
||||
bool cloneExpandoChain(JSContext* cx, JS::HandleObject dst, JS::HandleObject srcChain);
|
||||
|
||||
protected:
|
||||
static const JSClass HolderClass;
|
||||
|
Loading…
Reference in New Issue
Block a user