Bug 959012 - Create separate js_GetClassPrototype and js_FindClassPrototype to mimic js_{Get,Find}ClassObject. r=jorendorff

The current behavior is crazy, and most definitely not Xray-safe.
This commit is contained in:
Bobby Holley 2014-01-30 07:45:16 -08:00
parent 9bdb964f42
commit ed1c3f92c1
4 changed files with 58 additions and 31 deletions

View File

@ -1984,7 +1984,7 @@ TypeCompartment::addAllocationSiteTypeObject(JSContext *cx, AllocationSiteKey ke
if (!res) {
RootedObject proto(cx);
if (!js_GetClassPrototype(cx, key.kind, &proto, nullptr))
if (!js_GetClassPrototype(cx, key.kind, &proto))
return nullptr;
Rooted<TaggedProto> tagged(cx, TaggedProto(proto));

View File

@ -3237,21 +3237,28 @@ js::SetClassAndProto(JSContext *cx, HandleObject obj,
return true;
}
bool
js_GetClassObject(ExclusiveContext *cxArg, JSObject *obj, JSProtoKey key, MutableHandleObject objp)
static bool
MaybeResolveConstructor(ExclusiveContext *cxArg, Handle<GlobalObject*> global, JSProtoKey key)
{
Rooted<GlobalObject*> global(cxArg, &obj->global());
if (global->isStandardClassResolved(key))
return true;
if (!cxArg->shouldBeJSContext())
return false;
// We can only resolve constructors with a real JSContext.
if (!global->isStandardClassResolved(key)) {
if (!cxArg->shouldBeJSContext())
return false;
JSContext *cx = cxArg->asJSContext();
RootedId name(cx, NameToId(ClassName(key, cx)));
AutoResolving resolving(cx, global, name);
if (!resolving.alreadyStarted() && !global->ensureConstructor(cx, key))
return false;
}
JSContext *cx = cxArg->asJSContext();
RootedId name(cx, NameToId(ClassName(key, cx)));
AutoResolving resolving(cx, global, name);
if (resolving.alreadyStarted())
return true;
return global->ensureConstructor(cx, key);
}
bool
js_GetClassObject(ExclusiveContext *cx, JSObject *obj, JSProtoKey key, MutableHandleObject objp)
{
Rooted<GlobalObject*> global(cx, &obj->global());
if (!MaybeResolveConstructor(cx, global, key))
return false;
Value v = global->getConstructor(key);
if (v.isObject())
@ -3259,6 +3266,19 @@ js_GetClassObject(ExclusiveContext *cxArg, JSObject *obj, JSProtoKey key, Mutabl
return true;
}
bool
js_GetClassPrototype(ExclusiveContext *cx, JSProtoKey key, MutableHandleObject protop)
{
Rooted<GlobalObject*> global(cx, cx->global());
if (!MaybeResolveConstructor(cx, global, key))
return false;
Value v = global->getPrototype(key);
if (v.isObject())
protop.set(&v.toObject());
return true;
}
JSProtoKey
js_IdentifyClassPrototype(JSObject *obj)
{
@ -5428,12 +5448,14 @@ js::GetClassPrototypePure(GlobalObject *global, JSProtoKey protoKey)
* NewBuiltinClassInstance in jsobjinlines.h.
*/
bool
js_GetClassPrototype(ExclusiveContext *cx, JSProtoKey protoKey,
MutableHandleObject protop, const Class *clasp)
js_FindClassPrototype(ExclusiveContext *cx, JSProtoKey protoKey,
MutableHandleObject protop, const Class *clasp)
{
if (JSObject *proto = GetClassPrototypePure(cx->global(), protoKey)) {
protop.set(proto);
return true;
if (protoKey != JSProto_Null) {
if (!js_GetClassPrototype(cx, protoKey, protop))
return false;
if (protop)
return true;
}
RootedValue v(cx);

View File

@ -1324,6 +1324,10 @@ extern bool
js_GetClassObject(js::ExclusiveContext *cx, JSObject *obj, JSProtoKey key,
js::MutableHandleObject objp);
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.
@ -1339,6 +1343,18 @@ bool
js_FindClassObject(js::ExclusiveContext *cx, JSProtoKey protoKey, js::MutableHandleValue vp,
const js::Class *clasp = nullptr);
/*
* If protoKey is not JSProto_Null, then clasp is ignored. If protoKey is
* JSProto_Null, clasp must non-null.
*
* If protoKey is constant and scope is non-null, use GlobalObject's prototype
* methods instead.
*/
extern bool
js_FindClassPrototype(js::ExclusiveContext *cx, JSProtoKey protoKey, js::MutableHandleObject protop,
const js::Class *clasp = nullptr);
namespace js {
extern bool
@ -1597,17 +1613,6 @@ extern unsigned
js_InferFlags(JSContext *cx, unsigned defaultFlags);
/*
* If protoKey is not JSProto_Null, then clasp is ignored. If protoKey is
* JSProto_Null, clasp must non-null.
*
* If protoKey is constant and scope is non-null, use GlobalObject's prototype
* methods instead.
*/
extern bool
js_GetClassPrototype(js::ExclusiveContext *cx, JSProtoKey protoKey, js::MutableHandleObject protop,
const js::Class *clasp = nullptr);
namespace js {
JSObject *

View File

@ -877,7 +877,7 @@ inline bool
FindProto(ExclusiveContext *cx, const js::Class *clasp, MutableHandleObject proto)
{
JSProtoKey protoKey = GetClassProtoKey(clasp);
if (!js_GetClassPrototype(cx, protoKey, proto, clasp))
if (!js_FindClassPrototype(cx, protoKey, proto, clasp))
return false;
if (!proto && !js_GetClassPrototype(cx, JSProto_Object, proto))
return false;