зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1125567 - Simplify FindClassPrototype/FindClassObject machinery. r=Waldo
This commit is contained in:
Родитель
19c6c0b0f3
Коммит
201e79d435
160
js/src/jsobj.cpp
160
js/src/jsobj.cpp
|
@ -1404,6 +1404,90 @@ ClassProtoKeyOrAnonymousOrNull(const js::Class *clasp)
|
||||||
return JSProto_Null;
|
return JSProto_Null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline bool
|
||||||
|
NativeGetPureInline(NativeObject *pobj, Shape *shape, MutableHandleValue vp)
|
||||||
|
{
|
||||||
|
if (shape->hasSlot()) {
|
||||||
|
vp.set(pobj->getSlot(shape->slot()));
|
||||||
|
MOZ_ASSERT(!vp.isMagic());
|
||||||
|
} else {
|
||||||
|
vp.setUndefined();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Fail if we have a custom getter. */
|
||||||
|
return shape->hasDefaultGetter();
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
FindClassPrototype(ExclusiveContext *cx, MutableHandleObject protop, const Class *clasp)
|
||||||
|
{
|
||||||
|
protop.set(nullptr);
|
||||||
|
|
||||||
|
JSAtom *atom = Atomize(cx, clasp->name, strlen(clasp->name));
|
||||||
|
if (!atom)
|
||||||
|
return false;
|
||||||
|
RootedId id(cx, AtomToId(atom));
|
||||||
|
|
||||||
|
RootedObject pobj(cx);
|
||||||
|
RootedShape shape(cx);
|
||||||
|
if (!NativeLookupProperty<CanGC>(cx, cx->global(), id, &pobj, &shape))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
RootedObject ctor(cx);
|
||||||
|
if (shape && pobj->isNative()) {
|
||||||
|
if (shape->hasSlot()) {
|
||||||
|
RootedValue v(cx, pobj->as<NativeObject>().getSlot(shape->slot()));
|
||||||
|
if (v.isObject())
|
||||||
|
ctor.set(&v.toObject());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ctor && ctor->is<JSFunction>()) {
|
||||||
|
JSFunction *nctor = &ctor->as<JSFunction>();
|
||||||
|
RootedValue v(cx);
|
||||||
|
if (cx->isJSContext()) {
|
||||||
|
if (!GetProperty(cx->asJSContext(), ctor, ctor, cx->names().prototype, &v))
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
Shape *shape = nctor->lookup(cx, cx->names().prototype);
|
||||||
|
if (!shape || !NativeGetPureInline(nctor, shape, &v))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (v.isObject())
|
||||||
|
protop.set(&v.toObject());
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find the appropriate proto for a class. There are three different ways to achieve this:
|
||||||
|
// 1. Built-in classes have a cached proto and anonymous classes get Object.prototype.
|
||||||
|
// 2. Lookup global[clasp->name].prototype
|
||||||
|
// 3. Fallback to Object.prototype
|
||||||
|
//
|
||||||
|
// Step 2 is in some circumstances an observable operation, which is probably wrong
|
||||||
|
// as a matter of specifications. It's legacy garbage that we're working to remove eventually.
|
||||||
|
static bool
|
||||||
|
FindProto(ExclusiveContext *cx, const js::Class *clasp, MutableHandleObject proto)
|
||||||
|
{
|
||||||
|
JSProtoKey protoKey = ClassProtoKeyOrAnonymousOrNull(clasp);
|
||||||
|
if (protoKey != JSProto_Null)
|
||||||
|
return GetBuiltinPrototype(cx, protoKey, proto);
|
||||||
|
|
||||||
|
if (!FindClassPrototype(cx, proto, clasp))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!proto) {
|
||||||
|
// We're looking for the prototype of a class that is currently being
|
||||||
|
// resolved; the global object's resolve hook is on the
|
||||||
|
// stack. js::FindClassPrototype detects this goofy case and returns
|
||||||
|
// true with proto null. Fall back on Object.prototype.
|
||||||
|
MOZ_ASSERT(JSCLASS_CACHED_PROTO_KEY(clasp) == JSProto_Null);
|
||||||
|
return GetBuiltinPrototype(cx, JSProto_Object, proto);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
JSObject *
|
JSObject *
|
||||||
js::NewObjectWithClassProtoCommon(ExclusiveContext *cxArg,
|
js::NewObjectWithClassProtoCommon(ExclusiveContext *cxArg,
|
||||||
const js::Class *clasp, JSObject *protoArg, JSObject *parentArg,
|
const js::Class *clasp, JSObject *protoArg, JSObject *parentArg,
|
||||||
|
@ -2779,35 +2863,6 @@ JS::IdentifyStandardConstructor(JSObject *obj)
|
||||||
return JSProto_Null;
|
return JSProto_Null;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
|
||||||
js::FindClassObject(ExclusiveContext *cx, MutableHandleObject protop, const Class *clasp)
|
|
||||||
{
|
|
||||||
JSProtoKey protoKey = ClassProtoKeyOrAnonymousOrNull(clasp);
|
|
||||||
if (protoKey != JSProto_Null) {
|
|
||||||
MOZ_ASSERT(JSProto_Null < protoKey);
|
|
||||||
MOZ_ASSERT(protoKey < JSProto_LIMIT);
|
|
||||||
return GetBuiltinConstructor(cx, protoKey, protop);
|
|
||||||
}
|
|
||||||
|
|
||||||
JSAtom *atom = Atomize(cx, clasp->name, strlen(clasp->name));
|
|
||||||
if (!atom)
|
|
||||||
return false;
|
|
||||||
RootedId id(cx, AtomToId(atom));
|
|
||||||
|
|
||||||
RootedObject pobj(cx);
|
|
||||||
RootedShape shape(cx);
|
|
||||||
if (!NativeLookupProperty<CanGC>(cx, cx->global(), id, &pobj, &shape))
|
|
||||||
return false;
|
|
||||||
RootedValue v(cx);
|
|
||||||
if (shape && pobj->isNative()) {
|
|
||||||
if (shape->hasSlot())
|
|
||||||
v = pobj->as<NativeObject>().getSlot(shape->slot());
|
|
||||||
}
|
|
||||||
if (v.isObject())
|
|
||||||
protop.set(&v.toObject());
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
JSObject::isCallable() const
|
JSObject::isCallable() const
|
||||||
{
|
{
|
||||||
|
@ -3050,20 +3105,6 @@ LookupPropertyPureInline(ExclusiveContext *cx, JSObject *obj, jsid id, NativeObj
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static MOZ_ALWAYS_INLINE bool
|
|
||||||
NativeGetPureInline(NativeObject *pobj, Shape *shape, Value *vp)
|
|
||||||
{
|
|
||||||
if (shape->hasSlot()) {
|
|
||||||
*vp = pobj->getSlot(shape->slot());
|
|
||||||
MOZ_ASSERT(!vp->isMagic());
|
|
||||||
} else {
|
|
||||||
vp->setUndefined();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Fail if we have a custom getter. */
|
|
||||||
return shape->hasDefaultGetter();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
js::LookupPropertyPure(ExclusiveContext *cx, JSObject *obj, jsid id, NativeObject **objp,
|
js::LookupPropertyPure(ExclusiveContext *cx, JSObject *obj, jsid id, NativeObject **objp,
|
||||||
Shape **propp)
|
Shape **propp)
|
||||||
|
@ -3571,39 +3612,6 @@ js::GetBuiltinPrototypePure(GlobalObject *global, JSProtoKey protoKey)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* The first part of this function has been hand-expanded and optimized into
|
|
||||||
* NewBuiltinClassInstance in jsobjinlines.h.
|
|
||||||
*/
|
|
||||||
bool
|
|
||||||
js::FindClassPrototype(ExclusiveContext *cx, MutableHandleObject protop, const Class *clasp)
|
|
||||||
{
|
|
||||||
protop.set(nullptr);
|
|
||||||
JSProtoKey protoKey = ClassProtoKeyOrAnonymousOrNull(clasp);
|
|
||||||
if (protoKey != JSProto_Null)
|
|
||||||
return GetBuiltinPrototype(cx, protoKey, protop);
|
|
||||||
|
|
||||||
RootedObject ctor(cx);
|
|
||||||
if (!FindClassObject(cx, &ctor, clasp))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (ctor && ctor->is<JSFunction>()) {
|
|
||||||
JSFunction *nctor = &ctor->as<JSFunction>();
|
|
||||||
RootedValue v(cx);
|
|
||||||
if (cx->isJSContext()) {
|
|
||||||
if (!GetProperty(cx->asJSContext(), ctor, ctor, cx->names().prototype, &v))
|
|
||||||
return false;
|
|
||||||
} else {
|
|
||||||
Shape *shape = nctor->lookup(cx, cx->names().prototype);
|
|
||||||
if (!shape || !NativeGetPureInline(nctor, shape, v.address()))
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (v.isObject())
|
|
||||||
protop.set(&v.toObject());
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
JSObject *
|
JSObject *
|
||||||
js::PrimitiveToObject(JSContext *cx, const Value &v)
|
js::PrimitiveToObject(JSContext *cx, const Value &v)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1092,18 +1092,6 @@ extern bool
|
||||||
SetClassAndProto(JSContext *cx, HandleObject obj,
|
SetClassAndProto(JSContext *cx, HandleObject obj,
|
||||||
const Class *clasp, Handle<TaggedProto> proto);
|
const Class *clasp, Handle<TaggedProto> proto);
|
||||||
|
|
||||||
/*
|
|
||||||
* Property-lookup-based access to interface and prototype objects for classes.
|
|
||||||
* If the class is built-in (hhas a non-null JSProtoKey), these forward to
|
|
||||||
* GetClass{Object,Prototype}.
|
|
||||||
*/
|
|
||||||
|
|
||||||
bool
|
|
||||||
FindClassObject(ExclusiveContext *cx, MutableHandleObject protop, const Class *clasp);
|
|
||||||
|
|
||||||
extern bool
|
|
||||||
FindClassPrototype(ExclusiveContext *cx, MutableHandleObject protop, const Class *clasp);
|
|
||||||
|
|
||||||
} /* namespace js */
|
} /* namespace js */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -554,23 +554,6 @@ NewObjectWithGivenProto(ExclusiveContext *cx, JSObject *proto, JSObject *parent,
|
||||||
return obj ? &obj->as<T>() : nullptr;
|
return obj ? &obj->as<T>() : nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool
|
|
||||||
FindProto(ExclusiveContext *cx, const js::Class *clasp, MutableHandleObject proto)
|
|
||||||
{
|
|
||||||
if (!FindClassPrototype(cx, proto, clasp))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (!proto) {
|
|
||||||
// We're looking for the prototype of a class that is currently being
|
|
||||||
// resolved; the global object's resolve hook is on the
|
|
||||||
// stack. js::FindClassPrototype detects this goofy case and returns
|
|
||||||
// true with proto null. Fall back on Object.prototype.
|
|
||||||
MOZ_ASSERT(JSCLASS_CACHED_PROTO_KEY(clasp) == JSProto_Null);
|
|
||||||
return GetBuiltinPrototype(cx, JSProto_Object, proto);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Make an object with the prototype set according to the specified prototype or class:
|
* Make an object with the prototype set according to the specified prototype or class:
|
||||||
*
|
*
|
||||||
|
|
Загрузка…
Ссылка в новой задаче