Bug 946906 part 6. Clear the relevant slots on Xray expandos when clearing cached slots on a DOM object. r=bholley

This commit is contained in:
Boris Zbarsky 2016-10-10 18:16:26 -04:00
parent 8070de70a2
commit fba67a8141
3 changed files with 46 additions and 0 deletions

View File

@ -36,6 +36,11 @@ def memberReservedSlot(member, descriptor):
member.slotIndices[descriptor.interface.identifier.name])
def memberXrayExpandoReservedSlot(member, descriptor):
return ("(xpc::JSSLOT_EXPANDO_COUNT + %d)" %
member.slotIndices[descriptor.interface.identifier.name])
def toStringBool(arg):
return str(not not arg).lower()
@ -3889,6 +3894,16 @@ class CGClearCachedValueMethod(CGAbstractMethod):
saveMember = ""
regetMember = ""
if self.descriptor.wantsXrays:
clearXrayExpandoSlots = fill(
"""
xpc::ClearXrayExpandoSlots(obj, ${xraySlotIndex});
""",
xraySlotIndex=memberXrayExpandoReservedSlot(self.member,
self.descriptor))
else :
clearXrayExpandoSlots = ""
return fill(
"""
$*{declObj}
@ -3898,12 +3913,14 @@ class CGClearCachedValueMethod(CGAbstractMethod):
}
$*{saveMember}
js::SetReservedSlot(obj, ${slotIndex}, JS::UndefinedValue());
$*{clearXrayExpandoSlots}
$*{regetMember}
""",
declObj=declObj,
noopRetval=noopRetval,
saveMember=saveMember,
slotIndex=slotIndex,
clearXrayExpandoSlots=clearXrayExpandoSlots,
regetMember=regetMember)

View File

@ -11,6 +11,7 @@
#include "nsDependentString.h"
#include "nsIScriptError.h"
#include "mozilla/dom/Element.h"
#include "mozilla/dom/ScriptSettings.h"
#include "XPCWrapper.h"
#include "xpcprivate.h"
@ -1249,6 +1250,26 @@ XrayTraits::cloneExpandoChain(JSContext* cx, HandleObject dst, HandleObject src)
return true;
}
void
ClearXrayExpandoSlots(JSObject* target, size_t slotIndex)
{
if (!NS_IsMainThread()) {
// No Xrays
return;
}
MOZ_ASSERT(GetXrayTraits(target) == &DOMXrayTraits::singleton);
RootingContext* rootingCx = RootingCx();
RootedObject rootedTarget(rootingCx, target);
RootedObject head(rootingCx,
DOMXrayTraits::singleton.getExpandoChain(rootedTarget));
while (head) {
MOZ_ASSERT(JSCLASS_RESERVED_SLOTS(js::GetObjectClass(head)) > slotIndex);
js::SetReservedSlot(head, slotIndex, UndefinedValue());
head = js::GetReservedSlot(head, JSSLOT_EXPANDO_NEXT).toObjectOrNull();
}
}
const JSClass*
XrayTraits::getExpandoClass(JSContext* cx, HandleObject target) const
{

View File

@ -596,6 +596,14 @@ enum ExpandoSlots {
extern const JSClassOps XrayExpandoObjectClassOps;
/*
* Clear the given slot on all Xray expandos for the given object.
*
* No-op when called on non-main threads (where Xrays don't exist).
*/
void
ClearXrayExpandoSlots(JSObject* target, size_t slotIndex);
} // namespace xpc
#endif