From e7a220aae2dd6f92c57b92fdd08ff94e5826c035 Mon Sep 17 00:00:00 2001 From: janekptacijarabaci Date: Sun, 25 Mar 2018 14:48:34 +0200 Subject: Bug 1331585 - Allow falsy "done" values for IteratorClose due to exception during array destructuring Issue #74 --- js/src/jit/JitFrames.cpp | 12 ++++++------ .../tests/ecma_6/Destructuring/array-iterator-close.js | 16 ++++++++++++++++ js/src/vm/Interpreter.cpp | 5 +++-- 3 files changed, 25 insertions(+), 8 deletions(-) (limited to 'js/src') 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(stackPointer))); - MOZ_ASSERT(doneValue.isBoolean()); - if (doneValue.isFalse()) { + RootedValue doneValue(cx, *(reinterpret_cast(stackPointer))); + bool done = ToBoolean(doneValue); + if (!done) { Value iterValue(*(reinterpret_cast(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); -- cgit v1.2.3