mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-26 06:11:37 +00:00
Bug 975277 - Introduce a mechanism to identify instances of standard classes. r=luke
This commit is contained in:
parent
97f387fd67
commit
30907ef9cb
@ -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)
|
||||
{
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user