Bug 965898 - Implement proper behavior for [[Enumerate]] And [[OwnPropertyKeys]]. r=gabor

This commit is contained in:
Bobby Holley 2014-07-29 21:35:31 -07:00
parent ea11a4e359
commit f2b2ae9683
6 changed files with 33 additions and 14 deletions

View File

@ -20,7 +20,6 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=862380
function checkNotEnumerable(obj) {
try {
is(Object.getOwnPropertyNames(obj).length, 0, "Object.getOwnPropertyNames gives empty array");
is(Object.keys(obj).length, 0, "Object.keys gives empty array");
for (var i in obj)
ok(false, "Enumerated something: " + i);

View File

@ -154,15 +154,13 @@ AccessCheck::isCrossOriginAccessPermitted(JSContext *cx, JSObject *wrapperArg, j
if (act == Wrapper::CALL)
return false;
if (act == Wrapper::ENUMERATE)
return true;
RootedId id(cx, idArg);
RootedObject wrapper(cx, wrapperArg);
RootedObject obj(cx, Wrapper::wrappedObject(wrapper));
// For XOWs, we generally want to deny enumerate-like operations, but fail
// silently (see CrossOriginAccessiblePropertiesOnly::deny).
if (act == Wrapper::ENUMERATE)
return false;
const char *name;
const js::Class *clasp = js::GetObjectClass(obj);
MOZ_ASSERT(!XrayUtils::IsXPCWNHolderClass(Jsvalify(clasp)), "shouldn't have a holder here");

View File

@ -219,6 +219,24 @@ CrossOriginXrayWrapper::getPrototypeOf(JSContext *cx, JS::HandleObject wrapper,
return true;
}
bool
CrossOriginXrayWrapper::getOwnPropertyNames(JSContext *cx, JS::Handle<JSObject*> wrapper,
JS::AutoIdVector &props) const
{
// All properties on cross-origin objects are supposed |own|, despite what
// the underlying native object may report. Override the inherited trap to
// avoid passing JSITER_OWNONLY as a flag.
return SecurityXrayDOM::enumerate(cx, wrapper, JSITER_HIDDEN, props);
}
bool
CrossOriginXrayWrapper::enumerate(JSContext *cx, JS::Handle<JSObject*> wrapper,
JS::AutoIdVector &props) const
{
// Cross-origin properties are non-enumerable.
return true;
}
#define XOW FilteringWrapper<CrossOriginXrayWrapper, CrossOriginAccessiblePropertiesOnly>
#define NNXOW FilteringWrapper<CrossCompartmentSecurityWrapper, Opaque>
#define NNXOWC FilteringWrapper<CrossCompartmentSecurityWrapper, OpaqueWithCall>

View File

@ -68,6 +68,11 @@ class CrossOriginXrayWrapper : public SecurityXrayDOM {
JS::Handle<jsid> id,
JS::MutableHandle<JSPropertyDescriptor> desc) const MOZ_OVERRIDE;
virtual bool getOwnPropertyNames(JSContext *cx, JS::Handle<JSObject*> wrapper,
JS::AutoIdVector &props) const MOZ_OVERRIDE;
virtual bool enumerate(JSContext *cx, JS::Handle<JSObject*> wrapper,
JS::AutoIdVector &props) const MOZ_OVERRIDE;
virtual bool getPrototypeOf(JSContext *cx, JS::HandleObject wrapper,
JS::MutableHandleObject protop) const MOZ_OVERRIDE;
};

View File

@ -1912,16 +1912,18 @@ XPCWrappedNativeXrayTraits::enumerateNames(JSContext *cx, HandleObject wrapper,
return false;
}
// Go through the properties we got and enumerate all native ones.
// Go through the properties we found on the underlying object and see if
// they appear on the XrayWrapper. If it throws (which may happen if the
// wrapper is a SecurityWrapper), just clear the exception and move on.
MOZ_ASSERT(!JS_IsExceptionPending(cx));
if (!props.reserve(wnProps.length()))
return false;
for (size_t n = 0; n < wnProps.length(); ++n) {
RootedId id(cx, wnProps[n]);
bool hasProp;
if (!JS_HasPropertyById(cx, wrapper, id, &hasProp))
return false;
if (hasProp)
if (JS_HasPropertyById(cx, wrapper, id, &hasProp) && hasProp)
props.infallibleAppend(id);
JS_ClearPendingException(cx);
}
return true;
}
@ -2669,10 +2671,6 @@ XrayWrapper<Base, Traits>::enumerate(JSContext *cx, HandleObject wrapper, unsign
AutoIdVector &props) const
{
assertEnteredPolicy(cx, wrapper, JSID_VOID, BaseProxyHandler::ENUMERATE);
if (!AccessCheck::wrapperSubsumes(wrapper)) {
JS_ReportError(cx, "Not allowed to enumerate cross origin objects");
return false;
}
// Enumerate expando properties first. Note that the expando object lives
// in the target compartment.

View File

@ -138,6 +138,7 @@ class XrayWrapper : public Base {
protop);
}
protected:
bool enumerate(JSContext *cx, JS::Handle<JSObject*> wrapper, unsigned flags,
JS::AutoIdVector &props) const;
};