Bug 783829 - Factor out NativeIteratorNext. r=efaust

This commit is contained in:
Tom Schuster 2014-12-17 00:28:37 +01:00
Родитель 56b818b46f
Коммит 73077d1cd2
1 изменённых файлов: 47 добавлений и 30 удалений

Просмотреть файл

@ -849,6 +849,38 @@ js::IteratorConstructor(JSContext *cx, unsigned argc, Value *vp)
return true;
}
MOZ_ALWAYS_INLINE bool
NativeIteratorNext(JSContext *cx, NativeIterator *ni, MutableHandleValue rval, bool *done)
{
*done = false;
if (ni->props_cursor >= ni->props_end) {
*done = true;
return true;
}
if (MOZ_LIKELY(ni->isKeyIter())) {
rval.setString(*ni->current());
ni->incCursor();
return true;
}
// Non-standard Iterator for "for each"
RootedId id(cx);
RootedValue current(cx, StringValue(*ni->current()));
if (!ValueToId<CanGC>(cx, current, &id))
return false;
ni->incCursor();
RootedObject obj(cx, ni->obj);
if (!JSObject::getGeneric(cx, obj, obj, id, rval))
return false;
// JS 1.7 only: for each (let [k, v] in obj)
if (ni->flags & JSITER_KEYVALUE)
return NewKeyValuePair(cx, id, rval, rval);
return true;
}
MOZ_ALWAYS_INLINE bool
IsIterator(HandleValue v)
{
@ -862,14 +894,19 @@ iterator_next_impl(JSContext *cx, CallArgs args)
RootedObject thisObj(cx, &args.thisv().toObject());
if (!IteratorMore(cx, thisObj, args.rval()))
return false;
NativeIterator *ni = thisObj.as<PropertyIteratorObject>()->getNativeIterator();
RootedValue value(cx);
bool done;
if (!NativeIteratorNext(cx, ni, &value, &done))
return false;
if (args.rval().isMagic(JS_NO_ITER_VALUE)) {
// Use old iterator protocol for compatibility reasons.
if (done) {
ThrowStopIteration(cx);
return false;
}
args.rval().set(value);
return true;
}
@ -1226,40 +1263,20 @@ bool
js::IteratorMore(JSContext *cx, HandleObject iterobj, MutableHandleValue rval)
{
/* Fast path for native iterators */
NativeIterator *ni = nullptr;
if (iterobj->is<PropertyIteratorObject>()) {
/* Key iterators are handled by fast-paths. */
ni = iterobj->as<PropertyIteratorObject>().getNativeIterator();
if (ni->props_cursor >= ni->props_end) {
NativeIterator *ni = iterobj->as<PropertyIteratorObject>().getNativeIterator();
bool done;
if (!NativeIteratorNext(cx, ni, rval, &done))
return false;
if (done)
rval.setMagic(JS_NO_ITER_VALUE);
return true;
}
if (ni->isKeyIter()) {
rval.setString(*ni->current());
ni->incCursor();
return true;
}
return true;
}
/* We're reentering below and can call anything. */
JS_CHECK_RECURSION(cx, return false);
/* Fetch and cache the next value from the iterator. */
if (ni) {
MOZ_ASSERT(!ni->isKeyIter());
RootedId id(cx);
RootedValue current(cx, StringValue(*ni->current()));
if (!ValueToId<CanGC>(cx, current, &id))
return false;
ni->incCursor();
RootedObject obj(cx, ni->obj);
if (!JSObject::getGeneric(cx, obj, obj, id, rval))
return false;
if ((ni->flags & JSITER_KEYVALUE) && !NewKeyValuePair(cx, id, rval, rval))
return false;
return true;
}
/* Call the iterator object's .next method. */
if (!JSObject::getProperty(cx, iterobj, iterobj, cx->names().next, rval))
return false;