From fce8b5852d7d9d3839dea6922bae306934ac115a Mon Sep 17 00:00:00 2001 From: jugglinmike Date: Fri, 1 Jul 2016 14:24:27 -0400 Subject: [PATCH] Extend coverage for Section 25 - Generators (#700) * Improve tests for GeneratorPrototype methods - Assert return values more consistently - Expand tests for constraints on `this` value * Add more tests for dynamic GeneratorFunctions * Add more tests for GenerationFunction.prototype * Add more tests for the GeneratorFunction object * Extend test: GeneratorFunction.prototype.prototype * Improve precision of tests for generator methods Extend existing assertions to explicitly verify that execution halts at the intended location. Correct tests which were previously asserting this behavior in contexts that did not match their name/description. * Remove unused variables * fixup! Improve tests for GeneratorPrototype methods * fixup! Improve tests for GeneratorPrototype methods --- .../GeneratorFunction/extensibility.js | 14 +++ .../GeneratorFunction/instance-length.js | 38 ++++++++ .../GeneratorFunction/instance-prototype.js | 35 +++++++ .../instance-yield-expr-in-param.js | 34 +++++++ test/built-ins/GeneratorFunction/length.js | 18 ++++ test/built-ins/GeneratorFunction/name.js | 28 ++++++ .../prototype/constructor.js | 23 +++++ .../prototype/extensibility.js | 14 +++ .../GeneratorFunction/prototype/prop-desc.js | 16 ++++ .../GeneratorFunction/prototype/prototype.js | 11 ++- .../next/from-state-executing.js | 61 ++++++++++++- .../next/incorrect-context.js | 22 ----- .../next/this-val-not-generator.js | 69 ++++++++++++++ .../next/this-val-not-object.js | 91 +++++++++++++++++++ .../return/from-state-completed.js | 9 +- .../return/from-state-executing.js | 40 +++++++- .../return/from-state-suspended-start.js | 9 +- .../return/incorrect-context.js | 17 ---- .../return/this-val-not-generator.js | 69 ++++++++++++++ .../return/this-val-not-object.js | 91 +++++++++++++++++++ .../return/try-catch-before-try.js | 17 +++- .../return/try-catch-following-catch.js | 20 +++- .../return/try-catch-within-catch.js | 19 +++- .../return/try-catch-within-try.js | 19 +++- .../return/try-finally-before-try.js | 18 +++- .../return/try-finally-following-finally.js | 17 +++- ...y-finally-nested-try-catch-within-catch.js | 29 ++++-- ...finally-nested-try-catch-within-finally.js | 20 +++- ...nally-nested-try-catch-within-inner-try.js | 31 ++++--- ...try-catch-within-outer-try-after-nested.js | 24 +++-- ...ry-catch-within-outer-try-before-nested.js | 30 ++++-- .../return/try-finally-within-finally.js | 20 +++- .../return/try-finally-within-try.js | 28 ++++-- .../throw/from-state-executing.js | 40 +++++++- .../throw/incorrect-context.js | 17 ---- .../throw/this-val-not-generator.js | 69 ++++++++++++++ .../throw/this-val-not-object.js | 91 +++++++++++++++++++ .../throw/try-catch-before-try.js | 17 +++- .../throw/try-catch-following-catch.js | 11 +++ .../throw/try-catch-within-catch.js | 14 ++- .../throw/try-catch-within-try.js | 16 ++++ .../throw/try-finally-before-try.js | 14 +++ .../throw/try-finally-following-finally.js | 12 ++- ...y-finally-nested-try-catch-within-catch.js | 11 +++ ...finally-nested-try-catch-within-finally.js | 12 +++ ...nally-nested-try-catch-within-inner-try.js | 11 +++ ...try-catch-within-outer-try-after-nested.js | 11 +++ ...ry-catch-within-outer-try-before-nested.js | 11 +++ .../throw/try-finally-within-finally.js | 15 ++- .../throw/try-finally-within-try.js | 15 ++- 50 files changed, 1227 insertions(+), 161 deletions(-) create mode 100644 test/built-ins/GeneratorFunction/extensibility.js create mode 100644 test/built-ins/GeneratorFunction/instance-length.js create mode 100644 test/built-ins/GeneratorFunction/instance-prototype.js create mode 100644 test/built-ins/GeneratorFunction/instance-yield-expr-in-param.js create mode 100644 test/built-ins/GeneratorFunction/length.js create mode 100644 test/built-ins/GeneratorFunction/name.js create mode 100644 test/built-ins/GeneratorFunction/prototype/constructor.js create mode 100644 test/built-ins/GeneratorFunction/prototype/extensibility.js create mode 100644 test/built-ins/GeneratorFunction/prototype/prop-desc.js delete mode 100644 test/built-ins/GeneratorPrototype/next/incorrect-context.js create mode 100644 test/built-ins/GeneratorPrototype/next/this-val-not-generator.js create mode 100644 test/built-ins/GeneratorPrototype/next/this-val-not-object.js delete mode 100644 test/built-ins/GeneratorPrototype/return/incorrect-context.js create mode 100644 test/built-ins/GeneratorPrototype/return/this-val-not-generator.js create mode 100644 test/built-ins/GeneratorPrototype/return/this-val-not-object.js delete mode 100644 test/built-ins/GeneratorPrototype/throw/incorrect-context.js create mode 100644 test/built-ins/GeneratorPrototype/throw/this-val-not-generator.js create mode 100644 test/built-ins/GeneratorPrototype/throw/this-val-not-object.js diff --git a/test/built-ins/GeneratorFunction/extensibility.js b/test/built-ins/GeneratorFunction/extensibility.js new file mode 100644 index 0000000000..e8cd2ff078 --- /dev/null +++ b/test/built-ins/GeneratorFunction/extensibility.js @@ -0,0 +1,14 @@ +// 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-properties-of-the-generatorfunction-constructor +es6id: 25.2.2 +description: Object extensibility +info: > + The value of the [[Extensible]] internal slot of the GeneratorFunction + constructor is true. +---*/ + +var GeneratorFunction = Object.getPrototypeOf(function* () {}).constructor; + +assert(Object.isExtensible(GeneratorFunction)); diff --git a/test/built-ins/GeneratorFunction/instance-length.js b/test/built-ins/GeneratorFunction/instance-length.js new file mode 100644 index 0000000000..3906167d67 --- /dev/null +++ b/test/built-ins/GeneratorFunction/instance-length.js @@ -0,0 +1,38 @@ +// Copyright (C) Copyright 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-generatorfunction +es6id: 25.2.1.1 +description: Definition of instance `length` property +info: | + [...] + 3. Return CreateDynamicFunction(C, NewTarget, "generator", args). + + 19.2.1.1.1 Runtime Semantics: CreateDynamicFunction + + [...] + 26. Perform FunctionInitialize(F, Normal, parameters, body, scope). + [...] + + 9.2.4 FunctionInitialize + + [...] + 3. Perform ! DefinePropertyOrThrow(F, "length", + PropertyDescriptor{[[Value]]: len, [[Writable]]: false, [[Enumerable]]: + false, [[Configurable]]: true}). + [...] +includes: [propertyHelper.js] +---*/ + +var GeneratorFunction = Object.getPrototypeOf(function* () {}).constructor; + +assert.sameValue(GeneratorFunction().length, 0); +assert.sameValue(GeneratorFunction('').length, 0); +assert.sameValue(GeneratorFunction('x').length, 0); +assert.sameValue(GeneratorFunction('x', '').length, 1); +assert.sameValue(GeneratorFunction('x', 'y', '').length, 2); +assert.sameValue(GeneratorFunction('x, y', '').length, 2); + +verifyNotEnumerable(GeneratorFunction(), 'length'); +verifyNotWritable(GeneratorFunction(), 'length'); +verifyConfigurable(GeneratorFunction(), 'length'); diff --git a/test/built-ins/GeneratorFunction/instance-prototype.js b/test/built-ins/GeneratorFunction/instance-prototype.js new file mode 100644 index 0000000000..dba638945a --- /dev/null +++ b/test/built-ins/GeneratorFunction/instance-prototype.js @@ -0,0 +1,35 @@ +// Copyright (C) Copyright 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-generatorfunction +es6id: 25.2.1.1 +description: Definition of instance `prototype` property +info: | + [...] + 3. Return CreateDynamicFunction(C, NewTarget, "generator", args). + + 19.2.1.1.1 Runtime Semantics: CreateDynamicFunction + + [...] + 27. If kind is "generator", then + a. Let prototype be ObjectCreate(%GeneratorPrototype%). + b. Perform DefinePropertyOrThrow(F, "prototype", + PropertyDescriptor{[[Value]]: prototype, [[Writable]]: true, + [[Enumerable]]: false, [[Configurable]]: false}). + [...] +includes: [propertyHelper.js] +---*/ + +var GeneratorFunction = Object.getPrototypeOf(function* () {}).constructor; + +var instance = GeneratorFunction(); + +assert.sameValue(typeof instance.prototype, 'object'); +assert.sameValue( + Object.getPrototypeOf(instance.prototype), + Object.getPrototypeOf(instance).prototype +); + +verifyNotEnumerable(instance, 'prototype'); +verifyWritable(instance, 'prototype'); +verifyNotConfigurable(instance, 'prototype'); diff --git a/test/built-ins/GeneratorFunction/instance-yield-expr-in-param.js b/test/built-ins/GeneratorFunction/instance-yield-expr-in-param.js new file mode 100644 index 0000000000..e170f3c308 --- /dev/null +++ b/test/built-ins/GeneratorFunction/instance-yield-expr-in-param.js @@ -0,0 +1,34 @@ +// Copyright (C) Copyright 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-generatorfunction +es6id: 25.2.1.1 +description: Definition of instance `length` property +info: | + [...] + 3. Return CreateDynamicFunction(C, NewTarget, "generator", args). + + 19.2.1.1.1 Runtime Semantics: CreateDynamicFunction + + [...] + 20. If kind is "generator", then + a. If parameters Contains YieldExpression is true, throw a SyntaxError + exception. +---*/ + +var GeneratorFunction = Object.getPrototypeOf(function* () {}).constructor; + +// YieldExpression is permitted in function body. +GeneratorFunction('x = yield'); + +assert.throws(SyntaxError, function() { + GeneratorFunction('x = yield', ''); +}, 'YieldExpression not permitted generally'); + +var withinGenerator = function*() { + GeneratorFunction('x = yield', ''); +}; + +assert.throws(SyntaxError, function() { + withinGenerator().next(); +}, 'YieldExpression not permitted when calling context is a generator'); diff --git a/test/built-ins/GeneratorFunction/length.js b/test/built-ins/GeneratorFunction/length.js new file mode 100644 index 0000000000..f60239cc2a --- /dev/null +++ b/test/built-ins/GeneratorFunction/length.js @@ -0,0 +1,18 @@ +// 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-generatorfunction.length +es6id: 25.2.2.1 +description: > + This is a data property with a value of 1. This property has the attributes { + [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }. +includes: [propertyHelper.js] +---*/ + +var GeneratorFunction = Object.getPrototypeOf(function* () {}).constructor; + +assert.sameValue(GeneratorFunction.length, 1); + +verifyNotEnumerable(GeneratorFunction, 'length'); +verifyNotWritable(GeneratorFunction, 'length'); +verifyConfigurable(GeneratorFunction, 'length'); diff --git a/test/built-ins/GeneratorFunction/name.js b/test/built-ins/GeneratorFunction/name.js new file mode 100644 index 0000000000..707489cc70 --- /dev/null +++ b/test/built-ins/GeneratorFunction/name.js @@ -0,0 +1,28 @@ +// 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-properties-of-the-generatorfunction-constructor +es6id: 25.2.2 +description: Function "name" property +info: > + The value of the name property of the GeneratorFunction is + "GeneratorFunction". + + 17 ECMAScript Standard Built-in Objects: + Every built-in Function object, including constructors, that is not + identified as an anonymous function has a name property whose value is a + String. + + Unless otherwise specified, the name property of a built-in Function object, + if it exists, has the attributes { [[Writable]]: false, [[Enumerable]]: + false, [[Configurable]]: true }. +includes: [propertyHelper.js] +---*/ + +var GeneratorFunction = Object.getPrototypeOf(function* () {}).constructor; + +assert.sameValue(GeneratorFunction.name, 'GeneratorFunction'); + +verifyNotEnumerable(GeneratorFunction, 'name'); +verifyNotWritable(GeneratorFunction, 'name'); +verifyConfigurable(GeneratorFunction, 'name'); diff --git a/test/built-ins/GeneratorFunction/prototype/constructor.js b/test/built-ins/GeneratorFunction/prototype/constructor.js new file mode 100644 index 0000000000..132bde1001 --- /dev/null +++ b/test/built-ins/GeneratorFunction/prototype/constructor.js @@ -0,0 +1,23 @@ +// Copyright (C) 2016 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-generatorfunction.prototype.constructor +es6id: 25.2.3.1 +description: > + `constructor` property of the GeneratorFunction.prototype object +info: > + The initial value of GeneratorFunction.prototype.constructor is the intrinsic + object %GeneratorFunction%. + + This property has the attributes { [[Writable]]: false, [[Enumerable]]: + false, [[Configurable]]: true }. +includes: [propertyHelper.js] +---*/ + +var GeneratorFunction = Object.getPrototypeOf(function* () {}).constructor; + +assert.sameValue(GeneratorFunction.prototype.constructor, GeneratorFunction); + +verifyNotEnumerable(GeneratorFunction.prototype, 'constructor'); +verifyNotWritable(GeneratorFunction.prototype, 'constructor'); +verifyConfigurable(GeneratorFunction.prototype, 'constructor'); diff --git a/test/built-ins/GeneratorFunction/prototype/extensibility.js b/test/built-ins/GeneratorFunction/prototype/extensibility.js new file mode 100644 index 0000000000..231a23b0a1 --- /dev/null +++ b/test/built-ins/GeneratorFunction/prototype/extensibility.js @@ -0,0 +1,14 @@ +// 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-properties-of-the-generatorfunction-prototype-object +es6id: 25.2.3 +description: Object extensibility +info: > + The initial value of the [[Extensible]] internal slot of the + GeneratorFunction prototype object is true. +---*/ + +var GeneratorFunction = Object.getPrototypeOf(function* () {}).constructor; + +assert(Object.isExtensible(GeneratorFunction.prototype)); diff --git a/test/built-ins/GeneratorFunction/prototype/prop-desc.js b/test/built-ins/GeneratorFunction/prototype/prop-desc.js new file mode 100644 index 0000000000..ffb674591e --- /dev/null +++ b/test/built-ins/GeneratorFunction/prototype/prop-desc.js @@ -0,0 +1,16 @@ +// Copyright (C) 2015 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +es6id: 25.4.5.1 +description: GeneratorFunction.prototype property descriptor +info: > + This property has the attributes { [[Writable]]: false, [[Enumerable]]: + false, [[Configurable]]: false }. +includes: [propertyHelper.js] +---*/ + +var GeneratorFunction = Object.getPrototypeOf(function* () {}).constructor; + +verifyNotEnumerable(GeneratorFunction, 'prototype'); +verifyNotWritable(GeneratorFunction, 'prototype'); +verifyNotConfigurable(GeneratorFunction, 'prototype'); diff --git a/test/built-ins/GeneratorFunction/prototype/prototype.js b/test/built-ins/GeneratorFunction/prototype/prototype.js index 742611edfc..c90d452741 100644 --- a/test/built-ins/GeneratorFunction/prototype/prototype.js +++ b/test/built-ins/GeneratorFunction/prototype/prototype.js @@ -5,9 +5,18 @@ es6id: 25.2.3.2 description: > The value of GeneratorFunction.prototype.prototype is the %GeneratorPrototype% intrinsic object. + + This property has the attributes { [[Writable]]: false, [[Enumerable]]: + false, [[Configurable]]: true }. +includes: [propertyHelper.js] ---*/ +var GeneratorFunctionPrototype = Object.getPrototypeOf(function*() {}); assert.sameValue( - Object.getPrototypeOf(function*() {}).prototype, + GeneratorFunctionPrototype.prototype, Object.getPrototypeOf(function*() {}.prototype) ); + +verifyNotEnumerable(GeneratorFunctionPrototype, 'prototype'); +verifyNotWritable(GeneratorFunctionPrototype, 'prototype'); +verifyConfigurable(GeneratorFunctionPrototype, 'prototype'); diff --git a/test/built-ins/GeneratorPrototype/next/from-state-executing.js b/test/built-ins/GeneratorPrototype/next/from-state-executing.js index 2a49244f3b..0490ed31dc 100644 --- a/test/built-ins/GeneratorPrototype/next/from-state-executing.js +++ b/test/built-ins/GeneratorPrototype/next/from-state-executing.js @@ -1,12 +1,41 @@ // Copyright (C) 2013 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- +esid: sec-generatorvalidate es6id: 25.3.3.2 description: > - A TypeError should be thrown if the generator is resumed while running. + A TypeError should be thrown if the generator is resumed while in the + "executing" state and the generator should be marked as "completed" +info: | + 25.3.3.1 GeneratorStart + + [...] + 4. Set the code evaluation state of genContext such that when evaluation is + resumed for that execution context the following steps will be performed: + a. Let result be the result of evaluating generatorBody. + b. Assert: If we return here, the generator either threw an exception or + performed either an implicit or explicit return. + c. Remove genContext from the execution context stack and restore the + execution context that is at the top of the execution context stack as + the running execution context. + d. Set generator.[[GeneratorState]] to "completed". + [...] + + 25.3.3.3 GeneratorResume + + 1. Let state be ? GeneratorValidate(generator). + + 25.3.3.2 GeneratorValidate + + 1. If Type(generator) is not Object, throw a TypeError exception. + 2. If generator does not have a [[GeneratorState]] internal slot, throw a + TypeError exception. + 3. Assert: generator also has a [[GeneratorContext]] internal slot. + 4. Let state be generator.[[GeneratorState]]. + 5. If state is "executing", throw a TypeError exception. ---*/ -var iter; +var iter, result; function* withoutVal() { iter.next(); } @@ -17,9 +46,33 @@ function* withVal() { iter = withoutVal(); assert.throws(TypeError, function() { iter.next(); -}); +}, 'Error when invoked without value'); + +result = iter.next(); + +assert.sameValue( + typeof result, 'object', 'type following invocation without value' +); +assert.sameValue( + result.value, undefined, '`value` following invocation without value' +); +assert.sameValue( + result.done, true, '`done` following invocation without value' +); iter = withVal(); assert.throws(TypeError, function() { iter.next(); -}); +}, 'Error when invoked with value'); + +result = iter.next(); + +assert.sameValue( + typeof result, 'object', 'type following invocation with value' +); +assert.sameValue( + result.value, undefined, '`value` following invocation with value' +); +assert.sameValue( + result.done, true, '`done` following invocation with value' +); diff --git a/test/built-ins/GeneratorPrototype/next/incorrect-context.js b/test/built-ins/GeneratorPrototype/next/incorrect-context.js deleted file mode 100644 index e88f109dd5..0000000000 --- a/test/built-ins/GeneratorPrototype/next/incorrect-context.js +++ /dev/null @@ -1,22 +0,0 @@ -// 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.3.1.2 -description: > - A TypeError should be thrown from GeneratorValidate (25.3.3.2) if the - context of `next` does not defined the [[GeneratorState]] internal slot. ----*/ - -function* g() {} -var GeneratorPrototype = Object.getPrototypeOf(g).prototype; - -assert.throws(TypeError, function() { GeneratorPrototype.next.call(1); }); -assert.throws(TypeError, function() { GeneratorPrototype.next.call(1, 1); }); -assert.throws(TypeError, function() { GeneratorPrototype.next.call({}); }); -assert.throws(TypeError, function() { GeneratorPrototype.next.call({}, 1); }); -assert.throws(TypeError, function() { GeneratorPrototype.next.call(function() {}); }); -assert.throws(TypeError, function() { GeneratorPrototype.next.call(function() {}, 1); }); -assert.throws(TypeError, function() { GeneratorPrototype.next.call(g); }); -assert.throws(TypeError, function() { GeneratorPrototype.next.call(g, 1); }); -assert.throws(TypeError, function() { GeneratorPrototype.next.call(g.prototype); }); -assert.throws(TypeError, function() { GeneratorPrototype.next.call(g.prototype, 1); }); diff --git a/test/built-ins/GeneratorPrototype/next/this-val-not-generator.js b/test/built-ins/GeneratorPrototype/next/this-val-not-generator.js new file mode 100644 index 0000000000..afabed53b2 --- /dev/null +++ b/test/built-ins/GeneratorPrototype/next/this-val-not-generator.js @@ -0,0 +1,69 @@ +// Copyright (C) 2013 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-generator.prototype.next +es6id: 25.3.1.2 +description: > + A TypeError should be thrown from GeneratorValidate (25.3.3.2) if the + context of `next` does not define the [[GeneratorState]] internal slot. +info: | + 1. Let g be the this value. + 2. Return GeneratorResume(g, value). + + 25.3.3.3 GeneratorResume + + 1. Let state be ? GeneratorValidate(generator). + + 25.3.3.2 GeneratorValidate + + [...] + 2. If generator does not have a [[GeneratorState]] internal slot, throw a + TypeError exception. +---*/ + +function* g() {} +var GeneratorPrototype = Object.getPrototypeOf(g).prototype; + +assert.throws( + TypeError, + function() { GeneratorPrototype.next.call({}); }, + 'ordinary object (without value)' +); +assert.throws( + TypeError, + function() { GeneratorPrototype.next.call({}, 1); }, + 'ordinary object (with value)' +); + +assert.throws( + TypeError, + function() { GeneratorPrototype.next.call(function() {}); }, + 'function object (without value)' +); +assert.throws( + TypeError, + function() { GeneratorPrototype.next.call(function() {}, 1); }, + 'function object (with value)' +); + +assert.throws( + TypeError, + function() { GeneratorPrototype.next.call(g); }, + 'generator function object (without value)' +); +assert.throws( + TypeError, + function() { GeneratorPrototype.next.call(g, 1); }, + 'generator function object (with value)' +); + +assert.throws( + TypeError, + function() { GeneratorPrototype.next.call(g.prototype); }, + 'generator function prototype object (without value)' +); +assert.throws( + TypeError, + function() { GeneratorPrototype.next.call(g.prototype, 1); }, + 'generator function prototype object (with value)' +); diff --git a/test/built-ins/GeneratorPrototype/next/this-val-not-object.js b/test/built-ins/GeneratorPrototype/next/this-val-not-object.js new file mode 100644 index 0000000000..6530075e6a --- /dev/null +++ b/test/built-ins/GeneratorPrototype/next/this-val-not-object.js @@ -0,0 +1,91 @@ +// Copyright (C) 2013 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-generator.prototype.next +es6id: 25.3.1.2 +description: > + A TypeError should be thrown from GeneratorValidate (25.3.3.2) if the "this" + value of `next` is not an object. +info: | + 1. Let g be the this value. + 2. Return GeneratorResume(g, value). + + 25.3.3.3 GeneratorResume + + 1. Let state be ? GeneratorValidate(generator). + + 25.3.3.2 GeneratorValidate + + 1. If Type(generator) is not Object, throw a TypeError exception. +features: [Symbol] +---*/ + +function* g() {} +var GeneratorPrototype = Object.getPrototypeOf(g).prototype; +var symbol = Symbol(); + +assert.throws( + TypeError, + function() { GeneratorPrototype.next.call(undefined); }, + 'undefined (without value)' +); +assert.throws( + TypeError, + function() { GeneratorPrototype.next.call(undefined, 1); }, + 'undefined (with value)' +); + +assert.throws( + TypeError, + function() { GeneratorPrototype.next.call(null); }, + 'null (without value)' +); +assert.throws( + TypeError, + function() { GeneratorPrototype.next.call(null, 1); }, + 'null (with value)' +); + +assert.throws( + TypeError, + function() { GeneratorPrototype.next.call(true); }, + 'boolean (without value)' +); +assert.throws( + TypeError, + function() { GeneratorPrototype.next.call(true, 1); }, + 'boolean (with value)' +); + +assert.throws( + TypeError, + function() { GeneratorPrototype.next.call('s'); }, + 'string (without value)' +); +assert.throws( + TypeError, + function() { GeneratorPrototype.next.call('s', 1); }, + 'string (with value)' +); + +assert.throws( + TypeError, + function() { GeneratorPrototype.next.call(1); }, + 'number (without value)' +); +assert.throws( + TypeError, + function() { GeneratorPrototype.next.call(1, 1); }, + 'number (with value)' +); + +assert.throws( + TypeError, + function() { GeneratorPrototype.next.call(symbol); }, + 'symbol (without value)' +); +assert.throws( + TypeError, + function() { GeneratorPrototype.next.call(symbol, 1); }, + 'symbol (with value)' +); diff --git a/test/built-ins/GeneratorPrototype/return/from-state-completed.js b/test/built-ins/GeneratorPrototype/return/from-state-completed.js index 8497c954fa..6748f90e3c 100644 --- a/test/built-ins/GeneratorPrototype/return/from-state-completed.js +++ b/test/built-ins/GeneratorPrototype/return/from-state-completed.js @@ -13,9 +13,12 @@ var iter, result; iter = G(); iter.next(); -iter.return(33); +result = iter.return(33); + +assert.sameValue(result.value, 33, 'return: result `value`'); +assert.sameValue(result.done, true, 'return: result `done` flag'); result = iter.next(); -assert.sameValue(result.value, undefined, 'Result `value`'); -assert.sameValue(result.done, true, 'Result `done` flag'); +assert.sameValue(result.value, undefined, 'next: result `value`'); +assert.sameValue(result.done, true, 'next: result `done` flag'); diff --git a/test/built-ins/GeneratorPrototype/return/from-state-executing.js b/test/built-ins/GeneratorPrototype/return/from-state-executing.js index be2517fcd6..2dc4c51536 100644 --- a/test/built-ins/GeneratorPrototype/return/from-state-executing.js +++ b/test/built-ins/GeneratorPrototype/return/from-state-executing.js @@ -1,13 +1,41 @@ // Copyright (C) 2015 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- +esid: sec-generatorvalidate es6id: 25.3.3.2 description: > - A TypeError should be thrown if the generator is resumed abruptly while - running. + A TypeError should be thrown if the generator is in the "executing" state, + and the generator should be marked as "completed" +info: | + 25.3.3.1 GeneratorStart + + [...] + 4. Set the code evaluation state of genContext such that when evaluation is + resumed for that execution context the following steps will be performed: + a. Let result be the result of evaluating generatorBody. + b. Assert: If we return here, the generator either threw an exception or + performed either an implicit or explicit return. + c. Remove genContext from the execution context stack and restore the + execution context that is at the top of the execution context stack as + the running execution context. + d. Set generator.[[GeneratorState]] to "completed". + [...] + + 25.3.3.4 GeneratorResumeAbrupt + + 1. Let state be ? GeneratorValidate(generator). + + 25.3.3.2 GeneratorValidate + + 1. If Type(generator) is not Object, throw a TypeError exception. + 2. If generator does not have a [[GeneratorState]] internal slot, throw a + TypeError exception. + 3. Assert: generator also has a [[GeneratorContext]] internal slot. + 4. Let state be generator.[[GeneratorState]]. + 5. If state is "executing", throw a TypeError exception. ---*/ -var iter; +var iter, result; function* g() { iter.return(42); } @@ -16,3 +44,9 @@ iter = g(); assert.throws(TypeError, function() { iter.next(); }); + +result = iter.next(); + +assert.sameValue(typeof result, 'object'); +assert.sameValue(result.value, undefined); +assert.sameValue(result.done, true); diff --git a/test/built-ins/GeneratorPrototype/return/from-state-suspended-start.js b/test/built-ins/GeneratorPrototype/return/from-state-suspended-start.js index 8011b82c88..a824596d9d 100644 --- a/test/built-ins/GeneratorPrototype/return/from-state-suspended-start.js +++ b/test/built-ins/GeneratorPrototype/return/from-state-suspended-start.js @@ -8,8 +8,9 @@ description: > state. ---*/ +var bodyCount = 0; function* G() { - yield 1; + bodyCount += 1; } var iter = G(); var result; @@ -18,8 +19,14 @@ result = iter.return(56); assert.sameValue(result.value, 56); assert.sameValue(result.done, true); +assert.sameValue( + bodyCount, 0, 'body not evaluated during processing of `return` method' +); result = iter.next(); assert.sameValue(result.value, undefined, 'Result `value`'); assert.sameValue(result.done, true, 'Result `done` flag'); +assert.sameValue( + bodyCount, 0, 'body not evaluated when "completed" generator is advanced' +); diff --git a/test/built-ins/GeneratorPrototype/return/incorrect-context.js b/test/built-ins/GeneratorPrototype/return/incorrect-context.js deleted file mode 100644 index 17328db8a2..0000000000 --- a/test/built-ins/GeneratorPrototype/return/incorrect-context.js +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright (C) 2015 the V8 project authors. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. -/*--- -es6id: 25.3.1.3 -description: > - A TypeError should be thrown from GeneratorValidate (25.3.3.2) if the - context of `return` does not defined the [[GeneratorState]] internal slot. ----*/ - -function* g() {} -var GeneratorPrototype = Object.getPrototypeOf(g).prototype; - -assert.throws(TypeError, function() { GeneratorPrototype.return.call(1); }); -assert.throws(TypeError, function() { GeneratorPrototype.return.call({}); }); -assert.throws(TypeError, function() { GeneratorPrototype.return.call(function() {}); }); -assert.throws(TypeError, function() { GeneratorPrototype.return.call(g); }); -assert.throws(TypeError, function() { GeneratorPrototype.return.call(g.prototype); }); diff --git a/test/built-ins/GeneratorPrototype/return/this-val-not-generator.js b/test/built-ins/GeneratorPrototype/return/this-val-not-generator.js new file mode 100644 index 0000000000..b0f0177879 --- /dev/null +++ b/test/built-ins/GeneratorPrototype/return/this-val-not-generator.js @@ -0,0 +1,69 @@ +// Copyright (C) 2015 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-generator.prototype.return +es6id: 25.3.1.3 +description: > + A TypeError should be thrown from GeneratorValidate (25.3.3.2) if the + context of `return` does not define the [[GeneratorState]] internal slot. +info: | + [...] + 3. Return ? GeneratorResumeAbrupt(g, C). + + 25.3.3.4 GeneratorResumeAbrupt + + 1. Let state be ? GeneratorValidate(generator). + + 25.3.3.2 GeneratorValidate + + [...] + 2. If generator does not have a [[GeneratorState]] internal slot, throw a + TypeError exception. +---*/ + +function* g() {} +var GeneratorPrototype = Object.getPrototypeOf(g).prototype; + +assert.throws( + TypeError, + function() { GeneratorPrototype.return.call({}); }, + 'ordinary object (without value)' +); +assert.throws( + TypeError, + function() { GeneratorPrototype.return.call({}, 1); }, + 'ordinary object (with value)' +); + +assert.throws( + TypeError, + function() { GeneratorPrototype.return.call(function() {}); }, + 'function object (without value)' +); +assert.throws( + TypeError, + function() { GeneratorPrototype.return.call(function() {}, 1); }, + 'function object (with value)' +); + +assert.throws( + TypeError, + function() { GeneratorPrototype.return.call(g); }, + 'generator function object (without value)' +); +assert.throws( + TypeError, + function() { GeneratorPrototype.return.call(g, 1); }, + 'generator function object (with value)' +); + +assert.throws( + TypeError, + function() { GeneratorPrototype.return.call(g.prototype); }, + 'generator function prototype object (without value)' +); +assert.throws( + TypeError, + function() { GeneratorPrototype.return.call(g.prototype, 1); }, + 'generator function prototype object (with value)' +); diff --git a/test/built-ins/GeneratorPrototype/return/this-val-not-object.js b/test/built-ins/GeneratorPrototype/return/this-val-not-object.js new file mode 100644 index 0000000000..942991cecf --- /dev/null +++ b/test/built-ins/GeneratorPrototype/return/this-val-not-object.js @@ -0,0 +1,91 @@ +// Copyright (C) 2015 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-generator.prototype.return +es6id: 25.3.1.3 +description: > + A TypeError should be thrown from GeneratorValidate (25.3.3.2) if the "this" + value of `return` is not an object. +info: | + [...] + 3. Return ? GeneratorResumeAbrupt(g, C). + + 25.3.3.4 GeneratorResumeAbrupt + + 1. Let state be ? GeneratorValidate(generator). + + 25.3.3.2 GeneratorValidate + + 1. If Type(generator) is not Object, throw a TypeError exception. +features: [Symbol] +---*/ + +function* g() {} +var GeneratorPrototype = Object.getPrototypeOf(g).prototype; +var symbol = Symbol(); + +assert.throws( + TypeError, + function() { GeneratorPrototype.return.call(undefined); }, + 'undefined (without value)' +); +assert.throws( + TypeError, + function() { GeneratorPrototype.return.call(undefined, 1); }, + 'undefined (with value)' +); + +assert.throws( + TypeError, + function() { GeneratorPrototype.return.call(null); }, + 'null (without value)' +); +assert.throws( + TypeError, + function() { GeneratorPrototype.return.call(null, 1); }, + 'null (with value)' +); + +assert.throws( + TypeError, + function() { GeneratorPrototype.return.call(true); }, + 'boolean (without value)' +); +assert.throws( + TypeError, + function() { GeneratorPrototype.return.call(true, 1); }, + 'boolean (with value)' +); + +assert.throws( + TypeError, + function() { GeneratorPrototype.return.call('s'); }, + 'string (without value)' +); +assert.throws( + TypeError, + function() { GeneratorPrototype.return.call('s', 1); }, + 'string (with value)' +); + +assert.throws( + TypeError, + function() { GeneratorPrototype.return.call(1); }, + 'number (without value)' +); +assert.throws( + TypeError, + function() { GeneratorPrototype.return.call(1, 1); }, + 'number (with value)' +); + +assert.throws( + TypeError, + function() { GeneratorPrototype.return.call(symbol); }, + 'symbol (without value)' +); +assert.throws( + TypeError, + function() { GeneratorPrototype.return.call(symbol, 1); }, + 'symbol (with value)' +); diff --git a/test/built-ins/GeneratorPrototype/return/try-catch-before-try.js b/test/built-ins/GeneratorPrototype/return/try-catch-before-try.js index 34a494d199..6d91d185c8 100644 --- a/test/built-ins/GeneratorPrototype/return/try-catch-before-try.js +++ b/test/built-ins/GeneratorPrototype/return/try-catch-before-try.js @@ -8,24 +8,34 @@ description: > location in the function body. ---*/ +var unreachable = 0; function* g() { yield; try { - $ERROR('This code is unreachable (within `try` block)'); + unreachable += 1; } catch (e) { throw e; } - $ERROR('This code is unreachable (following `try` statement)'); + unreachable += 1; } var iter = g(); var result; iter.next(); +assert.sameValue( + unreachable, 0, 'statement following `yield` not executed (paused at yield)' +); result = iter.return(45); assert.sameValue(result.value, 45, 'Result `value` following `return`'); assert.sameValue(result.done, true, 'Result `done` flag following `return`'); +assert.sameValue( + unreachable, + 0, + 'statement following `yield` not executed (following `return`)' +); + result = iter.next(); assert.sameValue(result.value, undefined, 'Result `value` is undefined when complete' @@ -33,3 +43,6 @@ assert.sameValue(result.value, assert.sameValue( result.done, true, 'Result `done` flag is `true` when complete' ); +assert.sameValue( + unreachable, 0, 'statement following `yield` not executed (once "completed")' +); diff --git a/test/built-ins/GeneratorPrototype/return/try-catch-following-catch.js b/test/built-ins/GeneratorPrototype/return/try-catch-following-catch.js index 2e00f03989..1e65a7cb2a 100644 --- a/test/built-ins/GeneratorPrototype/return/try-catch-following-catch.js +++ b/test/built-ins/GeneratorPrototype/return/try-catch-following-catch.js @@ -8,27 +8,36 @@ description: > location in the function body. ---*/ -var afterCatch = false; +var afterCatch = 0; +var unreachable = 0; function* g() { try { throw new Error(); } catch (e) {} - afterCatch = true; + afterCatch += 1; yield; - $ERROR('This code is unreachable'); + unreachable += 1; } var iter = g(); var result; result = iter.next(); -assert.sameValue(afterCatch, true); +assert.sameValue(afterCatch, 1); +assert.sameValue( + unreachable, 0, 'statement following `yield` not executed (paused at yield)' +); result = iter.return(45); assert.sameValue( result.value, 45, 'Result `value` following `return`' ); assert.sameValue(result.done, true, 'Result `done` flag following `return`'); +assert.sameValue( + unreachable, + 0, + 'statement following `yield` not executed (following `return`)' +); result = iter.next(); assert.sameValue( @@ -37,3 +46,6 @@ assert.sameValue( assert.sameValue( result.done, true, 'Result `done` flag is `true` when complete' ); +assert.sameValue( + unreachable, 0, 'statement following `yield` not executed (once "completed")' +); diff --git a/test/built-ins/GeneratorPrototype/return/try-catch-within-catch.js b/test/built-ins/GeneratorPrototype/return/try-catch-within-catch.js index 4c3648a5ee..61e0bed611 100644 --- a/test/built-ins/GeneratorPrototype/return/try-catch-within-catch.js +++ b/test/built-ins/GeneratorPrototype/return/try-catch-within-catch.js @@ -8,29 +8,35 @@ description: > statement had appeared at that location in the function body. ---*/ -var inCatch = false; +var inCatch = 0; +var unreachable = 0; function* g() { try { throw new Error(); } catch (e) { - inCatch = true; + inCatch += 1; yield; - $ERROR('This code is unreachable (within `catch` block)'); + unreachable += 1; } - $ERROR('This code is unreachable (following `try` statement)'); + unreachable += 1; } var iter = g(); var result; result = iter.next(); -assert.sameValue(inCatch, true); +assert.sameValue(inCatch, 1); result = iter.return(45); assert.sameValue( result.value, 45, 'Result `value` following `return`' ); assert.sameValue(result.done, true, 'Result `done` flag following `return`'); +assert.sameValue( + unreachable, + 0, + 'statement following `yield` not executed (following `return`)' +); result = iter.next(); assert.sameValue( @@ -39,3 +45,6 @@ assert.sameValue( assert.sameValue( result.done, true, 'Result `done` flag is `true` when complete' ); +assert.sameValue( + unreachable, 0, 'statement following `yield` not executed (once "completed")' +); diff --git a/test/built-ins/GeneratorPrototype/return/try-catch-within-try.js b/test/built-ins/GeneratorPrototype/return/try-catch-within-try.js index 646785ee97..4e67c78d2a 100644 --- a/test/built-ins/GeneratorPrototype/return/try-catch-within-try.js +++ b/test/built-ins/GeneratorPrototype/return/try-catch-within-try.js @@ -8,27 +8,33 @@ description: > statement had appeared at that location in the function body. ---*/ -var inTry = false; +var inTry = 0; +var unreachable = 0; function* g() { try { - inTry = true; + inTry += 1; yield; - $ERROR('This code is unreachable (within `try` block)'); + unreachable += 1; } catch (e) { throw e; } - $ERROR('This code is unreachable (following `try` statement)'); + unreachable += 1; } var iter = g(); var result; result = iter.next(); -assert.sameValue(inTry, true); +assert.sameValue(inTry, 1); result = iter.return(44); assert.sameValue(result.value, 44, 'Result `value` following `return`'); assert.sameValue(result.done, true, 'Result `done` flag following `return`'); +assert.sameValue( + unreachable, + 0, + 'statement following `yield` not executed (following `return`)' +); result = iter.next(); assert.sameValue( @@ -37,3 +43,6 @@ assert.sameValue( assert.sameValue( result.done, true, 'Result `done` flag is `true` when complete' ); +assert.sameValue( + unreachable, 0, 'statement following `yield` not executed (once "completed")' +); diff --git a/test/built-ins/GeneratorPrototype/return/try-finally-before-try.js b/test/built-ins/GeneratorPrototype/return/try-finally-before-try.js index 9da2b4a1d4..0dfc83a19a 100644 --- a/test/built-ins/GeneratorPrototype/return/try-finally-before-try.js +++ b/test/built-ins/GeneratorPrototype/return/try-finally-before-try.js @@ -8,23 +8,32 @@ description: > that location in the function body. ---*/ +var unreachable = 0; function* g() { yield; + unreachable += 1; try { - $ERROR('This code is unreachable (within `try` block)'); } finally { - $ERROR('This code is unreachable (within `finally` block)'); } - $ERROR('This code is unreachable (following `try` statement)'); } var iter = g(); var result; iter.next(); +assert.sameValue( + unreachable, + 0, + 'statement following `yield` not executed (paused at yield)' +); result = iter.return(45); assert.sameValue(result.value, 45, 'Result `value` following `return`'); assert.sameValue(result.done, true, 'Result `done` flag following `return`'); +assert.sameValue( + unreachable, + 0, + 'statement following `yield` not executed (following `return`)' +); result = iter.next(); assert.sameValue( @@ -33,3 +42,6 @@ assert.sameValue( assert.sameValue( result.done, true, 'Result `done` flag is `true` when complete' ); +assert.sameValue( + unreachable, 0, 'statement following `yield` not executed (once "completed")' +); diff --git a/test/built-ins/GeneratorPrototype/return/try-finally-following-finally.js b/test/built-ins/GeneratorPrototype/return/try-finally-following-finally.js index 253fc14ef2..8f6b893147 100644 --- a/test/built-ins/GeneratorPrototype/return/try-finally-following-finally.js +++ b/test/built-ins/GeneratorPrototype/return/try-finally-following-finally.js @@ -8,26 +8,37 @@ description: > that location in the function body. ---*/ -var afterFinally = false; +var afterFinally = 0; +var unreachable = 0; function* g() { try { } finally {} - afterFinally = true; + afterFinally += 1; yield; + unreachable += 1; } var iter = g(); var result; iter.next(); -assert.sameValue(afterFinally, true); +assert.sameValue(afterFinally, 1); result = iter.return(45); assert.sameValue(result.value, 45, 'Result `value` following `return`'); assert.sameValue(result.done, true, 'Result `done` flag following `return`'); +assert.sameValue( + unreachable, + 0, + 'statement following `yield` not executed (following `return`)' +); + result = iter.next(); assert.sameValue( result.value, undefined, 'Result `value` is undefined when done' ); assert.sameValue(result.done, true, 'Result `done` flag is `true` when done'); +assert.sameValue( + unreachable, 0, 'statement following `yield` not executed (once "completed")' +); diff --git a/test/built-ins/GeneratorPrototype/return/try-finally-nested-try-catch-within-catch.js b/test/built-ins/GeneratorPrototype/return/try-finally-nested-try-catch-within-catch.js index 96baefa616..0eccc18b30 100644 --- a/test/built-ins/GeneratorPrototype/return/try-finally-nested-try-catch-within-catch.js +++ b/test/built-ins/GeneratorPrototype/return/try-finally-nested-try-catch-within-catch.js @@ -9,35 +9,41 @@ description: > function body. ---*/ -var inCatch = false; -var inFinally = false; +var inCatch = 0; +var inFinally = 0; +var unreachable = 0; function* g() { try { try { throw new Error(); } catch (e) { - inCatch = true; + inCatch += 1; yield; - $ERROR('This code is unreachable (within `catch` block)'); + unreachable += 1; } - $ERROR('This code is unreachable (following nested `try` statement)'); + unreachable += 1; } finally { - inFinally = true; + inFinally += 1; } - $ERROR('This code is unreachable (following outer `try` statement)'); + unreachable += 1; } var iter = g(); var result; result = iter.next(); -assert.sameValue(inCatch, true, '`catch` code patch executed'); -assert.sameValue(inFinally, false, '`finally` code path not executed'); +assert.sameValue(inCatch, 1, '`catch` code patch executed'); +assert.sameValue(inFinally, 0, '`finally` code path not executed'); result = iter.return(45); assert.sameValue(result.value, 45, 'Result `value` following `return`'); assert.sameValue(result.done, true, 'Result `done` flag following `return`'); -assert.sameValue(inFinally, true, '`finally` code path executed'); +assert.sameValue(inFinally, 1, '`finally` code path executed'); +assert.sameValue( + unreachable, + 0, + 'statement following `yield` not executed (following `return`)' +); result = iter.next(); assert.sameValue( @@ -46,3 +52,6 @@ assert.sameValue( assert.sameValue( result.done, true, 'Result `done` flag is `true` when compelete' ); +assert.sameValue( + unreachable, 0, 'statement following `yield` not executed (once "completed")' +); diff --git a/test/built-ins/GeneratorPrototype/return/try-finally-nested-try-catch-within-finally.js b/test/built-ins/GeneratorPrototype/return/try-finally-nested-try-catch-within-finally.js index b145c8b70a..033e7bfd9f 100644 --- a/test/built-ins/GeneratorPrototype/return/try-finally-nested-try-catch-within-finally.js +++ b/test/built-ins/GeneratorPrototype/return/try-finally-nested-try-catch-within-finally.js @@ -8,30 +8,37 @@ description: > statement had appeared at that location in the function body. ---*/ -var inFinally = false; +var inFinally = 0; +var unreachable = 0; function* g() { try { throw new Error(); try { } catch (e) {} } finally { - inFinally = true; + inFinally += 1; yield; - $ERROR('This code is unreachable (within `finally` block)'); + unreachable += 1; } - $ERROR('This code is unreachable (following outer `try` statement)'); + unreachable += 1; } var iter = g(); var result; result = iter.next(); -assert.sameValue(inFinally, true, '`finally` code path executed'); +assert.sameValue(inFinally, 1, '`finally` code path executed'); result = iter.return(45); assert.sameValue(result.value, 45, 'Result `value` following `return`'); assert.sameValue(result.done, true, 'Result `done` flag following `return`'); +assert.sameValue( + unreachable, + 0, + 'statement following `yield` not executed (following `return`)' +); + result = iter.next(); assert.sameValue( result.value, undefined, 'Result `value` is undefined when complete' @@ -39,3 +46,6 @@ assert.sameValue( assert.sameValue( result.done, true, 'Result `done` flag is `true` when complete' ); +assert.sameValue( + unreachable, 0, 'statement following `yield` not executed (once "completed")' +); diff --git a/test/built-ins/GeneratorPrototype/return/try-finally-nested-try-catch-within-inner-try.js b/test/built-ins/GeneratorPrototype/return/try-finally-nested-try-catch-within-inner-try.js index 99a3e5ab37..2c3e9e94d9 100644 --- a/test/built-ins/GeneratorPrototype/return/try-finally-nested-try-catch-within-inner-try.js +++ b/test/built-ins/GeneratorPrototype/return/try-finally-nested-try-catch-within-inner-try.js @@ -9,37 +9,43 @@ description: > function body. ---*/ -var inTry = false; -var inFinally = false; +var inTry = 0; +var inFinally = 0; +var unreachable = 0; function* g() { try { try { - inTry = true; + inTry += 1; yield; - $ERROR('This code is unreachable (within nested `try` block)'); + unreachable += 1; } catch (e) { throw e; } - $ERROR('This code is unreachable (following nested `try` statement)'); + unreachable += 1; } finally { - inFinally = true; + inFinally += 1; } - $ERROR('This code is unreachable (following outer `try` statement)'); + unreachable += 1; } var iter = g(); -var exception = new Error(); var result; iter.next(); -assert.sameValue(inTry, true, 'Nested `try` code patch executed'); -assert.sameValue(inFinally, false, '`finally` code path not executed'); +assert.sameValue(inTry, 1, 'Nested `try` code patch executed'); +assert.sameValue(inFinally, 0, '`finally` code path not executed'); result = iter.return(45); assert.sameValue(result.value, 45, 'Result `value` following `return`'); assert.sameValue(result.done, true, 'Result `done` flag following `return`'); -assert.sameValue(inFinally, true, '`finally` code path executed'); +assert.sameValue(inFinally, 1, '`finally` code path executed'); + +assert.sameValue( + unreachable, + 0, + 'statement following `yield` not executed (following `return`)' +); result = iter.next(); assert.sameValue( @@ -48,3 +54,6 @@ assert.sameValue( assert.sameValue( result.done, true, 'Result `done` flag is `true` when complete' ); +assert.sameValue( + unreachable, 0, 'statement following `yield` not executed (once "completed")' +); diff --git a/test/built-ins/GeneratorPrototype/return/try-finally-nested-try-catch-within-outer-try-after-nested.js b/test/built-ins/GeneratorPrototype/return/try-finally-nested-try-catch-within-outer-try-after-nested.js index 15d4fa1f24..c30896370f 100644 --- a/test/built-ins/GeneratorPrototype/return/try-finally-nested-try-catch-within-outer-try-after-nested.js +++ b/test/built-ins/GeneratorPrototype/return/try-finally-nested-try-catch-within-outer-try-after-nested.js @@ -9,33 +9,40 @@ description: > the function body. ---*/ -var inCatch = false; -var inFinally = false; +var inCatch = 0; +var inFinally = 0; +var unreachable = 0; function* g() { try { try { throw new Error(); } catch (e) { - inCatch = true; + inCatch += 1; } } finally { - inFinally = true; + inFinally += 1; } yield; - $ERROR('This code is unreachable'); + unreachable += 1; } var iter = g(); var result; iter.next(); -assert.sameValue(inCatch, true, '`catch` code path executed'); -assert.sameValue(inFinally, true, '`finally` code path executed'); +assert.sameValue(inCatch, 1, '`catch` code path executed'); +assert.sameValue(inFinally, 1, '`finally` code path executed'); result = iter.return(45); assert.sameValue(result.value, 45, 'Result `value` following `return`'); assert.sameValue(result.done, true, 'Result `done` flag following `return`'); +assert.sameValue( + unreachable, + 0, + 'statement following `yield` not executed (following `return`)' +); + result = iter.next(); assert.sameValue( result.value, undefined, 'Result `value` is undefined when complete' @@ -43,3 +50,6 @@ assert.sameValue( assert.sameValue( result.done, true, 'Result `done` flag is `true` when complete' ); +assert.sameValue( + unreachable, 0, 'statement following `yield` not executed (once "completed")' +); diff --git a/test/built-ins/GeneratorPrototype/return/try-finally-nested-try-catch-within-outer-try-before-nested.js b/test/built-ins/GeneratorPrototype/return/try-finally-nested-try-catch-within-outer-try-before-nested.js index 5e4b87999c..d47c5f9e63 100644 --- a/test/built-ins/GeneratorPrototype/return/try-finally-nested-try-catch-within-outer-try-before-nested.js +++ b/test/built-ins/GeneratorPrototype/return/try-finally-nested-try-catch-within-outer-try-before-nested.js @@ -9,35 +9,42 @@ description: > the function body. ---*/ -var inTry = false; -var inFinally = false; +var inTry = 0; +var inFinally = 0; +var unreachable = 0; function* g() { try { - inTry = true; + inTry += 1; yield; try { - $ERROR('This code is unreachable (within nested `try` block)'); + unreachable += 1; } catch (e) { throw e; } - $ERROR('This code is unreacahable (following nested `try` statement)'); + unreachable += 1; } finally { - inFinally = true; + inFinally += 1; } - $ERROR('This codeis unreachable (following outer `try` statement)'); + unreachable += 1; } var iter = g(); var result; iter.next(); -assert.sameValue(inTry, true, '`try` code path executed'); -assert.sameValue(inFinally, false, '`finally` code path not executed'); +assert.sameValue(inTry, 1, '`try` code path executed'); +assert.sameValue(inFinally, 0, '`finally` code path not executed'); result = iter.return(45); assert.sameValue(result.value, 45, 'Second result `value`'); assert.sameValue(result.done, true, 'Second result `done` flag'); -assert.sameValue(inFinally, true, '`finally` code path executed'); +assert.sameValue(inFinally, 1, '`finally` code path executed'); + +assert.sameValue( + unreachable, + 0, + 'statement following `yield` not executed (following `return`)' +); result = iter.next(); assert.sameValue( @@ -46,3 +53,6 @@ assert.sameValue( assert.sameValue( result.done, true, 'Result `done` flag is `true` when complete' ); +assert.sameValue( + unreachable, 0, 'statement following `yield` not executed (once "completed")' +); diff --git a/test/built-ins/GeneratorPrototype/return/try-finally-within-finally.js b/test/built-ins/GeneratorPrototype/return/try-finally-within-finally.js index ae0b022c58..738a2c0c16 100644 --- a/test/built-ins/GeneratorPrototype/return/try-finally-within-finally.js +++ b/test/built-ins/GeneratorPrototype/return/try-finally-within-finally.js @@ -8,27 +8,34 @@ description: > statement had appeared at that location in the function body. ---*/ -var inFinally = true; +var inFinally = 0; +var unreachable = 0; function* g() { try { } finally { - inFinally = true; + inFinally += 1; yield; - $ERROR('This code is unreachable (within `finally` block)'); + unreachable += 1; } - $ERROR('This code is unreachable (following `try` statement)'); + unreachable += 1; } var iter = g(); var result; iter.next(); -assert.sameValue(inFinally, true, '`finally` code path executed'); +assert.sameValue(inFinally, 1, '`finally` code path executed'); result = iter.return(45); assert.sameValue(result.value, 45, 'Result `value` following `return`'); assert.sameValue(result.done, true, 'Result `done` flag following `return`'); +assert.sameValue( + unreachable, + 0, + 'statement following `yield` not executed (following `return`)' +); + result = iter.next(); assert.sameValue( result.value, undefined, 'Result `value` is undefined when complete' @@ -36,3 +43,6 @@ assert.sameValue( assert.sameValue( result.done, true, 'Result `done` flag is `true` when complete' ); +assert.sameValue( + unreachable, 0, 'statement following `yield` not executed (once "completed")' +); diff --git a/test/built-ins/GeneratorPrototype/return/try-finally-within-try.js b/test/built-ins/GeneratorPrototype/return/try-finally-within-try.js index 6a098be79d..829bf00aa7 100644 --- a/test/built-ins/GeneratorPrototype/return/try-finally-within-try.js +++ b/test/built-ins/GeneratorPrototype/return/try-finally-within-try.js @@ -8,30 +8,37 @@ description: > statement had appeared at that location in the function body. ---*/ -var inTry = false; -var inFinally = false; +var inTry = 0; +var inFinally = 0; +var unreachable = 0; function* g() { try { - inTry = true; + inTry += 1; yield; - $ERROR('This code is unreachable (within `try` block)'); + unreachable += 1; } finally { - inFinally = true; + inFinally += 1; } - $ERROR('This code is unreachable (following `try` statement)'); + unreachable += 1; } var iter = g(); var result; iter.next(); -assert.sameValue(inTry, true, '`try` block code path executed'); -assert.sameValue(inFinally, false, '`finally` code path not executed'); +assert.sameValue(inTry, 1, '`try` block code path executed'); +assert.sameValue(inFinally, 0, '`finally` code path not executed'); result = iter.return(45); assert.sameValue(result.value, 45, 'Result `value` following `return`'); assert.sameValue(result.done, true, 'Result `done` flag following `return`'); -assert.sameValue(inFinally, true, '`finally` code path executed'); +assert.sameValue(inFinally, 1, '`finally` code path executed'); + +assert.sameValue( + unreachable, + 0, + 'statement following `yield` not executed (following `return`)' +); result = iter.next(); assert.sameValue( @@ -40,3 +47,6 @@ assert.sameValue( assert.sameValue( result.done, true, 'Result `done` flag is `true` when complete' ); +assert.sameValue( + unreachable, 0, 'statement following `yield` not executed (once "completed")' +); diff --git a/test/built-ins/GeneratorPrototype/throw/from-state-executing.js b/test/built-ins/GeneratorPrototype/throw/from-state-executing.js index 546ef91040..76c05ea91a 100644 --- a/test/built-ins/GeneratorPrototype/throw/from-state-executing.js +++ b/test/built-ins/GeneratorPrototype/throw/from-state-executing.js @@ -1,13 +1,41 @@ // Copyright (C) 2013 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- +esid: sec-generatorvalidate es6id: 25.3.3.2 description: > - A TypeError should be thrown if the generator is resumed abruptly while - running. + A TypeError should be thrown if the generator is in the "executing" state, + and the generator should be marked as "completed" +info: | + 25.3.3.1 GeneratorStart + + [...] + 4. Set the code evaluation state of genContext such that when evaluation is + resumed for that execution context the following steps will be performed: + a. Let result be the result of evaluating generatorBody. + b. Assert: If we return here, the generator either threw an exception or + performed either an implicit or explicit return. + c. Remove genContext from the execution context stack and restore the + execution context that is at the top of the execution context stack as + the running execution context. + d. Set generator.[[GeneratorState]] to "completed". + [...] + + 25.3.3.4 GeneratorResumeAbrupt + + 1. Let state be ? GeneratorValidate(generator). + + 25.3.3.2 GeneratorValidate + + 1. If Type(generator) is not Object, throw a TypeError exception. + 2. If generator does not have a [[GeneratorState]] internal slot, throw a + TypeError exception. + 3. Assert: generator also has a [[GeneratorContext]] internal slot. + 4. Let state be generator.[[GeneratorState]]. + 5. If state is "executing", throw a TypeError exception. ---*/ -var iter; +var iter, result; function* g() { iter.throw(42); } @@ -16,3 +44,9 @@ iter = g(); assert.throws(TypeError, function() { iter.next(); }); + +result = iter.next(); + +assert.sameValue(typeof result, 'object'); +assert.sameValue(result.value, undefined); +assert.sameValue(result.done, true); diff --git a/test/built-ins/GeneratorPrototype/throw/incorrect-context.js b/test/built-ins/GeneratorPrototype/throw/incorrect-context.js deleted file mode 100644 index 827292acbb..0000000000 --- a/test/built-ins/GeneratorPrototype/throw/incorrect-context.js +++ /dev/null @@ -1,17 +0,0 @@ -// 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.3.1.4 -description: > - A TypeError should be thrown from GeneratorValidate (25.3.3.2) if the - context of `throw` does not defined the [[GeneratorState]] internal slot. ----*/ - -function* g() {} -var GeneratorPrototype = Object.getPrototypeOf(g).prototype; - -assert.throws(TypeError, function() { GeneratorPrototype.throw.call(1); }); -assert.throws(TypeError, function() { GeneratorPrototype.throw.call({}); }); -assert.throws(TypeError, function() { GeneratorPrototype.throw.call(function() {}); }); -assert.throws(TypeError, function() { GeneratorPrototype.throw.call(g); }); -assert.throws(TypeError, function() { GeneratorPrototype.throw.call(g.prototype); }); diff --git a/test/built-ins/GeneratorPrototype/throw/this-val-not-generator.js b/test/built-ins/GeneratorPrototype/throw/this-val-not-generator.js new file mode 100644 index 0000000000..cfdf1deb4b --- /dev/null +++ b/test/built-ins/GeneratorPrototype/throw/this-val-not-generator.js @@ -0,0 +1,69 @@ +// Copyright (C) 2013 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-generator.prototype.throw +es6id: 25.3.1.4 +description: > + A TypeError should be thrown from GeneratorValidate (25.3.3.2) if the + context of `throw` does not define the [[GeneratorState]] internal slot. +info: | + [...] + 3. Return ? GeneratorResumeAbrupt(g, C). + + 25.3.3.4 GeneratorResumeAbrupt + + 1. Let state be ? GeneratorValidate(generator). + + 25.3.3.2 GeneratorValidate + + [...] + 2. If generator does not have a [[GeneratorState]] internal slot, throw a + TypeError exception. +---*/ + +function* g() {} +var GeneratorPrototype = Object.getPrototypeOf(g).prototype; + +assert.throws( + TypeError, + function() { GeneratorPrototype.throw.call({}); }, + 'ordinary object (without value)' +); +assert.throws( + TypeError, + function() { GeneratorPrototype.throw.call({}, 1); }, + 'ordinary object (with value)' +); + +assert.throws( + TypeError, + function() { GeneratorPrototype.throw.call(function() {}); }, + 'function object (without value)' +); +assert.throws( + TypeError, + function() { GeneratorPrototype.throw.call(function() {}, 1); }, + 'function object (with value)' +); + +assert.throws( + TypeError, + function() { GeneratorPrototype.throw.call(g); }, + 'generator function object (without value)' +); +assert.throws( + TypeError, + function() { GeneratorPrototype.throw.call(g, 1); }, + 'generator function object (with value)' +); + +assert.throws( + TypeError, + function() { GeneratorPrototype.throw.call(g.prototype); }, + 'generator function prototype object (without value)' +); +assert.throws( + TypeError, + function() { GeneratorPrototype.throw.call(g.prototype, 1); }, + 'generator function prototype object (with value)' +); diff --git a/test/built-ins/GeneratorPrototype/throw/this-val-not-object.js b/test/built-ins/GeneratorPrototype/throw/this-val-not-object.js new file mode 100644 index 0000000000..945798405c --- /dev/null +++ b/test/built-ins/GeneratorPrototype/throw/this-val-not-object.js @@ -0,0 +1,91 @@ +// Copyright (C) 2013 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-generator.prototype.throw +es6id: 25.3.1.4 +description: > + A TypeError should be thrown from GeneratorValidate (25.3.3.2) if the "this" + value of `throw` is not an object. +info: | + [...] + 3. Return ? GeneratorResumeAbrupt(g, C). + + 25.3.3.4 GeneratorResumeAbrupt + + 1. Let state be ? GeneratorValidate(generator). + + 25.3.3.2 GeneratorValidate + + 1. If Type(generator) is not Object, throw a TypeError exception. +features: [Symbol] +---*/ + +function* g() {} +var GeneratorPrototype = Object.getPrototypeOf(g).prototype; +var symbol = Symbol(); + +assert.throws( + TypeError, + function() { GeneratorPrototype.throw.call(undefined); }, + 'undefined (without value)' +); +assert.throws( + TypeError, + function() { GeneratorPrototype.throw.call(undefined, 1); }, + 'undefined (with value)' +); + +assert.throws( + TypeError, + function() { GeneratorPrototype.throw.call(null); }, + 'null (without value)' +); +assert.throws( + TypeError, + function() { GeneratorPrototype.throw.call(null, 1); }, + 'null (with value)' +); + +assert.throws( + TypeError, + function() { GeneratorPrototype.throw.call(true); }, + 'boolean (without value)' +); +assert.throws( + TypeError, + function() { GeneratorPrototype.throw.call(true, 1); }, + 'boolean (with value)' +); + +assert.throws( + TypeError, + function() { GeneratorPrototype.throw.call('s'); }, + 'string (without value)' +); +assert.throws( + TypeError, + function() { GeneratorPrototype.throw.call('s', 1); }, + 'string (with value)' +); + +assert.throws( + TypeError, + function() { GeneratorPrototype.throw.call(1); }, + 'number (without value)' +); +assert.throws( + TypeError, + function() { GeneratorPrototype.throw.call(1, 1); }, + 'number (with value)' +); + +assert.throws( + TypeError, + function() { GeneratorPrototype.throw.call(symbol); }, + 'symbol (without value)' +); +assert.throws( + TypeError, + function() { GeneratorPrototype.throw.call(symbol, 1); }, + 'symbol (with value)' +); diff --git a/test/built-ins/GeneratorPrototype/throw/try-catch-before-try.js b/test/built-ins/GeneratorPrototype/throw/try-catch-before-try.js index 3b5f7d13a9..968cd39b1a 100644 --- a/test/built-ins/GeneratorPrototype/throw/try-catch-before-try.js +++ b/test/built-ins/GeneratorPrototype/throw/try-catch-before-try.js @@ -8,8 +8,10 @@ description: > location in the function body. ---*/ +var unreachable = 0; function* g() { yield 1; + unreachable += 1; try { yield 2; } catch (e) { @@ -17,19 +19,32 @@ function* g() { } yield 3; } -var iter, result, exception; +var iter, result; iter = g(); result = iter.next(); assert.sameValue(result.value, 1, 'First result `value`'); assert.sameValue(result.done, false, 'First result `done` flag'); +assert.sameValue( + unreachable, 0, 'statement following `yield` not executed (paused at yield)' +); + assert.throws(Test262Error, function() { iter.throw(new Test262Error()); }); +assert.sameValue( + unreachable, + 0, + 'statement following `yield` not executed (following `throw`)' +); + result = iter.next(); assert.sameValue(result.value, undefined, 'Result `value` is undefined when done' ); assert.sameValue(result.done, true, 'Result `done` flag is `true` when done'); +assert.sameValue( + unreachable, 0, 'statement following `yield` not executed (once "completed")' +); iter.next(); diff --git a/test/built-ins/GeneratorPrototype/throw/try-catch-following-catch.js b/test/built-ins/GeneratorPrototype/throw/try-catch-following-catch.js index 5da206774c..c358765e4e 100644 --- a/test/built-ins/GeneratorPrototype/throw/try-catch-following-catch.js +++ b/test/built-ins/GeneratorPrototype/throw/try-catch-following-catch.js @@ -9,6 +9,7 @@ description: > ---*/ var obj = {}; +var unreachable = 0; function* g() { yield 1; try { @@ -18,6 +19,7 @@ function* g() { yield e; } yield 3; + unreachable += 1; } var iter, result; @@ -40,10 +42,19 @@ assert.sameValue(result.done, false, 'Fourth result `done` flag'); assert.throws(Test262Error, function() { iter.throw(new Test262Error()); }); +assert.sameValue( + unreachable, + 0, + 'statement following `yield` not executed (following `throw`)' +); + result = iter.next(); assert.sameValue( result.value, undefined, 'Result `value` is undefined when done' ); assert.sameValue(result.done, true, 'Result `done` flag is `true` when done'); +assert.sameValue( + unreachable, 0, 'statement following `yield` not executed (once "completed")' +); iter.next(); diff --git a/test/built-ins/GeneratorPrototype/throw/try-catch-within-catch.js b/test/built-ins/GeneratorPrototype/throw/try-catch-within-catch.js index 9e2329e9d4..a5329ad427 100644 --- a/test/built-ins/GeneratorPrototype/throw/try-catch-within-catch.js +++ b/test/built-ins/GeneratorPrototype/throw/try-catch-within-catch.js @@ -8,6 +8,7 @@ description: > had appeared at that location in the function body. ---*/ +var unreachable = 0; function* g() { yield 1; try { @@ -15,6 +16,7 @@ function* g() { throw exception; } catch (e) { yield e; + unreachable += 1; } yield 3; } @@ -35,15 +37,21 @@ result = iter.next(); assert.sameValue(result.value, exception, 'Third result `value`'); assert.sameValue(result.done, false, 'Third result `done` flag'); -result = iter.next(); -assert.sameValue(result.value, 3, 'Fourth result `value`'); -assert.sameValue(result.done, false, 'Fourth result `done` flag'); assert.throws(Test262Error, function() { iter.throw(new Test262Error()); }); +assert.sameValue( + unreachable, + 0, + 'statement following `yield` not executed (following `throw`)' +); + result = iter.next(); assert.sameValue( result.value, undefined, 'Result `value` is undefined when done' ); assert.sameValue(result.done, true, 'Result `done` flag is `true` when done'); +assert.sameValue( + unreachable, 0, 'statement following `yield` not executed (once "completed")' +); iter.next(); diff --git a/test/built-ins/GeneratorPrototype/throw/try-catch-within-try.js b/test/built-ins/GeneratorPrototype/throw/try-catch-within-try.js index b768c3860c..56920f9949 100644 --- a/test/built-ins/GeneratorPrototype/throw/try-catch-within-try.js +++ b/test/built-ins/GeneratorPrototype/throw/try-catch-within-try.js @@ -8,10 +8,12 @@ description: > had appeared at that location in the function body. ---*/ +var unreachable = 0; function* g() { yield 1; try { yield 2; + unreachable += 1; } catch (e) { yield e; } @@ -34,14 +36,28 @@ result = iter.throw(exception); assert.sameValue(result.value, exception, 'Third result `value`'); assert.sameValue(result.done, false, 'Third result `done` flag'); +assert.sameValue( + unreachable, + 0, + 'statement following `yield` not executed (following `throw`)' +); + result = iter.next(); assert.sameValue(result.value, 3, 'Fourth result `done` flag'); assert.sameValue(result.done, false, 'Fourth result `value`'); +assert.sameValue( + unreachable, + 0, + 'statement following `yield` not executed (following `catch`)' +); result = iter.next(); assert.sameValue( result.value, undefined, 'Result `value` is undefined when done' ); assert.sameValue(result.done, true, 'Result `done` flag is `true` when done'); +assert.sameValue( + unreachable, 0, 'statement following `yield` not executed (once "completed")' +); iter.next(); diff --git a/test/built-ins/GeneratorPrototype/throw/try-finally-before-try.js b/test/built-ins/GeneratorPrototype/throw/try-finally-before-try.js index 87518726ba..f0859a5769 100644 --- a/test/built-ins/GeneratorPrototype/throw/try-finally-before-try.js +++ b/test/built-ins/GeneratorPrototype/throw/try-finally-before-try.js @@ -8,8 +8,10 @@ description: > that location in the function body. ---*/ +var unreachable = 0; function* g() { yield 1; + unreachable += 1; try { yield 2; } finally { @@ -26,13 +28,25 @@ assert.sameValue(result.value, 1, 'First result `value`'); assert.sameValue( result.done, false, 'First result `done` flag' ); +assert.sameValue( + unreachable, 0, 'statement following `yield` not executed (paused at yield)' +); assert.throws(Test262Error, function() { iter.throw(new Test262Error()); }); +assert.sameValue( + unreachable, + 0, + 'statement following `yield` not executed (following `throw`)' +); + result = iter.next(); assert.sameValue( result.value, undefined, 'Result `value` is undefined when done' ); assert.sameValue( result.done, true, 'Result `done` flag is `true` when done'); +assert.sameValue( + unreachable, 0, 'statement following `yield` not executed (once "completed")' +); iter.next(); diff --git a/test/built-ins/GeneratorPrototype/throw/try-finally-following-finally.js b/test/built-ins/GeneratorPrototype/throw/try-finally-following-finally.js index 0c7c061019..d4b894ec04 100644 --- a/test/built-ins/GeneratorPrototype/throw/try-finally-following-finally.js +++ b/test/built-ins/GeneratorPrototype/throw/try-finally-following-finally.js @@ -8,6 +8,7 @@ description: > location in the function body. ---*/ +var unreachable = 0; function* g() { yield 1; try { @@ -16,7 +17,7 @@ function* g() { yield 3; } yield 4; - $ERROR('This code is unreachable'); + unreachable += 1; } var iter = g(); var result; @@ -39,10 +40,19 @@ assert.sameValue(result.done, false, 'Third result `done` flag'); assert.throws(Test262Error, function() { iter.throw(new Test262Error()); }); +assert.sameValue( + unreachable, + 0, + 'statement following `yield` not executed (following `throw`)' +); + result = iter.next(); assert.sameValue( result.value, undefined, 'Result `value` is undefined when done' ); assert.sameValue(result.done, true, 'Result `done` flag is `true` when done'); +assert.sameValue( + unreachable, 0, 'statement following `yield` not executed (once "completed")' +); iter.next(); diff --git a/test/built-ins/GeneratorPrototype/throw/try-finally-nested-try-catch-within-catch.js b/test/built-ins/GeneratorPrototype/throw/try-finally-nested-try-catch-within-catch.js index abc3466dd3..edbb9d2ee6 100644 --- a/test/built-ins/GeneratorPrototype/throw/try-finally-nested-try-catch-within-catch.js +++ b/test/built-ins/GeneratorPrototype/throw/try-finally-nested-try-catch-within-catch.js @@ -9,6 +9,7 @@ description: > function body. ---*/ +var unreachable = 0; function* g() { try { yield 1; @@ -17,6 +18,7 @@ function* g() { throw exception; } catch (e) { yield e; + unreachable += 1; } yield 3; } finally { @@ -46,10 +48,19 @@ assert.sameValue(result.done, false, 'Fourth result `done` flag'); assert.throws(Test262Error, function() { iter.next(); }); +assert.sameValue( + unreachable, + 0, + 'statement following `yield` not executed (following `throw`)' +); + result = iter.next(); assert.sameValue( result.value, undefined, 'Result `value` is undefined when done' ); assert.sameValue(result.done, true, 'Result `done` flag is `true` when done'); +assert.sameValue( + unreachable, 0, 'statement following `yield` not executed (once "completed")' +); iter.next(); diff --git a/test/built-ins/GeneratorPrototype/throw/try-finally-nested-try-catch-within-finally.js b/test/built-ins/GeneratorPrototype/throw/try-finally-nested-try-catch-within-finally.js index 8c3ec7377a..7042aab620 100644 --- a/test/built-ins/GeneratorPrototype/throw/try-finally-nested-try-catch-within-finally.js +++ b/test/built-ins/GeneratorPrototype/throw/try-finally-nested-try-catch-within-finally.js @@ -8,6 +8,7 @@ description: > had appeared at that location in the function body. ---*/ +var unreachable = 0; function* g() { try { yield 1; @@ -20,7 +21,9 @@ function* g() { yield 3; } finally { yield 4; + unreachable += 1; } + unreachable += 1; yield 5; } var iter = g(); @@ -36,10 +39,19 @@ assert.sameValue(result.done, false, 'First result `done` flag'); assert.throws(Test262Error, function() { iter.throw(new Test262Error()); }); +assert.sameValue( + unreachable, + 0, + 'statement following `yield` not executed (following `throw`)' +); + result = iter.next(); assert.sameValue( result.value, undefined, 'Result `value` is undefined when done' ); assert.sameValue(result.done, true, 'Result `done` flag is `true` when done'); +assert.sameValue( + unreachable, 0, 'statement following `yield` not executed (once "completed")' +); iter.next(); diff --git a/test/built-ins/GeneratorPrototype/throw/try-finally-nested-try-catch-within-inner-try.js b/test/built-ins/GeneratorPrototype/throw/try-finally-nested-try-catch-within-inner-try.js index 38a40083d4..13ea93f04b 100644 --- a/test/built-ins/GeneratorPrototype/throw/try-finally-nested-try-catch-within-inner-try.js +++ b/test/built-ins/GeneratorPrototype/throw/try-finally-nested-try-catch-within-inner-try.js @@ -9,11 +9,13 @@ description: > function body. ---*/ +var unreachable = 0; function* g() { try { yield 1; try { yield 2; + unreachable += 1; } catch (e) { yield e; } @@ -39,6 +41,12 @@ result = iter.throw(exception); assert.sameValue(result.value, exception, 'Third result `value`'); assert.sameValue(result.done, false, 'Third result `done` flag'); +assert.sameValue( + unreachable, + 0, + 'statement following `yield` not executed (following `throw`)' +); + result = iter.next(); assert.sameValue(result.value, 3, 'Fourth result `value'); assert.sameValue(result.done, false, 'Fourth result `done` flag'); @@ -56,5 +64,8 @@ assert.sameValue( result.value, undefined, 'Result `value` is undefined when done' ); assert.sameValue(result.done, true, 'Result `done` flag is `true` when done'); +assert.sameValue( + unreachable, 0, 'statement following `yield` not executed (once "completed")' +); iter.next(); diff --git a/test/built-ins/GeneratorPrototype/throw/try-finally-nested-try-catch-within-outer-try-after-nested.js b/test/built-ins/GeneratorPrototype/throw/try-finally-nested-try-catch-within-outer-try-after-nested.js index f5d8d5f5f8..0f0145696d 100644 --- a/test/built-ins/GeneratorPrototype/throw/try-finally-nested-try-catch-within-outer-try-after-nested.js +++ b/test/built-ins/GeneratorPrototype/throw/try-finally-nested-try-catch-within-outer-try-after-nested.js @@ -9,6 +9,7 @@ description: > function body. ---*/ +var unreachable = 0; function* g() { try { yield 1; @@ -19,6 +20,7 @@ function* g() { yield e; } yield 3; + unreachable += 1; } finally { yield 4; } @@ -48,6 +50,12 @@ result = iter.throw(new Test262Error()); assert.sameValue(result.value, 4, 'Fifth result `value`'); assert.sameValue(result.done, false, 'Fifth result `done` flag'); +assert.sameValue( + unreachable, + 0, + 'statement following `yield` not executed (following `throw`)' +); + assert.throws(Test262Error, function() { iter.next(); }); result = iter.next(); @@ -55,5 +63,8 @@ assert.sameValue( result.value, undefined, 'Result `value` is undefined when done' ); assert.sameValue(result.done, true, 'Result `done` flag is `true` when done'); +assert.sameValue( + unreachable, 0, 'statement following `yield` not executed (once "completed")' +); iter.next(); diff --git a/test/built-ins/GeneratorPrototype/throw/try-finally-nested-try-catch-within-outer-try-before-nested.js b/test/built-ins/GeneratorPrototype/throw/try-finally-nested-try-catch-within-outer-try-before-nested.js index aaee096930..70a1caa642 100644 --- a/test/built-ins/GeneratorPrototype/throw/try-finally-nested-try-catch-within-outer-try-before-nested.js +++ b/test/built-ins/GeneratorPrototype/throw/try-finally-nested-try-catch-within-outer-try-before-nested.js @@ -9,9 +9,11 @@ description: > function body. ---*/ +var unreachable = 0; function* g() { try { yield 1; + unreachable += 1; try { yield 2; } catch (e) { @@ -34,6 +36,12 @@ result = iter.throw(new Test262Error()); assert.sameValue(result.value, 4, 'Second result `value`'); assert.sameValue(result.done, false, 'Second result `done` flag'); +assert.sameValue( + unreachable, + 0, + 'statement following `yield` not executed (following `throw`)' +); + assert.throws(Test262Error, function() { iter.next(); }); result = iter.next(); @@ -41,5 +49,8 @@ assert.sameValue( result.value, undefined, 'Result `value` is undefined when done' ); assert.sameValue(result.done, true, 'Result `done` flag is `true` when done'); +assert.sameValue( + unreachable, 0, 'statement following `yield` not executed (once "completed")' +); iter.next(); diff --git a/test/built-ins/GeneratorPrototype/throw/try-finally-within-finally.js b/test/built-ins/GeneratorPrototype/throw/try-finally-within-finally.js index 1345eeaee9..47660bfbb4 100644 --- a/test/built-ins/GeneratorPrototype/throw/try-finally-within-finally.js +++ b/test/built-ins/GeneratorPrototype/throw/try-finally-within-finally.js @@ -8,12 +8,14 @@ description: > had appeared at that location in the function body. ---*/ +var unreachable = 0; function* g() { yield 1; try { yield 2; } finally { yield 3; + unreachable += 1; } yield 4; } @@ -32,16 +34,21 @@ 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, 4, 'Fourth result `value`'); -assert.sameValue(result.done, false, 'Fourth result `done` flag'); - assert.throws(Test262Error, function() { iter.throw(new Test262Error()); }); +assert.sameValue( + unreachable, + 0, + 'statement following `yield` not executed (following `throw`)' +); + result = iter.next(); assert.sameValue( result.value, undefined, 'Result `value` is undefined when done' ); assert.sameValue(result.done, true, 'Result `done` flag is `true` when done'); +assert.sameValue( + unreachable, 0, 'statement following `yield` not executed (once "completed")' +); iter.next(); diff --git a/test/built-ins/GeneratorPrototype/throw/try-finally-within-try.js b/test/built-ins/GeneratorPrototype/throw/try-finally-within-try.js index d7c28f8b3b..0fb8336139 100644 --- a/test/built-ins/GeneratorPrototype/throw/try-finally-within-try.js +++ b/test/built-ins/GeneratorPrototype/throw/try-finally-within-try.js @@ -8,10 +8,12 @@ description: > had appeared at that location in the function body. ---*/ +var unreachable = 0; function* g() { yield 1; try { yield 2; + unreachable += 1; } finally { yield 3; } @@ -28,16 +30,25 @@ result = iter.next(); assert.sameValue(result.value, 2, 'Second result `value`'); assert.sameValue(result.done, false, 'Second result `done` flag'); -result = iter.next(); +result = iter.throw(new Test262Error()); assert.sameValue(result.value, 3, 'Third result `value`'); assert.sameValue(result.done, false, 'Third result `done` flag'); -assert.throws(Test262Error, function() { iter.throw(new Test262Error()); }); +assert.sameValue( + unreachable, + 0, + 'statement following `yield` not executed (following `throw`)' +); + +assert.throws(Test262Error, function() { iter.next(); }); result = iter.next(); assert.sameValue( result.value, undefined, 'Result `value` is undefined when done' ); assert.sameValue(result.done, true, 'Result `done` flag is `true` when done'); +assert.sameValue( + unreachable, 0, 'statement following `yield` not executed (once "completed")' +); iter.next();