Bug 751377 - Begin to implement [[GetOwnProperty]] for named properties in the new representation. r=bhackett

--HG--
extra : rebase_source : 87bf1863596e92c987ebc6aeedbd7829fbecfa8f
This commit is contained in:
Jeff Walden 2012-05-17 11:38:25 -07:00
parent 54f304976b
commit 873826e87c
5 changed files with 133 additions and 0 deletions

View File

@ -1235,6 +1235,22 @@ js_IsCallable(const js::Value &v)
namespace js {
PropDesc::PropDesc(const Value &getter, const Value &setter,
Enumerability enumerable, Configurability configurable)
: pd_(UndefinedValue()),
value_(UndefinedValue()),
get_(getter), set_(setter),
attrs(JSPROP_GETTER | JSPROP_SETTER | JSPROP_SHARED |
(enumerable ? JSPROP_ENUMERATE : 0) |
(configurable ? 0 : JSPROP_PERMANENT)),
hasGet_(true), hasSet_(true),
hasValue_(false), hasWritable_(false), hasEnumerable_(true), hasConfigurable_(true),
isUndefined_(false)
{
MOZ_ASSERT(getter.isUndefined() || js_IsCallable(getter));
MOZ_ASSERT(setter.isUndefined() || js_IsCallable(setter));
}
inline JSObject *
GetInnerObject(JSContext *cx, HandleObject obj)
{

View File

@ -780,6 +780,16 @@ struct Shape : public js::gc::Cell
return (attrs & (JSPROP_SETTER | JSPROP_GETTER)) != 0;
}
PropDesc::Writability writability() const {
return (attrs & JSPROP_READONLY) ? PropDesc::NonWritable : PropDesc::Writable;
}
PropDesc::Enumerability enumerability() const {
return (attrs & JSPROP_ENUMERATE) ? PropDesc::Enumerable : PropDesc::NonEnumerable;
}
PropDesc::Configurability configurability() const {
return (attrs & JSPROP_PERMANENT) ? PropDesc::NonConfigurable : PropDesc::Configurable;
}
/*
* For ES5 compatibility, we allow properties with PropertyOp-flavored
* setters to be shadowed when set. The "own" property thereby created in

View File

@ -40,6 +40,32 @@ Debug_SetSlotRangeToCrashOnTouch(HeapSlot *begin, HeapSlot *end)
} // namespace js
inline const js::Shape *
js::ObjectImpl::nativeLookup(JSContext *cx, PropertyId pid)
{
return nativeLookup(cx, pid.asId());
}
inline const js::Shape *
js::ObjectImpl::nativeLookup(JSContext *cx, PropertyName *name)
{
return nativeLookup(cx, PropertyId(name));
}
#ifdef DEBUG
inline const js::Shape *
js::ObjectImpl::nativeLookupNoAllocation(JSContext *cx, PropertyId pid)
{
return nativeLookupNoAllocation(cx, pid.asId());
}
inline const js::Shape *
js::ObjectImpl::nativeLookupNoAllocation(JSContext *cx, PropertyName *name)
{
return nativeLookupNoAllocation(cx, PropertyId(name));
}
#endif
inline bool
js::ObjectImpl::isExtensible() const
{

View File

@ -488,6 +488,64 @@ ArrayBufferElementsHeader::defineElement(JSContext *cx, Handle<ObjectImpl*> obj,
return DefineElement(cx, delegate, index, desc, shouldThrow, resolveFlags, succeeded);
}
bool
js::GetOwnProperty(JSContext *cx, Handle<ObjectImpl*> obj, PropertyId pid_, unsigned resolveFlags,
PropDesc *desc)
{
NEW_OBJECT_REPRESENTATION_ONLY();
JS_CHECK_RECURSION(cx, return false);
Rooted<PropertyId> pid(cx, pid_);
if (static_cast<JSObject *>(obj.value())->isProxy()) {
MOZ_NOT_REACHED("NYI: proxy [[GetOwnProperty]]");
return false;
}
const Shape *shape = obj->nativeLookup(cx, pid);
if (!shape) {
/* Not found: attempt to resolve it. */
Class *clasp = obj->getClass();
JSResolveOp resolve = clasp->resolve;
if (resolve != JS_ResolveStub) {
Rooted<jsid> id(cx, pid.reference().asId());
Rooted<JSObject*> robj(cx, static_cast<JSObject*>(obj.value()));
if (clasp->flags & JSCLASS_NEW_RESOLVE) {
Rooted<JSObject*> obj2(cx, NULL);
JSNewResolveOp op = reinterpret_cast<JSNewResolveOp>(resolve);
if (!op(cx, robj, id, resolveFlags, obj2.address()))
return false;
} else {
if (!resolve(cx, robj, id))
return false;
}
}
/* Now look it up again. */
shape = obj->nativeLookup(cx, pid);
if (!shape) {
desc->setUndefined();
return true;
}
}
if (shape->isDataDescriptor()) {
*desc = PropDesc(obj->nativeGetSlot(shape->slot()), shape->writability(),
shape->enumerability(), shape->configurability());
return true;
}
if (shape->isAccessorDescriptor()) {
*desc = PropDesc(shape->getterValue(), shape->setterValue(),
shape->enumerability(), shape->configurability());
return true;
}
MOZ_NOT_REACHED("NYI: PropertyOp-based properties");
return false;
}
bool
js::GetOwnElement(JSContext *cx, Handle<ObjectImpl*> obj, uint32_t index, unsigned resolveFlags,
PropDesc *desc)

