summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--js/src/jit/JitFrames.cpp12
-rw-r--r--js/src/tests/ecma_6/Destructuring/array-iterator-close.js16
-rw-r--r--js/src/vm/Interpreter.cpp5
3 files changed, 25 insertions, 8 deletions
diff --git a/js/src/jit/JitFrames.cpp b/js/src/jit/JitFrames.cpp
index 30bbd0b9b..7c3f0d120 100644
--- a/js/src/jit/JitFrames.cpp
+++ b/js/src/jit/JitFrames.cpp
@@ -353,11 +353,11 @@ CloseLiveIteratorIon(JSContext* cx, const InlineFrameIterator& frame, JSTryNote*
RootedObject iterObject(cx, &v.toObject());
if (isDestructuring) {
- Value v = si.read();
- MOZ_ASSERT(v.isBoolean());
+ RootedValue doneValue(cx, si.read());
+ bool done = ToBoolean(doneValue);
// Do not call IteratorClose if the destructuring iterator is already
// done.
- if (v.isTrue())
+ if (done)
return;
}
@@ -654,9 +654,9 @@ ProcessTryNotesBaseline(JSContext* cx, const JitFrameIterator& frame, Environmen
uint8_t* framePointer;
uint8_t* stackPointer;
BaselineFrameAndStackPointersFromTryNote(tn, frame, &framePointer, &stackPointer);
- Value doneValue(*(reinterpret_cast<Value*>(stackPointer)));
- MOZ_ASSERT(doneValue.isBoolean());
- if (doneValue.isFalse()) {
+ RootedValue doneValue(cx, *(reinterpret_cast<Value*>(stackPointer)));
+ bool done = ToBoolean(doneValue);
+ if (!done) {
Value iterValue(*(reinterpret_cast<Value*>(stackPointer) + 1));
RootedObject iterObject(cx, &iterValue.toObject());
if (!IteratorCloseForException(cx, iterObject)) {
diff --git a/js/src/tests/ecma_6/Destructuring/array-iterator-close.js b/js/src/tests/ecma_6/Destructuring/array-iterator-close.js
index f7805540d..ed35135db 100644
--- a/js/src/tests/ecma_6/Destructuring/array-iterator-close.js
+++ b/js/src/tests/ecma_6/Destructuring/array-iterator-close.js
@@ -43,6 +43,22 @@ function test() {
}, "in lhs");
assertEq(returnCalled, ++returnCalledExpected);
+ // throw in lhs ref calls IteratorClose with falsy "done".
+ iterable[Symbol.iterator] = makeIterator({
+ next: function() {
+ // "done" is undefined.
+ return {};
+ },
+ ret: function() {
+ returnCalled++;
+ return {};
+ }
+ });
+ assertThrowsValue(function() {
+ 0, [...{}[throwlhs()]] = iterable;
+ }, "in lhs");
+ assertEq(returnCalled, ++returnCalledExpected);
+
// throw in iter.next doesn't call IteratorClose
iterable[Symbol.iterator] = makeIterator({
next: function() {
diff --git a/js/src/vm/Interpreter.cpp b/js/src/vm/Interpreter.cpp
index 9a8c6777f..7f8ff8445 100644
--- a/js/src/vm/Interpreter.cpp
+++ b/js/src/vm/Interpreter.cpp
@@ -1205,8 +1205,9 @@ ProcessTryNotes(JSContext* cx, EnvironmentIter& ei, InterpreterRegs& regs)
// stack. The iterator object is second from the top.
MOZ_ASSERT(tn->stackDepth > 1);
Value* sp = regs.spForStackDepth(tn->stackDepth);
- MOZ_ASSERT(sp[-1].isBoolean());
- if (sp[-1].isFalse()) {
+ RootedValue doneValue(cx, sp[-1]);
+ bool done = ToBoolean(doneValue);
+ if (!done) {
RootedObject iterObject(cx, &sp[-2].toObject());
if (!IteratorCloseForException(cx, iterObject)) {
SettleOnTryNote(cx, tn, ei, regs);