Bug 975277 - Introduce a mechanism to identify instances of standard classes. r=luke

This commit is contained in:
Bobby Holley 2014-02-21 16:03:11 -08:00
parent 97f387fd67
commit 30907ef9cb
7 changed files with 48 additions and 34 deletions

View File

@ -1352,13 +1352,6 @@ JS_GetClassPrototype(JSContext *cx, JSProtoKey key, MutableHandleObject objp)
return js_GetClassPrototype(cx, key, objp);
}
JS_PUBLIC_API(JSProtoKey)
JS_IdentifyClassPrototype(JSObject *obj)
{
JS_ASSERT(!obj->is<CrossCompartmentWrapperObject>());
return js_IdentifyClassPrototype(obj);
}
extern JS_PUBLIC_API(JSProtoKey)
JS_IdToProtoKey(JSContext *cx, HandleId id)
{

View File

@ -1770,8 +1770,23 @@ JS_GetClassObject(JSContext *cx, JSProtoKey key, JS::MutableHandle<JSObject*> ob
extern JS_PUBLIC_API(bool)
JS_GetClassPrototype(JSContext *cx, JSProtoKey key, JS::MutableHandle<JSObject*> objp);
namespace JS {
/*
* Determine if the given object is an instance or prototype for a standard
* class. If so, return the associated JSProtoKey. If not, return JSProto_Null.
*/
extern JS_PUBLIC_API(JSProtoKey)
JS_IdentifyClassPrototype(JSObject *obj);
IdentifyStandardInstance(JSObject *obj);
extern JS_PUBLIC_API(JSProtoKey)
IdentifyStandardPrototype(JSObject *obj);
extern JS_PUBLIC_API(JSProtoKey)
IdentifyStandardInstanceOrPrototype(JSObject *obj);
} /* namespace JS */
extern JS_PUBLIC_API(JSProtoKey)
JS_IdToProtoKey(JSContext *cx, JS::HandleId id);

View File

@ -3254,29 +3254,42 @@ js_GetClassPrototype(ExclusiveContext *cx, JSProtoKey key, MutableHandleObject p
return true;
}
JSProtoKey
js_IdentifyClassPrototype(JSObject *obj)
static bool
IsStandardPrototype(JSObject *obj, JSProtoKey key)
{
// First, get the key off the JSClass. This tells us which prototype we
// _might_ be. But we still don't know for sure, since the prototype shares
// its JSClass with instances.
JSProtoKey key = JSCLASS_CACHED_PROTO_KEY(obj->getClass());
if (key == JSProto_Null)
return JSProto_Null;
// Now, see if the cached object matches |obj|.
//
// Note that standard class objects are cached in the range [0, JSProto_LIMIT),
// and the prototypes are cached in [JSProto_LIMIT, 2*JSProto_LIMIT).
GlobalObject &global = obj->global();
Value v = global.getPrototype(key);
if (v.isObject() && obj == &v.toObject())
return key;
return v.isObject() && obj == &v.toObject();
}
// False alarm - just an instance.
JSProtoKey
JS::IdentifyStandardInstance(JSObject *obj)
{
// Note: The prototype shares its JSClass with instances.
JS_ASSERT(!obj->is<CrossCompartmentWrapperObject>());
JSProtoKey key = JSCLASS_CACHED_PROTO_KEY(obj->getClass());
if (key != JSProto_Null && !IsStandardPrototype(obj, key))
return key;
return JSProto_Null;
}
JSProtoKey
JS::IdentifyStandardPrototype(JSObject *obj)
{
// Note: The prototype shares its JSClass with instances.
JS_ASSERT(!obj->is<CrossCompartmentWrapperObject>());
JSProtoKey key = JSCLASS_CACHED_PROTO_KEY(obj->getClass());
if (key != JSProto_Null && IsStandardPrototype(obj, key))
return key;
return JSProto_Null;
}
JSProtoKey
JS::IdentifyStandardInstanceOrPrototype(JSObject *obj)
{
return JSCLASS_CACHED_PROTO_KEY(obj->getClass());
}
bool
js_FindClassObject(ExclusiveContext *cx, MutableHandleObject protop, const Class *clasp)
{

View File

@ -1328,13 +1328,6 @@ extern bool
js_GetClassPrototype(js::ExclusiveContext *cx, JSProtoKey key,
js::MutableHandleObject objp);
/*
* Determine if the given object is a prototype for a standard class. If so,
* return the associated JSProtoKey. If not, return JSProto_Null.
*/
extern JSProtoKey
js_IdentifyClassPrototype(JSObject *obj);
/*
* Property-lookup-based access to interface and prototype objects for classes.
* If the class is built-in (and has a non-null JSProtoKey), these forward to

View File

@ -640,7 +640,7 @@ GlobalWorkerThreadState::finishParseTask(JSContext *maybecx, JSRuntime *rt, void
if (!proto.isObject())
continue;
JSProtoKey key = js_IdentifyClassPrototype(proto.toObject());
JSProtoKey key = JS::IdentifyStandardPrototype(proto.toObject());
if (key == JSProto_Null)
continue;

View File

@ -36,7 +36,7 @@ PropIsFromStandardPrototype(JSContext *cx, JS::MutableHandle<JSPropertyDescripto
MOZ_ASSERT(desc.object());
RootedObject unwrapped(cx, js::UncheckedUnwrap(desc.object()));
JSAutoCompartment ac(cx, unwrapped);
return JS_IdentifyClassPrototype(unwrapped) != JSProto_Null;
return IdentifyStandardPrototype(unwrapped) != JSProto_Null;
}
// Note that we're past the policy enforcement stage, here, so we can query

View File

@ -174,7 +174,7 @@ WrapperFactory::PrepareForWrapping(JSContext *cx, HandleObject scope,
JSProtoKey key = JSProto_Null;
{
JSAutoCompartment ac(cx, obj);
key = JS_IdentifyClassPrototype(obj);
key = IdentifyStandardPrototype(obj);
}
if (key != JSProto_Null) {
RootedObject homeProto(cx);