View File

@ -152,6 +152,9 @@ struct PropDesc {
isUndefined_(false)
{}
inline PropDesc(const Value &getter, const Value &setter,
Enumerability enumerable, Configurability configurable);
/*
* 8.10.5 ToPropertyDescriptor(Obj)
*
@ -1136,9 +1139,13 @@ class ObjectImpl : public gc::Cell
inline uint32_t numDynamicSlots() const;
const Shape * nativeLookup(JSContext *cx, jsid id);
inline const Shape * nativeLookup(JSContext *cx, PropertyId pid);
inline const Shape * nativeLookup(JSContext *cx, PropertyName *name);
#ifdef DEBUG
const Shape * nativeLookupNoAllocation(JSContext *cx, jsid id);
inline const Shape * nativeLookupNoAllocation(JSContext *cx, PropertyId pid);
inline const Shape * nativeLookupNoAllocation(JSContext *cx, PropertyName *name);
#endif
inline Class *getClass() const;
@ -1312,9 +1319,25 @@ Downcast(Handle<ObjectImpl*> obj)
return Handle<JSObject*>::fromMarkedLocation(reinterpret_cast<JSObject* const*>(obj.address()));
}
/* Generic [[GetOwnProperty]] method. */
bool
GetOwnElement(JSContext *cx, Handle<ObjectImpl*> obj, uint32_t index, unsigned resolveFlags,
PropDesc *desc);
extern bool
GetOwnProperty(JSContext *cx, Handle<ObjectImpl*> obj, PropertyId pid, unsigned resolveFlags,
PropDesc *desc);
inline bool
GetOwnProperty(JSContext *cx, Handle<ObjectImpl*> obj, Handle<PropertyName*> name,
unsigned resolveFlags, PropDesc *desc)
{
return GetOwnProperty(cx, obj, PropertyId(name), resolveFlags, desc);
}
inline bool
GetOwnProperty(JSContext *cx, Handle<ObjectImpl*> obj, Handle<SpecialId> sid, unsigned resolveFlags,
PropDesc *desc)
{
return GetOwnProperty(cx, obj, PropertyId(sid), resolveFlags, desc);
}
/* Proposed default [[GetP]](Receiver, P) method. */
extern bool