author | Jeff Walden <jwalden@mit.edu> |
Thu, 17 May 2012 11:38:25 -0700 | |
changeset 106409 | b63ee06d4f51b9a72a022fe8d529fa6f0fa8d660 |
parent 106408 | 44d76a524b7051b5e3ec5948a0fc2b5cb4fa6678 |
child 106410 | 7f98d720cdb1d6501e8741e83ee96f27253b6d95 |
push id | 23447 |
push user | danderson@mozilla.com |
push date | Tue, 11 Sep 2012 17:34:27 +0000 |
treeherder | mozilla-central@fdfaef738a00 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | bhackett |
bugs | 751377 |
milestone | 16.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/js/src/jsobjinlines.h +++ b/js/src/jsobjinlines.h @@ -1229,16 +1229,32 @@ JSObject::global() const static inline bool js_IsCallable(const js::Value &v) { return v.isObject() && v.toObject().isCallable(); } 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) { if (JSObjectOp op = obj->getClass()->ext.innerObject) return op(cx, obj); return obj; }
--- a/js/src/jsscope.h +++ b/js/src/jsscope.h @@ -775,16 +775,26 @@ struct Shape : public js::gc::Cell bool isDataDescriptor() const { return (attrs & (JSPROP_SETTER | JSPROP_GETTER)) == 0; } bool isAccessorDescriptor() const { 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 * the directly referenced object will have the same getter and setter as * the prototype property. See bug 552432. */ bool shadowable() const { JS_ASSERT_IF(isDataDescriptor(), writable());
--- a/js/src/vm/ObjectImpl-inl.h +++ b/js/src/vm/ObjectImpl-inl.h @@ -35,16 +35,42 @@ Debug_SetSlotRangeToCrashOnTouch(HeapSlo { #ifdef DEBUG Debug_SetValueRangeToCrashOnTouch((Value *) begin, end - begin); #endif } } // 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 { return !lastProperty()->hasObjectFlag(BaseShape::NOT_EXTENSIBLE); } inline bool js::ObjectImpl::isDenseArray() const
--- a/js/src/vm/ObjectImpl.cpp +++ b/js/src/vm/ObjectImpl.cpp @@ -484,16 +484,74 @@ ArrayBufferElementsHeader::defineElement Rooted<JSObject*> delegate(cx, ArrayBufferDelegate(cx, obj)); if (!delegate) return false; 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) { ElementsHeader &header = obj->elementsHeader(); switch (header.kind()) { case DenseElements: return header.asDenseElements().getOwnElement(cx, obj, index, resolveFlags, desc); case SparseElements:
--- a/js/src/vm/ObjectImpl.h +++ b/js/src/vm/ObjectImpl.h @@ -147,16 +147,19 @@ struct PropDesc { attrs((writable ? 0 : JSPROP_READONLY) | (enumerable ? JSPROP_ENUMERATE : 0) | (configurable ? 0 : JSPROP_PERMANENT)), hasGet_(false), hasSet_(false), hasValue_(true), hasWritable_(true), hasEnumerable_(true), hasConfigurable_(true), isUndefined_(false) {} + inline PropDesc(const Value &getter, const Value &setter, + Enumerability enumerable, Configurability configurable); + /* * 8.10.5 ToPropertyDescriptor(Obj) * * If checkAccessors is false, skip steps 7.b and 8.b, which throw a * TypeError if .get or .set is neither a callable object nor undefined. * * (DebuggerObject_defineProperty uses this: the .get and .set properties * are expected to be Debugger.Object wrappers of functions, which are not @@ -1131,19 +1134,23 @@ class ObjectImpl : public gc::Cell bool hasLazyType() const { return type_->lazy(); } inline uint32_t slotSpan() const; /* Compute dynamicSlotsCount() for this object. */ 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; inline JSClass *getJSClass() const; inline bool hasClass(const Class *c) const; inline const ObjectOps *getOps() const; /* @@ -1307,19 +1314,35 @@ ObjectValue(ObjectImpl &obj) } inline Handle<JSObject*> 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 GetElement(JSContext *cx, Handle<ObjectImpl*> obj, Handle<ObjectImpl*> receiver, uint32_t index, unsigned resolveFlags, Value *vp); extern bool DefineElement(JSContext *cx, Handle<ObjectImpl*> obj, uint32_t index, const PropDesc &desc,