Bug 655649 - Introduce an API to recompute wrappers based on various filters. r=billm

This commit is contained in:
Bobby Holley 2012-07-04 12:13:01 +02:00
parent 4624f40980
commit 73a191f725
2 changed files with 80 additions and 0 deletions

View File

@ -1189,3 +1189,45 @@ js::RemapAllWrappersForObject(JSContext *cx, JSObject *oldTarget,
return true;
}
JS_FRIEND_API(bool)
js::RecomputeWrappers(JSContext *cx, const CompartmentFilter &sourceFilter,
const CompartmentFilter &targetFilter)
{
AutoValueVector toRecompute(cx);
for (CompartmentsIter c(cx->runtime); !c.done(); c.next()) {
// Filter by source compartment.
if (!sourceFilter.match(c))
continue;
// Iterate over the wrappers, filtering appropriately.
WrapperMap &pmap = c->crossCompartmentWrappers;
for (WrapperMap::Enum e(pmap); !e.empty(); e.popFront()) {
// Filter out non-objects.
const CrossCompartmentKey &k = e.front().key;
if (k.kind != CrossCompartmentKey::ObjectWrapper)
continue;
// Filter by target compartment.
Value wrapper = e.front().value.get();
if (!targetFilter.match(k.wrapped->compartment()))
continue;
// Add it to the list.
if (!toRecompute.append(wrapper))
return false;
}
}
// Recompute all the wrappers in the list.
for (Value *begin = toRecompute.begin(), *end = toRecompute.end(); begin != end; ++begin)
{
JSObject *wrapper = &begin->toObject();
JSObject *wrapped = Wrapper::wrappedObject(wrapper);
if (!RemapWrapper(cx, wrapper, wrapped))
return false;
}
return true;
}

View File

@ -340,6 +340,44 @@ RemapWrapper(JSContext *cx, JSObject *wobj, JSObject *newTarget);
bool
RemapAllWrappersForObject(JSContext *cx, JSObject *oldTarget,
JSObject *newTarget);
// API to recompute all cross-compartment wrappers whose source and target
// match the given filters.
//
// These filters are designed to be ephemeral stack classes, and thus don't
// do any rooting or holding of their members.
struct CompartmentFilter {
virtual bool match(JSCompartment *c) const = 0;
};
struct AllCompartments : public CompartmentFilter {
virtual bool match(JSCompartment *c) const { return true; };
};
struct ContentCompartmentsOnly : public CompartmentFilter {
virtual bool match(JSCompartment *c) const {
return !IsSystemCompartment(c);
};
};
struct SingleCompartment : public CompartmentFilter {
JSCompartment *ours;
SingleCompartment(JSCompartment *c) : ours(c) {};
virtual bool match(JSCompartment *c) const { return c == ours; };
};
struct CompartmentsWithPrincipals : public CompartmentFilter {
JSPrincipals *principals;
CompartmentsWithPrincipals(JSPrincipals *p) : principals(p) {};
virtual bool match(JSCompartment *c) const {
return JS_GetCompartmentPrincipals(c) == principals;
};
};
JS_FRIEND_API(bool)
RecomputeWrappers(JSContext *cx, const CompartmentFilter &sourceFilter,
const CompartmentFilter &targetFilter);
} /* namespace js */
#endif