diff --git a/test/language/expressions/assignment/destructuring/array-elem-iter-get-err.js b/test/language/expressions/assignment/destructuring/array-elem-iter-get-err.js new file mode 100644 index 0000000000000000000000000000000000000000..2f545842fdec310241fe1ea53082a1052d024cd4 --- /dev/null +++ b/test/language/expressions/assignment/destructuring/array-elem-iter-get-err.js @@ -0,0 +1,23 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: Abrupt completion returned from GetIterator +info: | + ArrayAssignmentPattern : [ AssignmentElementList ] + + 1. Let iterator be GetIterator(value). + 2. ReturnIfAbrupt(iterator). +features: [Symbol.iterator] +es6id: 12.14.5.2 +esid: sec-runtime-semantics-destructuringassignmentevaluation +---*/ + +var iterable = {}; +iterable[Symbol.iterator] = function() { + throw new Test262Error(); +}; +var x; + +assert.throws(Test262Error, function() { + [ x ] = iterable; +}); diff --git a/test/language/expressions/assignment/destructuring/array-elem-iter-nrml-close-err.js b/test/language/expressions/assignment/destructuring/array-elem-iter-nrml-close-err.js new file mode 100644 index 0000000000000000000000000000000000000000..414495122ca13bd92fec79be6f486c5c0f42ad20 --- /dev/null +++ b/test/language/expressions/assignment/destructuring/array-elem-iter-nrml-close-err.js @@ -0,0 +1,40 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: Abrupt completion returned from IteratorClose +info: | + ArrayAssignmentPattern : [ AssignmentElementList ] + + [...] + 5. If iteratorRecord.[[done]] is false, return IteratorClose(iterator, result). +features: [Symbol.iterator] +es6id: 12.14.5.2 +esid: sec-runtime-semantics-destructuringassignmentevaluation +---*/ + +var nextCount = 0; +var returnCount = 0; +var x; +var iterable = {}; +var iterator = { + next: function() { + nextCount += 1; + // Set an upper-bound to limit unnecessary iteration in non-conformant + // implementations + return { done: nextCount > 10 }; + }, + return: function() { + returnCount += 1; + throw new Test262Error(); + } +}; +iterable[Symbol.iterator] = function() { + return iterator; +}; + +assert.throws(Test262Error, function() { + [ x ] = iterable; +}); + +assert.sameValue(nextCount, 1); +assert.sameValue(returnCount, 1); diff --git a/test/language/expressions/assignment/destructuring/array-elem-iter-nrml-close-null.js b/test/language/expressions/assignment/destructuring/array-elem-iter-nrml-close-null.js new file mode 100644 index 0000000000000000000000000000000000000000..67e3ead4d0d579817c4c7009c21ca3f307b20976 --- /dev/null +++ b/test/language/expressions/assignment/destructuring/array-elem-iter-nrml-close-null.js @@ -0,0 +1,47 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: > + IteratorClose throws a TypeError when `return` returns a non-Object value +info: | + ArrayAssignmentPattern : [ AssignmentElementList ] + + [...] + 5. If iteratorRecord.[[done]] is false, return IteratorClose(iterator, + result). + 6. Return result. + + 7.4.6 IteratorClose( iterator, completion ) + + [...] + 6. Let innerResult be Call(return, iterator, « »). + 7. If completion.[[type]] is throw, return Completion(completion). + 8. If innerResult.[[type]] is throw, return Completion(innerResult). + 9. If Type(innerResult.[[value]]) is not Object, throw a TypeError + exception. +features: [Symbol.iterator] +es6id: 12.14.5.2 +esid: sec-runtime-semantics-destructuringassignmentevaluation +---*/ + +var x; +var iterable = {}; +var nextCount = 0; +var iterator = { + next: function() { + nextCount += 1; + // Set an upper-bound to limit unnecessary iteration in non-conformant + // implementations + return { done: nextCount > 10 }; + }, + return: function() { + return null; + } +}; +iterable[Symbol.iterator] = function() { + return iterator; +}; + +assert.throws(TypeError, function() { + [ x ] = iterable; +}); diff --git a/test/language/expressions/assignment/destructuring/array-elem-iter-nrml-close-skip.js b/test/language/expressions/assignment/destructuring/array-elem-iter-nrml-close-skip.js new file mode 100644 index 0000000000000000000000000000000000000000..c3b2087e8b0b2c313456741f8b62b2c9ca1028a5 --- /dev/null +++ b/test/language/expressions/assignment/destructuring/array-elem-iter-nrml-close-skip.js @@ -0,0 +1,39 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: > + IteratorClose is not called when assignment evaluation has exhausted the + iterator +info: | + ArrayAssignmentPattern : [ AssignmentElementList ] + + [...] + 5. If iteratorRecord.[[done]] is false, return IteratorClose(iterator, result). + 6. Return result. +features: [Symbol.iterator] +es6id: 12.14.5.2 +esid: sec-runtime-semantics-destructuringassignmentevaluation +---*/ + +var nextCount = 0; +var returnCount = 0; +var x; +var iterable = {}; +var iterator = { + next: function() { + nextCount += 1; + return { done: true }; + }, + return: function() { + returnCount += 1; + return {}; + } +}; +iterable[Symbol.iterator] = function() { + return iterator; +}; + +[ x ] = iterable; + +assert.sameValue(nextCount, 1); +assert.sameValue(returnCount, 0); diff --git a/test/language/expressions/assignment/destructuring/array-elem-iter-nrml-close.js b/test/language/expressions/assignment/destructuring/array-elem-iter-nrml-close.js new file mode 100644 index 0000000000000000000000000000000000000000..80f9902b03a7db0749619d490a66a54dab52f741 --- /dev/null +++ b/test/language/expressions/assignment/destructuring/array-elem-iter-nrml-close.js @@ -0,0 +1,55 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: > + IteratorClose is called when assignment evaluation has not exhausted the + iterator +info: | + ArrayAssignmentPattern : [ AssignmentElementList ] + + [...] + 5. If iteratorRecord.[[done]] is false, return IteratorClose(iterator, + result). + 6. Return result. + + 7.4.6 IteratorClose( iterator, completion ) + + [...] + 6. Let innerResult be Call(return, iterator, « »). + [...] +features: [Symbol.iterator] +es6id: 12.14.5.2 +esid: sec-runtime-semantics-destructuringassignmentevaluation +---*/ + +var nextCount = 0; +var returnCount = 0; +var thisValue = null; +var args = null; +var x; +var iterable = {}; +var iterator = { + next: function() { + nextCount += 1; + // Set an upper-bound to limit unnecessary iteration in non-conformant + // implementations + return { done: nextCount > 10 }; + }, + return: function() { + returnCount += 1; + thisValue = this; + args = arguments; + return {}; + } +}; +iterable[Symbol.iterator] = function() { + return iterator; +}; + +[ x ] = iterable; + +assert.sameValue(nextCount, 1); +assert.sameValue(returnCount, 1); +assert.sameValue(thisValue, iterator, 'correct `this` value'); +assert(!!args, 'arguments object provided'); +assert.sameValue(args.length, 0, 'zero arguments specified'); diff --git a/test/language/expressions/assignment/destructuring/array-elem-iter-rtrn-close-err.js b/test/language/expressions/assignment/destructuring/array-elem-iter-rtrn-close-err.js new file mode 100644 index 0000000000000000000000000000000000000000..4b3b2a36ae75b0623dd3c6178be83806f413777f --- /dev/null +++ b/test/language/expressions/assignment/destructuring/array-elem-iter-rtrn-close-err.js @@ -0,0 +1,51 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: > + IteratorClose is called when reference evaluation produces a "return" + completion +info: | + ArrayAssignmentPattern : [ AssignmentElementList ] + + [...] + 5. If iteratorRecord.[[done]] is false, return IteratorClose(iterator, + result). + 6. Return result. + + 7.4.6 IteratorClose( iterator, completion ) + + [...] + 6. Let innerResult be Call(return, iterator, « »). + 7. If completion.[[type]] is throw, return Completion(completion). + 8. If innerResult.[[type]] is throw, return Completion(innerResult). +features: [Symbol.iterator, generators] +es6id: 12.14.5.2 +esid: sec-runtime-semantics-destructuringassignmentevaluation +---*/ + +var returnCount = 0; +var unreachable = 0; +var iterable = {}; +var iterator = { + return: function() { + returnCount += 1; + throw new Test262Error(); + } +}; +var iter; +iterable[Symbol.iterator] = function() { + return iterator; +}; + +function* g() { + [ {}[yield] ] = iterable; + unreachable += 1; +} +iter = g(); +iter.next(); +assert.throws(Test262Error, function() { + iter.return(); +}); + +assert.sameValue(returnCount, 1); +assert.sameValue(unreachable, 0, 'Unreachable statement was not executed'); diff --git a/test/language/expressions/assignment/destructuring/array-elem-iter-rtrn-close-null.js b/test/language/expressions/assignment/destructuring/array-elem-iter-rtrn-close-null.js new file mode 100644 index 0000000000000000000000000000000000000000..4e95868e8c4bc681a4685c2c81cd0a21a79d9aac --- /dev/null +++ b/test/language/expressions/assignment/destructuring/array-elem-iter-rtrn-close-null.js @@ -0,0 +1,47 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: > + IteratorClose throws a TypeError when `return` returns a non-Object value +info: | + ArrayAssignmentPattern : [ AssignmentElementList ] + + [...] + 5. If iteratorRecord.[[done]] is false, return IteratorClose(iterator, + result). + 6. Return result. + + 7.4.6 IteratorClose( iterator, completion ) + + [...] + 6. Let innerResult be Call(return, iterator, « »). + 7. If completion.[[type]] is throw, return Completion(completion). + 8. If innerResult.[[type]] is throw, return Completion(innerResult). + 9. If Type(innerResult.[[value]]) is not Object, throw a TypeError + exception. +features: [Symbol.iterator, generators] +es6id: 12.14.5.2 +esid: sec-runtime-semantics-destructuringassignmentevaluation +---*/ + +var iterable = {}; +var iterator = { + return: function() { + return null; + } +}; +var iter; +iterable[Symbol.iterator] = function() { + return iterator; +}; +function* g() { + [ {}[yield] ] = iterable; + unreachable += 1; +} + +iter = g(); +iter.next(); + +assert.throws(TypeError, function() { + iter.return(); +}); diff --git a/test/language/expressions/assignment/destructuring/array-elem-iter-rtrn-close.js b/test/language/expressions/assignment/destructuring/array-elem-iter-rtrn-close.js new file mode 100644 index 0000000000000000000000000000000000000000..2d9380de2053f86b0d8a1c7a293efc07792adde3 --- /dev/null +++ b/test/language/expressions/assignment/destructuring/array-elem-iter-rtrn-close.js @@ -0,0 +1,58 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: > + IteratorClose is called when reference evaluation produces a "return" + completion +info: | + ArrayAssignmentPattern : [ AssignmentElementList ] + + [...] + 5. If iteratorRecord.[[done]] is false, return IteratorClose(iterator, + result). + 6. Return result. + + 7.4.6 IteratorClose( iterator, completion ) + + [...] + 6. Let innerResult be Call(return, iterator, « »). + 7. If completion.[[type]] is throw, return Completion(completion). + 8. If innerResult.[[type]] is throw, return Completion(innerResult). +features: [Symbol.iterator, generators] +es6id: 12.14.5.2 +esid: sec-runtime-semantics-destructuringassignmentevaluation +---*/ + +var returnCount = 0; +var unreachable = 0; +var thisValue = null; +var args = null; +var iterable = {}; +var iterator = { + return: function() { + returnCount += 1; + thisValue = this; + args = arguments; + return {}; + } +}; +var iter, result; +iterable[Symbol.iterator] = function() { + return iterator; +}; + +function* g() { + [ {}[yield] ] = iterable; + unreachable += 1; +} +iter = g(); +iter.next(); +result = iter.return(777); + +assert.sameValue(returnCount, 1); +assert.sameValue(unreachable, 0, 'Unreachable statement was not executed'); +assert.sameValue(result.value, 777); +assert(result.done, 'Iterator correctly closed'); +assert.sameValue(thisValue, iterator, 'correct `this` value'); +assert(!!args, 'arguments object provided'); +assert.sameValue(args.length, 0, 'zero arguments specified'); diff --git a/test/language/expressions/assignment/destructuring/array-elem-iter-thrw-close-err.js b/test/language/expressions/assignment/destructuring/array-elem-iter-thrw-close-err.js new file mode 100644 index 0000000000000000000000000000000000000000..d92f9a4359970bcd815710d76916b8558c525421 --- /dev/null +++ b/test/language/expressions/assignment/destructuring/array-elem-iter-thrw-close-err.js @@ -0,0 +1,47 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: > + IteratorClose is called when reference evaluation produces a "throw" + completion +info: | + ArrayAssignmentPattern : [ AssignmentElementList ] + + [...] + 5. If iteratorRecord.[[done]] is false, return IteratorClose(iterator, + result). + 6. Return result. +features: [Symbol.iterator] +es6id: 12.14.5.2 +esid: sec-runtime-semantics-destructuringassignmentevaluation +---*/ + +var nextCount = 0; +var returnCount = 0; +function ReturnError() {} +var iterable = {}; +var iterator = { + next: function() { + nextCount += 1; + return { done: true }; + }, + return: function() { + returnCount += 1; + + // This value should be discarded. + throw new ReturnError(); + } +}; +var thrower = function() { + throw new Test262Error(); +}; +iterable[Symbol.iterator] = function() { + return iterator; +}; + +assert.throws(Test262Error, function() { + [ {}[thrower()] ] = iterable; +}); + +assert.sameValue(nextCount, 0); +assert.sameValue(returnCount, 1); diff --git a/test/language/expressions/assignment/destructuring/array-elem-iter-thrw-close-skip.js b/test/language/expressions/assignment/destructuring/array-elem-iter-thrw-close-skip.js new file mode 100644 index 0000000000000000000000000000000000000000..fc27f58e38d58458f6fcd7b6d5a29bcd46fa2247 --- /dev/null +++ b/test/language/expressions/assignment/destructuring/array-elem-iter-thrw-close-skip.js @@ -0,0 +1,40 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: > + IteratorClose is not called when iteration produces an abrupt completion +info: | + ArrayAssignmentPattern : [ AssignmentElementList ] + + [...] + 5. If iteratorRecord.[[done]] is false, return IteratorClose(iterator, + result). + 6. Return result. +features: [Symbol.iterator] +es6id: 12.14.5.2 +esid: sec-runtime-semantics-destructuringassignmentevaluation +---*/ + +var nextCount = 0; +var returnCount = 0; +var iterable = {}; +var iterator = { + next: function() { + nextCount += 1; + throw new Test262Error(); + }, + return: function() { + returnCount += 1; + } +}; +iterable[Symbol.iterator] = function() { + return iterator; +}; +var x; + +assert.throws(Test262Error, function() { + [ x ] = iterable; +}); + +assert.sameValue(nextCount, 1); +assert.sameValue(returnCount, 0); diff --git a/test/language/expressions/assignment/destructuring/array-elem-iter-thrw-close.js b/test/language/expressions/assignment/destructuring/array-elem-iter-thrw-close.js new file mode 100644 index 0000000000000000000000000000000000000000..4474c432fc36ffd9573af3dc95cf20fc5af8a122 --- /dev/null +++ b/test/language/expressions/assignment/destructuring/array-elem-iter-thrw-close.js @@ -0,0 +1,56 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: > + IteratorClose is called when reference evaluation produces a "throw" + completion +info: | + ArrayAssignmentPattern : [ AssignmentElementList ] + + [...] + 5. If iteratorRecord.[[done]] is false, return IteratorClose(iterator, + result). + 6. Return result. + + 7.4.6 IteratorClose( iterator, completion ) + + [...] + 6. Let innerResult be Call(return, iterator, « »). + [...] +features: [Symbol.iterator] +es6id: 12.14.5.2 +esid: sec-runtime-semantics-destructuringassignmentevaluation +---*/ + +var nextCount = 0; +var returnCount = 0; +var thisValue = null; +var args = null; +var iterable = {}; +var iterator = { + next: function() { + nextCount += 1; + return { done: true }; + }, + return: function() { + returnCount += 1; + thisValue = this; + args = arguments; + } +}; +var thrower = function() { + throw new Test262Error(); +}; +iterable[Symbol.iterator] = function() { + return iterator; +}; + +assert.throws(Test262Error, function() { + [ {}[thrower()] ] = iterable; +}); + +assert.sameValue(nextCount, 0); +assert.sameValue(returnCount, 1); +assert.sameValue(thisValue, iterator, 'correct `this` value'); +assert(!!args, 'arguments object provided'); +assert.sameValue(args.length, 0, 'zero arguments specified'); diff --git a/test/language/expressions/assignment/destructuring/array-elem-trlg-iter-elision-iter-abpt.js b/test/language/expressions/assignment/destructuring/array-elem-trlg-iter-elision-iter-abpt.js new file mode 100644 index 0000000000000000000000000000000000000000..c4624b2c48109267299735651ae59bd4433c2421 --- /dev/null +++ b/test/language/expressions/assignment/destructuring/array-elem-trlg-iter-elision-iter-abpt.js @@ -0,0 +1,52 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: Abrupt completion returned during evaluation of elision +info: | + ArrayAssignmentPattern : + [ AssignmentElementList , Elisionopt AssignmentRestElementopt ] + + [...] + 6. If Elision is present, then + a. Let status be the result of performing + IteratorDestructuringAssignmentEvaluation of Elision with + iteratorRecord as the argument. + b. If status is an abrupt completion, then + i. If iteratorRecord.[[done]] is false, return + IteratorClose(iterator, status). + ii. Return Completion(status). +features: [Symbol.iterator] +es6id: 12.14.5.2 +esid: sec-runtime-semantics-destructuringassignmentevaluation +---*/ + +var nextCount = 0; +var returnCount = 0; +var iterable = {}; +var x; +var iterator = { + next: function() { + nextCount += 1; + + if (nextCount === 2) { + throw new Test262Error(); + } + + // Set an upper-bound to limit unnecessary iteration in non-conformant + // implementations + return { done: nextCount > 10 }; + }, + return: function() { + returnCount += 1; + } +}; +iterable[Symbol.iterator] = function() { + return iterator; +}; + +assert.throws(Test262Error, function() { + [ x , , ] = iterable; +}); + +assert.sameValue(nextCount, 2); +assert.sameValue(returnCount, 0); diff --git a/test/language/expressions/assignment/destructuring/array-elem-trlg-iter-elision-iter-nrml-close-err.js b/test/language/expressions/assignment/destructuring/array-elem-trlg-iter-elision-iter-nrml-close-err.js new file mode 100644 index 0000000000000000000000000000000000000000..abb0aa22bbf9312399004ea8a9fb7f22b39cec69 --- /dev/null +++ b/test/language/expressions/assignment/destructuring/array-elem-trlg-iter-elision-iter-nrml-close-err.js @@ -0,0 +1,49 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: Abrupt completion returned from IteratorClose +info: | + ArrayAssignmentPattern : + [ AssignmentElementList , Elisionopt AssignmentRestElementopt ] + + [...] + 6. If Elision is present, then + a. Let status be the result of performing + IteratorDestructuringAssignmentEvaluation of Elision with + iteratorRecord as the argument. + b. If status is an abrupt completion, then + [...] + 8. If iteratorRecord.[[done]] is false, return IteratorClose(iterator, + status). +features: [Symbol.iterator] +es6id: 12.14.5.2 +esid: sec-runtime-semantics-destructuringassignmentevaluation +---*/ + +var nextCount = 0; +var returnCount = 0; +var iterable = {}; +var x; +var iterator = { + next: function() { + nextCount += 1; + + // Set an upper-bound to limit unnecessary iteration in non-conformant + // implementations + return { done: nextCount > 10 }; + }, + return: function() { + returnCount += 1; + throw new Test262Error(); + } +}; +iterable[Symbol.iterator] = function() { + return iterator; +}; + +assert.throws(Test262Error, function() { + [ x , , ] = iterable; +}); + +assert.sameValue(nextCount, 2); +assert.sameValue(returnCount, 1); diff --git a/test/language/expressions/assignment/destructuring/array-elem-trlg-iter-elision-iter-nrml-close-null.js b/test/language/expressions/assignment/destructuring/array-elem-trlg-iter-elision-iter-nrml-close-null.js new file mode 100644 index 0000000000000000000000000000000000000000..edb875d5e6b1a6d685e17b6001eb38b4ebe36b6c --- /dev/null +++ b/test/language/expressions/assignment/destructuring/array-elem-trlg-iter-elision-iter-nrml-close-null.js @@ -0,0 +1,53 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: > + IteratorClose throws a TypeError when `return` returns a non-Object value +info: | + ArrayAssignmentPattern : + [ AssignmentElementList , Elisionopt AssignmentRestElementopt ] + + [...] + 6. If Elision is present, then + a. Let status be the result of performing + IteratorDestructuringAssignmentEvaluation of Elision with + iteratorRecord as the argument. + b. If status is an abrupt completion, then + [...] + 8. If iteratorRecord.[[done]] is false, return IteratorClose(iterator, + status). + + 7.4.6 IteratorClose( iterator, completion ) + + [...] + 6. Let innerResult be Call(return, iterator, « »). + 7. If completion.[[type]] is throw, return Completion(completion). + 8. If innerResult.[[type]] is throw, return Completion(innerResult). + 9. If Type(innerResult.[[value]]) is not Object, throw a TypeError + exception. +features: [Symbol.iterator] +es6id: 12.14.5.2 +esid: sec-runtime-semantics-destructuringassignmentevaluation +---*/ + +var iterable = {}; +var x; +var nextCount = 0; +var iterator = { + next: function() { + nextCount += 1; + // Set an upper-bound to limit unnecessary iteration in non-conformant + // implementations + return { done: nextCount > 10 }; + }, + return: function() { + return null; + } +}; +iterable[Symbol.iterator] = function() { + return iterator; +}; + +assert.throws(TypeError, function() { + [ x , , ] = iterable; +}); diff --git a/test/language/expressions/assignment/destructuring/array-elem-trlg-iter-elision-iter-nrml-close-skip.js b/test/language/expressions/assignment/destructuring/array-elem-trlg-iter-elision-iter-nrml-close-skip.js new file mode 100644 index 0000000000000000000000000000000000000000..e1ba46661f39ab4b9c774c73db393dc61ac525d3 --- /dev/null +++ b/test/language/expressions/assignment/destructuring/array-elem-trlg-iter-elision-iter-nrml-close-skip.js @@ -0,0 +1,45 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: IteratorClose not invoked when elision exhausts the iterator +info: | + ArrayAssignmentPattern : + [ AssignmentElementList , Elisionopt AssignmentRestElementopt ] + + [...] + 6. If Elision is present, then + a. Let status be the result of performing + IteratorDestructuringAssignmentEvaluation of Elision with + iteratorRecord as the argument. + b. If status is an abrupt completion, then + [...] + 8. If iteratorRecord.[[done]] is false, return IteratorClose(iterator, + status). + 9. Return Completion(status). +features: [Symbol.iterator] +es6id: 12.14.5.2 +esid: sec-runtime-semantics-destructuringassignmentevaluation +---*/ + +var nextCount = 0; +var returnCount = 0; +var iterable = {}; +var x; +var iterator = { + next: function() { + nextCount += 1; + + return { done: nextCount > 1 }; + }, + return: function() { + returnCount += 1; + } +}; +iterable[Symbol.iterator] = function() { + return iterator; +}; + +[ x , , ] = iterable; + +assert.sameValue(nextCount, 2); +assert.sameValue(returnCount, 0); diff --git a/test/language/expressions/assignment/destructuring/array-elem-trlg-iter-elision-iter-nrml-close.js b/test/language/expressions/assignment/destructuring/array-elem-trlg-iter-elision-iter-nrml-close.js new file mode 100644 index 0000000000000000000000000000000000000000..b7846bb1abe28ac06409a531d85f7b71f7659790 --- /dev/null +++ b/test/language/expressions/assignment/destructuring/array-elem-trlg-iter-elision-iter-nrml-close.js @@ -0,0 +1,60 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: IteratorClose invoked when elision does not exhaust the iterator +info: | + ArrayAssignmentPattern : + [ AssignmentElementList , Elisionopt AssignmentRestElementopt ] + + [...] + 6. If Elision is present, then + a. Let status be the result of performing + IteratorDestructuringAssignmentEvaluation of Elision with + iteratorRecord as the argument. + b. If status is an abrupt completion, then + [...] + 8. If iteratorRecord.[[done]] is false, return IteratorClose(iterator, + status). + + 7.4.6 IteratorClose( iterator, completion ) + + [...] + 6. Let innerResult be Call(return, iterator, « »). + [...] +features: [Symbol.iterator] +es6id: 12.14.5.2 +esid: sec-runtime-semantics-destructuringassignmentevaluation +---*/ + +var nextCount = 0; +var returnCount = 0; +var thisValue = null; +var args = null; +var iterable = {}; +var x; +var iterator = { + next: function() { + nextCount += 1; + + // Set an upper-bound to limit unnecessary iteration in non-conformant + // implementations + return { done: nextCount > 10 }; + }, + return: function() { + returnCount += 1; + thisValue = this; + args = arguments; + return {}; + } +}; +iterable[Symbol.iterator] = function() { + return iterator; +}; + +[ x , , ] = iterable; + +assert.sameValue(nextCount, 2); +assert.sameValue(returnCount, 1); +assert.sameValue(thisValue, iterator, 'correct `this` value'); +assert(!!args, 'arguments object provided'); +assert.sameValue(args.length, 0, 'zero arguments specified'); diff --git a/test/language/expressions/assignment/destructuring/array-elem-trlg-iter-get-err.js b/test/language/expressions/assignment/destructuring/array-elem-trlg-iter-get-err.js new file mode 100644 index 0000000000000000000000000000000000000000..7a3e3a9a3a4c2e7286cb4b551295e526fbd47f1e --- /dev/null +++ b/test/language/expressions/assignment/destructuring/array-elem-trlg-iter-get-err.js @@ -0,0 +1,24 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: Abrupt completion returned from GetIterator +info: | + ArrayAssignmentPattern : + [ AssignmentElementList , Elisionopt AssignmentRestElementopt ] + + 1. Let iterator be GetIterator(value). + 2. ReturnIfAbrupt(iterator). +features: [Symbol.iterator] +es6id: 12.14.5.2 +esid: sec-runtime-semantics-destructuringassignmentevaluation +---*/ + +var iterable = {}; +iterable[Symbol.iterator] = function() { + throw new Test262Error(); +}; +var x; + +assert.throws(Test262Error, function() { + [ x , ] = iterable; +}); diff --git a/test/language/expressions/assignment/destructuring/array-elem-trlg-iter-list-nrml-close-err.js b/test/language/expressions/assignment/destructuring/array-elem-trlg-iter-list-nrml-close-err.js new file mode 100644 index 0000000000000000000000000000000000000000..491d91e86c2ef75a466d2df23452bec6f787d62f --- /dev/null +++ b/test/language/expressions/assignment/destructuring/array-elem-trlg-iter-list-nrml-close-err.js @@ -0,0 +1,49 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: Abrupt completion returned from IteratorClose +info: | + ArrayAssignmentPattern : + [ AssignmentElementList , Elisionopt AssignmentRestElementopt ] + + [...] + 3. Let iteratorRecord be Record {[[iterator]]: iterator, [[done]]: false}. + 4. Let status be the result of performing + IteratorDestructuringAssignmentEvaluation of AssignmentElementList using + iteratorRecord as the argument. + 5. If status is an abrupt completion, then + a. If iteratorRecord.[[done]] is false, return IteratorClose(iterator, + status). + b. Return Completion(status). +features: [Symbol.iterator] +es6id: 12.14.5.2 +esid: sec-runtime-semantics-destructuringassignmentevaluation +---*/ + +var nextCount = 0; +var returnCount = 0; +var iterable = {}; +var thrower = function() { + throw new Test262Error(); +}; +var x; +var iterator = { + next: function() { + nextCount += 1; + return { done: nextCount > 10 }; + }, + return: function() { + returnCount += 1; + throw new Test262Error(); + } +}; +iterable[Symbol.iterator] = function() { + return iterator; +}; + +assert.throws(Test262Error, function() { + [ x , ] = iterable; +}); + +assert.sameValue(nextCount, 1); +assert.sameValue(returnCount, 1); diff --git a/test/language/expressions/assignment/destructuring/array-elem-trlg-iter-list-nrml-close-null.js b/test/language/expressions/assignment/destructuring/array-elem-trlg-iter-list-nrml-close-null.js new file mode 100644 index 0000000000000000000000000000000000000000..daa2b227b3713b89f710e999a26bf43407994a91 --- /dev/null +++ b/test/language/expressions/assignment/destructuring/array-elem-trlg-iter-list-nrml-close-null.js @@ -0,0 +1,53 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: > + IteratorClose throws a TypeError when `return` returns a non-Object value +info: | + ArrayAssignmentPattern : + [ AssignmentElementList , Elisionopt AssignmentRestElementopt ] + + [...] + 3. Let iteratorRecord be Record {[[iterator]]: iterator, [[done]]: false}. + 4. Let status be the result of performing + IteratorDestructuringAssignmentEvaluation of AssignmentElementList using + iteratorRecord as the argument. + 5. If status is an abrupt completion, then + a. If iteratorRecord.[[done]] is false, return IteratorClose(iterator, + status). + b. Return Completion(status). + + 7.4.6 IteratorClose( iterator, completion ) + + [...] + 6. Let innerResult be Call(return, iterator, « »). + 7. If completion.[[type]] is throw, return Completion(completion). + 8. If innerResult.[[type]] is throw, return Completion(innerResult). + 9. If Type(innerResult.[[value]]) is not Object, throw a TypeError + exception. +features: [Symbol.iterator] +es6id: 12.14.5.2 +esid: sec-runtime-semantics-destructuringassignmentevaluation +---*/ + +var iterable = {}; +var x; +var nextCount = 0; +var iterator = { + next: function() { + nextCount += 1; + // Set an upper-bound to limit unnecessary iteration in non-conformant + // implementations + return { done: nextCount > 10 }; + }, + return: function() { + return null; + } +}; +iterable[Symbol.iterator] = function() { + return iterator; +}; + +assert.throws(TypeError, function() { + [ x , ] = iterable; +}); diff --git a/test/language/expressions/assignment/destructuring/array-elem-trlg-iter-list-nrml-close-skip.js b/test/language/expressions/assignment/destructuring/array-elem-trlg-iter-list-nrml-close-skip.js new file mode 100644 index 0000000000000000000000000000000000000000..a7b0f41c068ea1115ccc6c5f240546a8691f9628 --- /dev/null +++ b/test/language/expressions/assignment/destructuring/array-elem-trlg-iter-list-nrml-close-skip.js @@ -0,0 +1,48 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: > + IteratorClose is not invoked when evaluation of AssignmentElementList + exhausts the iterator +info: | + ArrayAssignmentPattern : + [ AssignmentElementList , Elisionopt AssignmentRestElementopt ] + + [...] + 3. Let iteratorRecord be Record {[[iterator]]: iterator, [[done]]: false}. + 4. Let status be the result of performing + IteratorDestructuringAssignmentEvaluation of AssignmentElementList using + iteratorRecord as the argument. + 5. If status is an abrupt completion, then + a. If iteratorRecord.[[done]] is false, return IteratorClose(iterator, + status). + b. Return Completion(status). +features: [Symbol.iterator] +es6id: 12.14.5.2 +esid: sec-runtime-semantics-destructuringassignmentevaluation +---*/ + +var nextCount = 0; +var returnCount = 0; +var iterable = {}; +var thrower = function() { + throw new Test262Error(); +}; +var x; +var iterator = { + next: function() { + nextCount += 1; + return { done: true }; + }, + return: function() { + returnCount += 1; + } +}; +iterable[Symbol.iterator] = function() { + return iterator; +}; + +[ x , ] = iterable; + +assert.sameValue(nextCount, 1); +assert.sameValue(returnCount, 0); diff --git a/test/language/expressions/assignment/destructuring/array-elem-trlg-iter-list-nrml-close.js b/test/language/expressions/assignment/destructuring/array-elem-trlg-iter-list-nrml-close.js new file mode 100644 index 0000000000000000000000000000000000000000..76582ec71b60c14b7951fc15ea857dfd34543bbd --- /dev/null +++ b/test/language/expressions/assignment/destructuring/array-elem-trlg-iter-list-nrml-close.js @@ -0,0 +1,61 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: > + IteratorClose is invoked when evaluation of AssignmentElementList completes + without exhausting the iterator +info: | + ArrayAssignmentPattern : + [ AssignmentElementList , Elisionopt AssignmentRestElementopt ] + + [...] + 3. Let iteratorRecord be Record {[[iterator]]: iterator, [[done]]: false}. + 4. Let status be the result of performing + IteratorDestructuringAssignmentEvaluation of AssignmentElementList using + iteratorRecord as the argument. + 5. If status is an abrupt completion, then + a. If iteratorRecord.[[done]] is false, return IteratorClose(iterator, + status). + b. Return Completion(status). + + 7.4.6 IteratorClose( iterator, completion ) + + [...] + 6. Let innerResult be Call(return, iterator, « »). + [...] +features: [Symbol.iterator] +es6id: 12.14.5.2 +esid: sec-runtime-semantics-destructuringassignmentevaluation +---*/ + +var nextCount = 0; +var returnCount = 0; +var thisValue = null; +var args = null; +var iterable = {}; +var x; +var iterator = { + next: function() { + nextCount += 1; + // Set an upper-bound to limit unnecessary iteration in non-conformant + // implementations + return { done: nextCount > 10 }; + }, + return: function() { + returnCount += 1; + thisValue = this; + args = arguments; + return {}; + } +}; +iterable[Symbol.iterator] = function() { + return iterator; +}; + +[ x , ] = iterable; + +assert.sameValue(nextCount, 1); +assert.sameValue(returnCount, 1); +assert.sameValue(thisValue, iterator, 'correct `this` value'); +assert(!!args, 'arguments object provided'); +assert.sameValue(args.length, 0, 'zero arguments specified'); diff --git a/test/language/expressions/assignment/destructuring/array-elem-trlg-iter-list-rtrn-close-err.js b/test/language/expressions/assignment/destructuring/array-elem-trlg-iter-list-rtrn-close-err.js new file mode 100644 index 0000000000000000000000000000000000000000..7591e15c5e22539fb0e6455ba12df2865a2cee45 --- /dev/null +++ b/test/language/expressions/assignment/destructuring/array-elem-trlg-iter-list-rtrn-close-err.js @@ -0,0 +1,58 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: > + IteratorClose is invoked when evaluation of AssignmentElementList returns + a "return" completion and the iterator has not been marked as "done" +info: | + ArrayAssignmentPattern : + [ AssignmentElementList , Elisionopt AssignmentRestElementopt ] + + [...] + 3. Let iteratorRecord be Record {[[iterator]]: iterator, [[done]]: false}. + 4. Let status be the result of performing + IteratorDestructuringAssignmentEvaluation of AssignmentElementList using + iteratorRecord as the argument. + 5. If status is an abrupt completion, then + a. If iteratorRecord.[[done]] is false, return IteratorClose(iterator, + status). + + 7.4.6 IteratorClose( iterator, completion ) + + [...] + 6. Let innerResult be Call(return, iterator, « »). + 7. If completion.[[type]] is throw, return Completion(completion). + 8. If innerResult.[[type]] is throw, return Completion(innerResult). +features: [Symbol.iterator, generators] +es6id: 12.14.5.2 +esid: sec-runtime-semantics-destructuringassignmentevaluation +---*/ + +var returnCount = 0; +var unreachable = 0; +var iterable = {}; +var iterator = { + return: function() { + returnCount += 1; + + throw new Test262Error(); + } +}; +var iter; +iterable[Symbol.iterator] = function() { + return iterator; +}; + +function* g() { + [ {}[yield] , ] = iterable; + unreachable += 1; +} + +iter = g(); +iter.next(); +assert.throws(Test262Error, function() { + iter.return(); +}); + +assert.sameValue(returnCount, 1); +assert.sameValue(unreachable, 0, 'Unreachable statement was not executed'); diff --git a/test/language/expressions/assignment/destructuring/array-elem-trlg-iter-list-rtrn-close-null.js b/test/language/expressions/assignment/destructuring/array-elem-trlg-iter-list-rtrn-close-null.js new file mode 100644 index 0000000000000000000000000000000000000000..c635b1b1304696f45ffb1d198501ee8990a554ed --- /dev/null +++ b/test/language/expressions/assignment/destructuring/array-elem-trlg-iter-list-rtrn-close-null.js @@ -0,0 +1,53 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: > + IteratorClose throws a TypeError when `return` returns a non-Object value +info: | + ArrayAssignmentPattern : + [ AssignmentElementList , Elisionopt AssignmentRestElementopt ] + + [...] + 3. Let iteratorRecord be Record {[[iterator]]: iterator, [[done]]: false}. + 4. Let status be the result of performing + IteratorDestructuringAssignmentEvaluation of AssignmentElementList using + iteratorRecord as the argument. + 5. If status is an abrupt completion, then + a. If iteratorRecord.[[done]] is false, return IteratorClose(iterator, + status). + b. Return Completion(status). + + 7.4.6 IteratorClose( iterator, completion ) + + [...] + 6. Let innerResult be Call(return, iterator, « »). + 7. If completion.[[type]] is throw, return Completion(completion). + 8. If innerResult.[[type]] is throw, return Completion(innerResult). + 9. If Type(innerResult.[[value]]) is not Object, throw a TypeError + exception. +features: [Symbol.iterator, generators] +es6id: 12.14.5.2 +esid: sec-runtime-semantics-destructuringassignmentevaluation +---*/ + +var iterable = {}; +var iterator = { + return: function() { + return null; + } +}; +var iter; +iterable[Symbol.iterator] = function() { + return iterator; +}; + +function* g() { + [ {}[yield] , ] = iterable; +} + +iter = g(); +iter.next(); + +assert.throws(TypeError, function() { + iter.return(); +}); diff --git a/test/language/expressions/assignment/destructuring/array-elem-trlg-iter-list-rtrn-close.js b/test/language/expressions/assignment/destructuring/array-elem-trlg-iter-list-rtrn-close.js new file mode 100644 index 0000000000000000000000000000000000000000..076dfeaccaadd012318668dce6a97e5160458b68 --- /dev/null +++ b/test/language/expressions/assignment/destructuring/array-elem-trlg-iter-list-rtrn-close.js @@ -0,0 +1,66 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: > + IteratorClose is invoked when evaluation of AssignmentElementList returns + a "return" completion and the iterator has not been marked as "done" +info: | + ArrayAssignmentPattern : + [ AssignmentElementList , Elisionopt AssignmentRestElementopt ] + + [...] + 3. Let iteratorRecord be Record {[[iterator]]: iterator, [[done]]: false}. + 4. Let status be the result of performing + IteratorDestructuringAssignmentEvaluation of AssignmentElementList using + iteratorRecord as the argument. + 5. If status is an abrupt completion, then + a. If iteratorRecord.[[done]] is false, return IteratorClose(iterator, + status). + b. Return Completion(status). + + 7.4.6 IteratorClose( iterator, completion ) + + [...] + 6. Let innerResult be Call(return, iterator, « »). + 7. If completion.[[type]] is throw, return Completion(completion). + 8. If innerResult.[[type]] is throw, return Completion(innerResult). +features: [Symbol.iterator, generators] +es6id: 12.14.5.2 +esid: sec-runtime-semantics-destructuringassignmentevaluation +---*/ + +var returnCount = 0; +var unreachable = 0; +var thisValue = null; +var args = null; +var iterable = {}; +var iterator = { + return: function() { + returnCount += 1; + thisValue = this; + args = arguments; + return {}; + } +}; +var iter, result; + +iterable[Symbol.iterator] = function() { + return iterator; +}; + +function* g() { + [ {}[yield] , ] = iterable; + unreachable += 1; +}; + +iter = g(); +iter.next(); +result = iter.return(888); + +assert.sameValue(returnCount, 1); +assert.sameValue(unreachable, 0, 'Unreachable statement was not executed'); +assert.sameValue(result.value, 888); +assert(result.done, 'Iterator correctly closed'); +assert.sameValue(thisValue, iterator, 'correct `this` value'); +assert(!!args, 'arguments object provided'); +assert.sameValue(args.length, 0, 'zero arguments specified'); diff --git a/test/language/expressions/assignment/destructuring/array-elem-trlg-iter-list-thrw-close-err.js b/test/language/expressions/assignment/destructuring/array-elem-trlg-iter-list-thrw-close-err.js new file mode 100644 index 0000000000000000000000000000000000000000..6580d3f941ff504d1d4402c97bc36a95b46db845 --- /dev/null +++ b/test/language/expressions/assignment/destructuring/array-elem-trlg-iter-list-thrw-close-err.js @@ -0,0 +1,58 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: > + IteratorClose is invoked when evaluation of AssignmentElementList returns + a "throw" completion and the iterator has not been marked as "done" +info: | + ArrayAssignmentPattern : + [ AssignmentElementList , Elisionopt AssignmentRestElementopt ] + + [...] + 3. Let iteratorRecord be Record {[[iterator]]: iterator, [[done]]: false}. + 4. Let status be the result of performing + IteratorDestructuringAssignmentEvaluation of AssignmentElementList using + iteratorRecord as the argument. + 5. If status is an abrupt completion, then + a. If iteratorRecord.[[done]] is false, return IteratorClose(iterator, + status). + + 7.4.6 IteratorClose( iterator, completion ) + + [...] + 7. If completion.[[type]] is throw, return Completion(completion). + +features: [Symbol.iterator] +es6id: 12.14.5.2 +esid: sec-runtime-semantics-destructuringassignmentevaluation +---*/ + +var nextCount = 0; +var returnCount = 0; +var iterable = {}; +var thrower = function() { + throw new Test262Error(); +}; +function ReturnError() {} +var iterator = { + next: function() { + nextCount += 1; + return { done: true }; + }, + return: function() { + returnCount += 1; + + // This value should be discarded. + throw new ReturnError(); + } +}; +iterable[Symbol.iterator] = function() { + return iterator; +}; + +assert.throws(Test262Error, function() { + [ {}[thrower()] , ] = iterable; +}); + +assert.sameValue(nextCount, 0); +assert.sameValue(returnCount, 1); diff --git a/test/language/expressions/assignment/destructuring/array-elem-trlg-iter-list-thrw-close-skip.js b/test/language/expressions/assignment/destructuring/array-elem-trlg-iter-list-thrw-close-skip.js new file mode 100644 index 0000000000000000000000000000000000000000..f07335161db882dc2d806908509e68ad1d5fa780 --- /dev/null +++ b/test/language/expressions/assignment/destructuring/array-elem-trlg-iter-list-thrw-close-skip.js @@ -0,0 +1,50 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: > + IteratorClose is not invoked when evaluation of AssignmentElementList + returns an abrupt completion and the iterator has been marked as "done" +info: | + ArrayAssignmentPattern : + [ AssignmentElementList , Elisionopt AssignmentRestElementopt ] + + [...] + 3. Let iteratorRecord be Record {[[iterator]]: iterator, [[done]]: false}. + 4. Let status be the result of performing + IteratorDestructuringAssignmentEvaluation of AssignmentElementList using + iteratorRecord as the argument. + 5. If status is an abrupt completion, then + a. If iteratorRecord.[[done]] is false, return IteratorClose(iterator, + status). + b. Return Completion(status). +features: [Symbol.iterator] +es6id: 12.14.5.2 +esid: sec-runtime-semantics-destructuringassignmentevaluation +---*/ + +var nextCount = 0; +var returnCount = 0; +var iterable = {}; +var thrower = function() { + throw new Test262Error(); +}; +var iterator = { + next: function() { + nextCount += 1; + throw new Test262Error(); + }, + return: function() { + returnCount += 1; + } +}; +iterable[Symbol.iterator] = function() { + return iterator; +}; +var x; + +assert.throws(Test262Error, function() { + [ x , ] = iterable; +}); + +assert.sameValue(nextCount, 1); +assert.sameValue(returnCount, 0); diff --git a/test/language/expressions/assignment/destructuring/array-elem-trlg-iter-list-thrw-close.js b/test/language/expressions/assignment/destructuring/array-elem-trlg-iter-list-thrw-close.js new file mode 100644 index 0000000000000000000000000000000000000000..d0b18b6d9df53a352da7403a64974d8f4f714143 --- /dev/null +++ b/test/language/expressions/assignment/destructuring/array-elem-trlg-iter-list-thrw-close.js @@ -0,0 +1,62 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: > + IteratorClose is invoked when evaluation of AssignmentElementList returns + a "throw" completion and the iterator has not been marked as "done" +info: | + ArrayAssignmentPattern : + [ AssignmentElementList , Elisionopt AssignmentRestElementopt ] + + [...] + 3. Let iteratorRecord be Record {[[iterator]]: iterator, [[done]]: false}. + 4. Let status be the result of performing + IteratorDestructuringAssignmentEvaluation of AssignmentElementList using + iteratorRecord as the argument. + 5. If status is an abrupt completion, then + a. If iteratorRecord.[[done]] is false, return IteratorClose(iterator, + status). + b. Return Completion(status). + + 7.4.6 IteratorClose( iterator, completion ) + + [...] + 6. Let innerResult be Call(return, iterator, « »). + [...] +features: [Symbol.iterator] +es6id: 12.14.5.2 +esid: sec-runtime-semantics-destructuringassignmentevaluation +---*/ + +var nextCount = 0; +var returnCount = 0; +var thisValue = null; +var args = null; +var iterable = {}; +var thrower = function() { + throw new Test262Error(); +}; +var iterator = { + next: function() { + nextCount += 1; + return { done: true }; + }, + return: function() { + returnCount += 1; + thisValue = this; + args = arguments; + } +}; +iterable[Symbol.iterator] = function() { + return iterator; +}; + +assert.throws(Test262Error, function() { + [ {}[thrower()] , ] = iterable; +}); + +assert.sameValue(nextCount, 0); +assert.sameValue(returnCount, 1); +assert.sameValue(thisValue, iterator, 'correct `this` value'); +assert(!!args, 'arguments object provided'); +assert.sameValue(args.length, 0, 'zero arguments specified'); diff --git a/test/language/expressions/assignment/destructuring/array-elem-trlg-iter-rest-nrml-close-skip.js b/test/language/expressions/assignment/destructuring/array-elem-trlg-iter-rest-nrml-close-skip.js new file mode 100644 index 0000000000000000000000000000000000000000..4f4cf16281dad1038844a9d010bfc5483a8ff633 --- /dev/null +++ b/test/language/expressions/assignment/destructuring/array-elem-trlg-iter-rest-nrml-close-skip.js @@ -0,0 +1,46 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: > + IteratorClose is not called when rest element evaluation has exhausted the + iterator +info: | + ArrayAssignmentPattern : + [ AssignmentElementList , Elisionopt AssignmentRestElementopt ] + + [...] + 7. If AssignmentRestElement is present, then + a. Let status be the result of performing + IteratorDestructuringAssignmentEvaluation of AssignmentRestElement + with iteratorRecord as the argument. + 8. If iteratorRecord.[[done]] is false, return IteratorClose(iterator, + status). + 9. Return Completion(status). +features: [Symbol.iterator] +es6id: 12.14.5.2 +esid: sec-runtime-semantics-destructuringassignmentevaluation +---*/ + +var nextCount = 0; +var returnCount = 0; +var iterable = {}; +var x, y; +var iterator = { + next: function() { + nextCount += 1; + return { value: nextCount, done: nextCount > 1 }; + }, + return: function() { + returnCount += 1; + } +}; +iterable[Symbol.iterator] = function() { + return iterator; +}; + +[ x , ...y ] = iterable; + +assert.sameValue(nextCount, 2, 'nextCount'); +assert.sameValue(returnCount, 0, 'returnCount'); +assert.sameValue(x, 1, 'x'); +assert.sameValue(y.length, 0, 'y.length'); diff --git a/test/language/expressions/assignment/destructuring/array-elem-trlg-iter-rest-rtrn-close-err.js b/test/language/expressions/assignment/destructuring/array-elem-trlg-iter-rest-rtrn-close-err.js new file mode 100644 index 0000000000000000000000000000000000000000..ce2189ac37f4aca2bd8915be761f36390499479d --- /dev/null +++ b/test/language/expressions/assignment/destructuring/array-elem-trlg-iter-rest-rtrn-close-err.js @@ -0,0 +1,67 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: > + IteratorClose is called when AssignmentRestEvaluation produces a "return" + completion due to reference evaluation +info: | + ArrayAssignmentPattern : + [ AssignmentElementList , Elisionopt AssignmentRestElementopt ] + + [...] + 7. If AssignmentRestElement is present, then + a. Let status be the result of performing + IteratorDestructuringAssignmentEvaluation of AssignmentRestElement + with iteratorRecord as the argument. + 8. If iteratorRecord.[[done]] is false, return IteratorClose(iterator, + status). + 9. Return Completion(status). + + 7.4.6 IteratorClose( iterator, completion ) + + [...] + 6. Let innerResult be Call(return, iterator, « »). + 7. If completion.[[type]] is throw, return Completion(completion). + 8. If innerResult.[[type]] is throw, return Completion(innerResult). +features: [Symbol.iterator, generators] +es6id: 12.14.5.2 +esid: sec-runtime-semantics-destructuringassignmentevaluation +---*/ + +var nextCount = 0; +var returnCount = 0; +var unreachable = 0; +var x; +var iterable = {}; +var iterator = { + next: function() { + nextCount += 1; + // Set an upper-bound to limit unnecessary iteration in non-conformant + // implementations + return { done: nextCount > 10 }; + }, + return: function() { + returnCount += 1; + + throw new Test262Error(); + } +}; +var iter; +iterable[Symbol.iterator] = function() { + return iterator; +}; +function* g() { + [ x , ...{}[yield] ] = iterable; + unreachable += 1; +} + +iter = g(); +iter.next(); + +assert.throws(Test262Error, function() { + iter.return(); +}); + +assert.sameValue(nextCount, 1); +assert.sameValue(returnCount, 1); +assert.sameValue(unreachable, 0, 'Unreachable statement was not executed'); diff --git a/test/language/expressions/assignment/destructuring/array-elem-trlg-iter-rest-rtrn-close-null.js b/test/language/expressions/assignment/destructuring/array-elem-trlg-iter-rest-rtrn-close-null.js new file mode 100644 index 0000000000000000000000000000000000000000..f25ec5b79aee23951408bc07c2acb3bbf3391344 --- /dev/null +++ b/test/language/expressions/assignment/destructuring/array-elem-trlg-iter-rest-rtrn-close-null.js @@ -0,0 +1,60 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: > + IteratorClose throws a TypeError when `return` returns a non-Object value +info: | + ArrayAssignmentPattern : + [ AssignmentElementList , Elisionopt AssignmentRestElementopt ] + + [...] + 7. If AssignmentRestElement is present, then + a. Let status be the result of performing + IteratorDestructuringAssignmentEvaluation of AssignmentRestElement + with iteratorRecord as the argument. + 8. If iteratorRecord.[[done]] is false, return IteratorClose(iterator, + status). + 9. Return Completion(status). + + 7.4.6 IteratorClose( iterator, completion ) + + [...] + 6. Let innerResult be Call(return, iterator, « »). + 7. If completion.[[type]] is throw, return Completion(completion). + 8. If innerResult.[[type]] is throw, return Completion(innerResult). +features: [Symbol.iterator, generators] +es6id: 12.14.5.2 +esid: sec-runtime-semantics-destructuringassignmentevaluation +---*/ + +var nextCount = 0; +var iterable = {}; +var x; +var iterator = { + next: function() { + nextCount += 1; + // Set an upper-bound to limit unnecessary iteration in non-conformant + // implementations + return { done: nextCount > 10 }; + }, + return: function() { + return null; + } +}; +var iter; +iterable[Symbol.iterator] = function() { + return iterator; +}; + +function* g() { + [ x , ...{}[yield] ] = iterable; +} + +iter = g(); +iter.next(); + +assert.throws(TypeError, function() { + iter.return(); +}); + +assert.sameValue(nextCount, 1); diff --git a/test/language/expressions/assignment/destructuring/array-elem-trlg-iter-rest-rtrn-close.js b/test/language/expressions/assignment/destructuring/array-elem-trlg-iter-rest-rtrn-close.js new file mode 100644 index 0000000000000000000000000000000000000000..da1e805331884c3b21e9c41fda3c6fd35b8dd607 --- /dev/null +++ b/test/language/expressions/assignment/destructuring/array-elem-trlg-iter-rest-rtrn-close.js @@ -0,0 +1,73 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: > + IteratorClose is called when AssignmentRestEvaluation produces a "return" + completion due to reference evaluation +info: | + ArrayAssignmentPattern : + [ AssignmentElementList , Elisionopt AssignmentRestElementopt ] + + [...] + 7. If AssignmentRestElement is present, then + a. Let status be the result of performing + IteratorDestructuringAssignmentEvaluation of AssignmentRestElement + with iteratorRecord as the argument. + 8. If iteratorRecord.[[done]] is false, return IteratorClose(iterator, + status). + 9. Return Completion(status). + + 7.4.6 IteratorClose( iterator, completion ) + + [...] + 6. Let innerResult be Call(return, iterator, « »). + 7. If completion.[[type]] is throw, return Completion(completion). + 8. If innerResult.[[type]] is throw, return Completion(innerResult). +features: [Symbol.iterator, generators] +es6id: 12.14.5.2 +esid: sec-runtime-semantics-destructuringassignmentevaluation +---*/ + +var nextCount = 0; +var returnCount = 0; +var unreachable = 0; +var thisValue = null; +var args = null; +var iterable = {}; +var x; +var iterator = { + next: function() { + nextCount += 1; + // Set an upper-bound to limit unnecessary iteration in non-conformant + // implementations + return { done: nextCount > 10 }; + }, + return: function() { + returnCount += 1; + thisValue = this; + args = arguments; + return {}; + } +}; +var iter, result; +iterable[Symbol.iterator] = function() { + return iterator; +}; + +function* g() { + [ x , ...{}[yield] ] = iterable; + unreachable += 1; +} + +iter = g(); +iter.next(); +result = iter.return(999); + +assert.sameValue(nextCount, 1); +assert.sameValue(returnCount, 1); +assert.sameValue(unreachable, 0, 'Unreachable statement was not executed'); +assert.sameValue(result.value, 999); +assert(result.done, 'Iterator correctly closed'); +assert.sameValue(thisValue, iterator, 'correct `this` value'); +assert(!!args, 'arguments object provided'); +assert.sameValue(args.length, 0, 'zero arguments specified'); diff --git a/test/language/expressions/assignment/destructuring/array-elem-trlg-iter-rest-thrw-close-err.js b/test/language/expressions/assignment/destructuring/array-elem-trlg-iter-rest-thrw-close-err.js new file mode 100644 index 0000000000000000000000000000000000000000..beea275ccca5e70d3b003376d8ba82d70925297c --- /dev/null +++ b/test/language/expressions/assignment/destructuring/array-elem-trlg-iter-rest-thrw-close-err.js @@ -0,0 +1,60 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: > + IteratorClose is called when AssignmentRestEvaluation produces a "throw" + completion due to reference evaluation +info: | + ArrayAssignmentPattern : + [ AssignmentElementList , Elisionopt AssignmentRestElementopt ] + + [...] + 7. If AssignmentRestElement is present, then + a. Let status be the result of performing + IteratorDestructuringAssignmentEvaluation of AssignmentRestElement + with iteratorRecord as the argument. + 8. If iteratorRecord.[[done]] is false, return IteratorClose(iterator, + status). + 9. Return Completion(status). + + 7.4.6 IteratorClose( iterator, completion ) + + [...] + 7. If completion.[[type]] is throw, return Completion(completion) +features: [Symbol.iterator] +es6id: 12.14.5.2 +esid: sec-runtime-semantics-destructuringassignmentevaluation +---*/ + +var nextCount = 0; +var returnCount = 0; +var x; +function ReturnError() {} +var iterable = {}; +var iterator = { + next: function() { + nextCount += 1; + // Set an upper-bound to limit unnecessary iteration in non-conformant + // implementations + return { done: nextCount > 10 }; + }, + return: function() { + returnCount += 1; + + // This value should be discarded. + throw new ReturnError(); + } +}; +var thrower = function() { + throw new Test262Error(); +}; +iterable[Symbol.iterator] = function() { + return iterator; +}; + +assert.throws(Test262Error, function() { + [ x , ...{}[thrower()] ] = iterable; +}); + +assert.sameValue(nextCount, 1); +assert.sameValue(returnCount, 1); diff --git a/test/language/expressions/assignment/destructuring/array-elem-trlg-iter-rest-thrw-close-skip.js b/test/language/expressions/assignment/destructuring/array-elem-trlg-iter-rest-thrw-close-skip.js new file mode 100644 index 0000000000000000000000000000000000000000..4619bc0738d1a2b359953bb12eddb9142390bdce --- /dev/null +++ b/test/language/expressions/assignment/destructuring/array-elem-trlg-iter-rest-thrw-close-skip.js @@ -0,0 +1,51 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: Abrupt completion returned during iteration for rest element +info: | + ArrayAssignmentPattern : + [ AssignmentElementList , Elisionopt AssignmentRestElementopt ] + + [...] + 7. If AssignmentRestElement is present, then + a. Let status be the result of performing + IteratorDestructuringAssignmentEvaluation of AssignmentRestElement + with iteratorRecord as the argument. + 8. If iteratorRecord.[[done]] is false, return IteratorClose(iterator, + status). + 9. Return Completion(status). +features: [Symbol.iterator] +es6id: 12.14.5.2 +esid: sec-runtime-semantics-destructuringassignmentevaluation +---*/ + +var nextCount = 0; +var returnCount = 0; +var iterable = {}; +var x; +var iterator = { + next: function() { + nextCount += 1; + + if (nextCount === 2) { + throw new Test262Error(); + } + + // Set an upper-bound to limit unnecessary iteration in non-conformant + // implementations + return { done: nextCount > 10 }; + }, + return: function() { + returnCount += 1; + } +}; +iterable[Symbol.iterator] = function() { + return iterator; +}; + +assert.throws(Test262Error, function() { + [ x , ...x ] = iterable; +}); + +assert.sameValue(nextCount, 2); +assert.sameValue(returnCount, 0); diff --git a/test/language/expressions/assignment/destructuring/array-elem-trlg-iter-rest-thrw-close.js b/test/language/expressions/assignment/destructuring/array-elem-trlg-iter-rest-thrw-close.js new file mode 100644 index 0000000000000000000000000000000000000000..eefc3e146645dedafd4fcf2bee60b120685a37ef --- /dev/null +++ b/test/language/expressions/assignment/destructuring/array-elem-trlg-iter-rest-thrw-close.js @@ -0,0 +1,64 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: > + IteratorClose is called when AssignmentRestEvaluation produces a "throw" + completion due to reference evaluation +info: | + ArrayAssignmentPattern : + [ AssignmentElementList , Elisionopt AssignmentRestElementopt ] + + [...] + 7. If AssignmentRestElement is present, then + a. Let status be the result of performing + IteratorDestructuringAssignmentEvaluation of AssignmentRestElement + with iteratorRecord as the argument. + 8. If iteratorRecord.[[done]] is false, return IteratorClose(iterator, + status). + 9. Return Completion(status). + + 7.4.6 IteratorClose( iterator, completion ) + + [...] + 6. Let innerResult be Call(return, iterator, « »). + [...] +features: [Symbol.iterator] +es6id: 12.14.5.2 +esid: sec-runtime-semantics-destructuringassignmentevaluation +---*/ + +var nextCount = 0; +var returnCount = 0; +var thisValue = null; +var args = null; +var iterable = {}; +var x; +var iterator = { + next: function() { + nextCount += 1; + // Set an upper-bound to limit unnecessary iteration in non-conformant + // implementations + return { done: nextCount > 10 }; + }, + return: function() { + returnCount += 1; + thisValue = this; + args = arguments; + } +}; +var thrower = function() { + throw new Test262Error(); +}; +iterable[Symbol.iterator] = function() { + return iterator; +}; + +assert.throws(Test262Error, function() { + [ x , ...{}[thrower()] ] = iterable; +}); + +assert.sameValue(nextCount, 1); +assert.sameValue(returnCount, 1); +assert.sameValue(thisValue, iterator, 'correct `this` value'); +assert(!!args, 'arguments object provided'); +assert.sameValue(args.length, 0, 'zero arguments specified'); diff --git a/test/language/expressions/assignment/destructuring/array-elision-iter-abpt.js b/test/language/expressions/assignment/destructuring/array-elision-iter-abpt.js new file mode 100644 index 0000000000000000000000000000000000000000..82d43234bc0cc15521ead2c8bb7bed3db55ee932 --- /dev/null +++ b/test/language/expressions/assignment/destructuring/array-elision-iter-abpt.js @@ -0,0 +1,40 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: > + IteratorClose is not called when iteration produces an abrupt completion +info: | + ArrayAssignmentPattern : [ Elision ] + + 1. Let iterator be GetIterator(value). + [...] + 5. If iteratorRecord.[[done]] is false, return IteratorClose(iterator, + result). + [...] +features: [Symbol.iterator] +es6id: 12.14.5.2 +esid: sec-runtime-semantics-destructuringassignmentevaluation +---*/ + +var nextCount = 0; +var returnCount = 0; +var iterable = {}; +var iterator = { + next: function() { + nextCount += 1; + throw new Test262Error(); + }, + return: function() { + returnCount += 1; + } +}; +iterable[Symbol.iterator] = function() { + return iterator; +}; + +assert.throws(Test262Error, function() { + [ , ] = iterable; +}); + +assert.sameValue(nextCount, 1); +assert.sameValue(returnCount, 0); diff --git a/test/language/expressions/assignment/destructuring/array-elision-iter-get-err.js b/test/language/expressions/assignment/destructuring/array-elision-iter-get-err.js new file mode 100644 index 0000000000000000000000000000000000000000..8900065f15b6a899aa038fe7e7d7fcd32cdb2447 --- /dev/null +++ b/test/language/expressions/assignment/destructuring/array-elision-iter-get-err.js @@ -0,0 +1,22 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: Abrupt completion returned from GetIterator +info: | + ArrayAssignmentPattern : [ Elision ] + + 1. Let iterator be GetIterator(value). + 2. ReturnIfAbrupt(iterator). +features: [Symbol.iterator] +es6id: 12.14.5.2 +esid: sec-runtime-semantics-destructuringassignmentevaluation +---*/ + +var iterable = {}; +iterable[Symbol.iterator] = function() { + throw new Test262Error(); +}; + +assert.throws(Test262Error, function() { + [ , ] = iterable; +}); diff --git a/test/language/expressions/assignment/destructuring/array-elision-iter-nrml-close-err.js b/test/language/expressions/assignment/destructuring/array-elision-iter-nrml-close-err.js new file mode 100644 index 0000000000000000000000000000000000000000..ad5fb2da511b64a4ba90d40b2a8ce88fa0091f57 --- /dev/null +++ b/test/language/expressions/assignment/destructuring/array-elision-iter-nrml-close-err.js @@ -0,0 +1,43 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: > + Abrupt completion returned from IteratorClose +info: | + ArrayAssignmentPattern : [ Elision ] + + 1. Let iterator be GetIterator(value). + [...] + 5. If iteratorRecord.[[done]] is false, return IteratorClose(iterator, + result). + 6. Return result. +features: [Symbol.iterator] +es6id: 12.14.5.2 +esid: sec-runtime-semantics-destructuringassignmentevaluation +---*/ + +var nextCount = 0; +var returnCount = 0; +var iterable = {}; +var iterator = { + next: function() { + nextCount += 1; + // Set an upper-bound to limit unnecessary iteration in non-conformant + // implementations + return { done: nextCount > 10 }; + }, + return: function() { + returnCount += 1; + throw new Test262Error(); + } +}; +iterable[Symbol.iterator] = function() { + return iterator; +}; + +assert.throws(Test262Error, function() { + [ , ] = iterable; +}); + +assert.sameValue(nextCount, 1); +assert.sameValue(returnCount, 1); diff --git a/test/language/expressions/assignment/destructuring/array-elision-iter-nrml-close-null.js b/test/language/expressions/assignment/destructuring/array-elision-iter-nrml-close-null.js new file mode 100644 index 0000000000000000000000000000000000000000..528c0eaf19a05859b17485256270d426233885f6 --- /dev/null +++ b/test/language/expressions/assignment/destructuring/array-elision-iter-nrml-close-null.js @@ -0,0 +1,47 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: > + IteratorClose throws a TypeError when `return` returns a non-Object value +info: | + ArrayAssignmentPattern : [ Elision ] + + 1. Let iterator be GetIterator(value). + [...] + 5. If iteratorRecord.[[done]] is false, return IteratorClose(iterator, + result). + [...] + + 7.4.6 IteratorClose( iterator, completion ) + + [...] + 6. Let innerResult be Call(return, iterator, « »). + 7. If completion.[[type]] is throw, return Completion(completion). + 8. If innerResult.[[type]] is throw, return Completion(innerResult). + 9. If Type(innerResult.[[value]]) is not Object, throw a TypeError + exception. +features: [Symbol.iterator] +es6id: 12.14.5.2 +esid: sec-runtime-semantics-destructuringassignmentevaluation +---*/ + +var iterable = {}; +var nextCount = 0; +var iterator = { + next: function() { + nextCount += 1; + // Set an upper-bound to limit unnecessary iteration in non-conformant + // implementations + return { done: nextCount > 10 }; + }, + return: function() { + return null; + } +}; +iterable[Symbol.iterator] = function() { + return iterator; +}; + +assert.throws(TypeError, function() { + [ , ] = iterable; +}); diff --git a/test/language/expressions/assignment/destructuring/array-elision-iter-nrml-close-skip.js b/test/language/expressions/assignment/destructuring/array-elision-iter-nrml-close-skip.js new file mode 100644 index 0000000000000000000000000000000000000000..ecff8153389d691fb3b85cd34ccdef2bafdf849b --- /dev/null +++ b/test/language/expressions/assignment/destructuring/array-elision-iter-nrml-close-skip.js @@ -0,0 +1,39 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: > + IteratorClose is not called when iteration has exhausted the iterator +info: | + ArrayAssignmentPattern : [ Elision ] + + 1. Let iterator be GetIterator(value). + [...] + 5. If iteratorRecord.[[done]] is false, return IteratorClose(iterator, + result). + [...] +features: [Symbol.iterator] +es6id: 12.14.5.2 +esid: sec-runtime-semantics-destructuringassignmentevaluation +---*/ + +var nextCount = 0; +var returnCount = 0; +var iterable = {}; +var iterator = { + next: function() { + nextCount += 1; + return { done: true }; + }, + return: function() { + returnCount += 1; + return {}; + } +}; +iterable[Symbol.iterator] = function() { + return iterator; +}; + +[ , ] = iterable; + +assert.sameValue(nextCount, 1); +assert.sameValue(returnCount, 0); diff --git a/test/language/expressions/assignment/destructuring/array-elision-iter-nrml-close.js b/test/language/expressions/assignment/destructuring/array-elision-iter-nrml-close.js new file mode 100644 index 0000000000000000000000000000000000000000..eba1f3cef4177101b4b3333247cbb8d33ca80f64 --- /dev/null +++ b/test/language/expressions/assignment/destructuring/array-elision-iter-nrml-close.js @@ -0,0 +1,55 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: > + IteratorClose is called when assignment evaluation has not exhausted the + iterator +info: | + ArrayAssignmentPattern : [ Elision ] + + 1. Let iterator be GetIterator(value). + [...] + 5. If iteratorRecord.[[done]] is false, return IteratorClose(iterator, + result). + [...] + + 7.4.6 IteratorClose( iterator, completion ) + + [...] + 6. Let innerResult be Call(return, iterator, « »). + [...] +features: [Symbol.iterator] +es6id: 12.14.5.2 +esid: sec-runtime-semantics-destructuringassignmentevaluation +---*/ + +var nextCount = 0; +var returnCount = 0; +var thisValue = null; +var args = null; +var iterable = {}; +var iterator = { + next: function() { + nextCount += 1; + // Set an upper-bound to limit unnecessary iteration in non-conformant + // implementations + return { done: nextCount > 10 }; + }, + return: function() { + returnCount += 1; + thisValue = this; + args = arguments; + return {}; + } +}; +iterable[Symbol.iterator] = function() { + return iterator; +}; + +[ , ] = iterable; + +assert.sameValue(nextCount, 1); +assert.sameValue(returnCount, 1); +assert.sameValue(thisValue, iterator, 'correct `this` value'); +assert(!!args, 'arguments object provided'); +assert.sameValue(args.length, 0, 'zero arguments specified'); diff --git a/test/language/expressions/assignment/destructuring/array-sparse.js b/test/language/expressions/assignment/destructuring/array-elision.js similarity index 83% rename from test/language/expressions/assignment/destructuring/array-sparse.js rename to test/language/expressions/assignment/destructuring/array-elision.js index 0699f8909b1fbeeac5ac259cf4791af710d761fb..8933cb5a147735902ac1805a7ba66111151be17c 100644 --- a/test/language/expressions/assignment/destructuring/array-sparse.js +++ b/test/language/expressions/assignment/destructuring/array-elision.js @@ -3,8 +3,8 @@ /*--- description: > - A sparse ArrayAssignmentPattern without an AssignmentElementList requires - iterable values and throws for other values. + An ArrayAssignmentPattern containing only Elisions requires iterable values + and throws for other values. es6id: 12.14.5.2 ---*/ diff --git a/test/language/expressions/assignment/destructuring/array-empty-iter-close-err.js b/test/language/expressions/assignment/destructuring/array-empty-iter-close-err.js new file mode 100644 index 0000000000000000000000000000000000000000..a7e1d225fde16658fb2a54a1512b8f3312176e78 --- /dev/null +++ b/test/language/expressions/assignment/destructuring/array-empty-iter-close-err.js @@ -0,0 +1,38 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: Abrupt completion returned from IteratorClose +info: | + ArrayAssignmentPattern : [ ] + + 1. Let iterator be GetIterator(value). + 2. ReturnIfAbrupt(iterator). + 3. Return IteratorClose(iterator, NormalCompletion(empty)). +features: [Symbol.iterator] +es6id: 12.14.5.2 +esid: sec-runtime-semantics-destructuringassignmentevaluation +---*/ + +var nextCount = 0; +var returnCount = 0; +var iterable = {}; +var iterator = { + next: function() { + nextCount += 1; + return { done: true }; + }, + return: function() { + returnCount += 1; + throw new Test262Error(); + } +}; +iterable[Symbol.iterator] = function() { + return iterator; +}; + +assert.throws(Test262Error, function() { + [] = iterable; +}); + +assert.sameValue(nextCount, 0); +assert.sameValue(returnCount, 1); diff --git a/test/language/expressions/assignment/destructuring/array-empty-iter-close-null.js b/test/language/expressions/assignment/destructuring/array-empty-iter-close-null.js new file mode 100644 index 0000000000000000000000000000000000000000..1ef76906be2dec057d14af5572744f4d6ea981f4 --- /dev/null +++ b/test/language/expressions/assignment/destructuring/array-empty-iter-close-null.js @@ -0,0 +1,41 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: > + IteratorClose throws a TypeError when `return` returns a non-Object value +info: | + ArrayAssignmentPattern : [ ] + + 1. Let iterator be GetIterator(value). + 2. ReturnIfAbrupt(iterator). + 3. Return IteratorClose(iterator, NormalCompletion(empty)). + + 7.4.6 IteratorClose( iterator, completion ) + + [...] + 6. Let innerResult be Call(return, iterator, « »). + 7. If completion.[[type]] is throw, return Completion(completion). + 8. If innerResult.[[type]] is throw, return Completion(innerResult). + 9. If Type(innerResult.[[value]]) is not Object, throw a TypeError + exception. +features: [Symbol.iterator] +es6id: 12.14.5.2 +esid: sec-runtime-semantics-destructuringassignmentevaluation +---*/ + +var iterable = {}; +var iterator = { + next: function() { + return { done: true }; + }, + return: function() { + return null; + } +}; +iterable[Symbol.iterator] = function() { + return iterator; +}; + +assert.throws(TypeError, function() { + [] = iterable; +}); diff --git a/test/language/expressions/assignment/destructuring/array-empty-iter-close.js b/test/language/expressions/assignment/destructuring/array-empty-iter-close.js new file mode 100644 index 0000000000000000000000000000000000000000..c9a70d9c9aba42612f42c0cd74af760164cca4df --- /dev/null +++ b/test/language/expressions/assignment/destructuring/array-empty-iter-close.js @@ -0,0 +1,49 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: Iterator is closed without iterating +info: | + ArrayAssignmentPattern : [ ] + + 1. Let iterator be GetIterator(value). + 2. ReturnIfAbrupt(iterator). + 3. Return IteratorClose(iterator, NormalCompletion(empty)). + + 7.4.6 IteratorClose( iterator, completion ) + + [...] + 6. Let innerResult be Call(return, iterator, « »). + [...] +features: [Symbol.iterator] +es6id: 12.14.5.2 +esid: sec-runtime-semantics-destructuringassignmentevaluation +---*/ + +var nextCount = 0; +var returnCount = 0; +var thisValue = null; +var args = null; +var iterable = {}; +var iterator = { + next: function() { + nextCount += 1; + return { done: true }; + }, + return: function() { + returnCount += 1; + thisValue = this; + args = arguments; + return {}; + } +}; +iterable[Symbol.iterator] = function() { + return iterator; +}; + +[] = iterable; + +assert.sameValue(nextCount, 0); +assert.sameValue(returnCount, 1); +assert.sameValue(thisValue, iterator, 'correct `this` value'); +assert(!!args, 'arguments object provided'); +assert.sameValue(args.length, 0, 'zero arguments specified'); diff --git a/test/language/expressions/assignment/destructuring/array-empty-iter-get-err.js b/test/language/expressions/assignment/destructuring/array-empty-iter-get-err.js new file mode 100644 index 0000000000000000000000000000000000000000..efd5b21d4a4e4896adae9ec2f442392664e46ca1 --- /dev/null +++ b/test/language/expressions/assignment/destructuring/array-empty-iter-get-err.js @@ -0,0 +1,22 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: Abrupt completion returned from GetIterator +info: | + ArrayAssignmentPattern : [ ] + + 1. Let iterator be GetIterator(value). + 2. ReturnIfAbrupt(iterator). +features: [Symbol.iterator] +es6id: 12.14.5.2 +esid: sec-runtime-semantics-destructuringassignmentevaluation +---*/ + +var iterable = {}; +iterable[Symbol.iterator] = function() { + throw new Test262Error(); +}; + +assert.throws(Test262Error, function() { + [] = iterable; +}); diff --git a/test/language/expressions/assignment/destructuring/array-rest-elision-iter-abpt.js b/test/language/expressions/assignment/destructuring/array-rest-elision-iter-abpt.js new file mode 100644 index 0000000000000000000000000000000000000000..367cc892fe7d16eb757d0f0cfac3f306d672d449 --- /dev/null +++ b/test/language/expressions/assignment/destructuring/array-rest-elision-iter-abpt.js @@ -0,0 +1,46 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: > + IteratorClose is not called when assignment evaluation produces an abrupt + completion +info: | + ArrayAssignmentPattern : [ Elisionopt AssignmentRestElement ] + + [...] + 4. If Elision is present, then + a. Let status be the result of performing + IteratorDestructuringAssignmentEvaluation of Elision with + iteratorRecord as the argument. + b. If status is an abrupt completion, then + i. If iteratorRecord.[[done]] is false, return + IteratorClose(iterator, status). + ii. Return Completion(status). +features: [Symbol.iterator] +es6id: 12.14.5.2 +esid: sec-runtime-semantics-destructuringassignmentevaluation +---*/ + +var nextCount = 0; +var returnCount = 0; +var iterable = {}; +var iterator = { + next: function() { + nextCount += 1; + throw new Test262Error(); + }, + return: function() { + returnCount += 1; + } +}; +iterable[Symbol.iterator] = function() { + return iterator; +}; +var x; + +assert.throws(Test262Error, function() { + [ , ...x] = iterable; +}); + +assert.sameValue(nextCount, 1); +assert.sameValue(returnCount, 0); diff --git a/test/language/expressions/assignment/destructuring/array-rest-iter-get-err.js b/test/language/expressions/assignment/destructuring/array-rest-iter-get-err.js new file mode 100644 index 0000000000000000000000000000000000000000..6cf2f2d45ec5f2d939ec4643403ad0c9ce6e1b1b --- /dev/null +++ b/test/language/expressions/assignment/destructuring/array-rest-iter-get-err.js @@ -0,0 +1,23 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: Abrupt completion returned from GetIterator +info: | + ArrayAssignmentPattern : [ Elisionopt AssignmentRestElement ] + + 1. Let iterator be GetIterator(value). + 2. ReturnIfAbrupt(iterator). +features: [Symbol.iterator] +es6id: 12.14.5.2 +esid: sec-runtime-semantics-destructuringassignmentevaluation +---*/ + +var iterable = {}; +var x; +iterable[Symbol.iterator] = function() { + throw new Test262Error(); +}; + +assert.throws(Test262Error, function() { + [...x] = iterable; +}); diff --git a/test/language/expressions/assignment/destructuring/array-rest-iter-nrml-close-skip.js b/test/language/expressions/assignment/destructuring/array-rest-iter-nrml-close-skip.js new file mode 100644 index 0000000000000000000000000000000000000000..5bb22af60b9a42e57fbd74a6e4d15f9cf23a0fe7 --- /dev/null +++ b/test/language/expressions/assignment/destructuring/array-rest-iter-nrml-close-skip.js @@ -0,0 +1,42 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: > + IteratorClose is not called when assignment evaluation has exhausted the + iterator +info: | + ArrayAssignmentPattern : [ Elisionopt AssignmentRestElement ] + + [...] + 5. Let result be the result of performing + IteratorDestructuringAssignmentEvaluation of AssignmentRestElement with + iteratorRecord as the argument + 6. If iteratorRecord.[[done]] is false, return IteratorClose(iterator, + result). + 7. Return result. +features: [Symbol.iterator] +es6id: 12.14.5.2 +esid: sec-runtime-semantics-destructuringassignmentevaluation +---*/ + +var nextCount = 0; +var returnCount = 0; +var x; +var iterable = {}; +var iterator = { + next: function() { + nextCount += 1; + return { done: true }; + }, + return: function() { + returnCount += 1; + } +}; +iterable[Symbol.iterator] = function() { + return iterator; +}; + +[ ...x ] = iterable; + +assert.sameValue(nextCount, 1); +assert.sameValue(returnCount, 0); diff --git a/test/language/expressions/assignment/destructuring/array-rest-iter-rtrn-close-err.js b/test/language/expressions/assignment/destructuring/array-rest-iter-rtrn-close-err.js new file mode 100644 index 0000000000000000000000000000000000000000..b86607956f56e2a72e6e29eb03b5211cddad5452 --- /dev/null +++ b/test/language/expressions/assignment/destructuring/array-rest-iter-rtrn-close-err.js @@ -0,0 +1,63 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: > + IteratorClose is called when reference evaluation produces a "return" + completion +info: | + ArrayAssignmentPattern : [ Elisionopt AssignmentRestElement ] + + [...] + 5. Let result be the result of performing + IteratorDestructuringAssignmentEvaluation of AssignmentRestElement with + iteratorRecord as the argument + 6. If iteratorRecord.[[done]] is false, return IteratorClose(iterator, + result). + + AssignmentRestElement[Yield] : ... DestructuringAssignmentTarget + + 1. If DestructuringAssignmentTarget is neither an ObjectLiteral nor an + ArrayLiteral, then + a. Let lref be the result of evaluating DestructuringAssignmentTarget. + b. ReturnIfAbrupt(lref). + + 7.4.6 IteratorClose( iterator, completion ) + + [...] + 6. Let innerResult be Call(return, iterator, « »). + 7. If completion.[[type]] is throw, return Completion(completion). + 8. If innerResult.[[type]] is throw, return Completion(innerResult). +features: [Symbol.iterator, generators] +es6id: 12.14.5.2 +esid: sec-runtime-semantics-destructuringassignmentevaluation +---*/ + +var returnCount = 0; +var unreachable = 0; +function ReturnError() {} +var iterable = {}; +var iterator = { + return: function() { + returnCount += 1; + + throw new Test262Error(); + } +}; +var iter; +iterable[Symbol.iterator] = function() { + return iterator; +}; + +function* g() { + [...{}[yield]] = iterable; + unreachable += 1; +} + +iter = g(); +iter.next(); +assert.throws(Test262Error, function() { + iter.return(); +}); + +assert.sameValue(returnCount, 1); +assert.sameValue(unreachable, 0, 'Unreachable statement was not executed'); diff --git a/test/language/expressions/assignment/destructuring/array-rest-iter-rtrn-close-null.js b/test/language/expressions/assignment/destructuring/array-rest-iter-rtrn-close-null.js new file mode 100644 index 0000000000000000000000000000000000000000..4b37e9f599eecf207f923981bfab3b1b925b8760 --- /dev/null +++ b/test/language/expressions/assignment/destructuring/array-rest-iter-rtrn-close-null.js @@ -0,0 +1,60 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: > + IteratorClose throws a TypeError when `return` returns a non-Object value +info: | + ArrayAssignmentPattern : [ Elisionopt AssignmentRestElement ] + + [...] + 5. Let result be the result of performing + IteratorDestructuringAssignmentEvaluation of AssignmentRestElement with + iteratorRecord as the argument + 6. If iteratorRecord.[[done]] is false, return IteratorClose(iterator, + result). + + AssignmentRestElement[Yield] : ... DestructuringAssignmentTarget + + 1. If DestructuringAssignmentTarget is neither an ObjectLiteral nor an + ArrayLiteral, then + a. Let lref be the result of evaluating DestructuringAssignmentTarget. + b. ReturnIfAbrupt(lref). + + 7.4.6 IteratorClose( iterator, completion ) + + [...] + 6. Let innerResult be Call(return, iterator, « »). + [...] + + 7.4.6 IteratorClose( iterator, completion ) + + [...] + 6. Let innerResult be Call(return, iterator, « »). + 7. If completion.[[type]] is throw, return Completion(completion). + 8. If innerResult.[[type]] is throw, return Completion(innerResult). +features: [Symbol.iterator, generators] +es6id: 12.14.5.2 +esid: sec-runtime-semantics-destructuringassignmentevaluation +---*/ + +var iterable = {}; +var iterator = { + return: function() { + return null; + } +}; +var iter; +iterable[Symbol.iterator] = function() { + return iterator; +}; + +function* g() { + [...{}[yield]] = iterable; +} + +iter = g(); +iter.next(); + +assert.throws(TypeError, function() { + iter.return(); +}); diff --git a/test/language/expressions/assignment/destructuring/array-rest-iter-rtrn-close.js b/test/language/expressions/assignment/destructuring/array-rest-iter-rtrn-close.js new file mode 100644 index 0000000000000000000000000000000000000000..da30120406d87c28c68692239fb483e311429e8b --- /dev/null +++ b/test/language/expressions/assignment/destructuring/array-rest-iter-rtrn-close.js @@ -0,0 +1,74 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: > + IteratorClose is called when reference evaluation produces a "return" + completion +info: | + ArrayAssignmentPattern : [ Elisionopt AssignmentRestElement ] + + [...] + 5. Let result be the result of performing + IteratorDestructuringAssignmentEvaluation of AssignmentRestElement with + iteratorRecord as the argument + 6. If iteratorRecord.[[done]] is false, return IteratorClose(iterator, + result). + + AssignmentRestElement[Yield] : ... DestructuringAssignmentTarget + + 1. If DestructuringAssignmentTarget is neither an ObjectLiteral nor an + ArrayLiteral, then + a. Let lref be the result of evaluating DestructuringAssignmentTarget. + b. ReturnIfAbrupt(lref). + + 7.4.6 IteratorClose( iterator, completion ) + + [...] + 6. Let innerResult be Call(return, iterator, « »). + [...] + + 7.4.6 IteratorClose( iterator, completion ) + + [...] + 6. Let innerResult be Call(return, iterator, « »). + 7. If completion.[[type]] is throw, return Completion(completion). + 8. If innerResult.[[type]] is throw, return Completion(innerResult). +features: [Symbol.iterator, generators] +es6id: 12.14.5.2 +esid: sec-runtime-semantics-destructuringassignmentevaluation +---*/ + +var returnCount = 0; +var unreachable = 0; +var thisValue = null; +var args = null; +var iterable = {}; +var iterator = { + return: function() { + returnCount += 1; + thisValue = this; + args = arguments; + return {}; + } +}; +var iter, result; +iterable[Symbol.iterator] = function() { + return iterator; +}; + +function* g() { + [...{}[yield]] = iterable; + unreachable += 1; +} + +iter = g(); +iter.next(); +result = iter.return(444); + +assert.sameValue(returnCount, 1); +assert.sameValue(unreachable, 0, 'Unreachable statement was not executed'); +assert.sameValue(result.value, 444); +assert(result.done, 'Iterator correctly closed'); +assert.sameValue(thisValue, iterator, 'correct `this` value'); +assert(!!args, 'arguments object provided'); +assert.sameValue(args.length, 0, 'zero arguments specified'); diff --git a/test/language/expressions/assignment/destructuring/array-rest-iter-thrw-close-err.js b/test/language/expressions/assignment/destructuring/array-rest-iter-thrw-close-err.js new file mode 100644 index 0000000000000000000000000000000000000000..f39a1465234a86cdfabab4a19fd37451198dbb73 --- /dev/null +++ b/test/language/expressions/assignment/destructuring/array-rest-iter-thrw-close-err.js @@ -0,0 +1,59 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: > + IteratorClose is called when reference evaluation produces a "throw" + completion +info: | + ArrayAssignmentPattern : [ Elisionopt AssignmentRestElement ] + + [...] + 5. Let result be the result of performing + IteratorDestructuringAssignmentEvaluation of AssignmentRestElement with + iteratorRecord as the argument + 6. If iteratorRecord.[[done]] is false, return IteratorClose(iterator, + result). + + AssignmentRestElement[Yield] : ... DestructuringAssignmentTarget + + 1. If DestructuringAssignmentTarget is neither an ObjectLiteral nor an + ArrayLiteral, then + a. Let lref be the result of evaluating DestructuringAssignmentTarget. + b. ReturnIfAbrupt(lref). +features: [Symbol.iterator] +es6id: 12.14.5.2 +esid: sec-runtime-semantics-destructuringassignmentevaluation +---*/ + +var nextCount = 0; +var returnCount = 0; +var x; +function ReturnError() {} +var iterable = {}; +var iterator = { + next: function() { + nextCount += 1; + // Set an upper-bound to limit unnecessary iteration in non-conformant + // implementations + return { done: nextCount > 10 }; + }, + return: function() { + returnCount += 1; + + // This value should be discarded. + throw new ReturnError(); + } +}; +var thrower = function() { + throw new Test262Error(); +}; +iterable[Symbol.iterator] = function() { + return iterator; +}; + +assert.throws(Test262Error, function() { + [...{}[thrower()]] = iterable; +}); + +assert.sameValue(nextCount, 0); +assert.sameValue(returnCount, 1); diff --git a/test/language/expressions/assignment/destructuring/array-rest-iter-thrw-close-skip.js b/test/language/expressions/assignment/destructuring/array-rest-iter-thrw-close-skip.js new file mode 100644 index 0000000000000000000000000000000000000000..84a4cac82012793f63013b4cb642527b2184eced --- /dev/null +++ b/test/language/expressions/assignment/destructuring/array-rest-iter-thrw-close-skip.js @@ -0,0 +1,41 @@ +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: > + IteratorClose is not called when iteration produces an abrupt completion +info: | + ArrayAssignmentPattern : [ Elisionopt AssignmentRestElement ] + + [...] + 5. Let result be the result of performing + IteratorDestructuringAssignmentEvaluation of AssignmentRestElement with + iteratorRecord as the argument + 6. If iteratorRecord.[[done]] is false, return IteratorClose(iterator, + result). +features: [Symbol.iterator] +es6id: 12.14.5.2 +esid: sec-runtime-semantics-destructuringassignmentevaluation +---*/ + +var nextCount = 0; +var returnCount = 0; +var x; +var iterable = {}; +var iterator = { + next: function() { + nextCount += 1; + throw new Test262Error(); + }, + return: function() { + returnCount += 1; + } +}; +iterable[Symbol.iterator] = function() { + return iterator; +}; + +assert.throws(Test262Error, function() { + [...x] = iterable; +}); + +assert.sameValue(nextCount, 1); +assert.sameValue(returnCount, 0); diff --git a/test/language/expressions/assignment/destructuring/array-rest-iter-thrw-close.js b/test/language/expressions/assignment/destructuring/array-rest-iter-thrw-close.js new file mode 100644 index 0000000000000000000000000000000000000000..8e5b4e634c32a233e62e437c69d31bbbfd3e090f --- /dev/null +++ b/test/language/expressions/assignment/destructuring/array-rest-iter-thrw-close.js @@ -0,0 +1,68 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: > + IteratorClose is called when reference evaluation produces a "throw" + completion +info: | + ArrayAssignmentPattern : [ Elisionopt AssignmentRestElement ] + + [...] + 5. Let result be the result of performing + IteratorDestructuringAssignmentEvaluation of AssignmentRestElement with + iteratorRecord as the argument + 6. If iteratorRecord.[[done]] is false, return IteratorClose(iterator, + result). + + AssignmentRestElement[Yield] : ... DestructuringAssignmentTarget + + 1. If DestructuringAssignmentTarget is neither an ObjectLiteral nor an + ArrayLiteral, then + a. Let lref be the result of evaluating DestructuringAssignmentTarget. + b. ReturnIfAbrupt(lref). + + 7.4.6 IteratorClose( iterator, completion ) + + [...] + 6. Let innerResult be Call(return, iterator, « »). + [...] +features: [Symbol.iterator] +es6id: 12.14.5.2 +esid: sec-runtime-semantics-destructuringassignmentevaluation +---*/ + +var nextCount = 0; +var returnCount = 0; +var thisValue = null; +var args = null; +var x; +var iterable = {}; +var iterator = { + next: function() { + nextCount += 1; + // Set an upper-bound to limit unnecessary iteration in non-conformant + // implementations + return { done: nextCount > 10 }; + }, + return: function() { + returnCount += 1; + thisValue = this; + args = arguments; + } +}; +var thrower = function() { + throw new Test262Error(); +}; +iterable[Symbol.iterator] = function() { + return iterator; +}; + +assert.throws(Test262Error, function() { + [...{}[thrower()]] = iterable; +}); + +assert.sameValue(nextCount, 0); +assert.sameValue(returnCount, 1); +assert.sameValue(thisValue, iterator, 'correct `this` value'); +assert(!!args, 'arguments object provided'); +assert.sameValue(args.length, 0, 'zero arguments specified'); diff --git a/test/language/expressions/assignment/destructuring/array-rest-lref-err.js b/test/language/expressions/assignment/destructuring/array-rest-lref-err.js new file mode 100644 index 0000000000000000000000000000000000000000..2a083bdceeb112a7dc2f50ef03e18900a7e2ee53 --- /dev/null +++ b/test/language/expressions/assignment/destructuring/array-rest-lref-err.js @@ -0,0 +1,52 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: > + IteratorClose is called when reference evaluation produces an abrupt + completion +info: | + ArrayAssignmentPattern : [ Elisionopt AssignmentRestElement ] + + [...] + 5. Let result be the result of performing + IteratorDestructuringAssignmentEvaluation of AssignmentRestElement with + iteratorRecord as the argument + 6. If iteratorRecord.[[done]] is false, return IteratorClose(iterator, + result). + + AssignmentRestElement[Yield] : ... DestructuringAssignmentTarget + + 1. If DestructuringAssignmentTarget is neither an ObjectLiteral nor an + ArrayLiteral, then + a. Let lref be the result of evaluating DestructuringAssignmentTarget. + b. ReturnIfAbrupt(lref). +features: [Symbol.iterator] +es6id: 12.14.5.2 +esid: sec-runtime-semantics-destructuringassignmentevaluation +---*/ + +var nextCount = 0; +var returnCount = 0; +var iterable = {}; +var iterator = { + next: function() { + nextCount += 1; + return { done: true }; + }, + return: function() { + returnCount += 1; + } +}; +var thrower = function() { + throw new Test262Error(); +}; +iterable[Symbol.iterator] = function() { + return iterator; +}; + +assert.throws(Test262Error, function() { + [...{}[thrower()]] = iterable; +}); + +assert.sameValue(nextCount, 0); +assert.sameValue(returnCount, 1); diff --git a/test/language/expressions/assignment/destructuring/array-rest-lref.js b/test/language/expressions/assignment/destructuring/array-rest-lref.js new file mode 100644 index 0000000000000000000000000000000000000000..68161c48e8546b2a2963632b8650664089cf3ef5 --- /dev/null +++ b/test/language/expressions/assignment/destructuring/array-rest-lref.js @@ -0,0 +1,49 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: Reference is evaluated during assignment +info: | + ArrayAssignmentPattern : [ Elisionopt AssignmentRestElement ] + + [...] + 5. Let result be the result of performing + IteratorDestructuringAssignmentEvaluation of AssignmentRestElement with + iteratorRecord as the argument + 6. If iteratorRecord.[[done]] is false, return IteratorClose(iterator, + result). + + AssignmentRestElement[Yield] : ... DestructuringAssignmentTarget + + 1. If DestructuringAssignmentTarget is neither an ObjectLiteral nor an + ArrayLiteral, then + a. Let lref be the result of evaluating DestructuringAssignmentTarget. + b. ReturnIfAbrupt(lref). + [...] +features: [Symbol.iterator] +es6id: 12.14.5.2 +esid: sec-runtime-semantics-destructuringassignmentevaluation +---*/ + +var nextCount = 0; +var returnCount = 0; +var iterable = {}; +var iterator = { + next: function() { + nextCount += 1; + return { done: true }; + }, + return: function() { + returnCount += 1; + } +}; +var obj = {}; +iterable[Symbol.iterator] = function() { + return iterator; +}; + +[...obj['a' + 'b']] = iterable; + +assert.sameValue(nextCount, 1); +assert.sameValue(returnCount, 0); +assert(!!obj.ab); +assert.sameValue(obj.ab.length, 0); diff --git a/test/language/expressions/assignment/destructuring/array-rest-nested-array-iter-thrw-close-skip.js b/test/language/expressions/assignment/destructuring/array-rest-nested-array-iter-thrw-close-skip.js new file mode 100644 index 0000000000000000000000000000000000000000..8d5749624b18b41bfc8a923b30969ceaea0ecf79 --- /dev/null +++ b/test/language/expressions/assignment/destructuring/array-rest-nested-array-iter-thrw-close-skip.js @@ -0,0 +1,55 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: > + IteratorClose is not called when nested array pattern evaluation produces + an abrupt completion +info: | + ArrayAssignmentPattern : [ Elisionopt AssignmentRestElement ] + + [...] + 5. Let result be the result of performing + IteratorDestructuringAssignmentEvaluation of AssignmentRestElement with + iteratorRecord as the argument + 6. If iteratorRecord.[[done]] is false, return IteratorClose(iterator, + result). + + AssignmentRestElement[Yield] : ... DestructuringAssignmentTarget + + [...] + 4. Repeat while iteratorRecord.[[done]] is false + [...] + d. If next is false, set iteratorRecord.[[done]] to true. + [...] + 7. Return the result of performing DestructuringAssignmentEvaluation of + nestedAssignmentPattern with A as the argument. +features: [Symbol.iterator] +es6id: 12.14.5.2 +esid: sec-runtime-semantics-destructuringassignmentevaluation +---*/ + +var nextCount = 0; +var returnCount = 0; +var iterable = {}; +var iterator = { + next: function() { + nextCount += 1; + return { done: true }; + }, + return: function() { + returnCount += 1; + } +}; +var thrower = function() { + throw new Test262Error(); +}; +iterable[Symbol.iterator] = function() { + return iterator; +}; + +assert.throws(Test262Error, function() { + [...[...{}[thrower()]]] = iterable; +}); + +assert.sameValue(nextCount, 1); +assert.sameValue(returnCount, 0); diff --git a/test/language/expressions/assignment/destructuring/array-rest-put-prop-ref-user-err-iter-close-skip.js b/test/language/expressions/assignment/destructuring/array-rest-put-prop-ref-user-err-iter-close-skip.js new file mode 100644 index 0000000000000000000000000000000000000000..513f433032c23b54ffabe74be13a633e3944eec3 --- /dev/null +++ b/test/language/expressions/assignment/destructuring/array-rest-put-prop-ref-user-err-iter-close-skip.js @@ -0,0 +1,57 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: > + IteratorClose is not called when value assignment produces an abrupt + completion. +info: | + ArrayAssignmentPattern : [ Elisionopt AssignmentRestElement ] + + [...] + 5. Let result be the result of performing + IteratorDestructuringAssignmentEvaluation of AssignmentRestElement with + iteratorRecord as the argument + 6. If iteratorRecord.[[done]] is false, return IteratorClose(iterator, + result). + + AssignmentRestElement[Yield] : ... DestructuringAssignmentTarget + + [...] + 4. Repeat while iteratorRecord.[[done]] is false + [...] + d. If next is false, set iteratorRecord.[[done]] to true. + [...] + 5. If DestructuringAssignmentTarget is neither an ObjectLiteral nor an + ArrayLiteral, then + a. Return PutValue(lref, A). +features: [Symbol.iterator] +es6id: 12.14.5.2 +esid: sec-runtime-semantics-destructuringassignmentevaluation +---*/ + +var nextCount = 0; +var returnCount = 0; +var iterable = {}; +var iterator = { + next: function() { + nextCount += 1; + return { done: true }; + }, + return: function() { + returnCount += 1; + } +}; +var obj = Object.defineProperty({}, 'poisoned', { + set: function(x) { + throw new Test262Error(); + } +}); +iterable[Symbol.iterator] = function() { + return iterator; +}; +assert.throws(Test262Error, function() { + [...obj.poisoned] = iterable; +}); + +assert.sameValue(nextCount, 1); +assert.sameValue(returnCount, 0);