Merge from TM
This commit is contained in:
@@ -201,19 +201,38 @@ struct ValueEnumeration
|
||||
template <class EnumPolicy>
|
||||
static inline bool
|
||||
Enumerate(JSContext *cx, JSObject *obj, JSObject *pobj, jsid id,
|
||||
bool enumerable, uintN flags, IdSet& ht,
|
||||
bool enumerable, bool sharedPermanent, uintN flags, IdSet& ht,
|
||||
typename EnumPolicy::ResultVector &vec)
|
||||
{
|
||||
JS_ASSERT(JSID_IS_INT(id) || JSID_IS_ATOM(id));
|
||||
|
||||
if (JS_LIKELY(!(flags & JSITER_OWNONLY))) {
|
||||
IdSet::AddPtr p = ht.lookupForAdd(id);
|
||||
/* property already encountered, done. */
|
||||
if (JS_UNLIKELY(!!p))
|
||||
IdSet::AddPtr p = ht.lookupForAdd(id);
|
||||
JS_ASSERT_IF(obj == pobj, !p);
|
||||
|
||||
/* If we've already seen this, we definitely won't add it. */
|
||||
if (JS_UNLIKELY(!!p))
|
||||
return true;
|
||||
|
||||
/*
|
||||
* It's not necessary to add properties to the hash table at the end of the
|
||||
* prototype chain.
|
||||
*/
|
||||
if (pobj->getProto() && !ht.add(p, id))
|
||||
return false;
|
||||
|
||||
if (JS_UNLIKELY(flags & JSITER_OWNONLY)) {
|
||||
/*
|
||||
* Shared-permanent hack: If this property is shared permanent
|
||||
* and pobj and obj have the same class, then treat it as an own
|
||||
* property of obj, even if pobj != obj. (But see bug 575997.)
|
||||
*
|
||||
* Omit the magic __proto__ property so that JS code can use
|
||||
* Object.getOwnPropertyNames without worrying about it.
|
||||
*/
|
||||
if (!pobj->getProto() && id == ATOM_TO_JSID(cx->runtime->atomState.protoAtom))
|
||||
return true;
|
||||
if (pobj != obj && !(sharedPermanent && pobj->getClass() == obj->getClass()))
|
||||
return true;
|
||||
/* no need to add properties to the hash table at the end of the prototype chain */
|
||||
if (pobj->getProto() && !ht.add(p, id))
|
||||
return false;
|
||||
}
|
||||
|
||||
if (enumerable || (flags & JSITER_HIDDEN))
|
||||
@@ -236,7 +255,9 @@ EnumerateNativeProperties(JSContext *cx, JSObject *obj, JSObject *pobj, uintN fl
|
||||
for (JSScopeProperty *sprop = scope->lastProperty(); sprop; sprop = sprop->parent) {
|
||||
if (!JSID_IS_DEFAULT_XML_NAMESPACE(sprop->id) &&
|
||||
!sprop->isAlias() &&
|
||||
!Enumerate<EnumPolicy>(cx, obj, pobj, sprop->id, sprop->enumerable(), flags, ht, vec)) {
|
||||
!Enumerate<EnumPolicy>(cx, obj, pobj, sprop->id, sprop->enumerable(), sprop->isSharedPermanent(),
|
||||
flags, ht, sprops))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -252,19 +273,23 @@ static bool
|
||||
EnumerateDenseArrayProperties(JSContext *cx, JSObject *obj, JSObject *pobj, uintN flags,
|
||||
IdSet &ht, typename EnumPolicy::ResultVector &vec)
|
||||
{
|
||||
size_t count = pobj->getDenseArrayCount();
|
||||
if (!Enumerate(cx, obj, pobj, ATOM_TO_JSID(cx->runtime->atomState.lengthAtom), false, true,
|
||||
flags, ht, props)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (count) {
|
||||
if (pobj->getDenseArrayCount() > 0) {
|
||||
size_t capacity = pobj->getDenseArrayCapacity();
|
||||
Value *vp = pobj->dslots;
|
||||
for (size_t i = 0; i < capacity; ++i, ++vp) {
|
||||
if (!vp->isMagic(JS_ARRAY_HOLE)) {
|
||||
/* Dense arrays never get so large that i would not fit into an integer id. */
|
||||
if (!Enumerate<EnumPolicy>(cx, obj, pobj, INT_TO_JSID(i), true, flags, ht, vec))
|
||||
if (!Enumerate<EnumPolicy>(cx, obj, pobj, INT_TO_JSID(i), true, false, flags, ht, props))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -272,8 +297,13 @@ template <class EnumPolicy>
|
||||
static bool
|
||||
Snapshot(JSContext *cx, JSObject *obj, uintN flags, typename EnumPolicy::ResultVector &vec)
|
||||
{
|
||||
/*
|
||||
* FIXME: Bug 575997 - We won't need to initialize this hash table if
|
||||
* (flags & JSITER_OWNONLY) when we eliminate inheritance of
|
||||
* shared-permanent properties as own properties.
|
||||
*/
|
||||
IdSet ht(cx);
|
||||
if (!(flags & JSITER_OWNONLY) && !ht.init(32))
|
||||
if (!ht.init(32))
|
||||
return NULL;
|
||||
|
||||
JSObject *pobj = obj;
|
||||
@@ -300,14 +330,15 @@ Snapshot(JSContext *cx, JSObject *obj, uintN flags, typename EnumPolicy::ResultV
|
||||
return false;
|
||||
}
|
||||
for (size_t n = 0, len = proxyProps.length(); n < len; n++) {
|
||||
if (!Enumerate<EnumPolicy>(cx, obj, pobj, proxyProps[n], true, flags, ht, vec))
|
||||
if (!Enumerate<EnumPolicy>(cx, obj, pobj, proxyProps[n], true, false, flags, ht, vec))
|
||||
return false;
|
||||
}
|
||||
/* Proxy objects enumerate the prototype on their own, so we are done here. */
|
||||
break;
|
||||
}
|
||||
Value state;
|
||||
if (!pobj->enumerate(cx, JSENUMERATE_INIT, &state, NULL))
|
||||
JSIterateOp op = (flags & JSITER_HIDDEN) ? JSENUMERATE_INIT_ALL : JSENUMERATE_INIT;
|
||||
if (!pobj->enumerate(cx, op, &state, NULL))
|
||||
return false;
|
||||
if (state.isMagic(JS_NATIVE_ENUMERATE)) {
|
||||
if (!EnumerateNativeProperties<EnumPolicy>(cx, obj, pobj, flags, ht, vec))
|
||||
@@ -319,13 +350,13 @@ Snapshot(JSContext *cx, JSObject *obj, uintN flags, typename EnumPolicy::ResultV
|
||||
return false;
|
||||
if (state.isNull())
|
||||
break;
|
||||
if (!Enumerate<EnumPolicy>(cx, obj, pobj, id, true, flags, ht, vec))
|
||||
if (!Enumerate<EnumPolicy>(cx, obj, pobj, id, true, false, flags, ht, vec))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (JS_UNLIKELY(pobj->isXML() || (flags & JSITER_OWNONLY)))
|
||||
if (JS_UNLIKELY(pobj->isXML()))
|
||||
break;
|
||||
} while ((pobj = pobj->getProto()) != NULL);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user