Bug 783829 - Change from Proxy iterate to enumerate. r=efaust,bholley

This commit is contained in:
Tom Schuster
2014-12-17 00:28:38 +01:00
parent 75ebb54849
commit a3bf7d8937
30 changed files with 218 additions and 138 deletions

View File

@@ -669,6 +669,16 @@ js::GetIterator(JSContext *cx, HandleObject obj, unsigned flags, MutableHandleOb
return true;
}
// We should only call the enumerate trap for "for-in".
// Or when we call GetIterator from the Proxy [[Enumerate]] hook.
// In the future also for Reflect.enumerate.
// JSITER_ENUMERATE is just an optimization and the same
// as flags == 0 otherwise.
if (flags == 0 || flags == JSITER_ENUMERATE) {
if (obj->is<ProxyObject>())
return Proxy::enumerate(cx, obj, objp);
}
Vector<Shape *, 8> shapes(cx);
uint32_t key = 0;
if (flags == JSITER_ENUMERATE) {
@@ -747,9 +757,6 @@ js::GetIterator(JSContext *cx, HandleObject obj, unsigned flags, MutableHandleOb
}
miss:
if (obj->is<ProxyObject>())
return Proxy::iterate(cx, obj, flags, objp);
if (!GetCustomIterator(cx, obj, flags, objp))
return false;
if (objp)
@@ -1262,7 +1269,7 @@ js::SuppressDeletedElements(JSContext *cx, HandleObject obj, uint32_t begin, uin
bool
js::IteratorMore(JSContext *cx, HandleObject iterobj, MutableHandleValue rval)
{
/* Fast path for native iterators */
// Fast path for native iterators.
if (iterobj->is<PropertyIteratorObject>()) {
NativeIterator *ni = iterobj->as<PropertyIteratorObject>().getNativeIterator();
bool done;
@@ -1274,14 +1281,15 @@ js::IteratorMore(JSContext *cx, HandleObject iterobj, MutableHandleValue rval)
return true;
}
/* We're reentering below and can call anything. */
// We're reentering below and can call anything.
JS_CHECK_RECURSION(cx, return false);
/* Call the iterator object's .next method. */
// Call the iterator object's .next method.
if (!JSObject::getProperty(cx, iterobj, iterobj, cx->names().next, rval))
return false;
// We try to support the old and new iterator protocol at the same time!
if (!Invoke(cx, ObjectValue(*iterobj), rval, 0, nullptr, rval)) {
/* Check for StopIteration. */
// We still check for StopIterator
if (!cx->isExceptionPending())
return false;
RootedValue exception(cx);
@@ -1295,7 +1303,39 @@ js::IteratorMore(JSContext *cx, HandleObject iterobj, MutableHandleValue rval)
return true;
}
return true;
if (!rval.isObject()) {
// Old style generators might return primitive values
return true;
}
// If the object has both the done and value property, we assume
// it's using the new style protocol. Otherwise just return the object.
RootedObject result(cx, &rval.toObject());
bool found = false;
if (!JSObject::hasProperty(cx, result, cx->names().done, &found))
return false;
if (!found)
return true;
if (!JSObject::hasProperty(cx, result, cx->names().value, &found))
return false;
if (!found)
return true;
// At this point we hopefully have a new style iterator result
// 7.4.4 IteratorComplete
// Get iterResult.done
if (!JSObject::getProperty(cx, result, result, cx->names().done, rval))
return false;
bool done = ToBoolean(rval);
if (done) {
rval.setMagic(JS_NO_ITER_VALUE);
return true;
}
// 7.4.5 IteratorValue
return JSObject::getProperty(cx, result, result, cx->names().value, rval);
}
static bool