Bug 1147371: Implement IteratorClose for for-of

Issue #74
This commit is contained in:
janekptacijarabaci 2018-03-24 12:09:30 +01:00 committed by Roy Tam
commit 5f3e5dc3fb
13 changed files with 704 additions and 203 deletions

View file

@ -12,6 +12,7 @@
#include "mozilla/Maybe.h"
#include "mozilla/MemoryReporting.h"
#include "mozilla/PodOperations.h"
#include "mozilla/Unused.h"
#include "jsarray.h"
#include "jsatom.h"
@ -1229,6 +1230,7 @@ js::CloseIterator(JSContext* cx, HandleObject obj)
}
return LegacyGeneratorObject::close(cx, obj);
}
return true;
}
@ -1246,6 +1248,56 @@ js::UnwindIteratorForException(JSContext* cx, HandleObject obj)
return true;
}
bool
js::IteratorCloseForException(JSContext* cx, HandleObject obj)
{
MOZ_ASSERT(cx->isExceptionPending());
bool isClosingGenerator = cx->isClosingGenerator();
JS::AutoSaveExceptionState savedExc(cx);
// Implements IteratorClose (ES 7.4.6) for exception unwinding. See
// also the bytecode generated by BytecodeEmitter::emitIteratorClose.
// Step 3.
//
// Get the "return" method.
RootedValue returnMethod(cx);
if (!GetProperty(cx, obj, obj, cx->names().return_, &returnMethod))
return false;
// Step 4.
//
// Do nothing if "return" is null or undefined. Throw a TypeError if the
// method is not IsCallable.
if (returnMethod.isNullOrUndefined())
return true;
if (!IsCallable(returnMethod))
return ReportIsNotFunction(cx, returnMethod);
// Step 5, 6, 8.
//
// Call "return" if it is not null or undefined.
RootedValue rval(cx);
bool ok = Call(cx, returnMethod, obj, &rval);
if (isClosingGenerator) {
// Closing an iterator is implemented as an exception, but in spec
// terms it is a Completion value with [[Type]] return. In this case
// we *do* care if the call threw and if it returned an object.
if (!ok)
return false;
if (!rval.isObject())
return ThrowCheckIsObject(cx, CheckIsObjectKind::IteratorReturn);
} else {
// We don't care if the call threw or that it returned an Object, as
// Step 6 says if IteratorClose is being called during a throw, the
// original throw has primacy.
savedExc.restore();
}
return true;
}
void
js::UnwindIteratorForUncatchableException(JSContext* cx, JSObject* obj)
{