Bug 923160 - Disallow initializers in for-of statements. r=jorendorff

This commit is contained in:
Andy Wingo
2013-10-15 16:43:55 +02:00
parent 2299c81839
commit bad7f8b5b7
13 changed files with 154 additions and 92 deletions

View File

@@ -564,37 +564,6 @@ UpdateNativeIterator(NativeIterator *ni, JSObject *obj)
bool
js::GetIterator(JSContext *cx, HandleObject obj, unsigned flags, MutableHandleValue vp)
{
if (flags == JSITER_FOR_OF) {
// for-of loop. The iterator is simply |obj[@@iterator]()|.
RootedValue method(cx);
if (!JSObject::getProperty(cx, obj, obj, cx->names().std_iterator, &method))
return false;
// Throw if obj[@@iterator] isn't callable. js::Invoke is about to check
// for this kind of error anyway, but it would throw an inscrutable
// error message about |method| rather than this nice one about |obj|.
if (!method.isObject() || !method.toObject().isCallable()) {
RootedValue val(cx, ObjectOrNullValue(obj));
char *bytes = DecompileValueGenerator(cx, JSDVG_SEARCH_STACK, val, NullPtr());
if (!bytes)
return false;
JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_NOT_ITERABLE, bytes);
js_free(bytes);
return false;
}
if (!Invoke(cx, ObjectOrNullValue(obj), method, 0, nullptr, vp))
return false;
JSObject *resultObj = ToObject(cx, vp);
if (!resultObj)
return false;
vp.setObject(*resultObj);
return true;
}
JS_ASSERT(!(flags & JSITER_FOR_OF));
Vector<Shape *, 8> shapes(cx);
uint32_t key = 0;
@@ -1321,6 +1290,46 @@ const Class StopIterationObject::class_ = {
nullptr /* construct */
};
bool
ForOfIterator::init(HandleValue iterable)
{
RootedObject iterableObj(cx, ToObject(cx, iterable));
if (!iterableObj)
return false;
// The iterator is the result of calling obj[@@iterator]().
InvokeArgs args(cx);
if (!args.init(0))
return false;
args.setThis(ObjectValue(*iterableObj));
RootedValue callee(cx);
if (!JSObject::getProperty(cx, iterableObj, iterableObj, cx->names().std_iterator, &callee))
return false;
// Throw if obj[@@iterator] isn't callable. js::Invoke is about to check
// for this kind of error anyway, but it would throw an inscrutable
// error message about |method| rather than this nice one about |obj|.
if (!callee.isObject() || !callee.toObject().isCallable()) {
char *bytes = DecompileValueGenerator(cx, JSDVG_SEARCH_STACK, iterable, NullPtr());
if (!bytes)
return false;
JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_NOT_ITERABLE, bytes);
js_free(bytes);
return false;
}
args.setCallee(callee);
if (!Invoke(cx, args))
return false;
iterator = ToObject(cx, args.rval());
if (!iterator)
return false;
return true;
}
bool
ForOfIterator::next(MutableHandleValue vp, bool *done)
{