Store JSStrings instead of jsids in native key iterators, bug 713754. r=dvander
This commit is contained in:
@@ -121,7 +121,8 @@ static const gc::AllocKind ITERATOR_FINALIZE_KIND = gc::FINALIZE_OBJECT2;
|
||||
void
|
||||
NativeIterator::mark(JSTracer *trc)
|
||||
{
|
||||
MarkIdRange(trc, begin(), end(), "props");
|
||||
for (HeapPtr<JSFlatString> *str = begin(); str < end(); str++)
|
||||
MarkString(trc, *str, "prop");
|
||||
if (obj)
|
||||
MarkObject(trc, obj, "obj");
|
||||
}
|
||||
@@ -507,14 +508,20 @@ NativeIterator::allocateIterator(JSContext *cx, uint32_t slength, const AutoIdVe
|
||||
{
|
||||
size_t plength = props.length();
|
||||
NativeIterator *ni = (NativeIterator *)
|
||||
cx->malloc_(sizeof(NativeIterator) + plength * sizeof(jsid) + slength * sizeof(Shape *));
|
||||
cx->malloc_(sizeof(NativeIterator)
|
||||
+ plength * sizeof(JSString *)
|
||||
+ slength * sizeof(Shape *));
|
||||
if (!ni)
|
||||
return NULL;
|
||||
ni->props_array = ni->props_cursor = (HeapId *) (ni + 1);
|
||||
ni->props_array = ni->props_cursor = (HeapPtr<JSFlatString> *) (ni + 1);
|
||||
ni->props_end = ni->props_array + plength;
|
||||
if (plength) {
|
||||
for (size_t i = 0; i < plength; i++)
|
||||
ni->props_array[i].init(props[i]);
|
||||
for (size_t i = 0; i < plength; i++) {
|
||||
JSFlatString *str = IdToString(cx, props[i]);
|
||||
if (!str)
|
||||
return NULL;
|
||||
ni->props_array[i].init(str);
|
||||
}
|
||||
}
|
||||
return ni;
|
||||
}
|
||||
@@ -916,9 +923,9 @@ js_CloseIterator(JSContext *cx, JSObject *obj)
|
||||
* false. It also must have a method |matchesAtMostOne| which allows us to
|
||||
* stop searching after the first deletion if true.
|
||||
*/
|
||||
template<typename IdPredicate>
|
||||
template<typename StringPredicate>
|
||||
static bool
|
||||
SuppressDeletedPropertyHelper(JSContext *cx, JSObject *obj, IdPredicate predicate)
|
||||
SuppressDeletedPropertyHelper(JSContext *cx, JSObject *obj, StringPredicate predicate)
|
||||
{
|
||||
JSObject *iterobj = cx->enumerators;
|
||||
while (iterobj) {
|
||||
@@ -927,9 +934,9 @@ SuppressDeletedPropertyHelper(JSContext *cx, JSObject *obj, IdPredicate predicat
|
||||
/* This only works for identified surpressed keys, not values. */
|
||||
if (ni->isKeyIter() && ni->obj == obj && ni->props_cursor < ni->props_end) {
|
||||
/* Check whether id is still to come. */
|
||||
HeapId *props_cursor = ni->current();
|
||||
HeapId *props_end = ni->end();
|
||||
for (HeapId *idp = props_cursor; idp < props_end; ++idp) {
|
||||
HeapPtr<JSFlatString> *props_cursor = ni->current();
|
||||
HeapPtr<JSFlatString> *props_end = ni->end();
|
||||
for (HeapPtr<JSFlatString> *idp = props_cursor; idp < props_end; ++idp) {
|
||||
if (predicate(*idp)) {
|
||||
/*
|
||||
* Check whether another property along the prototype chain
|
||||
@@ -939,13 +946,17 @@ SuppressDeletedPropertyHelper(JSContext *cx, JSObject *obj, IdPredicate predicat
|
||||
JSObject *proto = obj->getProto();
|
||||
JSObject *obj2;
|
||||
JSProperty *prop;
|
||||
if (!proto->lookupGeneric(cx, *idp, &obj2, &prop))
|
||||
jsid id;
|
||||
if (!ValueToId(cx, StringValue(*idp), &id))
|
||||
return false;
|
||||
id = js_CheckForStringIndex(id);
|
||||
if (!proto->lookupGeneric(cx, id, &obj2, &prop))
|
||||
return false;
|
||||
if (prop) {
|
||||
uintN attrs;
|
||||
if (obj2->isNative())
|
||||
attrs = ((Shape *) prop)->attributes();
|
||||
else if (!obj2->getGenericAttributes(cx, *idp, &attrs))
|
||||
else if (!obj2->getGenericAttributes(cx, id, &attrs))
|
||||
return false;
|
||||
|
||||
if (attrs & JSPROP_ENUMERATE)
|
||||
@@ -968,7 +979,7 @@ SuppressDeletedPropertyHelper(JSContext *cx, JSObject *obj, IdPredicate predicat
|
||||
if (idp == props_cursor) {
|
||||
ni->incCursor();
|
||||
} else {
|
||||
for (HeapId *p = idp; p + 1 != props_end; p++)
|
||||
for (HeapPtr<JSFlatString> *p = idp; p + 1 != props_end; p++)
|
||||
*p = *(p + 1);
|
||||
ni->props_end = ni->end() - 1;
|
||||
}
|
||||
@@ -986,20 +997,22 @@ SuppressDeletedPropertyHelper(JSContext *cx, JSObject *obj, IdPredicate predicat
|
||||
return true;
|
||||
}
|
||||
|
||||
class SingleIdPredicate {
|
||||
jsid id;
|
||||
class SingleStringPredicate {
|
||||
JSFlatString *str;
|
||||
public:
|
||||
SingleIdPredicate(jsid id) : id(id) {}
|
||||
SingleStringPredicate(JSFlatString *str) : str(str) {}
|
||||
|
||||
bool operator()(jsid id) { return id == this->id; }
|
||||
bool operator()(JSFlatString *str) { return EqualStrings(str, this->str); }
|
||||
bool matchesAtMostOne() { return true; }
|
||||
};
|
||||
|
||||
bool
|
||||
js_SuppressDeletedProperty(JSContext *cx, JSObject *obj, jsid id)
|
||||
{
|
||||
id = js_CheckForStringIndex(id);
|
||||
return SuppressDeletedPropertyHelper(cx, obj, SingleIdPredicate(id));
|
||||
JSFlatString *str = IdToString(cx, id);
|
||||
if (!str)
|
||||
return false;
|
||||
return SuppressDeletedPropertyHelper(cx, obj, SingleStringPredicate(str));
|
||||
}
|
||||
|
||||
bool
|
||||
@@ -1008,8 +1021,7 @@ js_SuppressDeletedElement(JSContext *cx, JSObject *obj, uint32_t index)
|
||||
jsid id;
|
||||
if (!IndexToId(cx, index, &id))
|
||||
return false;
|
||||
JS_ASSERT(id == js_CheckForStringIndex(id));
|
||||
return SuppressDeletedPropertyHelper(cx, obj, SingleIdPredicate(id));
|
||||
return js_SuppressDeletedProperty(cx, obj, id);
|
||||
}
|
||||
|
||||
class IndexRangePredicate {
|
||||
@@ -1018,19 +1030,9 @@ class IndexRangePredicate {
|
||||
public:
|
||||
IndexRangePredicate(uint32_t begin, uint32_t end) : begin(begin), end(end) {}
|
||||
|
||||
bool operator()(jsid id) {
|
||||
if (JSID_IS_INT(id)) {
|
||||
jsint i = JSID_TO_INT(id);
|
||||
return i > 0 && begin <= uint32_t(i) && uint32_t(i) < end;
|
||||
}
|
||||
|
||||
if (JS_LIKELY(JSID_IS_ATOM(id))) {
|
||||
JSAtom *atom = JSID_TO_ATOM(id);
|
||||
uint32_t index;
|
||||
return atom->isIndex(&index) && begin <= index && index < end;
|
||||
}
|
||||
|
||||
return false;
|
||||
bool operator()(JSFlatString *str) {
|
||||
uint32_t index;
|
||||
return str->isIndex(&index) && begin <= index && index < end;
|
||||
}
|
||||
|
||||
bool matchesAtMostOne() { return false; }
|
||||
@@ -1083,7 +1085,10 @@ js_IteratorMore(JSContext *cx, JSObject *iterobj, Value *rval)
|
||||
}
|
||||
} else {
|
||||
JS_ASSERT(!ni->isKeyIter());
|
||||
jsid id = *ni->current();
|
||||
jsid id;
|
||||
if (!ValueToId(cx, StringValue(*ni->current()), &id))
|
||||
return false;
|
||||
id = js_CheckForStringIndex(id);
|
||||
ni->incCursor();
|
||||
if (!ni->obj->getGeneric(cx, id, rval))
|
||||
return false;
|
||||
@@ -1110,7 +1115,7 @@ js_IteratorNext(JSContext *cx, JSObject *iterobj, Value *rval)
|
||||
NativeIterator *ni = iterobj->getNativeIterator();
|
||||
if (ni->isKeyIter()) {
|
||||
JS_ASSERT(ni->props_cursor < ni->props_end);
|
||||
*rval = IdToValue(*ni->current());
|
||||
*rval = StringValue(*ni->current());
|
||||
ni->incCursor();
|
||||
|
||||
if (rval->isString())
|
||||
|
||||
Reference in New Issue
Block a user