Bug 645416, part 27 - Implement Object.getOwnPropertySymbols(). r=Waldo.

This commit is contained in:
Jason Orendorff
2014-06-23 10:57:03 -05:00
parent b352550168
commit 79ded004dc
7 changed files with 191 additions and 80 deletions

View File

@@ -119,8 +119,9 @@ Enumerate(JSContext *cx, HandleObject pobj, jsid id,
}
// Symbol-keyed properties and nonenumerable properties are skipped unless
// the caller specifically asks for them.
if (JSID_IS_SYMBOL(id) && !(flags & JSITER_SYMBOLS))
// the caller specifically asks for them. A caller can also filter out
// non-symbols by asking for JSITER_SYMBOLSONLY.
if (JSID_IS_SYMBOL(id) ? !(flags & JSITER_SYMBOLS) : (flags & JSITER_SYMBOLSONLY))
return true;
if (!enumerable && !(flags & JSITER_HIDDEN))
return true;
@@ -132,50 +133,57 @@ static bool
EnumerateNativeProperties(JSContext *cx, HandleObject pobj, unsigned flags, IdSet &ht,
AutoIdVector *props)
{
/* Collect any dense elements from this object. */
size_t initlen = pobj->getDenseInitializedLength();
const Value *vp = pobj->getDenseElements();
for (size_t i = 0; i < initlen; ++i, ++vp) {
if (!vp->isMagic(JS_ELEMENTS_HOLE)) {
/* Dense arrays never get so large that i would not fit into an integer id. */
if (!Enumerate(cx, pobj, INT_TO_JSID(i), /* enumerable = */ true, flags, ht, props))
bool enumerateSymbols;
if (flags & JSITER_SYMBOLSONLY) {
enumerateSymbols = true;
} else {
/* Collect any dense elements from this object. */
size_t initlen = pobj->getDenseInitializedLength();
const Value *vp = pobj->getDenseElements();
for (size_t i = 0; i < initlen; ++i, ++vp) {
if (!vp->isMagic(JS_ELEMENTS_HOLE)) {
/* Dense arrays never get so large that i would not fit into an integer id. */
if (!Enumerate(cx, pobj, INT_TO_JSID(i), /* enumerable = */ true, flags, ht, props))
return false;
}
}
/* Collect any typed array elements from this object. */
if (pobj->is<TypedArrayObject>()) {
size_t len = pobj->as<TypedArrayObject>().length();
for (size_t i = 0; i < len; i++) {
if (!Enumerate(cx, pobj, INT_TO_JSID(i), /* enumerable = */ true, flags, ht, props))
return false;
}
}
size_t initialLength = props->length();
/* Collect all unique property names from this object's shape. */
bool symbolsFound = false;
Shape::Range<NoGC> r(pobj->lastProperty());
for (; !r.empty(); r.popFront()) {
Shape &shape = r.front();
jsid id = shape.propid();
if (JSID_IS_SYMBOL(id)) {
symbolsFound = true;
continue;
}
if (!Enumerate(cx, pobj, id, shape.enumerable(), flags, ht, props))
return false;
}
::Reverse(props->begin() + initialLength, props->end());
enumerateSymbols = symbolsFound && (flags & JSITER_SYMBOLS);
}
/* Collect any typed array elements from this object. */
if (pobj->is<TypedArrayObject>()) {
size_t len = pobj->as<TypedArrayObject>().length();
for (size_t i = 0; i < len; i++) {
if (!Enumerate(cx, pobj, INT_TO_JSID(i), /* enumerable = */ true, flags, ht, props))
return false;
}
}
size_t initialLength = props->length();
/* Collect all unique property names from this object's shape. */
Shape::Range<NoGC> r(pobj->lastProperty());
bool symbolsFound = false;
for (; !r.empty(); r.popFront()) {
Shape &shape = r.front();
jsid id = shape.propid();
if (JSID_IS_SYMBOL(id)) {
symbolsFound = true;
continue;
}
if (!Enumerate(cx, pobj, id, shape.enumerable(), flags, ht, props))
return false;
}
::Reverse(props->begin() + initialLength, props->end());
if (symbolsFound && (flags & JSITER_SYMBOLS)) {
if (enumerateSymbols) {
// Do a second pass to collect symbols. ES6 draft rev 25 (2014 May 22)
// 9.1.12 requires that all symbols appear after all strings in the
// result.
initialLength = props->length();
size_t initialLength = props->length();
for (Shape::Range<NoGC> r(pobj->lastProperty()); !r.empty(); r.popFront()) {
Shape &shape = r.front();
jsid id = shape.propid();
@@ -388,7 +396,9 @@ js::VectorToIdArray(JSContext *cx, AutoIdVector &props, JSIdArray **idap)
JS_FRIEND_API(bool)
js::GetPropertyNames(JSContext *cx, JSObject *obj, unsigned flags, AutoIdVector *props)
{
return Snapshot(cx, obj, flags & (JSITER_OWNONLY | JSITER_HIDDEN | JSITER_SYMBOLS), props);
return Snapshot(cx, obj,
flags & (JSITER_OWNONLY | JSITER_HIDDEN | JSITER_SYMBOLS | JSITER_SYMBOLSONLY),
props);
}
size_t sCustomIteratorCount = 0;