diff options
Diffstat (limited to 'js/src/tests/test262/language/expressions/yield')
65 files changed, 3418 insertions, 0 deletions
diff --git a/js/src/tests/test262/language/expressions/yield/arguments-object-attributes.js b/js/src/tests/test262/language/expressions/yield/arguments-object-attributes.js new file mode 100644 index 0000000000..d6db638781 --- /dev/null +++ b/js/src/tests/test262/language/expressions/yield/arguments-object-attributes.js @@ -0,0 +1,43 @@ +// Copyright (C) 2013 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +es6id: 25.2 +description: > + Attributes of the `arguments` object are valid yield expression operands. +features: [generators] +---*/ + +function* g() { + yield arguments[0]; + yield arguments[1]; + yield arguments[2]; + yield arguments[3]; +} +var iter = g(23, 45, 33); +var result; + +result = iter.next(); +assert.sameValue(result.value, 23, 'First result `value`'); +assert.sameValue(result.done, false, 'First result `done` flag'); + +result = iter.next(); +assert.sameValue(result.value, 45, 'Second result `value`'); +assert.sameValue(result.done, false, 'Second result `done` flag'); + +result = iter.next(); +assert.sameValue(result.value, 33, 'Third result `value`'); +assert.sameValue(result.done, false, 'Third result `done` flag'); + +result = iter.next(); +assert.sameValue( + result.value, undefined, 'Fourth result `value` (unspecified parameter)' +); +assert.sameValue( + result.done, false, 'Fourth result `done` flag (unspecified parameter)' +); + +result = iter.next(); +assert.sameValue(result.value, undefined, 'Final result `value`'); +assert.sameValue(result.done, true, 'Final result `done` flag'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/yield/browser.js b/js/src/tests/test262/language/expressions/yield/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/language/expressions/yield/browser.js diff --git a/js/src/tests/test262/language/expressions/yield/captured-free-vars.js b/js/src/tests/test262/language/expressions/yield/captured-free-vars.js new file mode 100644 index 0000000000..569cfba77c --- /dev/null +++ b/js/src/tests/test262/language/expressions/yield/captured-free-vars.js @@ -0,0 +1,38 @@ +// Copyright (C) 2013 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +es6id: 25.2 +description: > + Free variables captured within the GeneratorFunction closure are valid + yield expression operands. +features: [generators] +---*/ + +var a = 1; +var b = 2; +var c = 3; +function* g() { + yield a; + yield b; + yield c; +} +var iter = g(); +var result; + +result = iter.next(); +assert.sameValue(result.value, 1, 'First result `value`'); +assert.sameValue(result.done, false, 'First result `done` flag'); + +result = iter.next(); +assert.sameValue(result.value, 2, 'Second result `value`'); +assert.sameValue(result.done, false, 'Second result `done` flag'); + +result = iter.next(); +assert.sameValue(result.value, 3, 'Third result `value`'); +assert.sameValue(result.done, false, 'Third result `done` flag'); + +result = iter.next(); +assert.sameValue(result.value, undefined, 'Final result `value`'); +assert.sameValue(result.done, true, 'Final result `done` flag'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/yield/formal-parameters-after-reassignment-non-strict.js b/js/src/tests/test262/language/expressions/yield/formal-parameters-after-reassignment-non-strict.js new file mode 100644 index 0000000000..b79ec78a6b --- /dev/null +++ b/js/src/tests/test262/language/expressions/yield/formal-parameters-after-reassignment-non-strict.js @@ -0,0 +1,47 @@ +// Copyright (C) 2013 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +es6id: 25.2 +description: > + Formal parameters are valid yield expression operands. +flags: [noStrict] +features: [generators] +---*/ + +function* g(a, b, c, d) { + arguments[0] = 32; + arguments[1] = 54; + arguments[2] = 333; + yield a; + yield b; + yield c; + yield d; +} +var iter = g(23, 45, 33); +var result; + +result = iter.next(); +assert.sameValue(result.value, 32, 'First result `value`'); +assert.sameValue(result.done, false, 'First result `done` flag'); + +result = iter.next(); +assert.sameValue(result.value, 54, 'Second result `value`'); +assert.sameValue(result.done, false, 'Second result `done` flag'); + +result = iter.next(); +assert.sameValue(result.value, 333, 'Third result `value`'); +assert.sameValue(result.done, false, 'Third result `done` flag'); + +result = iter.next(); +assert.sameValue( + result.value, undefined, 'Fourth result `value` (unspecified parameter)' +); +assert.sameValue( + result.done, false, 'Fourth result `done` flag (unspecified parameter)' +); + +result = iter.next(); +assert.sameValue(result.value, undefined, 'Final result `value`'); +assert.sameValue(result.done, true, 'Final result `done` flag'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/yield/formal-parameters-after-reassignment-strict-strict.js b/js/src/tests/test262/language/expressions/yield/formal-parameters-after-reassignment-strict-strict.js new file mode 100644 index 0000000000..aa5c3a1b1e --- /dev/null +++ b/js/src/tests/test262/language/expressions/yield/formal-parameters-after-reassignment-strict-strict.js @@ -0,0 +1,48 @@ +'use strict'; +// Copyright (C) 2013 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +es6id: 25.2 +description: > + Formal parameters are valid yield expression operands. +flags: [onlyStrict] +features: [generators] +---*/ + +function* g(a, b, c, d) { + arguments[0] = 32; + arguments[1] = 54; + arguments[2] = 333; + yield a; + yield b; + yield c; + yield d; +} +var iter = g(23, 45, 33); +var result; + +result = iter.next(); +assert.sameValue(result.value, 23, 'First result `value`'); +assert.sameValue(result.done, false, 'First result `done` flag'); + +result = iter.next(); +assert.sameValue(result.value, 45, 'Second result `value`'); +assert.sameValue(result.done, false, 'Second result `done` flag'); + +result = iter.next(); +assert.sameValue(result.value, 33, 'Third result `value`'); +assert.sameValue(result.done, false, 'Third result `done` flag'); + +result = iter.next(); +assert.sameValue( + result.value, undefined, 'Fourth result `value` (unspecified parameter)' +); +assert.sameValue( + result.done, false, 'Fourth result `done` flag (unspecified parameter)' +); + +result = iter.next(); +assert.sameValue(result.value, undefined, 'Final result `value`'); +assert.sameValue(result.done, true, 'Final result `done` flag'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/yield/formal-parameters.js b/js/src/tests/test262/language/expressions/yield/formal-parameters.js new file mode 100644 index 0000000000..83467fc2b9 --- /dev/null +++ b/js/src/tests/test262/language/expressions/yield/formal-parameters.js @@ -0,0 +1,43 @@ +// Copyright (C) 2013 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +es6id: 25.2 +description: > + Formal parameters are valid yield expression operands. +features: [generators] +---*/ + +function* g(a, b, c, d) { + yield a; + yield b; + yield c; + yield d; +} +var iter = g(23, 45, 33); +var result; + +result = iter.next(); +assert.sameValue(result.value, 23, 'First result `value`'); +assert.sameValue(result.done, false, 'First result `done` flag'); + +result = iter.next(); +assert.sameValue(result.value, 45, 'Second result `value`'); +assert.sameValue(result.done, false, 'Second result `done` flag'); + +result = iter.next(); +assert.sameValue(result.value, 33, 'Third result `value`'); +assert.sameValue(result.done, false, 'Third result `done` flag'); + +result = iter.next(); +assert.sameValue( + result.value, undefined, 'Fourth result `value` (unspecified parameter)' +); +assert.sameValue( + result.done, false, 'Fourth result `done` flag (unspecified parameter)' +); + +result = iter.next(); +assert.sameValue(result.value, undefined, 'Final result `value`'); +assert.sameValue(result.done, true, 'Final result `done` flag'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/yield/from-catch.js b/js/src/tests/test262/language/expressions/yield/from-catch.js new file mode 100644 index 0000000000..a90a9ae34e --- /dev/null +++ b/js/src/tests/test262/language/expressions/yield/from-catch.js @@ -0,0 +1,29 @@ +// Copyright (C) 2013 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +es6id: 25.2 +description: > + The behavior of `yield` expressions should not be affected when they appear + within the `catch` block of `try` statements. +features: [generators] +---*/ + +function* g() { + try { + throw new Error(); + } catch (err) { + yield 1; + } +} +var iter = g(); +var result; + +result = iter.next(); +assert.sameValue(result.value, 1, 'First result `value`'); +assert.sameValue(result.done, false, 'First result `done` flag'); + +result = iter.next(); +assert.sameValue(result.value, undefined, 'Final result `value`'); +assert.sameValue(result.done, true, 'Final result `done`flag'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/yield/from-try.js b/js/src/tests/test262/language/expressions/yield/from-try.js new file mode 100644 index 0000000000..732ff70b78 --- /dev/null +++ b/js/src/tests/test262/language/expressions/yield/from-try.js @@ -0,0 +1,29 @@ +// Copyright (C) 2013 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +es6id: 25.2 +description: > + The behavior of `yield` expressions should not be affected when they appear + within the `try` block of `try` statements. +features: [generators] +---*/ + +function* g() { + try { + yield 1; + } catch (err) { + throw err; + } +} +var iter = g(); +var result; + +result = iter.next(); +assert.sameValue(result.value, 1, 'First result `value`'); +assert.sameValue(result.done, false, 'First result `done` flag'); + +result = iter.next(); +assert.sameValue(result.value, undefined, 'Final result `value`'); +assert.sameValue(result.done, true, 'Final result `done`flag'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/yield/from-with.js b/js/src/tests/test262/language/expressions/yield/from-with.js new file mode 100644 index 0000000000..6d30c8ecaf --- /dev/null +++ b/js/src/tests/test262/language/expressions/yield/from-with.js @@ -0,0 +1,42 @@ +// Copyright (C) 2013 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +es6id: 25.2 +description: > + The operand to a `yield` expression should honor the semantics of the + `with` statement. +flags: [noStrict] +features: [generators] +---*/ + +function* g() { + var x = 1; + + yield x; + + with ({ x: 2 }) { + yield x; + } + + yield x; +} +var iter = g(); +var result; + +result = iter.next(); +assert.sameValue(result.value, 1, 'First result `value`'); +assert.sameValue(result.done, false, 'First result `done` flag'); + +result = iter.next(); +assert.sameValue(result.value, 2, 'Second result `value`'); +assert.sameValue(result.done, false, 'Second result `done` flag'); + +result = iter.next(); +assert.sameValue(result.value, 1, 'Third result `value`'); +assert.sameValue(result.done, false, 'Third result `done` flag'); + +result = iter.next(); +assert.sameValue(result.value, undefined, 'Final result `value`'); +assert.sameValue(result.done, true, 'Final result `done` flag'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/yield/in-iteration-stmt.js b/js/src/tests/test262/language/expressions/yield/in-iteration-stmt.js new file mode 100644 index 0000000000..f85781f867 --- /dev/null +++ b/js/src/tests/test262/language/expressions/yield/in-iteration-stmt.js @@ -0,0 +1,24 @@ +// |reftest| error:SyntaxError +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-generator-function-definitions +es6id: 14.4 +description: > + YieldExpression operand may not include the `in` keyword in contexts where it + is disallowed +info: | + Syntax + + yield [no LineTerminator here] AssignmentExpression[?In, +Yield] +negative: + phase: parse + type: SyntaxError +features: [generators] +---*/ + +$DONOTEVALUATE(); + +function* g() { + for (yield '' in {}; ; ) ; +} diff --git a/js/src/tests/test262/language/expressions/yield/in-rltn-expr.js b/js/src/tests/test262/language/expressions/yield/in-rltn-expr.js new file mode 100644 index 0000000000..1d1e69ceb5 --- /dev/null +++ b/js/src/tests/test262/language/expressions/yield/in-rltn-expr.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. +/*--- +esid: sec-generator-function-definitions +es6id: 14.4 +description: > + YieldExpression contextually recognizes the `in` keyword as part of a + RelationalExpression +info: | + Syntax + + yield [no LineTerminator here] AssignmentExpression[?In, +Yield] +features: [generators] +---*/ + +var obj = Object.create(null); +var iter, iterResult, value; +function* g() { + value = yield 'hit' in obj; + value = yield 'miss' in obj; +} +obj.hit = true; + +iter = g(); + +iterResult = iter.next('first'); + +assert.sameValue(iterResult.done, false, '`done` property (first iteration)'); +assert.sameValue(iterResult.value, true, '`value` property (first iteration)'); +assert.sameValue( + value, undefined, 'generator paused prior to evaluating AssignmentExpression' +); + +iterResult = iter.next('second'); + +assert.sameValue(iterResult.done, false, '`done` property (second iteration)'); +assert.sameValue( + iterResult.value, false, '`value` property (second iteration)' +); +assert.sameValue(value, 'second', 'value of first AssignmentExpression'); + +iterResult = iter.next('third'); + +assert.sameValue(iterResult.done, true, '`done` property (third iteration)'); +assert.sameValue( + iterResult.value, undefined, '`value` property (third iteration)' +); +assert.sameValue(value, 'third', 'value of second AssignmentExpression'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/yield/invalid-left-hand-side.js b/js/src/tests/test262/language/expressions/yield/invalid-left-hand-side.js new file mode 100644 index 0000000000..656e27d75f --- /dev/null +++ b/js/src/tests/test262/language/expressions/yield/invalid-left-hand-side.js @@ -0,0 +1,29 @@ +// |reftest| error:SyntaxError +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-generator-function-definitions +es6id: 14.4 +description: A YieldExpression is not a valid LeftHandSideExpression +info: | + AssignmentExpression[In, Yield] : + ConditionalExpression[?In, ?Yield] + [+Yield]YieldExpression[?In] + ArrowFunction[?In, ?Yield] + LeftHandSideExpression[?Yield] = AssignmentExpression[?In, ?Yield] + LeftHandSideExpression[?Yield] AssignmentOperator AssignmentExpression[?In, ?Yield] + + LeftHandSideExpression[Yield] : + NewExpression[?Yield] + CallExpression[?Yield] +features: [generators] +negative: + phase: parse + type: SyntaxError +---*/ + +$DONOTEVALUATE(); + +function* g() { + yield = 1; +} diff --git a/js/src/tests/test262/language/expressions/yield/iter-value-specified.js b/js/src/tests/test262/language/expressions/yield/iter-value-specified.js new file mode 100644 index 0000000000..cd5355f6d0 --- /dev/null +++ b/js/src/tests/test262/language/expressions/yield/iter-value-specified.js @@ -0,0 +1,31 @@ +// Copyright (C) 2013 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +es6id: 25.2 +description: > + When the `next` method of a generator-produced iterable is invoked without + an argument, the corresponding `yield` expression should be evaluated as + `undefined`. +features: [generators] +---*/ + +function* g() { actual = yield; } +var expected = {}; +var iter = g(); +var actual, result; + +result = iter.next(); +assert.sameValue(result.value, undefined, 'First result `value`'); +assert.sameValue(result.done, false, 'First result `done` flag'); +assert.sameValue( + actual, undefined, 'Value of `yield` expression (prior to continuation)' +); + +result = iter.next(expected); +assert.sameValue(result.value, undefined, 'Second result `value`'); +assert.sameValue(result.done, true, 'Second result `done` flag'); +assert.sameValue( + actual, expected, 'Value of `yield` expression (following continuation)' +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/yield/iter-value-unspecified.js b/js/src/tests/test262/language/expressions/yield/iter-value-unspecified.js new file mode 100644 index 0000000000..97a0c7522d --- /dev/null +++ b/js/src/tests/test262/language/expressions/yield/iter-value-unspecified.js @@ -0,0 +1,26 @@ +// Copyright (C) 2013 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +es6id: 25.2 +description: > + When the `next` method of a generator-produced iterable is invoked without + an argument, the corresponding `yield` expression should be evaluated as + `undefined`. +features: [generators] +---*/ + +function* g() { actual = yield; } +var iter = g(); +var actual, result; + +result = iter.next(); +assert.sameValue(result.value, undefined); +assert.sameValue(result.done, false); +assert.sameValue(actual, undefined); + +result = iter.next(); +assert.sameValue(result.value, undefined); +assert.sameValue(result.done, true); +assert.sameValue(actual, undefined); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/yield/rhs-iter.js b/js/src/tests/test262/language/expressions/yield/rhs-iter.js new file mode 100644 index 0000000000..c837ba837a --- /dev/null +++ b/js/src/tests/test262/language/expressions/yield/rhs-iter.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. +/*--- +esid: sec-generator-function-definitions-runtime-semantics-evaluation +es6id: 14.4.14 +description: > + Iteration protocol is not initiated for non-delegating YieldExpression +info: | + YieldExpression:yieldAssignmentExpression + + 1. Let exprRef be the result of evaluating AssignmentExpression. + 2. Let value be ? GetValue(exprRef). + 3. Return ? GeneratorYield(CreateIterResultObject(value, false)). +features: [generators, Symbol.iterator] +---*/ + +var callCount = 0; +var iterSpy = Object.defineProperty({}, Symbol.iterator, { + get: function() { + callCount += 1; + } +}); +function* g() { + yield iterSpy; +} +var iter = g(); +var result; + +result = iter.next(); + +assert.sameValue(result.value, iterSpy); +assert.sameValue(result.done, false); +assert.sameValue(callCount, 0); + +result = iter.next(); + +assert.sameValue(result.value, undefined); +assert.sameValue(result.done, true); +assert.sameValue(callCount, 0); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/yield/rhs-omitted.js b/js/src/tests/test262/language/expressions/yield/rhs-omitted.js new file mode 100644 index 0000000000..23c3f710ff --- /dev/null +++ b/js/src/tests/test262/language/expressions/yield/rhs-omitted.js @@ -0,0 +1,128 @@ +// Copyright (C) 2013 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + `yield` is a valid expression within generator function bodies. +es6id: 14.4 +features: [generators] +---*/ + +var iter, result; +function* g1() { (yield) } +function* g2() { [yield] } +function* g3() { {yield} } +function* g4() { yield, yield; } +function* g5() { (yield) ? yield : yield; } + +iter = g1(); +result = iter.next(); +assert.sameValue( + result.value, undefined, 'Within grouping operator: result `value`' +); +assert.sameValue( + result.done, false, 'Within grouping operator: result `done` flag' +); +result = iter.next(); +assert.sameValue( + result.value, undefined, 'Following grouping operator: result `value`' +); +assert.sameValue( + result.done, true, 'Following grouping operator: result `done` flag' +); + +iter = g2(); +result = iter.next(); +assert.sameValue( + result.value, undefined, 'Within array literal: result `value`' +); +assert.sameValue( + result.done, false, 'Within array literal: result `done` flag' +); +result = iter.next(); +assert.sameValue( + result.value, undefined, 'Following array literal: result `value`' +); +assert.sameValue( + result.done, true, 'Following array literal: result `done` flag' +); + +iter = g3(); +result = iter.next(); +assert.sameValue( + result.value, undefined, 'Within object literal: result `value`' +); +assert.sameValue( + result.done, false, 'Within object literal: result `done` flag' +); +result = iter.next(); +assert.sameValue( + result.value, undefined, 'Following object literal: result `value`' +); +assert.sameValue( + result.done, true, 'Following object literal: result `done` flag' +); + +iter = g4(); +result = iter.next(); +assert.sameValue( + result.value, + undefined, + 'First expression in comma expression: result `value`' +); +assert.sameValue( + result.done, + false, + 'First expression in comma expression: result `done` flag' +); +result = iter.next(); +assert.sameValue( + result.value, + undefined, + 'Second expression in comma expression: result `value`' +); +assert.sameValue( + result.done, + false, + 'Second expression in comma expression: result `done` flag' +); +result = iter.next(); +assert.sameValue( + result.value, undefined, 'Following comma expression: result `value`' +); +assert.sameValue( + result.done, true, 'Following comma expression: result `done` flag' +); + +iter = g5(); +result = iter.next(); +assert.sameValue( + result.value, + undefined, + 'Conditional expression in conditional operator: result `value`' +); +assert.sameValue( + result.done, + false, + 'Conditional expression in conditional operator: result `done` flag' +); +result = iter.next(); +assert.sameValue( + result.value, + undefined, + 'Branch in conditional operator: result `value`' +); +assert.sameValue( + result.done, + false, + 'Branch in conditional operator: result `done` flag' +); +result = iter.next(); +assert.sameValue( + result.value, undefined, 'Following conditional operator: result `value`' +); +assert.sameValue( + result.done, true, 'Following conditional operator: result `done` flag' +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/yield/rhs-primitive.js b/js/src/tests/test262/language/expressions/yield/rhs-primitive.js new file mode 100644 index 0000000000..bde90dfbd8 --- /dev/null +++ b/js/src/tests/test262/language/expressions/yield/rhs-primitive.js @@ -0,0 +1,118 @@ +// Copyright (C) 2013 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +description: > + `yield` is a valid expression within generator function bodies. +es6id: 14.4 +features: [generators] +---*/ + +var result, iter; +function* g1() { (yield 1) } +function* g2() { [yield 1] } +function* g3() { {yield 1} } +function* g4() { yield 1, yield 2; } +function* g5() { (yield 1) ? yield 2 : yield 3; } + +iter = g1(); +result = iter.next(); +assert.sameValue(result.value, 1, 'Within grouping operator: result `value`'); +assert.sameValue( + result.done, false, 'Within grouping operator: result `done` flag' +); +result = iter.next(); +assert.sameValue( + result.value, undefined, 'Following grouping operator: result `value`' +); +assert.sameValue( + result.done, true, 'Following grouping operator: result `done` flag' +); + +iter = g2(); +result = iter.next(); +assert.sameValue(result.value, 1, 'Within array literal: result `value`'); +assert.sameValue( + result.done, false, 'Within array literal: result `done` flag' +); +result = iter.next(); +assert.sameValue( + result.value, undefined, 'Following array literal: result `value`' +); +assert.sameValue( + result.done, true, 'Following array literal: result `done` flag' +); + +iter = g3(); +result = iter.next(); +assert.sameValue(result.value, 1, 'Within object literal: result `value`'); +assert.sameValue( + result.done, false, 'Within object literal: result `done` flag' +); +result = iter.next(); +assert.sameValue( + result.value, undefined, 'Following object literal: result `value`' +); +assert.sameValue( + result.done, true, 'Following object literal: result `done` flag' +); + +iter = g4(); +result = iter.next(); +assert.sameValue( + result.value, 1, 'First expression in comma expression: result `value`' +); +assert.sameValue( + result.done, + false, + 'First expression in comma expression: result `done` flag' +); +result = iter.next(); +assert.sameValue( + result.value, 2, 'Second expression in comma expression: result `value`' +); +assert.sameValue( + result.done, + false, + 'Second expression in comma expression: result `done` flag' +); +result = iter.next(); +assert.sameValue( + result.value, undefined, 'Following comma expression: result `value`' +); +assert.sameValue( + result.done, true, 'Following comma expression: result `done` flag' +); + +iter = g5(); +result = iter.next(); +assert.sameValue( + result.value, + 1, + 'Conditional expression in conditional operator: result `value`' +); +assert.sameValue( + result.done, + false, + 'Conditional expression in conditional operator: result `done` flag' +); +result = iter.next(); +assert.sameValue( + result.value, + 3, + 'Branch in conditional operator: result `value`' +); +assert.sameValue( + result.done, + false, + 'Branch in conditional operator: result `done` flag' +); +result = iter.next(); +assert.sameValue( + result.value, undefined, 'Following conditional operator: result `value`' +); +assert.sameValue( + result.done, true, 'Following conditional operator: result `done` flag' +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/yield/rhs-regexp.js b/js/src/tests/test262/language/expressions/yield/rhs-regexp.js new file mode 100644 index 0000000000..96ee0985ed --- /dev/null +++ b/js/src/tests/test262/language/expressions/yield/rhs-regexp.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. +/*--- +esid: sec-generator-function-definitions +es6id: 14.4 +description: > + YieldExpression accepts a regular expression literal as its right-hand side +info: | + The syntactic context immediately following yield requires use of the + InputElementRegExpOrTemplateTail lexical goal. +features: [generators] +---*/ + +var complete = false; +var sent = {}; +var iter, iterResult, received; +// Unused variables declared to improve error messages in incorrect parsing +// scenarios. +var abc, i; +function* g() { + received = yield/abc/i; + complete = true; +} + +iter = g(); + +assert.sameValue(complete, false, 'generator initially paused'); +assert.sameValue(received, undefined, 'first statement no executed'); + +iterResult = iter.next(); + +assert.sameValue(complete, false, 'generator paused following expression'); +assert.sameValue(received, undefined, 'first statement not executed'); + +assert.sameValue(iterResult.done, false, 'iteration not complete'); +assert.sameValue(iterResult.value.test('ABC'), true, 'first iterated value'); + +iterResult = iter.next(sent); + +assert.sameValue(received, sent, 'YieldExpression value'); +assert.sameValue(complete, true, 'generator correctly re-started'); +assert.sameValue(iterResult.done, true, 'iteration complete'); +assert.sameValue(iterResult.value, undefined, 'second iterated value'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/yield/rhs-template-middle.js b/js/src/tests/test262/language/expressions/yield/rhs-template-middle.js new file mode 100644 index 0000000000..051e6dbab0 --- /dev/null +++ b/js/src/tests/test262/language/expressions/yield/rhs-template-middle.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. +/*--- +esid: sec-generator-function-definitions +es6id: 14.4 +description: YieldExpression may be followed by a TemplateMiddle construct +info: | + The syntactic context immediately following yield requires use of the + InputElementRegExpOrTemplateTail lexical goal. +features: [generators] +---*/ + +var complete = false; +var iter, iterResult, str; +function* g() { + str = `1${ yield }3${ 4 }5`; + complete = true; +} + +iter = g(); + +assert.sameValue(complete, false, 'generator initially paused'); +assert.sameValue(str, undefined, 'first statement not executed'); + +iterResult = iter.next(); + +assert.sameValue(complete, false, 'generator paused following expression'); +assert.sameValue(str, undefined, 'first statement not executed'); + +assert.sameValue(iterResult.done, false, 'iteration not complete'); +assert.sameValue(iterResult.value, undefined, 'first iterated value'); + +iterResult = iter.next(2); + +assert.sameValue(str, '12345', 'YieldExpression value'); +assert.sameValue(complete, true, 'generator correctly re-started'); +assert.sameValue(iterResult.done, true, 'iteration complete'); +assert.sameValue(iterResult.value, undefined, 'second iterated value'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/yield/rhs-unresolvable.js b/js/src/tests/test262/language/expressions/yield/rhs-unresolvable.js new file mode 100644 index 0000000000..b20f397850 --- /dev/null +++ b/js/src/tests/test262/language/expressions/yield/rhs-unresolvable.js @@ -0,0 +1,33 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-generator-function-definitions-runtime-semantics-evaluation +es6id: 14.4.14 +description: GetValue invoked on Reference value +info: | + YieldExpression : yield AssignmentExpression + + 1. Let exprRef be the result of evaluating AssignmentExpression. + 2. Let value be ? GetValue(exprRef). +features: [generators] +---*/ + +var err; +function* g() { + try { + yield test262unresolvable; + } catch (_err) { + err = _err; + } +} +var iter = g(); +var result; + +result = iter.next(); + +assert.sameValue(result.value, undefined); +assert.sameValue(result.done, true); +assert.sameValue(typeof err, 'object'); +assert.sameValue(err.constructor, ReferenceError); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/yield/rhs-yield.js b/js/src/tests/test262/language/expressions/yield/rhs-yield.js new file mode 100644 index 0000000000..1962517b83 --- /dev/null +++ b/js/src/tests/test262/language/expressions/yield/rhs-yield.js @@ -0,0 +1,28 @@ +// Copyright (C) 2013 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +es6id: 25.2 +description: > + Yield expressions are valid yield expression operands. +features: [generators] +---*/ + +function* g() { + yield yield 1; +} +var iter = g(); +var result; + +result = iter.next(); +assert.sameValue(result.value, 1, 'First result `value`'); +assert.sameValue(result.done, false, 'First result `done` flag'); + +result = iter.next(3); +assert.sameValue(result.value, 3, 'Second result `value`'); +assert.sameValue(result.done, false, 'Second result `done` flag'); + +result = iter.next(); +assert.sameValue(result.value, undefined, 'Final result `value`'); +assert.sameValue(result.done, true, 'Final result `done`flag'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/yield/shell.js b/js/src/tests/test262/language/expressions/yield/shell.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/test262/language/expressions/yield/shell.js diff --git a/js/src/tests/test262/language/expressions/yield/star-array.js b/js/src/tests/test262/language/expressions/yield/star-array.js new file mode 100644 index 0000000000..8e85b126e1 --- /dev/null +++ b/js/src/tests/test262/language/expressions/yield/star-array.js @@ -0,0 +1,33 @@ +// Copyright (C) 2013 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +es6id: 25.2 +description: > + When an array is the operand of a `yield *` expression, the generator + should produce an iterator that visits each element in order. +features: [generators] +---*/ + +function* g() { + yield* [1, 2, 3]; +} +var iter = g(); +var result; + +result = iter.next(); +assert.sameValue(result.value, 1, 'First result `value`'); +assert.sameValue(result.done, false, 'First result `done` flag'); + +result = iter.next(); +assert.sameValue(result.value, 2, 'Second result `value`'); +assert.sameValue(result.done, false, 'Second result `done` flag'); + +result = iter.next(); +assert.sameValue(result.value, 3, 'Third result `value`'); +assert.sameValue(result.done, false, 'Third result `done` flag'); + +result = iter.next(); +assert.sameValue(result.value, undefined, 'Final result `value`'); +assert.sameValue(result.done, true, 'Final result `done` flag'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/yield/star-in-iteration-stmt.js b/js/src/tests/test262/language/expressions/yield/star-in-iteration-stmt.js new file mode 100644 index 0000000000..4511806e2f --- /dev/null +++ b/js/src/tests/test262/language/expressions/yield/star-in-iteration-stmt.js @@ -0,0 +1,24 @@ +// |reftest| error:SyntaxError +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-generator-function-definitions +es6id: 14.4 +description: > + YieldExpression operand may not include the `in` keyword in contexts where it + is disallowed +info: | + Syntax + + yield [no LineTerminator here] * AssignmentExpression[?In, +Yield] +negative: + phase: parse + type: SyntaxError +features: [generators] +---*/ + +$DONOTEVALUATE(); + +function* g() { + for (yield * '' in {}; ; ) ; +} diff --git a/js/src/tests/test262/language/expressions/yield/star-in-rltn-expr.js b/js/src/tests/test262/language/expressions/yield/star-in-rltn-expr.js new file mode 100644 index 0000000000..3aa00be2b2 --- /dev/null +++ b/js/src/tests/test262/language/expressions/yield/star-in-rltn-expr.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. +/*--- +esid: sec-generator-function-definitions +es6id: 14.4 +description: > + YieldExpression contextually recognizes the `in` keyword as part of a + RelationalExpression +info: | + Syntax + + yield [no LineTerminator here] AssignmentExpression[?In, +Yield] +features: [generators, Symbol.iterator] +---*/ + +var obj = Object.create({ hit: true }); +var iter, iterResult, value; +Boolean.prototype[Symbol.iterator] = function* () { yield this.valueOf(); }; +function* g() { + value = yield * 'hit' in obj; + value = yield * 'miss' in obj; +} + +iter = g(); + +iterResult = iter.next('first'); + +assert.sameValue(iterResult.done, false, '`done` property (first iteration)'); +assert.sameValue(iterResult.value, true, '`value` property (first iteration)'); +assert.sameValue( + value, undefined, 'generator paused prior to evaluating AssignmentExpression' +); + +iterResult = iter.next('second'); + +assert.sameValue(iterResult.done, false, '`done` property (second iteration)'); +assert.sameValue( + iterResult.value, false, '`value` property (second iteration)' +); +assert.sameValue(value, undefined, 'value of first AssignmentExpression'); + +iterResult = iter.next('third'); + +assert.sameValue(iterResult.done, true, '`done` property (third iteration)'); +assert.sameValue( + iterResult.value, undefined, '`value` property (third iteration)' +); +assert.sameValue(value, undefined, 'value of second AssignmentExpression'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/yield/star-iterable.js b/js/src/tests/test262/language/expressions/yield/star-iterable.js new file mode 100644 index 0000000000..4c00f343ca --- /dev/null +++ b/js/src/tests/test262/language/expressions/yield/star-iterable.js @@ -0,0 +1,42 @@ +// Copyright (C) 2013 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +es6id: 25.2 +description: > + When an iterator is the operand of a `yield *` expression, the generator + should produce an iterator that visits each iterated item. +features: [generators, Symbol.iterator] +---*/ + +var results = [{ value: 1 }, { value: 8 }, { value: 34, done: true }]; +var idx = 0; +var iterator = {}; +var iterable = { + next: function() { + var result = results[idx]; + idx += 1; + return result; + } +}; +iterator[Symbol.iterator] = function() { + return iterable; +}; +function* g() { + yield* iterator; +} +var iter = g(); +var result; + +result = iter.next(); +assert.sameValue(result.value, 1, 'First result `value`'); +assert.sameValue(result.done, undefined, 'First result `done` flag'); + +result = iter.next(); +assert.sameValue(result.value, 8, 'Third result `value`'); +assert.sameValue(result.done, undefined, 'Third result `done` flag'); + +result = iter.next(); +assert.sameValue(result.value, undefined, 'Final result `value`'); +assert.sameValue(result.done, true, 'Final result `done` flag'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/yield/star-return-is-null.js b/js/src/tests/test262/language/expressions/yield/star-return-is-null.js new file mode 100644 index 0000000000..3b703ee5f8 --- /dev/null +++ b/js/src/tests/test262/language/expressions/yield/star-return-is-null.js @@ -0,0 +1,57 @@ +// Copyright (C) 2020 Alexey Shvayka. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-generator-function-definitions-runtime-semantics-evaluation +description: > + If iterator's "return" method is `null`, + received completion is forwarded to the runtime. +info: | + YieldExpression : yield * AssignmentExpression + + [...] + 7. Repeat, + [...] + c. Else, + i. Assert: received.[[Type]] is return. + ii. Let return be ? GetMethod(iterator, "return"). + iii. If return is undefined, then + [...] + 2. Return Completion(received). + + GetMethod ( V, P ) + + [...] + 2. Let func be ? GetV(V, P). + 3. If func is either undefined or null, return undefined. +features: [generators, Symbol.iterator] +---*/ + +var returnGets = 0; +var iterable = { + next: function() { + return {value: 1, done: false}; + }, + get return() { + returnGets += 1; + return null; + }, +}; + +iterable[Symbol.iterator] = function() { + return iterable; +}; + +function* generator() { + yield* iterable; +} + +var iterator = generator(); +iterator.next(); + +var result = iterator.return(2); +assert.sameValue(result.value, 2); +assert.sameValue(result.done, true); + +assert.sameValue(returnGets, 1); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/yield/star-rhs-iter-get-call-err.js b/js/src/tests/test262/language/expressions/yield/star-rhs-iter-get-call-err.js new file mode 100644 index 0000000000..74a20e2a24 --- /dev/null +++ b/js/src/tests/test262/language/expressions/yield/star-rhs-iter-get-call-err.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. +/*--- +esid: sec-generator-function-definitions-runtime-semantics-evaluation +es6id: 14.4.14 +description: Abrupt completion returned when invoking the @@iterator method +info: | + YieldExpression : yield * AssignmentExpression + + 1. Let exprRef be the result of evaluating AssignmentExpression. + 2. Let value be ? GetValue(exprRef). + 3. Let iterator be ? GetIterator(value). + + 7.4.1 GetIterator + + 1. If method was not passed, then + a. Let method be ? GetMethod(obj, @@iterator). + 2. Let iterator be ? Call(method, obj). +features: [generators, Symbol.iterator] +---*/ + +var thrown = new Test262Error(); +var badIter = {}; +badIter[Symbol.iterator] = function() { + throw thrown; +}; +function* g() { + try { + yield * badIter; + } catch (err) { + caught = err; + } +} +var iter = g(); +var result, caught; + +assert.sameValue(caught, undefined, 'method is not invoked eagerly'); + +result = iter.next(); + +assert.sameValue(result.value, undefined, 'iteration value'); +assert.sameValue(result.done, true, 'iteration status'); +assert.sameValue(caught, thrown, 'error value'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/yield/star-rhs-iter-get-call-non-obj.js b/js/src/tests/test262/language/expressions/yield/star-rhs-iter-get-call-non-obj.js new file mode 100644 index 0000000000..65fa89f754 --- /dev/null +++ b/js/src/tests/test262/language/expressions/yield/star-rhs-iter-get-call-non-obj.js @@ -0,0 +1,44 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-generator-function-definitions-runtime-semantics-evaluation +es6id: 14.4.14 +description: TypeError thrown when @@iterator method returns a non-object value +info: | + YieldExpression : yield * AssignmentExpression + + 1. Let exprRef be the result of evaluating AssignmentExpression. + 2. Let value be ? GetValue(exprRef). + 3. Let iterator be ? GetIterator(value). + + 7.4.1 GetIterator + + 1. If method was not passed, then + a. Let method be ? GetMethod(obj, @@iterator). + 2. Let iterator be ? Call(method, obj). + 3. If Type(iterator) is not Object, throw a TypeError exception. +features: [generators, Symbol.iterator] +---*/ + +var badIter = {}; +badIter[Symbol.iterator] = function() { + return 7; +}; +function* g() { + try { + yield * badIter; + } catch (err) { + caught = err; + } +} +var iter = g(); +var result, caught; + +result = iter.next(); + +assert.sameValue(result.value, undefined); +assert.sameValue(result.done, true); +assert.sameValue(typeof caught, 'object'); +assert.sameValue(caught.constructor, TypeError); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/yield/star-rhs-iter-get-get-err.js b/js/src/tests/test262/language/expressions/yield/star-rhs-iter-get-get-err.js new file mode 100644 index 0000000000..b9ededfdd7 --- /dev/null +++ b/js/src/tests/test262/language/expressions/yield/star-rhs-iter-get-get-err.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. +/*--- +esid: sec-generator-function-definitions-runtime-semantics-evaluation +es6id: 14.4.14 +description: Abrupt completion returned when accessing the @@iterator property +info: | + YieldExpression : yield * AssignmentExpression + + 1. Let exprRef be the result of evaluating AssignmentExpression. + 2. Let value be ? GetValue(exprRef). + 3. Let iterator be ? GetIterator(value). + + 7.4.1 GetIterator + + 1. If method was not passed, then + a. Let method be ? GetMethod(obj, @@iterator). +features: [generators, Symbol.iterator] +---*/ + +var thrown = new Test262Error(); +var poisonedIter = Object.defineProperty({}, Symbol.iterator, { + get: function() { + throw thrown; + } +}); +function* g() { + try { + yield * poisonedIter; + } catch (err) { + caught = err; + } +} +var iter = g(); +var result, caught; + +assert.sameValue(caught, undefined, 'property is not accessed eagerly'); + +result = iter.next(); + +assert.sameValue(result.value, undefined, 'iteration value'); +assert.sameValue(result.done, true, 'iteration status'); +assert.sameValue(caught, thrown, 'error value'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/yield/star-rhs-iter-nrml-next-call-err.js b/js/src/tests/test262/language/expressions/yield/star-rhs-iter-nrml-next-call-err.js new file mode 100644 index 0000000000..bfacb141ef --- /dev/null +++ b/js/src/tests/test262/language/expressions/yield/star-rhs-iter-nrml-next-call-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. +/*--- +esid: sec-generator-function-definitions-runtime-semantics-evaluation +es6id: 14.4.14 +description: Abrupt completion returned when invoking iterator `next` method +info: | + YieldExpression : yield * AssignmentExpression + + 1. Let exprRef be the result of evaluating AssignmentExpression. + 2. Let value be ? GetValue(exprRef). + 3. Let iterator be ? GetIterator(value). + 4. Let received be NormalCompletion(undefined). + 5. Repeat + a. If received.[[Type]] is normal, then + i. Let innerResult be ? IteratorNext(iterator, received.[[Value]]). + + 7.4.2 IteratorNext + + 1. If value was not passed, then + [...] + 2. Else, + a. Let result be ? Invoke(iterator, "next", « value »). +features: [generators, Symbol.iterator] +---*/ + +var thrown = new Test262Error(); +var badIter = {}; +badIter[Symbol.iterator] = function() { + return { + next: function() { + throw thrown; + } + }; +}; +function* g() { + try { + yield * badIter; + } catch (err) { + caught = err; + } +} +var iter = g(); +var result, caught; + +result = iter.next(); + +assert.sameValue(result.value, undefined); +assert.sameValue(result.done, true); +assert.sameValue(caught, thrown); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/yield/star-rhs-iter-nrml-next-call-non-obj.js b/js/src/tests/test262/language/expressions/yield/star-rhs-iter-nrml-next-call-non-obj.js new file mode 100644 index 0000000000..8d0e27e212 --- /dev/null +++ b/js/src/tests/test262/language/expressions/yield/star-rhs-iter-nrml-next-call-non-obj.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. +/*--- +esid: sec-generator-function-definitions-runtime-semantics-evaluation +es6id: 14.4.14 +description: > + TypeError thrown when iterator `next` method returns a non-object value +info: | + YieldExpression : yield * AssignmentExpression + + 1. Let exprRef be the result of evaluating AssignmentExpression. + 2. Let value be ? GetValue(exprRef). + 3. Let iterator be ? GetIterator(value). + 4. Let received be NormalCompletion(undefined). + 5. Repeat + a. If received.[[Type]] is normal, then + i. Let innerResult be ? IteratorNext(iterator, received.[[Value]]). + + 7.4.2 IteratorNext + + 1. If value was not passed, then + [...] + 2. Else, + a. Let result be ? Invoke(iterator, "next", « value »). +features: [generators, Symbol.iterator] +---*/ + +var badIter = {}; +badIter[Symbol.iterator] = function() { + return { + next: function() { + return 8; + } + }; +}; +function* g() { + try { + yield * badIter; + } catch (err) { + caught = err; + } +} +var iter = g(); +var result, caught; + +result = iter.next(); + +assert.sameValue(result.value, undefined); +assert.sameValue(result.done, true); +assert.sameValue(typeof caught, 'object'); +assert.sameValue(caught.constructor, TypeError); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/yield/star-rhs-iter-nrml-next-get-err.js b/js/src/tests/test262/language/expressions/yield/star-rhs-iter-nrml-next-get-err.js new file mode 100644 index 0000000000..3da74f2671 --- /dev/null +++ b/js/src/tests/test262/language/expressions/yield/star-rhs-iter-nrml-next-get-err.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. +/*--- +esid: sec-generator-function-definitions-runtime-semantics-evaluation +es6id: 14.4.14 +description: Abrupt completion returned when accessing iterator `next` method +info: | + YieldExpression : yield * AssignmentExpression + + 1. Let exprRef be the result of evaluating AssignmentExpression. + 2. Let value be ? GetValue(exprRef). + 3. Let iterator be ? GetIterator(value). + 4. Let received be NormalCompletion(undefined). + 5. Repeat + a. If received.[[Type]] is normal, then + i. Let innerResult be ? IteratorNext(iterator, received.[[Value]]). + + 7.4.2 IteratorNext + + 1. If value was not passed, then + [...] + 2. Else, + a. Let result be ? Invoke(iterator, "next", « value »). +features: [generators, Symbol.iterator] +---*/ + +var thrown = new Test262Error(); +var badIter = {}; +var poisonedNext = Object.defineProperty({}, 'next', { + get: function() { + throw thrown; + } +}); +badIter[Symbol.iterator] = function() { + return poisonedNext; +}; +function* g() { + try { + yield * badIter; + } catch (err) { + caught = err; + } +} +var iter = g(); +var result, caught; + +result = iter.next(); + +assert.sameValue(result.value, undefined); +assert.sameValue(result.done, true); +assert.sameValue(caught, thrown); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/yield/star-rhs-iter-nrml-next-invoke.js b/js/src/tests/test262/language/expressions/yield/star-rhs-iter-nrml-next-invoke.js new file mode 100644 index 0000000000..50fc345659 --- /dev/null +++ b/js/src/tests/test262/language/expressions/yield/star-rhs-iter-nrml-next-invoke.js @@ -0,0 +1,54 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-generator-function-definitions-runtime-semantics-evaluation +es6id: 14.4.14 +description: Invocation of iterator `next` method +info: | + YieldExpression : yield * AssignmentExpression + + 1. Let exprRef be the result of evaluating AssignmentExpression. + 2. Let value be ? GetValue(exprRef). + 3. Let iterator be ? GetIterator(value). + 4. Let received be NormalCompletion(undefined). + 5. Repeat + a. If received.[[Type]] is normal, then + i. Let innerResult be ? IteratorNext(iterator, received.[[Value]]). + + 7.4.2 IteratorNext + + 1. If value was not passed, then + [...] + 2. Else, + a. Let result be ? Invoke(iterator, "next", « value »). + [...] +features: [generators, Symbol.iterator] +---*/ + +var args, thisValue; +var callCount = 0; +var spyIterator = { + next: function() { + callCount += 1; + args = arguments; + thisValue = this; + return { done: true }; + } +}; +var spyIterable = {}; +spyIterable[Symbol.iterator] = function() { + return spyIterator; +}; +function* g() { + yield * spyIterable; +} +var iter = g(); + +iter.next(9876); + +assert.sameValue(callCount, 1); +assert.sameValue(args.length, 1); +assert.sameValue(args[0], undefined); +assert.sameValue(thisValue, spyIterator); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/yield/star-rhs-iter-nrml-res-done-err.js b/js/src/tests/test262/language/expressions/yield/star-rhs-iter-nrml-res-done-err.js new file mode 100644 index 0000000000..8888b974f3 --- /dev/null +++ b/js/src/tests/test262/language/expressions/yield/star-rhs-iter-nrml-res-done-err.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. +/*--- +esid: sec-generator-function-definitions-runtime-semantics-evaluation +es6id: 14.4.14 +description: > + Abrupt completion returned when accessing `done` property of iteration result +info: | + YieldExpression : yield * AssignmentExpression + + 1. Let exprRef be the result of evaluating AssignmentExpression. + 2. Let value be ? GetValue(exprRef). + 3. Let iterator be ? GetIterator(value). + 4. Let received be NormalCompletion(undefined). + 5. Repeat + a. If received.[[Type]] is normal, then + i. Let innerResult be ? IteratorNext(iterator, received.[[Value]]). + ii. Let done be ? IteratorComplete(innerResult). + + 7.4.3 IteratorComplete + + 1. Assert: Type(iterResult) is Object. + 2. Return ToBoolean(? Get(iterResult, "done")). +features: [generators, Symbol.iterator] +---*/ + +var thrown = new Test262Error(); +var badIter = {}; +var poisonedDone = Object.defineProperty({}, 'done', { + get: function() { + throw thrown; + } +}); +badIter[Symbol.iterator] = function() { + return { + next: function() { + return poisonedDone; + } + }; +}; +function* g() { + try { + yield * badIter; + } catch (err) { + caught = err; + } +} +var iter = g(); +var result, caught; + +result = iter.next(); + +assert.sameValue(caught, thrown); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/yield/star-rhs-iter-nrml-res-done-no-value.js b/js/src/tests/test262/language/expressions/yield/star-rhs-iter-nrml-res-done-no-value.js new file mode 100644 index 0000000000..2450ad2884 --- /dev/null +++ b/js/src/tests/test262/language/expressions/yield/star-rhs-iter-nrml-res-done-no-value.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. +/*--- +esid: sec-generator-function-definitions-runtime-semantics-evaluation +es6id: 14.4.14 +description: > + `value` property is not accessed when iteration is incomplete +info: | + YieldExpression : yield * AssignmentExpression + + 1. Let exprRef be the result of evaluating AssignmentExpression. + 2. Let value be ? GetValue(exprRef). + 3. Let iterator be ? GetIterator(value). + 4. Let received be NormalCompletion(undefined). + 5. Repeat + a. If received.[[Type]] is normal, then + i. Let innerResult be ? IteratorNext(iterator, received.[[Value]]). + ii. Let done be ? IteratorComplete(innerResult). + iii. If done is true, then + 1. Return ? IteratorValue(innerResult). +features: [generators, Symbol.iterator] +---*/ + +var badIter = {}; +var callCount = 0; +var spyValue = Object.defineProperty({ done: false }, 'value', { + get: function() { + callCount += 1; + } +}); +badIter[Symbol.iterator] = function() { + return { + next: function() { + return spyValue; + } + }; +}; +var delegationComplete = false; +function* g() { + yield * badIter; + delegationComplete = true; +} +var iter = g(); + +iter.next(); +assert.sameValue(callCount, 0, 'access count (first iteration)'); +assert.sameValue( + delegationComplete, false, 'delegation ongoing (first iteration)' +); + +iter.next(); +assert.sameValue(callCount, 0, 'access count (second iteration)'); +assert.sameValue( + delegationComplete, false, 'delegation ongoing (second iteration)' +); + +spyValue.done = true; +iter.next(); +assert.sameValue(callCount, 1, 'access count (final iteration)'); +assert.sameValue(delegationComplete, true, 'delegation complete'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/yield/star-rhs-iter-nrml-res-value-err.js b/js/src/tests/test262/language/expressions/yield/star-rhs-iter-nrml-res-value-err.js new file mode 100644 index 0000000000..efe0206098 --- /dev/null +++ b/js/src/tests/test262/language/expressions/yield/star-rhs-iter-nrml-res-value-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. +/*--- +esid: sec-generator-function-definitions-runtime-semantics-evaluation +es6id: 14.4.14 +description: > + Abrupt completion returned when accessing `value` property of iteration + result +info: | + YieldExpression : yield * AssignmentExpression + + 1. Let exprRef be the result of evaluating AssignmentExpression. + 2. Let value be ? GetValue(exprRef). + 3. Let iterator be ? GetIterator(value). + 4. Let received be NormalCompletion(undefined). + 5. Repeat + a. If received.[[Type]] is normal, then + i. Let innerResult be ? IteratorNext(iterator, received.[[Value]]). + ii. Let done be ? IteratorComplete(innerResult). + iii. If done is true, then + 1. Return ? IteratorValue(innerResult). + + 7.4.4 IteratorValue + + 1. Assert: Type(iterResult) is Object. + 2. Return ? Get(iterResult, "value"). +features: [generators, Symbol.iterator] +---*/ + +var thrown = new Test262Error(); +var badIter = {}; +var poisonedValue = Object.defineProperty({ done: true }, 'value', { + get: function() { + throw thrown; + } +}); +badIter[Symbol.iterator] = function() { + return { + next: function() { + return poisonedValue; + } + }; +}; +function* g() { + try { + yield * badIter; + } catch (err) { + caught = err; + } +} +var iter = g(); +var result, caught; + +result = iter.next(); + +assert.sameValue(caught, thrown); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/yield/star-rhs-iter-nrml-res-value-final.js b/js/src/tests/test262/language/expressions/yield/star-rhs-iter-nrml-res-value-final.js new file mode 100644 index 0000000000..3068878530 --- /dev/null +++ b/js/src/tests/test262/language/expressions/yield/star-rhs-iter-nrml-res-value-final.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. +/*--- +esid: sec-generator-function-definitions-runtime-semantics-evaluation +es6id: 14.4.14 +description: Value received from invocation of generator's `next` method +info: | + YieldExpression : yield * AssignmentExpression + + 1. Let exprRef be the result of evaluating AssignmentExpression. + 2. Let value be ? GetValue(exprRef). + 3. Let iterator be ? GetIterator(value). + 4. Let received be NormalCompletion(undefined). + 5. Repeat + a. If received.[[Type]] is normal, then + i. Let innerResult be ? IteratorNext(iterator, received.[[Value]]). + ii. Let done be ? IteratorComplete(innerResult). + iii. If done is true, then + 1. Return ? IteratorValue(innerResult). + + 7.4.4 IteratorValue + + 1. Assert: Type(iterResult) is Object. + 2. Return ? Get(iterResult, "value"). +features: [generators, Symbol.iterator] +---*/ + +var quickIter = {}; +var exprValue, nextReceived, done, iter; +quickIter[Symbol.iterator] = function() { + return { + next: function(x) { + nextReceived = x; + return { + done: done, + value: 3333 + }; + } + }; +}; +function* g() { + exprValue = yield * quickIter; +} + +done = true; +iter = g(); +iter.next(4444); + +assert.sameValue( + nextReceived, undefined, 'received value (previously-exhausted iterator)' +); +assert.sameValue(exprValue, 3333, 'expression value (previously-exhausted iterator)'); + +done = false; +exprValue = null; +iter = g(); +iter.next(2222); +done = true; +iter.next(5555); + +assert.sameValue(nextReceived, 5555, 'received value'); +assert.sameValue(exprValue, 3333, 'expression value'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/yield/star-rhs-iter-rtrn-no-rtrn.js b/js/src/tests/test262/language/expressions/yield/star-rhs-iter-rtrn-no-rtrn.js new file mode 100644 index 0000000000..8c2dd1bba9 --- /dev/null +++ b/js/src/tests/test262/language/expressions/yield/star-rhs-iter-rtrn-no-rtrn.js @@ -0,0 +1,78 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-generator-function-definitions-runtime-semantics-evaluation +es6id: 14.4.14 +description: > + "Return" completion returned when `return` method is not defined +info: | + YieldExpression : yield * AssignmentExpression + + 1. Let exprRef be the result of evaluating AssignmentExpression. + 2. Let value be ? GetValue(exprRef). + 3. Let iterator be ? GetIterator(value). + 4. Let received be NormalCompletion(undefined). + 5. Repeat + a. If received.[[Type]] is normal, then + [...] + b. Else if received.[[Type]] is throw, then + [...] + c. Else, + i. Assert: received.[[Type]] is return. + ii. Let return be ? GetMethod(iterator, "return"). + iii. If return is undefined, return Completion(received). +features: [generators, Symbol.iterator] +---*/ + +var badIter = {}; +var throwCount = 0; +var returnCount = 0; +var hitNextStatement = false; +var hitCatch = false; +var hitFinally = false; +var spyResult = { + next: function() { + return { done: false }; + } +}; +Object.defineProperty(spyResult, 'throw', { + get: function() { + throwCount += 1; + } +}); +Object.defineProperty(spyResult, 'return', { + get: function() { + returnCount += 1; + } +}); +badIter[Symbol.iterator] = function() { + return spyResult; +}; +function* g() { + try { + yield * badIter; + hitNextStatement = true; + } catch (_) { + hitCatch = true; + } finally { + hitFinally = true; + } +} +var iter = g(); + +iter.next(); +iter.return(); + +assert.sameValue(throwCount, 0, '`throw` property access'); +assert.sameValue(returnCount, 1, '`return` property access'); +assert.sameValue( + hitFinally, true, 'Generator execution was resumed' +); +assert.sameValue( + hitNextStatement, false, 'Abrupt completion interrupted control flow' +); +assert.sameValue( + hitCatch, false, 'Abrupt completion not interpreted as "throw"' +); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/yield/star-rhs-iter-rtrn-res-done-err.js b/js/src/tests/test262/language/expressions/yield/star-rhs-iter-rtrn-res-done-err.js new file mode 100644 index 0000000000..52d4b145e1 --- /dev/null +++ b/js/src/tests/test262/language/expressions/yield/star-rhs-iter-rtrn-res-done-err.js @@ -0,0 +1,69 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-generator-function-definitions-runtime-semantics-evaluation +es6id: 14.4.14 +description: > + Abrupt completion returned when accessing `done` property of iteration result +info: | + YieldExpression : yield * AssignmentExpression + + 1. Let exprRef be the result of evaluating AssignmentExpression. + 2. Let value be ? GetValue(exprRef). + 3. Let iterator be ? GetIterator(value). + 4. Let received be NormalCompletion(undefined). + 5. Repeat + a. If received.[[Type]] is normal, then + [...] + b. Else if received.[[Type]] is throw, then + [...] + c. Else, + i. Assert: received.[[Type]] is return. + ii. Let return be ? GetMethod(iterator, "return"). + iii. If return is undefined, return Completion(received). + iv. Let innerReturnResult be ? Call(return, iterator, « + received.[[Value]] »). + v. If Type(innerReturnResult) is not Object, throw a TypeError + exception. + vi. Let done be ? IteratorComplete(innerReturnResult). + + 7.4.3 IteratorComplete + + 1. Assert: Type(iterResult) is Object. + 2. Return ToBoolean(? Get(iterResult, "done")). +features: [generators, Symbol.iterator] +---*/ + +var thrown = new Test262Error(); +var badIter = {}; +var poisonedDone = Object.defineProperty({}, 'done', { + get: function() { + throw thrown; + } +}); +badIter[Symbol.iterator] = function() { + return { + next: function() { + return { done: false }; + }, + return: function() { + return poisonedDone; + } + }; +}; +function* g() { + try { + yield * badIter; + } catch (err) { + caught = err; + } +} +var iter = g(); +var caught; + +iter.next(); +iter.return(); + +assert.sameValue(caught, thrown); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/yield/star-rhs-iter-rtrn-res-done-no-value.js b/js/src/tests/test262/language/expressions/yield/star-rhs-iter-rtrn-res-done-no-value.js new file mode 100644 index 0000000000..b34b87dfd8 --- /dev/null +++ b/js/src/tests/test262/language/expressions/yield/star-rhs-iter-rtrn-res-done-no-value.js @@ -0,0 +1,93 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-generator-function-definitions-runtime-semantics-evaluation +es6id: 14.4.14 +description: > + `value` property is not accessed when iteration is incomplete +info: | + YieldExpression : yield * AssignmentExpression + + 1. Let exprRef be the result of evaluating AssignmentExpression. + 2. Let value be ? GetValue(exprRef). + 3. Let iterator be ? GetIterator(value). + 4. Let received be NormalCompletion(undefined). + 5. Repeat + a. If received.[[Type]] is normal, then + [...] + b. Else if received.[[Type]] is throw, then + [...] + c. Else, + i. Assert: received.[[Type]] is return. + ii. Let return be ? GetMethod(iterator, "return"). + iii. If return is undefined, return Completion(received). + iv. Let innerReturnResult be ? Call(return, iterator, « + received.[[Value]] »). + v. If Type(innerReturnResult) is not Object, throw a TypeError + exception. + vi. Let done be ? IteratorComplete(innerReturnResult). + vii. If done is true, then + 1. Let value be ? IteratorValue(innerReturnResult). + 2. Return Completion{[[Type]]: return, [[Value]]: value, + [[Target]]: empty}. + viii. Let received be GeneratorYield(innerReturnResult). + + 7.4.3 IteratorComplete + + 1. Assert: Type(iterResult) is Object. + 2. Return ToBoolean(? Get(iterResult, "done")). +features: [generators, Symbol.iterator] +---*/ + +var badIter = {}; +var callCount = 0; +var spyValue = Object.defineProperty({ done: false }, 'value', { + get: function() { + callCount += 1; + } +}); +badIter[Symbol.iterator] = function() { + return { + next: function() { + return { done: false }; + }, + return: function() { + return spyValue; + } + }; +}; +var normalCompletion = false; +var errorCompletion = false; +var delegationComplete = false; +function* g() { + try { + yield * badIter; + normalCompletion = true; + } catch (_) { + errorCompletion = true; + } finally { + delegationComplete = true; + } +} +var iter = g(); + +iter.next(); +assert.sameValue(callCount, 0, 'access count (first iteration)'); +assert.sameValue( + delegationComplete, false, 'delegation ongoing (first iteration)' +); + +iter.return(); +assert.sameValue(callCount, 0, 'access count (second iteration)'); +assert.sameValue( + delegationComplete, false, 'delegation ongoing (second iteration)' +); + +spyValue.done = true; +iter.return(); +assert.sameValue(callCount, 1, 'access count (final iteration)'); +assert.sameValue(delegationComplete, true, 'delegation complete'); +assert.sameValue(normalCompletion, false, 'completion was abrupt'); +assert.sameValue(errorCompletion, false, 'completion was not of type "throw"'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/yield/star-rhs-iter-rtrn-res-value-err.js b/js/src/tests/test262/language/expressions/yield/star-rhs-iter-rtrn-res-value-err.js new file mode 100644 index 0000000000..269dfe7cad --- /dev/null +++ b/js/src/tests/test262/language/expressions/yield/star-rhs-iter-rtrn-res-value-err.js @@ -0,0 +1,72 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-generator-function-definitions-runtime-semantics-evaluation +es6id: 14.4.14 +description: > + Abrupt completion returned when accessing `value` property of iteration + result +info: | + YieldExpression : yield * AssignmentExpression + + 1. Let exprRef be the result of evaluating AssignmentExpression. + 2. Let value be ? GetValue(exprRef). + 3. Let iterator be ? GetIterator(value). + 4. Let received be NormalCompletion(undefined). + 5. Repeat + a. If received.[[Type]] is normal, then + [...] + b. Else if received.[[Type]] is throw, then + [...] + c. Else, + i. Assert: received.[[Type]] is return. + ii. Let return be ? GetMethod(iterator, "return"). + iii. If return is undefined, return Completion(received). + iv. Let innerReturnResult be ? Call(return, iterator, « + received.[[Value]] »). + v. If Type(innerReturnResult) is not Object, throw a TypeError + exception. + vi. Let done be ? IteratorComplete(innerReturnResult). + vii. If done is true, then + 1. Let value be ? IteratorValue(innerReturnResult). + + 7.4.4 IteratorValue + + 1. Assert: Type(iterResult) is Object. + 2. Return ? Get(iterResult, "value"). +features: [generators, Symbol.iterator] +---*/ + +var thrown = new Test262Error(); +var badIter = {}; +var poisonedValue = Object.defineProperty({ done: true }, 'value', { + get: function() { + throw thrown; + } +}); +badIter[Symbol.iterator] = function() { + return { + next: function() { + return { done: false }; + }, + return: function() { + return poisonedValue; + } + }; +}; +function* g() { + try { + yield * badIter; + } catch (err) { + caught = err; + } +} +var iter = g(); +var caught; + +iter.next(); +iter.return(); + +assert.sameValue(caught, thrown); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/yield/star-rhs-iter-rtrn-res-value-final.js b/js/src/tests/test262/language/expressions/yield/star-rhs-iter-rtrn-res-value-final.js new file mode 100644 index 0000000000..878450d948 --- /dev/null +++ b/js/src/tests/test262/language/expressions/yield/star-rhs-iter-rtrn-res-value-final.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. +/*--- +esid: sec-generator-function-definitions-runtime-semantics-evaluation +es6id: 14.4.14 +description: Value received from invocation of generator's `return` method +info: | + YieldExpression : yield * AssignmentExpression + + 1. Let exprRef be the result of evaluating AssignmentExpression. + 2. Let value be ? GetValue(exprRef). + 3. Let iterator be ? GetIterator(value). + 4. Let received be NormalCompletion(undefined). + 5. Repeat + a. If received.[[Type]] is normal, then + [...] + b. Else if received.[[Type]] is throw, then + [...] + c. Else, + i. Assert: received.[[Type]] is return. + ii. Let return be ? GetMethod(iterator, "return"). + iii. If return is undefined, return Completion(received). + iv. Let innerReturnResult be ? Call(return, iterator, « + received.[[Value]] »). + v. If Type(innerReturnResult) is not Object, throw a TypeError + exception. + vi. Let done be ? IteratorComplete(innerReturnResult). + vii. If done is true, then + 1. Let value be ? IteratorValue(innerReturnResult). + 2. Return Completion{[[Type]]: return, [[Value]]: value, + [[Target]]: empty}. + viii. Let received be GeneratorYield(innerReturnResult). + +features: [generators, Symbol.iterator] +---*/ + +var quickIter = {}; +var normalCompletion = false; +var errorCompletion = false; +var delegationComplete = false; +var iter, returnReceived; +quickIter[Symbol.iterator] = function() { + return { + next: function() { + return { done: false }; + }, + return: function(x) { + returnReceived = x; + return { done: true, value: 3333 }; + } + }; +}; +function* g() { + try { + yield * quickIter; + normalCompletion = true; + } catch (e) { + errorCompletion = true; + } finally { + delegationComplete = true; + } +} + +iter = g(); + +iter.next(); +iter.return(2222); +assert.sameValue(returnReceived, 2222); +assert.sameValue(delegationComplete, true, 'delegation complete'); +assert.sameValue(normalCompletion, false, 'completion was abrupt'); +assert.sameValue(errorCompletion, false, 'completion was not of type "throw"'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/yield/star-rhs-iter-rtrn-rtrn-call-err.js b/js/src/tests/test262/language/expressions/yield/star-rhs-iter-rtrn-rtrn-call-err.js new file mode 100644 index 0000000000..9f16505ebf --- /dev/null +++ b/js/src/tests/test262/language/expressions/yield/star-rhs-iter-rtrn-rtrn-call-err.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. +/*--- +esid: sec-generator-function-definitions-runtime-semantics-evaluation +es6id: 14.4.14 +description: Abrupt completion returned when invoking iterator `return` method +info: | + YieldExpression : yield * AssignmentExpression + + 1. Let exprRef be the result of evaluating AssignmentExpression. + 2. Let value be ? GetValue(exprRef). + 3. Let iterator be ? GetIterator(value). + 4. Let received be NormalCompletion(undefined). + 5. Repeat + a. If received.[[Type]] is normal, then + [...] + b. Else if received.[[Type]] is throw, then + [...] + c. Else, + i. Assert: received.[[Type]] is return. + ii. Let return be ? GetMethod(iterator, "return"). + iii. If return is undefined, return Completion(received). + iv. Let innerReturnResult be ? Call(return, iterator, « + received.[[Value]] »). +features: [generators, Symbol.iterator] +---*/ + +var thrown = new Test262Error(); +var badIter = {}; +badIter[Symbol.iterator] = function() { + return { + next: function() { + return { done: false }; + }, + return: function() { + throw thrown; + } + }; +}; +function* g() { + try { + yield * badIter; + } catch (err) { + caught = err; + } +} +var iter = g(); +var result, caught; + +iter.next(); +result = iter.return(); + +assert.sameValue(result.value, undefined); +assert.sameValue(result.done, true); +assert.sameValue(caught, thrown); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/yield/star-rhs-iter-rtrn-rtrn-call-non-obj.js b/js/src/tests/test262/language/expressions/yield/star-rhs-iter-rtrn-rtrn-call-non-obj.js new file mode 100644 index 0000000000..53f2a56680 --- /dev/null +++ b/js/src/tests/test262/language/expressions/yield/star-rhs-iter-rtrn-rtrn-call-non-obj.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. +/*--- +esid: sec-generator-function-definitions-runtime-semantics-evaluation +es6id: 14.4.14 +description: > + TypeError thrown when iterator `return` method returns a non-object value +info: | + YieldExpression : yield * AssignmentExpression + + 1. Let exprRef be the result of evaluating AssignmentExpression. + 2. Let value be ? GetValue(exprRef). + 3. Let iterator be ? GetIterator(value). + 4. Let received be NormalCompletion(undefined). + 5. Repeat + a. If received.[[Type]] is normal, then + [...] + b. Else if received.[[Type]] is throw, then + [...] + c. Else, + i. Assert: received.[[Type]] is return. + ii. Let return be ? GetMethod(iterator, "return"). + iii. If return is undefined, return Completion(received). + iv. Let innerReturnResult be ? Call(return, iterator, « + received.[[Value]] »). + v. If Type(innerReturnResult) is not Object, throw a TypeError + exception. +features: [generators, Symbol.iterator] +---*/ + +var badIter = {}; +badIter[Symbol.iterator] = function() { + return { + next: function() { + return { done: false }; + }, + return: function() { + return 23; + } + }; +}; +function* g() { + try { + yield * badIter; + } catch (err) { + caught = err; + } +} +var iter = g(); +var result, caught; + +iter.next(); +result = iter.return(); + +assert.sameValue(result.value, undefined); +assert.sameValue(result.done, true); +assert.sameValue(typeof caught, 'object'); +assert.sameValue(caught.constructor, TypeError); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/yield/star-rhs-iter-rtrn-rtrn-get-err.js b/js/src/tests/test262/language/expressions/yield/star-rhs-iter-rtrn-rtrn-get-err.js new file mode 100644 index 0000000000..0f5450df23 --- /dev/null +++ b/js/src/tests/test262/language/expressions/yield/star-rhs-iter-rtrn-rtrn-get-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. +/*--- +esid: sec-generator-function-definitions-runtime-semantics-evaluation +es6id: 14.4.14 +description: Abrupt completion returned when accessing iterator `return` method +info: | + YieldExpression : yield * AssignmentExpression + + 1. Let exprRef be the result of evaluating AssignmentExpression. + 2. Let value be ? GetValue(exprRef). + 3. Let iterator be ? GetIterator(value). + 4. Let received be NormalCompletion(undefined). + 5. Repeat + a. If received.[[Type]] is normal, then + [...] + b. Else if received.[[Type]] is throw, then + [...] + c. Else, + i. Assert: received.[[Type]] is return. + ii. Let return be ? GetMethod(iterator, "return"). +features: [generators, Symbol.iterator] +---*/ + +var thrown = new Test262Error(); +var badIter = {}; +var callCount = 0; +var poisonedReturn = { + next: function() { + return { done: false }; + } +}; +Object.defineProperty(poisonedReturn, 'throw', { + get: function() { + callCount += 1; + } +}); +Object.defineProperty(poisonedReturn, 'return', { + get: function() { + throw thrown; + } +}); +badIter[Symbol.iterator] = function() { + return poisonedReturn; +}; +function* g() { + try { + yield * badIter; + } catch (err) { + caught = err; + } +} +var iter = g(); +var result, caught; + +iter.next(); + +assert.sameValue(caught, undefined, '`return` property not accessed eagerly'); + +result = iter.return(); + +assert.sameValue(result.value, undefined); +assert.sameValue(result.done, true); +assert.sameValue(caught, thrown); +assert.sameValue(callCount, 0, 'iterator `throw` property is not accessed'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/yield/star-rhs-iter-rtrn-rtrn-invoke.js b/js/src/tests/test262/language/expressions/yield/star-rhs-iter-rtrn-rtrn-invoke.js new file mode 100644 index 0000000000..88d9a4786c --- /dev/null +++ b/js/src/tests/test262/language/expressions/yield/star-rhs-iter-rtrn-rtrn-invoke.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. +/*--- +esid: sec-generator-function-definitions-runtime-semantics-evaluation +es6id: 14.4.14 +description: Invocation of iterator `return` method +info: | + YieldExpression : yield * AssignmentExpression + + 1. Let exprRef be the result of evaluating AssignmentExpression. + 2. Let value be ? GetValue(exprRef). + 3. Let iterator be ? GetIterator(value). + 4. Let received be NormalCompletion(undefined). + 5. Repeat + a. If received.[[Type]] is normal, then + [...] + b. Else if received.[[Type]] is throw, then + [...] + c. Else, + i. Assert: received.[[Type]] is return. + ii. Let return be ? GetMethod(iterator, "return"). + iii. If return is undefined, return Completion(received). + iv. Let innerReturnResult be ? Call(return, iterator, « + received.[[Value]] »). + [...] +features: [generators, Symbol.iterator] +---*/ + +var args, thisValue; +var callCount = 0; +var spyIterator = { + next: function() { + return { done: false }; + }, + return: function() { + callCount += 1; + args = arguments; + thisValue = this; + return { done: true }; + } +}; +var spyIterable = {}; +spyIterable[Symbol.iterator] = function() { + return spyIterator; +}; +function* g() { + yield * spyIterable; +} +var iter = g(); + +iter.next(8888); +iter.return(7777); + +assert.sameValue(callCount, 1); +assert.sameValue(args.length, 1); +assert.sameValue(args[0], 7777); +assert.sameValue(thisValue, spyIterator); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/yield/star-rhs-iter-thrw-res-done-err.js b/js/src/tests/test262/language/expressions/yield/star-rhs-iter-thrw-res-done-err.js new file mode 100644 index 0000000000..f1352e5789 --- /dev/null +++ b/js/src/tests/test262/language/expressions/yield/star-rhs-iter-thrw-res-done-err.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. +/*--- +esid: sec-generator-function-definitions-runtime-semantics-evaluation +es6id: 14.4.14 +description: > + Abrupt completion returned when accessing `done` property of iteration result +info: | + YieldExpression : yield * AssignmentExpression + + 1. Let exprRef be the result of evaluating AssignmentExpression. + 2. Let value be ? GetValue(exprRef). + 3. Let iterator be ? GetIterator(value). + 4. Let received be NormalCompletion(undefined). + 5. Repeat + a. If received.[[Type]] is normal, then + [...] + b. Else if received.[[Type]] is throw, then + i. Let throw be ? GetMethod(iterator, "throw"). + ii. If throw is not undefined, then + 1. Let innerResult be ? Call(throw, iterator, « received.[[Value]] + »). + 2. NOTE: Exceptions from the inner iterator throw method are + propagated. Normal completions from an inner throw method are + processed similarly to an inner next. + 3. If Type(innerResult) is not Object, throw a TypeError exception. + 4. Let done be ? IteratorComplete(innerResult). + + 7.4.3 IteratorComplete + + 1. Assert: Type(iterResult) is Object. + 2. Return ToBoolean(? Get(iterResult, "done")). +features: [generators, Symbol.iterator] +---*/ + +var thrown = new Test262Error(); +var badIter = {}; +var poisonedDone = Object.defineProperty({}, 'done', { + get: function() { + throw thrown; + } +}); +badIter[Symbol.iterator] = function() { + return { + next: function() { + return { done: false }; + }, + throw: function() { + return poisonedDone; + } + }; +}; +function* g() { + try { + yield * badIter; + } catch (err) { + caught = err; + } +} +var iter = g(); +var caught; + +iter.next(); +iter.throw(); + +assert.sameValue(caught, thrown); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/yield/star-rhs-iter-thrw-res-done-no-value.js b/js/src/tests/test262/language/expressions/yield/star-rhs-iter-thrw-res-done-no-value.js new file mode 100644 index 0000000000..ef844d38a8 --- /dev/null +++ b/js/src/tests/test262/language/expressions/yield/star-rhs-iter-thrw-res-done-no-value.js @@ -0,0 +1,78 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-generator-function-definitions-runtime-semantics-evaluation +description: > + `value` property is not accessed when iteration is complete +info: | + YieldExpression : yield * AssignmentExpression + + 1. Let exprRef be the result of evaluating AssignmentExpression. + 2. Let value be ? GetValue(exprRef). + 3. Let iterator be ? GetIterator(value). + 4. Let received be NormalCompletion(undefined). + 5. Repeat + a. If received.[[Type]] is normal, then + [...] + b. Else if received.[[Type]] is throw, then + i. Let throw be ? GetMethod(iterator, "throw"). + ii. If throw is not undefined, then + 1. Let innerResult be ? Call(throw, iterator, « received.[[Value]] + »). + 2. NOTE: Exceptions from the inner iterator throw method are + propagated. Normal completions from an inner throw method are + processed similarly to an inner next. + 3. If Type(innerResult) is not Object, throw a TypeError exception. + 4. Let done be ? IteratorComplete(innerResult). + 5. If done is true, then + a. Return ? IteratorValue(innerResult). + + 7.4.3 IteratorComplete + + 1. Assert: Type(iterResult) is Object. + 2. Return ToBoolean(? Get(iterResult, "done")). +features: [generators, Symbol.iterator] +---*/ + +var badIter = {}; +var callCount = 0; +var spyValue = Object.defineProperty({ done: false }, 'value', { + get: function() { + callCount += 1; + } +}); +badIter[Symbol.iterator] = function() { + return { + next: function() { + return { done: false }; + }, + throw: function() { + return spyValue; + } + }; +}; +var delegationComplete = false; +function* g() { + yield * badIter; + delegationComplete = true; +} +var iter = g(); + +iter.next(); +assert.sameValue(callCount, 0, 'access count (first iteration)'); +assert.sameValue( + delegationComplete, false, 'delegation ongoing (first iteration)' +); + +iter.throw(); +assert.sameValue(callCount, 0, 'access count (second iteration)'); +assert.sameValue( + delegationComplete, false, 'delegation ongoing (second iteration)' +); + +spyValue.done = true; +iter.throw(); +assert.sameValue(callCount, 1, 'access count (final iteration)'); +assert.sameValue(delegationComplete, true, 'delegation complete'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/yield/star-rhs-iter-thrw-res-value-err.js b/js/src/tests/test262/language/expressions/yield/star-rhs-iter-thrw-res-value-err.js new file mode 100644 index 0000000000..5ee80aed9a --- /dev/null +++ b/js/src/tests/test262/language/expressions/yield/star-rhs-iter-thrw-res-value-err.js @@ -0,0 +1,71 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-generator-function-definitions-runtime-semantics-evaluation +es6id: 14.4.14 +description: > + Abrupt completion returned when accessing `value` property of iteration + result +info: | + YieldExpression : yield * AssignmentExpression + + 1. Let exprRef be the result of evaluating AssignmentExpression. + 2. Let value be ? GetValue(exprRef). + 3. Let iterator be ? GetIterator(value). + 4. Let received be NormalCompletion(undefined). + 5. Repeat + a. If received.[[Type]] is normal, then + [...] + b. Else if received.[[Type]] is throw, then + i. Let throw be ? GetMethod(iterator, "throw"). + ii. If throw is not undefined, then + 1. Let innerResult be ? Call(throw, iterator, « received.[[Value]] + »). + 2. NOTE: Exceptions from the inner iterator throw method are + propagated. Normal completions from an inner throw method are + processed similarly to an inner next. + 3. If Type(innerResult) is not Object, throw a TypeError exception. + 4. Let done be ? IteratorComplete(innerResult). + 5. If done is true, then + a. Return ? IteratorValue(innerResult). + + 7.4.4 IteratorValue + + 1. Assert: Type(iterResult) is Object. + 2. Return ? Get(iterResult, "value"). +features: [generators, Symbol.iterator] +---*/ + +var thrown = new Test262Error(); +var badIter = {}; +var poisonedValue = Object.defineProperty({ done: true }, 'value', { + get: function() { + throw thrown; + } +}); +badIter[Symbol.iterator] = function() { + return { + next: function() { + return { done: false }; + }, + throw: function() { + return poisonedValue; + } + }; +}; +function* g() { + try { + yield * badIter; + } catch (err) { + caught = err; + } +} +var iter = g(); +var caught; + +iter.next(); +iter.throw(); + +assert.sameValue(caught, thrown); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/yield/star-rhs-iter-thrw-res-value-final.js b/js/src/tests/test262/language/expressions/yield/star-rhs-iter-thrw-res-value-final.js new file mode 100644 index 0000000000..7101f1bcfa --- /dev/null +++ b/js/src/tests/test262/language/expressions/yield/star-rhs-iter-thrw-res-value-final.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. +/*--- +esid: sec-generator-function-definitions-runtime-semantics-evaluation +description: Value received from invocation of generator's `throw` method +info: | + YieldExpression : yield * AssignmentExpression + + 1. Let exprRef be the result of evaluating AssignmentExpression. + 2. Let value be ? GetValue(exprRef). + 3. Let iterator be ? GetIterator(value). + 4. Let received be NormalCompletion(undefined). + 5. Repeat + a. If received.[[Type]] is normal, then + [...] + b. Else if received.[[Type]] is throw, then + i. Let throw be ? GetMethod(iterator, "throw"). + ii. If throw is not undefined, then + 1. Let innerResult be ? Call(throw, iterator, « received.[[Value]] + »). + 2. NOTE: Exceptions from the inner iterator throw method are + propagated. Normal completions from an inner throw method are + processed similarly to an inner next. + 3. If Type(innerResult) is not Object, throw a TypeError exception. + 4. Let done be ? IteratorComplete(innerResult). + 5. If done is true, then + [...] + 6. Let received be GeneratorYield(innerResult). +features: [generators, Symbol.iterator] +---*/ + +var quickIter = {}; +var iter, exprValue, throwReceived; +quickIter[Symbol.iterator] = function() { + return { + next: function() { + return { done: false }; + }, + throw: function(x) { + throwReceived = x; + return { done: true, value: 3333 }; + } + }; +}; +function* g() { + exprValue = yield * quickIter; +} + +iter = g(); + +iter.next(); +iter.throw(2222); +assert.sameValue(throwReceived, 2222); +assert.sameValue(exprValue, 3333); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/yield/star-rhs-iter-thrw-thrw-call-err.js b/js/src/tests/test262/language/expressions/yield/star-rhs-iter-thrw-thrw-call-err.js new file mode 100644 index 0000000000..5f588eefa6 --- /dev/null +++ b/js/src/tests/test262/language/expressions/yield/star-rhs-iter-thrw-thrw-call-err.js @@ -0,0 +1,54 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-generator-function-definitions-runtime-semantics-evaluation +es6id: 14.4.14 +description: Abrupt completion returned when invoking iterator `throw` method +info: | + YieldExpression : yield * AssignmentExpression + + 1. Let exprRef be the result of evaluating AssignmentExpression. + 2. Let value be ? GetValue(exprRef). + 3. Let iterator be ? GetIterator(value). + 4. Let received be NormalCompletion(undefined). + 5. Repeat + a. If received.[[Type]] is normal, then + [...] + b. Else if received.[[Type]] is throw, then + i. Let throw be ? GetMethod(iterator, "throw"). + ii. If throw is not undefined, then + 1. Let innerResult be ? Call(throw, iterator, « received.[[Value]] + »). +features: [generators, Symbol.iterator] +---*/ + +var thrown = new Test262Error(); +var badIter = {}; +badIter[Symbol.iterator] = function() { + return { + next: function() { + return { done: false }; + }, + throw: function() { + throw thrown; + } + }; +}; +function* g() { + try { + yield * badIter; + } catch (err) { + caught = err; + } +} +var iter = g(); +var result, caught; + +iter.next(); +result = iter.throw(); + +assert.sameValue(result.value, undefined); +assert.sameValue(result.done, true); +assert.sameValue(caught, thrown); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/yield/star-rhs-iter-thrw-thrw-call-non-obj.js b/js/src/tests/test262/language/expressions/yield/star-rhs-iter-thrw-thrw-call-non-obj.js new file mode 100644 index 0000000000..bbb7245e78 --- /dev/null +++ b/js/src/tests/test262/language/expressions/yield/star-rhs-iter-thrw-thrw-call-non-obj.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. +/*--- +esid: sec-generator-function-definitions-runtime-semantics-evaluation +es6id: 14.4.14 +description: > + TypeError thrown when iterator `throw` method returns a non-object value +info: | + YieldExpression : yield * AssignmentExpression + + 1. Let exprRef be the result of evaluating AssignmentExpression. + 2. Let value be ? GetValue(exprRef). + 3. Let iterator be ? GetIterator(value). + 4. Let received be NormalCompletion(undefined). + 5. Repeat + a. If received.[[Type]] is normal, then + [...] + b. Else if received.[[Type]] is throw, then + i. Let throw be ? GetMethod(iterator, "throw"). + ii. If throw is not undefined, then + 1. Let innerResult be ? Call(throw, iterator, « received.[[Value]] + »). + 2. NOTE: Exceptions from the inner iterator throw method are + propagated. Normal completions from an inner throw method are + processed similarly to an inner next. + 3. If Type(innerResult) is not Object, throw a TypeError exception. +features: [generators, Symbol.iterator] +---*/ + +var badIter = {}; +badIter[Symbol.iterator] = function() { + return { + next: function() { + return { done: false }; + }, + throw: function() { + return 23; + } + }; +}; +function* g() { + try { + yield * badIter; + } catch (err) { + caught = err; + } +} +var iter = g(); +var result, caught; + +iter.next(); +result = iter.throw(); + +assert.sameValue(result.value, undefined); +assert.sameValue(result.done, true); +assert.sameValue(typeof caught, 'object'); +assert.sameValue(caught.constructor, TypeError); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/yield/star-rhs-iter-thrw-thrw-get-err.js b/js/src/tests/test262/language/expressions/yield/star-rhs-iter-thrw-thrw-get-err.js new file mode 100644 index 0000000000..23d11ba8dc --- /dev/null +++ b/js/src/tests/test262/language/expressions/yield/star-rhs-iter-thrw-thrw-get-err.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. +/*--- +esid: sec-generator-function-definitions-runtime-semantics-evaluation +es6id: 14.4.14 +description: Abrupt completion returned when accessing iterator `throw` method +info: | + YieldExpression : yield * AssignmentExpression + + 1. Let exprRef be the result of evaluating AssignmentExpression. + 2. Let value be ? GetValue(exprRef). + 3. Let iterator be ? GetIterator(value). + 4. Let received be NormalCompletion(undefined). + 5. Repeat + a. If received.[[Type]] is normal, then + [...] + b. Else if received.[[Type]] is throw, then + i. Let throw be ? GetMethod(iterator, "throw"). +features: [generators, Symbol.iterator] +---*/ + +var thrown = new Test262Error(); +var badIter = {}; +var poisonedThrow = { + next: function() { + return { done: false }; + } +}; +Object.defineProperty(poisonedThrow, 'throw', { + get: function() { + throw thrown; + } +}); +badIter[Symbol.iterator] = function() { + return poisonedThrow; +}; +function* g() { + try { + yield * badIter; + } catch (err) { + caught = err; + } +} +var iter = g(); +var result, caught; + +iter.next(); + +assert.sameValue(caught, undefined, '`throw` property not accesed eagerly'); + +result = iter.throw(); + +assert.sameValue(result.value, undefined); +assert.sameValue(result.done, true); +assert.sameValue(caught, thrown); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/yield/star-rhs-iter-thrw-thrw-invoke.js b/js/src/tests/test262/language/expressions/yield/star-rhs-iter-thrw-thrw-invoke.js new file mode 100644 index 0000000000..5db1533f5f --- /dev/null +++ b/js/src/tests/test262/language/expressions/yield/star-rhs-iter-thrw-thrw-invoke.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. +/*--- +esid: sec-generator-function-definitions-runtime-semantics-evaluation +es6id: 14.4.14 +description: Invocation of iterator `throw` method +info: | + YieldExpression : yield * AssignmentExpression + + 1. Let exprRef be the result of evaluating AssignmentExpression. + 2. Let value be ? GetValue(exprRef). + 3. Let iterator be ? GetIterator(value). + 4. Let received be NormalCompletion(undefined). + 5. Repeat + a. If received.[[Type]] is normal, then + [...] + b. Else if received.[[Type]] is throw, then + i. Let throw be ? GetMethod(iterator, "throw"). + ii. If throw is not undefined, then + 1. Let innerResult be ? Call(throw, iterator, « received.[[Value]] + »). + [...] +features: [generators, Symbol.iterator] +---*/ + +var args, thisValue; +var callCount = 0; +var spyIterator = { + next: function() { + return { done: false }; + }, + throw: function() { + callCount += 1; + args = arguments; + thisValue = this; + return { done: true }; + } +}; +var spyIterable = {}; +spyIterable[Symbol.iterator] = function() { + return spyIterator; +}; +function* g() { + yield * spyIterable; +} +var iter = g(); + +iter.next(8888); +iter.throw(7777); + +assert.sameValue(callCount, 1); +assert.sameValue(args.length, 1); +assert.sameValue(args[0], 7777); +assert.sameValue(thisValue, spyIterator); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/yield/star-rhs-iter-thrw-violation-no-rtrn.js b/js/src/tests/test262/language/expressions/yield/star-rhs-iter-thrw-violation-no-rtrn.js new file mode 100644 index 0000000000..a32cee1265 --- /dev/null +++ b/js/src/tests/test262/language/expressions/yield/star-rhs-iter-thrw-violation-no-rtrn.js @@ -0,0 +1,82 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-generator-function-definitions-runtime-semantics-evaluation +es6id: 14.4.14 +description: > + Abrupt completion returned after protocol violation (and a `return` method + is not defined) +info: | + YieldExpression : yield * AssignmentExpression + + 1. Let exprRef be the result of evaluating AssignmentExpression. + 2. Let value be ? GetValue(exprRef). + 3. Let iterator be ? GetIterator(value). + 4. Let received be NormalCompletion(undefined). + 5. Repeat + a. If received.[[Type]] is normal, then + [...] + b. Else if received.[[Type]] is throw, then + i. Let throw be ? GetMethod(iterator, "throw"). + ii. If throw is not undefined, then + [...] + iii. Else, + 1. NOTE: If iterator does not have a throw method, this throw is + going to terminate the yield* loop. But first we need to give + iterator a chance to clean up. + 2. Perform ? IteratorClose(iterator, Completion{[[Type]]: normal, + [[Value]]: empty, [[Target]]: empty}). + 3. NOTE: The next step throws a TypeError to indicate that there + was a yield* protocol violation: iterator does not have a throw + method. + 4. Throw a TypeError exception. + + 7.4.6 IteratorClose + + 1. Assert: Type(iterator) is Object. + 2. Assert: completion is a Completion Record. + 3. Let return be ? GetMethod(iterator, "return"). + 4. If return is undefined, return Completion(completion). +features: [generators, Symbol.iterator] +---*/ + +var badIter = {}; +var throwCount = 0; +var returnCount = 0; +var spyResult = { + next: function() { + return { done: false }; + } +}; +Object.defineProperty(spyResult, 'throw', { + get: function() { + throwCount += 1; + } +}); +Object.defineProperty(spyResult, 'return', { + get: function() { + returnCount += 1; + } +}); +badIter[Symbol.iterator] = function() { + return spyResult; +}; +function* g() { + try { + yield * badIter; + } catch (err) { + caught = err; + } +} +var iter = g(); +var caught; + +iter.next(); +iter.throw(); + +assert.sameValue(throwCount, 1, '`throw` property access'); +assert.sameValue(returnCount, 1, '`return` property access'); +assert.sameValue(typeof caught, 'object'); +assert.sameValue(caught.constructor, TypeError); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/yield/star-rhs-iter-thrw-violation-rtrn-call-err.js b/js/src/tests/test262/language/expressions/yield/star-rhs-iter-thrw-violation-rtrn-call-err.js new file mode 100644 index 0000000000..8f6062bd4d --- /dev/null +++ b/js/src/tests/test262/language/expressions/yield/star-rhs-iter-thrw-violation-rtrn-call-err.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. +/*--- +esid: sec-generator-function-definitions-runtime-semantics-evaluation +es6id: 14.4.14 +description: > + Abrupt completion returned when invoking iterator `return` method following + protocol violation +info: | + YieldExpression : yield * AssignmentExpression + + 1. Let exprRef be the result of evaluating AssignmentExpression. + 2. Let value be ? GetValue(exprRef). + 3. Let iterator be ? GetIterator(value). + 4. Let received be NormalCompletion(undefined). + 5. Repeat + a. If received.[[Type]] is normal, then + [...] + b. Else if received.[[Type]] is throw, then + i. Let throw be ? GetMethod(iterator, "throw"). + ii. If throw is not undefined, then + [...] + iii. Else, + 1. NOTE: If iterator does not have a throw method, this throw is + going to terminate the yield* loop. But first we need to give + iterator a chance to clean up. + 2. Perform ? IteratorClose(iterator, Completion{[[Type]]: normal, + [[Value]]: empty, [[Target]]: empty}). + + 7.4.6 IteratorClose + + 1. Assert: Type(iterator) is Object. + 2. Assert: completion is a Completion Record. + 3. Let return be ? GetMethod(iterator, "return"). + 4. If return is undefined, return Completion(completion). + 5. Let innerResult be Call(return, iterator, « »). + 6. If completion.[[Type]] is throw, return Completion(completion). + 7. If innerResult.[[Type]] is throw, return Completion(innerResult). + 8. If Type(innerResult.[[Value]]) is not Object, throw a TypeError exception. +features: [generators, Symbol.iterator] +---*/ + +var badIter = {}; +badIter[Symbol.iterator] = function() { + return { + next: function() { + return { done: false }; + }, + return: function() { + // Using a primitive completion value ensures that the check for the type + // of the completion value (and resulting TypeError) occurs *after* the + // check for the type of the completion itself (which is the behavior + // under test). + throw 87; + } + }; +}; +function* g() { + try { + yield * badIter; + } catch (err) { + caught = err; + } +} +var iter = g(); +var caught; + +iter.next(); +iter.throw(); + +assert.sameValue(caught, 87); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/yield/star-rhs-iter-thrw-violation-rtrn-call-non-obj.js b/js/src/tests/test262/language/expressions/yield/star-rhs-iter-thrw-violation-rtrn-call-non-obj.js new file mode 100644 index 0000000000..8a8ac0314e --- /dev/null +++ b/js/src/tests/test262/language/expressions/yield/star-rhs-iter-thrw-violation-rtrn-call-non-obj.js @@ -0,0 +1,70 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-generator-function-definitions-runtime-semantics-evaluation +es6id: 14.4.14 +description: > + Non-object value returned by iterator `return` method following protocol + violation +info: | + YieldExpression : yield * AssignmentExpression + + 1. Let exprRef be the result of evaluating AssignmentExpression. + 2. Let value be ? GetValue(exprRef). + 3. Let iterator be ? GetIterator(value). + 4. Let received be NormalCompletion(undefined). + 5. Repeat + a. If received.[[Type]] is normal, then + [...] + b. Else if received.[[Type]] is throw, then + i. Let throw be ? GetMethod(iterator, "throw"). + ii. If throw is not undefined, then + [...] + iii. Else, + 1. NOTE: If iterator does not have a throw method, this throw is + going to terminate the yield* loop. But first we need to give + iterator a chance to clean up. + 2. Perform ? IteratorClose(iterator, Completion{[[Type]]: normal, + [[Value]]: empty, [[Target]]: empty}). + + 7.4.6 IteratorClose + + 1. Assert: Type(iterator) is Object. + 2. Assert: completion is a Completion Record. + 3. Let return be ? GetMethod(iterator, "return"). + 4. If return is undefined, return Completion(completion). + 5. Let innerResult be Call(return, iterator, « »). + 6. If completion.[[Type]] is throw, return Completion(completion). + 7. If innerResult.[[Type]] is throw, return Completion(innerResult). + 8. If Type(innerResult.[[Value]]) is not Object, throw a TypeError exception. +features: [generators, Symbol.iterator] +---*/ + +var badIter = {}; +badIter[Symbol.iterator] = function() { + return { + next: function() { + return { done: false }; + }, + return: function() { + return 87; + } + }; +}; +function* g() { + try { + yield * badIter; + } catch (err) { + caught = err; + } +} +var iter = g(); +var caught; + +iter.next(); +iter.throw(); + +assert.sameValue(typeof caught, 'object'); +assert.sameValue(caught.constructor, TypeError); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/yield/star-rhs-iter-thrw-violation-rtrn-get-err.js b/js/src/tests/test262/language/expressions/yield/star-rhs-iter-thrw-violation-rtrn-get-err.js new file mode 100644 index 0000000000..be98f16ef9 --- /dev/null +++ b/js/src/tests/test262/language/expressions/yield/star-rhs-iter-thrw-violation-rtrn-get-err.js @@ -0,0 +1,75 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-generator-function-definitions-runtime-semantics-evaluation +es6id: 14.4.14 +description: > + Abrupt completion returned when accessing iterator `return` property after + protocol violation +info: | + YieldExpression : yield * AssignmentExpression + + 1. Let exprRef be the result of evaluating AssignmentExpression. + 2. Let value be ? GetValue(exprRef). + 3. Let iterator be ? GetIterator(value). + 4. Let received be NormalCompletion(undefined). + 5. Repeat + a. If received.[[Type]] is normal, then + [...] + b. Else if received.[[Type]] is throw, then + i. Let throw be ? GetMethod(iterator, "throw"). + ii. If throw is not undefined, then + [...] + iii. Else, + 1. NOTE: If iterator does not have a throw method, this throw is + going to terminate the yield* loop. But first we need to give + iterator a chance to clean up. + 2. Perform ? IteratorClose(iterator, Completion{[[Type]]: normal, + [[Value]]: empty, [[Target]]: empty}). + + 7.4.6 IteratorClose + + 1. Assert: Type(iterator) is Object. + 2. Assert: completion is a Completion Record. + 3. Let return be ? GetMethod(iterator, "return"). +features: [generators, Symbol.iterator] +---*/ + +var thrown = new Test262Error(); +var badIter = {}; +var callCount = 0; +var poisonedReturn = { + next: function() { + return { done: false }; + } +}; +Object.defineProperty(poisonedReturn, 'throw', { + get: function() { + callCount += 1; + } +}); +Object.defineProperty(poisonedReturn, 'return', { + get: function() { + throw thrown; + } +}); +badIter[Symbol.iterator] = function() { + return poisonedReturn; +}; +function* g() { + try { + yield * badIter; + } catch (err) { + caught = err; + } +} +var iter = g(); +var caught; + +iter.next(); +iter.throw(); + +assert.sameValue(callCount, 1); +assert.sameValue(caught, thrown); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/yield/star-rhs-iter-thrw-violation-rtrn-invoke.js b/js/src/tests/test262/language/expressions/yield/star-rhs-iter-thrw-violation-rtrn-invoke.js new file mode 100644 index 0000000000..f6bcff0a05 --- /dev/null +++ b/js/src/tests/test262/language/expressions/yield/star-rhs-iter-thrw-violation-rtrn-invoke.js @@ -0,0 +1,91 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-generator-function-definitions-runtime-semantics-evaluation +es6id: 14.4.14 +description: > + Abrupt completion returned after protocol violation (and a `return` method + is defined) +info: | + YieldExpression : yield * AssignmentExpression + + 1. Let exprRef be the result of evaluating AssignmentExpression. + 2. Let value be ? GetValue(exprRef). + 3. Let iterator be ? GetIterator(value). + 4. Let received be NormalCompletion(undefined). + 5. Repeat + a. If received.[[Type]] is normal, then + [...] + b. Else if received.[[Type]] is throw, then + i. Let throw be ? GetMethod(iterator, "throw"). + ii. If throw is not undefined, then + [...] + iii. Else, + 1. NOTE: If iterator does not have a throw method, this throw is + going to terminate the yield* loop. But first we need to give + iterator a chance to clean up. + 2. Perform ? IteratorClose(iterator, Completion{[[Type]]: normal, + [[Value]]: empty, [[Target]]: empty}). + 3. NOTE: The next step throws a TypeError to indicate that there + was a yield* protocol violation: iterator does not have a throw + method. + 4. Throw a TypeError exception. + + 7.4.6 IteratorClose + + 1. Assert: Type(iterator) is Object. + 2. Assert: completion is a Completion Record. + 3. Let return be ? GetMethod(iterator, "return"). + 4. If return is undefined, return Completion(completion). + 5. Let innerResult be Call(return, iterator, « »). + 6. If completion.[[Type]] is throw, return Completion(completion). + 7. If innerResult.[[Type]] is throw, return Completion(innerResult). + 8. If Type(innerResult.[[Value]]) is not Object, throw a TypeError exception. + 9. Return Completion(completion). +features: [generators, Symbol.iterator] +---*/ + +var badIter = {}; +var throwCount = 0; +var thisValue, args; +var poisonedReturn = { + next: function() { + return { done: false }; + }, + return: function() { + thisValue = this; + args = arguments; + return 'this value has no effect on the protocol'; + } +}; +Object.defineProperty(poisonedReturn, 'throw', { + get: function() { + throwCount += 1; + } +}); +badIter[Symbol.iterator] = function() { + return poisonedReturn; +}; +function* g() { + try { + yield * badIter; + } catch (err) { + caught = err; + } +} +var iter = g(); +var caught; + +iter.next(); +iter.throw(); + +assert.sameValue(throwCount, 1); +assert.sameValue(thisValue, poisonedReturn, '"this" value'); +assert.sameValue( + typeof args, 'object', 'method invoked, arguments object provided' +); +assert.sameValue(args.length, 0); +assert.sameValue(typeof caught, 'object', 'object value thrown'); +assert.sameValue(caught.constructor, TypeError); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/yield/star-rhs-unresolvable.js b/js/src/tests/test262/language/expressions/yield/star-rhs-unresolvable.js new file mode 100644 index 0000000000..a5687a94c4 --- /dev/null +++ b/js/src/tests/test262/language/expressions/yield/star-rhs-unresolvable.js @@ -0,0 +1,33 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-generator-function-definitions-runtime-semantics-evaluation +es6id: 14.4.14 +description: GetValue invoked on Reference value +info: | + YieldExpression : yield * AssignmentExpression + + 1. Let exprRef be the result of evaluating AssignmentExpression. + 2. Let value be ? GetValue(exprRef). +features: [generators] +---*/ + +var err; +function* g() { + try { + yield * test262unresolvable; + } catch (_err) { + err = _err; + } +} +var iter = g(); +var result; + +result = iter.next(); + +assert.sameValue(result.value, undefined); +assert.sameValue(result.done, true); +assert.sameValue(typeof err, 'object'); +assert.sameValue(err.constructor, ReferenceError); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/yield/star-string.js b/js/src/tests/test262/language/expressions/yield/star-string.js new file mode 100644 index 0000000000..b2fc8c536d --- /dev/null +++ b/js/src/tests/test262/language/expressions/yield/star-string.js @@ -0,0 +1,33 @@ +// Copyright (C) 2013 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +es6id: 25.2 +description: > + When a string is the operand of a `yield *` expression, the generator + should produce an iterator that visits each character in order. +features: [generators] +---*/ + +function* g() { + yield* 'abc'; +} +var iter = g(); +var result; + +result = iter.next(); +assert.sameValue(result.value, 'a', 'First result `value`'); +assert.sameValue(result.done, false, 'First result `done` flag'); + +result = iter.next(); +assert.sameValue(result.value, 'b', 'Second result `value`'); +assert.sameValue(result.done, false, 'Second result `done` flag'); + +result = iter.next(); +assert.sameValue(result.value, 'c', 'Third result `value`'); +assert.sameValue(result.done, false, 'Third result `done` flag'); + +result = iter.next(); +assert.sameValue(result.value, undefined, 'Final result `value`'); +assert.sameValue(result.done, true, 'Final result `done` flag'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/yield/star-throw-is-null.js b/js/src/tests/test262/language/expressions/yield/star-throw-is-null.js new file mode 100644 index 0000000000..90c5c5de41 --- /dev/null +++ b/js/src/tests/test262/language/expressions/yield/star-throw-is-null.js @@ -0,0 +1,73 @@ +// Copyright (C) 2020 Alexey Shvayka. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-generator-function-definitions-runtime-semantics-evaluation +description: > + If iterator's "throw" method is `null`, + IteratorClose is called before rising TypeError. +info: | + YieldExpression : yield * AssignmentExpression + + [...] + 7. Repeat, + [...] + b. Else if received.[[Type]] is throw, then + i. Let throw be ? GetMethod(iterator, "throw"). + ii. If throw is not undefined, then + [...] + iii. Else, + [...] + 4. Else, perform ? IteratorClose(iteratorRecord, closeCompletion). + [...] + 6. Throw a TypeError exception. + + GetMethod ( V, P ) + + [...] + 2. Let func be ? GetV(V, P). + 3. If func is either undefined or null, return undefined. + + IteratorClose ( iteratorRecord, completion ) + + [...] + 4. Let innerResult be GetMethod(iterator, "return"). + 5. If innerResult.[[Type]] is normal, then + a. Let return be innerResult.[[Value]]. + b. If return is undefined, return Completion(completion). +features: [generators, Symbol.iterator] +---*/ + +var throwGets = 0; +var returnGets = 0; +var iterable = { + next: function() { + return {value: 1, done: false}; + }, + get throw() { + throwGets += 1; + return null; + }, + get return() { + returnGets += 1; + }, +}; + +iterable[Symbol.iterator] = function() { + return iterable; +}; + +function* generator() { + yield* iterable; +} + +var iterator = generator(); +iterator.next(); + +assert.throws(TypeError, function() { + iterator.throw(); +}); + +assert.sameValue(throwGets, 1); +assert.sameValue(returnGets, 1); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/yield/then-return.js b/js/src/tests/test262/language/expressions/yield/then-return.js new file mode 100644 index 0000000000..5ec10fac84 --- /dev/null +++ b/js/src/tests/test262/language/expressions/yield/then-return.js @@ -0,0 +1,24 @@ +// Copyright (C) 2013 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +es6id: 25.2 +description: > + When a generator body contains a yield statement followed by a return + statement, it should produce an iterator that visits the yieled value and + completes on the returned value. +features: [generators] +---*/ + +function* g() { yield 1; return 2; } +var iter = g(); +var result; + +result = iter.next(); +assert.sameValue(result.value, 1, 'First result `value`'); +assert.sameValue(result.done, false, 'First result `done` flag'); + +result = iter.next(); +assert.sameValue(result.value, 2, 'Second result `value`'); +assert.sameValue(result.done, true, 'Second result `done` flag'); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/language/expressions/yield/within-for.js b/js/src/tests/test262/language/expressions/yield/within-for.js new file mode 100644 index 0000000000..ddc98c63cd --- /dev/null +++ b/js/src/tests/test262/language/expressions/yield/within-for.js @@ -0,0 +1,34 @@ +// Copyright (C) 2013 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +es6id: 25.2 +description: > + `yield` expressions should suspend `for` loop iteration. +features: [generators] +---*/ + +function* g() { + for (var idx = 0; idx < 3; idx++) { + yield idx; + } +} +var iter = g(); +var result; + +result = iter.next(); +assert.sameValue(result.value, 0, 'First result `value`'); +assert.sameValue(result.done, false, 'First result `done` flag'); + +result = iter.next(); +assert.sameValue(result.value, 1, 'Second result `value`'); +assert.sameValue(result.done, false, 'Second result `done` flag'); + +result = iter.next(); +assert.sameValue(result.value, 2, 'Third result `value`'); +assert.sameValue(result.done, false, 'Third result `done` flag'); + +result = iter.next(); +assert.sameValue(result.value, undefined, 'Final result `value`'); +assert.sameValue(result.done, true, 'Final result `done` flag'); + +reportCompare(0, 0); |