{"action":"created","comment":{"url":"https://api.github.com/repos/Microsoft/ChakraCore/pulls/comments/67095847","id":67095847,"diff_hunk":"@@ -0,0 +1,982 @@\n+//-------------------------------------------------------------------------------------------------------\r\n+// Copyright (C) Microsoft. All rights reserved.\r\n+// Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.\r\n+//-------------------------------------------------------------------------------------------------------\r\n+\r\n+WScript.LoadScriptFile(\"..\\\\UnitTestFramework\\\\UnitTestFramework.js\");\r\n+\r\n+var nextCount = 0;\r\n+var returnCount = 0;\r\n+var value1 = 1;\r\n+var done1 = false;\r\n+var iterable = {};\r\n+var shouldNextThrow = false;\r\n+var shouldReturnThrow = false;\r\n+iterable[Symbol.iterator] = function () {\r\n+    return {\r\n+        next: function() {\r\n+            nextCount++;\r\n+            if (shouldNextThrow) { throw new Error('Exception from next function'); }\r\n+            return {value : value1, done:done1};\r\n+        },\r\n+        return: function (value) {\r\n+            returnCount++;\r\n+            if (shouldReturnThrow) { throw new Error('Exception from return function'); }\r\n+            return {done:true};\r\n+        }\r\n+    };\r\n+};\r\n+\r\n+var obj = {\r\n+  set prop(val) {\r\n+    throw new Error('From setter');\r\n+  }\r\n+};\r\n+\r\n+var tests = [\r\n+    {\r\n+\t\tname : \"Destructuring - no .return function defined is a valid scenario\",\r\n+\t\tbody : function () {\r\n+\t\t\tvar iterable = {};\r\n+\t\t\titerable[Symbol.iterator] = function () {\r\n+\t\t\t\treturn {\r\n+\t\t\t\t\tnext : function () {\r\n+\t\t\t\t\t\treturn {\r\n+\t\t\t\t\t\t\tvalue : 10,\r\n+\t\t\t\t\t\t\tdone : false\r\n+\t\t\t\t\t\t};\r\n+\t\t\t\t\t}\r\n+\t\t\t\t};\r\n+\t\t\t};\r\n+\r\n+\t\t\tvar [a] = iterable;\r\n+\t\t\tassert.areEqual(a, 10, \"Destructuring declaration calls next on iterator and should get 10\");\r\n+            var b;\r\n+            [b] = iterable;\r\n+\t\t\tassert.areEqual(b, 10, \"Destructuring expression calls next on iterator and should get 10\");\r\n+\t\t}\r\n+\t},\r\n+    {\r\n+\t\tname : \"Destructuring - validating that the iterable has .return field but not as a function\",\r\n+\t\tbody : function () {\r\n+            var returnFnc = undefined;\r\n+            var iterable = {};\r\n+            iterable[Symbol.iterator] = function() {\r\n+              return {\r\n+                next: function() {\r\n+                    return {value:10, done:false};\r\n+                },\r\n+                return: returnFnc\r\n+              };\r\n+            };\r\n+            \r\n+            var a;\r\n+            assert.doesNotThrow(function() {\r\n+                [a] = iterable;\r\n+            }, \"iterator has return field which returns 'undefined' and that should not throw\");\r\n+            \r\n+            assert.doesNotThrow(function() {\r\n+                returnFnc = null;\r\n+                [a] = iterable;\r\n+            }, \"iterator has return field which returns 'null' and that should not throw\");\r\n+            \r\n+            assert.throws(function () { returnFnc = {}; [a] = iterable; }, TypeError, \r\n+                    \"return field is not a function and returns other than 'undefined'/'null' should throw Type Error\");\r\n+\t\t}\r\n+\t},\r\n+    {\r\n+\t\tname : \"Destructuring - basic validation with .return function when the pattern is empty or has one element\",\r\n+\t\tbody : function () {\r\n+            nextCount = 0;\r\n+            returnCount = 0;\r\n+            [] = iterable;\r\n+            assert.areEqual(nextCount, 0, \"Empty LHS pattern should not call the next function\");\r\n+            assert.areEqual(returnCount, 1, \"Evaluation of empty LHS pattern will call return function\");\r\n+\r\n+            nextCount = 0;\r\n+            returnCount = 0;\r\n+            var [] = iterable;\r\n+            assert.areEqual(nextCount, 0, \"Empty LHS declaration pattern should not call the next function\");\r\n+            assert.areEqual(returnCount, 1, \"Evaluation of empty LHS declaration pattern call return function\");\r\n+            \r\n+            nextCount = 0;\r\n+            returnCount = 0;\r\n+            [,] = iterable;\r\n+            assert.areEqual(nextCount, 1, \"Comma operator causes the next to be called\");\r\n+            assert.areEqual(returnCount, 1, \"Exhausting the LHS pattern (after comma) will call the call return function\");\r\n+\r\n+            var a;\r\n+            nextCount = 0;\r\n+            returnCount = 0;\r\n+            [a] = iterable;\r\n+            assert.areEqual(nextCount, 1, \"Evaluating destructuring element will call next function\");\r\n+            assert.areEqual(returnCount, 1, \"Exhausting the LHS pattern (after comma) will call the call return function\");\r\n+            \r\n+\t\t}\r\n+\t},\r\n+    {\r\n+\t\tname : \"Destructuring - validation with .return function with nesting pattern\",\r\n+\t\tbody : function () {\r\n+            nextCount = 0;\r\n+            returnCount = 0;\r\n+            [[a]] = [iterable];\r\n+            assert.areEqual(nextCount, 1, \"Nested array pattern will call next function when 'a' is evauluated\");\r\n+            assert.areEqual(returnCount, 1, \"When nested array pattern exhausts the return function will be called\");\r\n+            \r\n+            nextCount = 0;\r\n+            returnCount = 0;\r\n+            value1 = iterable;\r\n+            [a, [a]] = iterable;\r\n+            \r\n+            assert.areEqual(nextCount, 3, \"Recursive iterators on RHS - next function will be called 3 times in order to exhaust elements\");\r\n+            assert.areEqual(returnCount, 2, \"Recursive iterators on RHS - return function for two nested iterators will be called\");\r\n+            value1 = 1; // Reset it back\r\n+\r\n+            nextCount = 0;\r\n+            returnCount = 0;\r\n+            value1 = iterable;\r\n+            var [a, [a]] = iterable;\r\n+            \r\n+            assert.areEqual(nextCount, 3, \"Array declaration - Recursive iterators on RHS - next function will be called 3 times in order to exhaust elements\");\r\n+            assert.areEqual(returnCount, 2, \"Array declaration - Recursive iterators on RHS - return function for two nested iterators will be called\");\r\n+            value1 = 1; // Reset it back\r\n+\t\t}\r\n+\t},    \r\n+    {\r\n+\t\tname : \"Destructuring - change .done to true will not call .return function\",\r\n+\t\tbody : function () {\r\n+            nextCount = 0;\r\n+            returnCount = 0;\r\n+            done1 = true;\r\n+            var [a] = iterable;\r\n+            \r\n+            assert.areEqual(nextCount, 1, \"next function is called to evaluate the element on the LHS\");\r\n+            assert.areEqual(returnCount, 0, \"'done' is set true on next function call - which will ensure that return function is not called\");\r\n+            done1 = false;\r\n+\t\t}\r\n+\t},    \r\n+    {\r\n+\t\tname : \"Destructuring - validating that exception will call the .return function\",\r\n+\t\tbody : function () {\r\n+            nextCount = 0;\r\n+            returnCount = 0;\r\n+            assert.throws(function () { [obj.prop] = iterable; }, Error, \"Pattern throws error while assigning .value\", \"From setter\");\r\n+            assert.areEqual(returnCount, 1, \"Abrupt completion due to exception will call the return function\");\r\n+\r\n+            nextCount = 0;\r\n+            returnCount = 0;\r\n+            value1 = iterable;\r\n+            assert.throws(function () { [k, [obj.prop]] = iterable; }, Error, \"Nested pattern throws error while assigning .value\", \"From setter\");\r\n+            assert.areEqual(returnCount, 2, \"Nested recursive iterators - abrupt completion due to exception will call the return function\");\r\n+            value1 = 1;\r\n+\r\n+            nextCount = 0;\r\n+            returnCount = 0;\r\n+            value1 = iterable;\r\n+            assert.throws(function () { [[[[obj.prop]]]] = iterable; }, Error, \"Nested pattern throws error while assigning .value\", \"From setter\");\r\n+            assert.areEqual(nextCount, 4, \"Nested recursing iterators - 4 times next function called due to 4 level depth of array pattern\");\r\n+            assert.areEqual(returnCount, 4, \"Nested recursing iterators - 4 times return function called due to abrupt comletion\");\r\n+            value1 = 1;\r\n+            \r\n+            done1 = true;\r\n+            nextCount = 0;\r\n+            returnCount = 0;\r\n+            assert.throws(function () { [obj.prop] = iterable; }, Error, \"Pattern throws error while assigning .value\", \"From setter\");\r\n+            assert.areEqual(returnCount, 0, \"Ensuring that return function is not called when 'done' is set to true during abrupt completion\");\r\n+            done1 = false; // Reset it back.\r\n+\t\t}\r\n+\t},    \r\n+    {\r\n+\t\tname : \"Destructuring - chained iterators will have their .return function called correctly\",\r\n+\t\tbody : function () {\r\n+            var nextCount1 = 0;\r\n+            var nextCount2 = 0;\r\n+            var returnCount1 = 0;\r\n+            var returnCount2 = 0;\r\n+            \r\n+            var iterable = {};\r\n+            iterable[Symbol.iterator] = function() {\r\n+              return {\r\n+                next: function() {\r\n+                    nextCount1++;\r\n+                  return { value: iterable2, done: false };\r\n+                },\r\n+                return: function() {\r\n+                    returnCount1++;\r\n+                    return {done:true};\r\n+                },\r\n+              };\r\n+            };\r\n+\r\n+            var iterable2 = {};\r\n+            iterable2[Symbol.iterator] = function() {\r\n+              return {\r\n+                next: function() {\r\n+                    nextCount2++;\r\n+                  return { value: [0], done: false };\r\n+                },\r\n+                return: function() {\r\n+                    returnCount2++;\r\n+                    return {done:true};\r\n+                }\r\n+              };\r\n+            };\r\n+\r\n+             nextCount1 = 0;\r\n+             nextCount2 = 0;\r\n+             returnCount1 = 0;\r\n+             returnCount2 = 0;\r\n+             assert.throws(function () {[[obj.prop]] = iterable; }, Error, \"Pattern throws error while assigning .value\", \"From setter\");\r\n+             assert.areEqual(nextCount1, 1, \"next function for the first iterator is called\");\r\n+             assert.areEqual(nextCount2, 1, \"next function for the second iterator is called\");\r\n+             assert.areEqual(returnCount1, 1, \"return function for the second iterator is called\" );\r\n+             assert.areEqual(returnCount2, 1, \"return function for the first iterator is called\");\r\n+\t\t}\r\n+\t},    \r\n+    {\r\n+\t\tname : \"Destructuring - .return function should not be called when .next function throws\",\r\n+\t\tbody : function () {\r\n+            shouldNextThrow = true;\r\n+            returnCount = 0;\r\n+            assert.throws(function () { var [a] = iterable; }, Error, \"Array declaration - Calling .next throws\", \"Exception from next function\");\r\n+            assert.areEqual(returnCount, 0, \"Ensuring that return function is not called in array declaration pattern\");\r\n+             \r\n+            assert.throws(function () { [a] = iterable; }, Error, \"Array expression - Calling .next throws\", \"Exception from next function\");\r\n+            assert.areEqual(returnCount, 0, \"Ensuring that return function is not called in array expression pattern\");\r\n+             \r\n+            assert.throws(function () { var [...a] = iterable; }, Error, \"Array declaration with rest - Calling .next throws\", \"Exception from next function\");\r\n+            assert.areEqual(returnCount, 0, \"Ensuring that return function is not called when evalauting rest in array declaration pattern\");\r\n+             \r\n+            assert.throws(function () { [...a] = iterable; }, Error, \"Array expression with rest - Calling .next throws\", \"Exception from next function\");\r\n+            assert.areEqual(returnCount, 0, \"Ensuring that return function is not called when evaluating rest in array expression pattern\");\r\n+             \r\n+            shouldNextThrow = false;\r\n+\t\t}\r\n+\t},    \r\n+    {\r\n+\t\tname : \"Destructuring - .return function should not be called when fetching .value throws\",\r\n+\t\tbody : function () {\r\n+            var iterable2 = {};\r\n+            iterable2[Symbol.iterator] = function() {\r\n+              return {\r\n+                next: function() {\r\n+                    return {get value () { throw new Error('Exception while getting value'); }, done:false};\r\n+                },\r\n+                return: function() {\r\n+                    assert.fail('return should not be called');\r\n+                    return {};\r\n+                },\r\n+              };\r\n+            };\r\n+\r\n+            assert.throws(function () { [a] = iterable2; }, Error, \"Fetch .value throws\", \"Exception while getting value\");\r\n+\t\t}\r\n+\t},    \r\n+    {\r\n+\t\tname : \"Destructuring - .return function can also throw\",\r\n+\t\tbody : function () {\r\n+            shouldReturnThrow = true;\r\n+            assert.throws(function () { [a] = iterable; }, Error, \"Calling .return throws\", \"Exception from return function\");\r\n+            shouldReturnThrow = false;\r\n+\t\t}\r\n+\t},    \r\n+    {\r\n+\t\tname : \"Destructuring - caller and .return function both throw and caller's exception wins\",\r\n+\t\tbody : function () {\r\n+            shouldReturnThrow = true;\r\n+            returnCount = 0;\r\n+            assert.throws(function () { [obj.prop] = iterable; }, Error, \"Setting value will throw\", \"From setter\");\r\n+            assert.areEqual(returnCount, 1, \"Ensuring that return function is called\");\r\n+            shouldReturnThrow = false;\r\n+\t\t}\r\n+\t},    \r\n+    {\r\n+\t\tname : \"Destructuring - with generator\",\r\n+\t\tbody : function () {\r\n+            var finallyCount = 0;\r\n+            function *gf() {\r\n+                try {\r\n+                    yield 1;\r\n+                    assert.fail('should not reach after yield');\r\n+                }\r\n+                finally {\r\n+                    finallyCount++;\r\n+                }\r\n+                assert.fail('should not reach after finally');;\r\n+            }\r\n+            \r\n+            [a] = gf();\r\n+            assert.areEqual(finallyCount, 1, \"Exhausting pattern will call return function on generator, which will execute finally block\");\r\n+            \r\n+            finallyCount = 0;\r\n+            assert.throws(function () { [obj.prop] = gf(); }, Error, \"Assigning value to destructuring element can throw\", \"From setter\");\r\n+            assert.areEqual(finallyCount, 1, \"Exception causes to call return function on generator, which will execute finally block\");\r\n+            \r\n+            function* gf2() {\r\n+                yield 1;\r\n+                assert.fail('should not reach after yield');\r\n+            }\r\n+            var returnCount = 0;\r\n+            gf2.prototype.return = function() {\r\n+                returnCount++;\r\n+                return {};\r\n+            };\r\n+            [a] = gf2();\r\n+            assert.areEqual(returnCount, 1, \"Exhausting pattern will call return function on generator\");\r\n+            \r\n+            gf2.prototype.return = function() {\r\n+                returnCount++;\r\n+                throw new Error('Exception from return function');\r\n+            };\r\n+            assert.throws(function () { [a] = gf2(); }, Error, \"Return function throws\", \"Exception from return function\");\r\n+            returnCount = 0;\r\n+            assert.throws(function () { [obj.prop] = gf2(); }, Error, \"Exception at destructuring element wins\", \"From setter\");\r\n+            assert.areEqual(returnCount, 1, \"Exception causes to call return function on generator\");\r\n+\t\t}\r\n+\t},    \r\n+    {\r\n+\t\tname : \"Destructuring - at function parameter\",\r\n+\t\tbody : function () {\r\n+            nextCount = 0;\r\n+            returnCount = 0;\r\n+            (function([a, b]) {})(iterable);\r\n+            assert.areEqual(nextCount, 2, \"next function will be called 2 times to evaluate 2 elements in the pattern\");\r\n+            assert.areEqual(returnCount, 1, \"return function will be called once the pattern exhausts\");\r\n+            \r\n+            shouldReturnThrow = true;\r\n+            assert.throws(function () { (function([a, b]) {})(iterable) }, Error, \"Calling return function while at param throws\", \"Exception from return function\");\r\n+            shouldReturnThrow = false;\r\n+\t\t}\r\n+\t},\r\n+    {\r\n+\t\tname : \"Destructuring - assigning to rest parameter can throw but should not call .return function\",\r\n+\t\tbody : function () {\r\n+            function* gf() {\r\n+                yield 1;\r\n+                yield 2;\r\n+            }\r\n+            gf.prototype.return = function() {\r\n+                assert.fail('return function should not be called');\r\n+            };\r\n+            \r\n+            assert.throws(function () { [...obj.prop] = gf(); }, Error, \"Assigning to rest head can throw\", \"From setter\");\r\n+\t\t}\r\n+\t},    \r\n+    {\r\n+\t\tname : \"Destructuring - .next throws during rest assignment but it should not call the .return function\",\r\n+\t\tbody : function () {\r\n+            returnCount = 0;\r\n+            shouldNextThrow = true;\r\n+            assert.throws(function () { var [...a] = iterable; }, Error, \"next function throws in the array declaration evaluation\", \"Exception from next function\");\r\n+            assert.throws(function () { [...a] = iterable; }, Error, \"next function throws in the array expression evaluation\", \"Exception from next function\");\r\n+            shouldNextThrow = false;\r\n+            assert.areEqual(returnCount, 0, \"return function should be called even when the next function throws\");\r\n+\t\t}\r\n+\t},    \r\n+    {\r\n+\t\tname : \"Destructuring - has yield as initializer\",\r\n+\t\tbody : function () {\r\n+            var returnCalled = 0;\r\n+            function *innerGen () { yield undefined; yield 21; }\r\n+\r\n+            innerGen.prototype.return = function () {\r\n+                returnCalled++;\r\n+                return {};\r\n+            };\r\n+            \r\n+            var x;\r\n+\r\n+            var iter = (function * () {\r\n+                ([x = yield] = innerGen());\r\n+            }());\r\n+\r\n+            iter.next();\r\n+            var iterationResult = iter.next(10);\r\n+            assert.areEqual(x, 10, \"calling next with value 10 will assign 'x' to 10\");\r\n+            assert.isTrue(iterationResult.done, \"iterator is completed as there is nothing more to yield\");\r\n+            assert.areEqual(returnCalled, 1, \"Destructuring elements exhaust and that should call return function\");\r\n+\t\t}\r\n+\t},    \r\n+    {\r\n+\t\tname : \"For..of - validation of calling .return function on abrupt loop break\",\r\n+\t\tbody : function () {\r\n+            returnCount = 0;\r\n+            for (i of iterable) {\r\n+                break;\r\n+            }\r\n+            assert.areEqual(returnCount, 1, \"return function is called as the loop is abruptly completed due to 'break'\");\r\n+\r\n+            returnCount = 0;\r\n+            (function () {\r\n+                for (i of iterable) {\r\n+                    return;\r\n+                }\r\n+            })();\r\n+            assert.areEqual(returnCount, 1, \"return function is called as the loop is abruptly completed due to 'return'\");\r\n+\r\n+            returnCount = 0;\r\n+            (function () {\r\n+                var loop = true;\r\n+                outer2 : while (loop) {\r\n+                    loop = false;\r\n+                    for (i of iterable) {\r\n+                        continue outer2;\r\n+                    }\r\n+                }\r\n+            })();\r\n+            assert.areEqual(returnCount, 1, \"return function is called as the loop is abruptly completed due to 'continue'\");\r\n+\r\n+            returnCount = 0;\r\n+            (function () {\r\n+                var loop = true;\r\n+                outer3 : while (loop) {\r\n+                    loop = false;\r\n+                    for (i of iterable) {\r\n+                        break outer3;\r\n+                    }\r\n+                }\r\n+            })();\r\n+            assert.areEqual(returnCount, 1, \"return function is called as the loop is abruptly completed due to 'break label'\");\r\n+\r\n+            nextCount = 0;\r\n+            returnCount = 0;\r\n+            assert.throws(function () {\r\n+                for (i of iterable) {\r\n+                    (function () {\r\n+                        throw new Error('break loop by causing an exception');\r\n+                    })();\r\n+                }\r\n+            }, Error);\r\n+            assert.areEqual(nextCount, 1, \"next function is called once as the loop iterates only once\");\r\n+            assert.areEqual(returnCount, 1, \"return function is called as the loop is abruptly completed due to an exception\");\r\n+            \r\n+\t\t}\r\n+\t},\r\n+    {\r\n+\t\tname : \"For..of - validation of .return function with nesting pattern\",\r\n+\t\tbody : function () {\r\n+            \r\n+            nextCount = 0;\r\n+            returnCount = 0;\r\n+            // Creating recursing iterator. the value is another iterator.\r\n+            value1 = iterable;\r\n+            (function() {\r\n+            for (var iter of iterable) {\r\n+                for (var iter2 of iter) {\r\n+                    return;\r\n+                }\r\n+            }\r\n+            })();\r\n+            \r\n+            assert.areEqual(nextCount, 2, \"Nested iterators - next function is called 2 times, once for each loop\");\r\n+            assert.areEqual(returnCount, 2, \"Nested iterators - return function is called 2 times as two loops are abruptly completed due to 'return'\");\r\n+            \r\n+            nextCount = 0;\r\n+            returnCount = 0;\r\n+            assert.throws(function() {\r\n+                for (var iter of iterable) {\r\n+                    for (var iter2 of iter) {\r\n+                        throw new Error('error');\r\n+                    }\r\n+                }\r\n+            }, Error);\r\n+            \r\n+            assert.areEqual(nextCount, 2, \"Nested iterators - next function is called 2 times, once for each loop\");\r\n+            assert.areEqual(returnCount, 2, \"Nested iterators - return function is called 2 times as two loops are abruptly completed due to exception\");\r\n+\t\t}\r\n+\t},    \r\n+    {\r\n+\t\tname : \"For..of - change .done to true will not call .return function\",\r\n+\t\tbody : function () {\r\n+            returnCount = 0;\r\n+            done1 = true;\r\n+            for (var i of iterable) {\r\n+                assert.fail('This will not reach as the .done is marked to true');\r\n+            }\r\n+            \r\n+            assert.areEqual(returnCount, 0, \"Loop is completed as .done is set to true, this ensures that return function should not be called\");\r\n+            done1 = false;\r\n+\t\t}\r\n+\t},    \r\n+    {\r\n+\t\tname : \"For..of - validating that causing an exception on assigning value to for..of head  will call .return function\",\r\n+\t\tbody : function () {\r\n+            returnCount = 0;\r\n+            assert.throws(function () {for (obj.prop of iterable) {\r\n+                assert.fail('Should not reach here as assigning to obj.prop throws');\r\n+            }}, Error, \"Assigning to loop head can throw\", \"From setter\");\r\n+            \r\n+            assert.areEqual(returnCount, 1, \"Abrupt loop break due to exception in assigning value to head should call return function\");\r\n+            \r\n+            returnCount = 0;\r\n+            value1 = iterable;\r\n+            assert.throws(function () {\r\n+                for (var iter1 of iterable) {\r\n+                    for (obj.prop of iter1) {\r\n+                        assert.fail('Should not reach here as assigning to obj.prop throws');\r\n+                    }\r\n+                }\r\n+            }, Error, \"Assigning to loop head can throw\", \"From setter\");\r\n+            \r\n+            assert.areEqual(returnCount, 2, \"Exception caused in inner loop when assigning value to head should call the return function\");\r\n+            value1 = 1;\r\n+\t\t}\r\n+\t},    \r\n+    {\r\n+\t\tname : \"For..of - .return function should not be called when .next function throws\",\r\n+\t\tbody : function () {\r\n+            returnCount = 0;\r\n+            shouldNextThrow = true;\r\n+            assert.throws(function () { for (var i of iterable) { } }, Error, \"Calling .next throws\", \"Exception from next function\");\r\n+            shouldNextThrow = false;\r\n+            assert.areEqual(returnCount, 0, \"Ensuring that exception in next function should not call the return function\");\r\n+\t\t}\r\n+\t},    \r\n+    {\r\n+\t\tname : \"For..of - .return function should not be called when fetching .value throws\",\r\n+\t\tbody : function () {\r\n+            var iterable2 = {};\r\n+            iterable2[Symbol.iterator] = function() {\r\n+              return {\r\n+                next: function() {\r\n+                    return {get value () { throw new Error('Exception while getting value'); }, done:false};\r\n+                },\r\n+                return: function() {\r\n+                    assert.fail('return should not be called');\r\n+                },\r\n+              };\r\n+            };\r\n+\r\n+            assert.throws(function () { for (var i of iterable2) { } }, Error,\r\n+                \".value causes an exception but that should not call the return function\",\r\n+                \"Exception while getting value\");\r\n+\t\t}\r\n+\t},    \r\n+    {\r\n+\t\tname : \"For..of - .return function can also throw\",\r\n+\t\tbody : function () {\r\n+            shouldReturnThrow = true;\r\n+            assert.throws(function () { for (var i of iterable) { break; } }, Error, \".return function throws\", \"Exception from return function\");\r\n+            shouldReturnThrow = false;\r\n+\t\t}\r\n+\t},    \r\n+    {\r\n+\t\tname : \"For..of - caller and .return function both throw and caller's exception wins\",\r\n+\t\tbody : function () {\r\n+            shouldReturnThrow = true;\r\n+            returnCount = 0;\r\n+            assert.throws(function () { for (obj.prop of iterable) { break; } }, Error, \"Setting value will throw\", \"From setter\");\r\n+            assert.areEqual(returnCount, 1, \"Ensuring that abrupt loop completion due to exception will call return function\");\r\n+            shouldReturnThrow = false;\r\n+\t\t}\r\n+\t},    \r\n+    {\r\n+\t\tname : \"For..of - with generator\",\r\n+\t\tbody : function () {\r\n+            var finallyCount = 0;\r\n+            function *gf() {\r\n+                try {\r\n+                    yield 1;\r\n+                    assert.fail('Should not reach here after yield');\r\n+                }\r\n+                finally {\r\n+                    finallyCount++;\r\n+                }\r\n+                assert.fail('Should not reach here after finally');;\r\n+            }\r\n+            \r\n+            for (var i of gf()) {\r\n+                break;\r\n+            }\r\n+\r\n+            assert.areEqual(finallyCount, 1, \"'break' causes the return function called which should execute the finally block\");\r\n+            \r\n+            finallyCount = 0;\r\n+            assert.throws(function () { for (obj.prop of gf()) { } }, Error, \"Setting value will throw\", \"From setter\");\r\n+            assert.areEqual(finallyCount, 1, \"Exception causes the return function called which should execute the finally block\");\r\n+            \r\n+            function* gf2() {\r\n+                yield 1;\r\n+                assert.fail('Should not reach here after yield');\r\n+            }\r\n+            var returnCount = 0;\r\n+            gf2.prototype.return = function() {\r\n+                returnCount++;\r\n+                return {};\r\n+            };\r\n+            \r\n+            for (var i of gf2()) {\r\n+                break;\r\n+            }\r\n+\r\n+            assert.areEqual(returnCount, 1, \"Loop break due to 'break' should call the return function on the generator\");\r\n+            \r\n+            gf2.prototype.return = function() {\r\n+                returnCount++;\r\n+                throw new Error('Exception from return function');\r\n+            };\r\n+            assert.throws(function () { for (i of gf2()) { break; } }, Error, \"return function throws\", \"Exception from return function\");\r\n+            returnCount = 0;\r\n+            assert.throws(function () { for (obj.prop of gf2()) { } }, Error, \"Exception at destructuring element wins\", \"From setter\");\r\n+            assert.areEqual(returnCount, 1, \"Exception in loop should call the return function\");\r\n+            \r\n+\t\t}\r\n+\t},    \r\n+    {\r\n+\t\tname : \"Iterator close with yield *\",\r","path":"test/es6/iteratorclose.js","position":626,"original_position":626,"commit_id":"22ecd5b591962eb464810b19943a5f32de29894e","original_commit_id":"22ecd5b591962eb464810b19943a5f32de29894e","user":{"login":"akroshg","id":13008822,"avatar_url":"https://avatars.githubusercontent.com/u/13008822?v=3","gravatar_id":"","url":"https://api.github.com/users/akroshg","html_url":"https://github.com/akroshg","followers_url":"https://api.github.com/users/akroshg/followers","following_url":"https://api.github.com/users/akroshg/following{/other_user}","gists_url":"https://api.github.com/users/akroshg/gists{/gist_id}","starred_url":"https://api.github.com/users/akroshg/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/akroshg/subscriptions","organizations_url":"https://api.github.com/users/akroshg/orgs","repos_url":"https://api.github.com/users/akroshg/repos","events_url":"https://api.github.com/users/akroshg/events{/privacy}","received_events_url":"https://api.github.com/users/akroshg/received_events","type":"User","site_admin":false},"body":"Thanks I'll take a look at that. I'll probably work on that in my next PR.","created_at":"2016-06-15T03:46:40Z","updated_at":"2016-06-15T03:46:40Z","html_url":"https://github.com/Microsoft/ChakraCore/pull/1107#discussion_r67095847","pull_request_url":"https://api.github.com/repos/Microsoft/ChakraCore/pulls/1107","_links":{"self":{"href":"https://api.github.com/repos/Microsoft/ChakraCore/pulls/comments/67095847"},"html":{"href":"https://github.com/Microsoft/ChakraCore/pull/1107#discussion_r67095847"},"pull_request":{"href":"https://api.github.com/repos/Microsoft/ChakraCore/pulls/1107"}}},"pull_request":{"url":"https://api.github.com/repos/Microsoft/ChakraCore/pulls/1107","id":73256681,"html_url":"https://github.com/Microsoft/ChakraCore/pull/1107","diff_url":"https://github.com/Microsoft/ChakraCore/pull/1107.diff","patch_url":"https://github.com/Microsoft/ChakraCore/pull/1107.patch","issue_url":"https://api.github.com/repos/Microsoft/ChakraCore/issues/1107","number":1107,"state":"open","locked":false,"title":"work for iteratorclose","user":{"login":"akroshg","id":13008822,"avatar_url":"https://avatars.githubusercontent.com/u/13008822?v=3","gravatar_id":"","url":"https://api.github.com/users/akroshg","html_url":"https://github.com/akroshg","followers_url":"https://api.github.com/users/akroshg/followers","following_url":"https://api.github.com/users/akroshg/following{/other_user}","gists_url":"https://api.github.com/users/akroshg/gists{/gist_id}","starred_url":"https://api.github.com/users/akroshg/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/akroshg/subscriptions","organizations_url":"https://api.github.com/users/akroshg/orgs","repos_url":"https://api.github.com/users/akroshg/repos","events_url":"https://api.github.com/users/akroshg/events{/privacy}","received_events_url":"https://api.github.com/users/akroshg/received_events","type":"User","site_admin":false},"body":"This changeset enables IteratorClose scenario for destructuring, for..of\nloop and built-ins (Promise, Array.from, Map, WeakMap, Set and WeakSet).\nClosing the iterator means calling the return function of the iterator. The implementation for destructuring and for..of is done in the Bytecode level.\nDestructuring : In the array destructuring pattern the try..finally\nbytecodes are emitted in order to capture the abrupt completion of the\ndestructuring elements assignment.\nFor..of : The loop is surrounded by try..catch..finally. The catch block\nis to tackle the abrupt completion due to exception and finally block is\nto tackle the scenarios which involves break, return, continue.\nAdded unittest.\n","created_at":"2016-06-09T17:48:35Z","updated_at":"2016-06-15T03:46:40Z","closed_at":null,"merged_at":null,"merge_commit_sha":"f2cabca49c55962d65e1d68a3d0fd1020f37728a","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/Microsoft/ChakraCore/pulls/1107/commits","review_comments_url":"https://api.github.com/repos/Microsoft/ChakraCore/pulls/1107/comments","review_comment_url":"https://api.github.com/repos/Microsoft/ChakraCore/pulls/comments{/number}","comments_url":"https://api.github.com/repos/Microsoft/ChakraCore/issues/1107/comments","statuses_url":"https://api.github.com/repos/Microsoft/ChakraCore/statuses/22ecd5b591962eb464810b19943a5f32de29894e","head":{"label":"akroshg:close2","ref":"close2","sha":"22ecd5b591962eb464810b19943a5f32de29894e","user":{"login":"akroshg","id":13008822,"avatar_url":"https://avatars.githubusercontent.com/u/13008822?v=3","gravatar_id":"","url":"https://api.github.com/users/akroshg","html_url":"https://github.com/akroshg","followers_url":"https://api.github.com/users/akroshg/followers","following_url":"https://api.github.com/users/akroshg/following{/other_user}","gists_url":"https://api.github.com/users/akroshg/gists{/gist_id}","starred_url":"https://api.github.com/users/akroshg/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/akroshg/subscriptions","organizations_url":"https://api.github.com/users/akroshg/orgs","repos_url":"https://api.github.com/users/akroshg/repos","events_url":"https://api.github.com/users/akroshg/events{/privacy}","received_events_url":"https://api.github.com/users/akroshg/received_events","type":"User","site_admin":false},"repo":{"id":50141519,"name":"ChakraCore","full_name":"akroshg/ChakraCore","owner":{"login":"akroshg","id":13008822,"avatar_url":"https://avatars.githubusercontent.com/u/13008822?v=3","gravatar_id":"","url":"https://api.github.com/users/akroshg","html_url":"https://github.com/akroshg","followers_url":"https://api.github.com/users/akroshg/followers","following_url":"https://api.github.com/users/akroshg/following{/other_user}","gists_url":"https://api.github.com/users/akroshg/gists{/gist_id}","starred_url":"https://api.github.com/users/akroshg/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/akroshg/subscriptions","organizations_url":"https://api.github.com/users/akroshg/orgs","repos_url":"https://api.github.com/users/akroshg/repos","events_url":"https://api.github.com/users/akroshg/events{/privacy}","received_events_url":"https://api.github.com/users/akroshg/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/akroshg/ChakraCore","description":"ChakraCore is the core part of the Chakra Javascript engine that powers Microsoft Edge","fork":true,"url":"https://api.github.com/repos/akroshg/ChakraCore","forks_url":"https://api.github.com/repos/akroshg/ChakraCore/forks","keys_url":"https://api.github.com/repos/akroshg/ChakraCore/keys{/key_id}","collaborators_url":"https://api.github.com/repos/akroshg/ChakraCore/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/akroshg/ChakraCore/teams","hooks_url":"https://api.github.com/repos/akroshg/ChakraCore/hooks","issue_events_url":"https://api.github.com/repos/akroshg/ChakraCore/issues/events{/number}","events_url":"https://api.github.com/repos/akroshg/ChakraCore/events","assignees_url":"https://api.github.com/repos/akroshg/ChakraCore/assignees{/user}","branches_url":"https://api.github.com/repos/akroshg/ChakraCore/branches{/branch}","tags_url":"https://api.github.com/repos/akroshg/ChakraCore/tags","blobs_url":"https://api.github.com/repos/akroshg/ChakraCore/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/akroshg/ChakraCore/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/akroshg/ChakraCore/git/refs{/sha}","trees_url":"https://api.github.com/repos/akroshg/ChakraCore/git/trees{/sha}","statuses_url":"https://api.github.com/repos/akroshg/ChakraCore/statuses/{sha}","languages_url":"https://api.github.com/repos/akroshg/ChakraCore/languages","stargazers_url":"https://api.github.com/repos/akroshg/ChakraCore/stargazers","contributors_url":"https://api.github.com/repos/akroshg/ChakraCore/contributors","subscribers_url":"https://api.github.com/repos/akroshg/ChakraCore/subscribers","subscription_url":"https://api.github.com/repos/akroshg/ChakraCore/subscription","commits_url":"https://api.github.com/repos/akroshg/ChakraCore/commits{/sha}","git_commits_url":"https://api.github.com/repos/akroshg/ChakraCore/git/commits{/sha}","comments_url":"https://api.github.com/repos/akroshg/ChakraCore/comments{/number}","issue_comment_url":"https://api.github.com/repos/akroshg/ChakraCore/issues/comments{/number}","contents_url":"https://api.github.com/repos/akroshg/ChakraCore/contents/{+path}","compare_url":"https://api.github.com/repos/akroshg/ChakraCore/compare/{base}...{head}","merges_url":"https://api.github.com/repos/akroshg/ChakraCore/merges","archive_url":"https://api.github.com/repos/akroshg/ChakraCore/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/akroshg/ChakraCore/downloads","issues_url":"https://api.github.com/repos/akroshg/ChakraCore/issues{/number}","pulls_url":"https://api.github.com/repos/akroshg/ChakraCore/pulls{/number}","milestones_url":"https://api.github.com/repos/akroshg/ChakraCore/milestones{/number}","notifications_url":"https://api.github.com/repos/akroshg/ChakraCore/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/akroshg/ChakraCore/labels{/name}","releases_url":"https://api.github.com/repos/akroshg/ChakraCore/releases{/id}","deployments_url":"https://api.github.com/repos/akroshg/ChakraCore/deployments","created_at":"2016-01-21T22:36:49Z","updated_at":"2016-01-21T22:37:05Z","pushed_at":"2016-06-14T23:04:44Z","git_url":"git://github.com/akroshg/ChakraCore.git","ssh_url":"git@github.com:akroshg/ChakraCore.git","clone_url":"https://github.com/akroshg/ChakraCore.git","svn_url":"https://github.com/akroshg/ChakraCore","homepage":null,"size":30126,"stargazers_count":0,"watchers_count":0,"language":"JavaScript","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"Microsoft:master","ref":"master","sha":"cc613d8d8c02897f98756e9ada9360628eb94cde","user":{"login":"Microsoft","id":6154722,"avatar_url":"https://avatars.githubusercontent.com/u/6154722?v=3","gravatar_id":"","url":"https://api.github.com/users/Microsoft","html_url":"https://github.com/Microsoft","followers_url":"https://api.github.com/users/Microsoft/followers","following_url":"https://api.github.com/users/Microsoft/following{/other_user}","gists_url":"https://api.github.com/users/Microsoft/gists{/gist_id}","starred_url":"https://api.github.com/users/Microsoft/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Microsoft/subscriptions","organizations_url":"https://api.github.com/users/Microsoft/orgs","repos_url":"https://api.github.com/users/Microsoft/repos","events_url":"https://api.github.com/users/Microsoft/events{/privacy}","received_events_url":"https://api.github.com/users/Microsoft/received_events","type":"Organization","site_admin":false},"repo":{"id":49086513,"name":"ChakraCore","full_name":"Microsoft/ChakraCore","owner":{"login":"Microsoft","id":6154722,"avatar_url":"https://avatars.githubusercontent.com/u/6154722?v=3","gravatar_id":"","url":"https://api.github.com/users/Microsoft","html_url":"https://github.com/Microsoft","followers_url":"https://api.github.com/users/Microsoft/followers","following_url":"https://api.github.com/users/Microsoft/following{/other_user}","gists_url":"https://api.github.com/users/Microsoft/gists{/gist_id}","starred_url":"https://api.github.com/users/Microsoft/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Microsoft/subscriptions","organizations_url":"https://api.github.com/users/Microsoft/orgs","repos_url":"https://api.github.com/users/Microsoft/repos","events_url":"https://api.github.com/users/Microsoft/events{/privacy}","received_events_url":"https://api.github.com/users/Microsoft/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/Microsoft/ChakraCore","description":"ChakraCore is the core part of the Chakra Javascript engine that powers Microsoft Edge","fork":false,"url":"https://api.github.com/repos/Microsoft/ChakraCore","forks_url":"https://api.github.com/repos/Microsoft/ChakraCore/forks","keys_url":"https://api.github.com/repos/Microsoft/ChakraCore/keys{/key_id}","collaborators_url":"https://api.github.com/repos/Microsoft/ChakraCore/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/Microsoft/ChakraCore/teams","hooks_url":"https://api.github.com/repos/Microsoft/ChakraCore/hooks","issue_events_url":"https://api.github.com/repos/Microsoft/ChakraCore/issues/events{/number}","events_url":"https://api.github.com/repos/Microsoft/ChakraCore/events","assignees_url":"https://api.github.com/repos/Microsoft/ChakraCore/assignees{/user}","branches_url":"https://api.github.com/repos/Microsoft/ChakraCore/branches{/branch}","tags_url":"https://api.github.com/repos/Microsoft/ChakraCore/tags","blobs_url":"https://api.github.com/repos/Microsoft/ChakraCore/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/Microsoft/ChakraCore/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/Microsoft/ChakraCore/git/refs{/sha}","trees_url":"https://api.github.com/repos/Microsoft/ChakraCore/git/trees{/sha}","statuses_url":"https://api.github.com/repos/Microsoft/ChakraCore/statuses/{sha}","languages_url":"https://api.github.com/repos/Microsoft/ChakraCore/languages","stargazers_url":"https://api.github.com/repos/Microsoft/ChakraCore/stargazers","contributors_url":"https://api.github.com/repos/Microsoft/ChakraCore/contributors","subscribers_url":"https://api.github.com/repos/Microsoft/ChakraCore/subscribers","subscription_url":"https://api.github.com/repos/Microsoft/ChakraCore/subscription","commits_url":"https://api.github.com/repos/Microsoft/ChakraCore/commits{/sha}","git_commits_url":"https://api.github.com/repos/Microsoft/ChakraCore/git/commits{/sha}","comments_url":"https://api.github.com/repos/Microsoft/ChakraCore/comments{/number}","issue_comment_url":"https://api.github.com/repos/Microsoft/ChakraCore/issues/comments{/number}","contents_url":"https://api.github.com/repos/Microsoft/ChakraCore/contents/{+path}","compare_url":"https://api.github.com/repos/Microsoft/ChakraCore/compare/{base}...{head}","merges_url":"https://api.github.com/repos/Microsoft/ChakraCore/merges","archive_url":"https://api.github.com/repos/Microsoft/ChakraCore/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/Microsoft/ChakraCore/downloads","issues_url":"https://api.github.com/repos/Microsoft/ChakraCore/issues{/number}","pulls_url":"https://api.github.com/repos/Microsoft/ChakraCore/pulls{/number}","milestones_url":"https://api.github.com/repos/Microsoft/ChakraCore/milestones{/number}","notifications_url":"https://api.github.com/repos/Microsoft/ChakraCore/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/Microsoft/ChakraCore/labels{/name}","releases_url":"https://api.github.com/repos/Microsoft/ChakraCore/releases{/id}","deployments_url":"https://api.github.com/repos/Microsoft/ChakraCore/deployments","created_at":"2016-01-05T19:05:31Z","updated_at":"2016-06-15T02:50:31Z","pushed_at":"2016-06-15T01:36:45Z","git_url":"git://github.com/Microsoft/ChakraCore.git","ssh_url":"git@github.com:Microsoft/ChakraCore.git","clone_url":"https://github.com/Microsoft/ChakraCore.git","svn_url":"https://github.com/Microsoft/ChakraCore","homepage":null,"size":41070,"stargazers_count":5266,"watchers_count":5266,"language":"JavaScript","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":589,"mirror_url":null,"open_issues_count":144,"forks":589,"open_issues":144,"watchers":5266,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/Microsoft/ChakraCore/pulls/1107"},"html":{"href":"https://github.com/Microsoft/ChakraCore/pull/1107"},"issue":{"href":"https://api.github.com/repos/Microsoft/ChakraCore/issues/1107"},"comments":{"href":"https://api.github.com/repos/Microsoft/ChakraCore/issues/1107/comments"},"review_comments":{"href":"https://api.github.com/repos/Microsoft/ChakraCore/pulls/1107/comments"},"review_comment":{"href":"https://api.github.com/repos/Microsoft/ChakraCore/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/Microsoft/ChakraCore/pulls/1107/commits"},"statuses":{"href":"https://api.github.com/repos/Microsoft/ChakraCore/statuses/22ecd5b591962eb464810b19943a5f32de29894e"}}}}
{"actor":{"display_login":"akroshg"}}