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
This commit is contained in:
jugglinmike 2016-07-01 14:24:27 -04:00 committed by Tom Care
parent e290a337b8
commit fce8b5852d
50 changed files with 1227 additions and 161 deletions

View File

@ -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));

View File

@ -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');

View File

@ -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');

View File

@ -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');

View File

@ -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');

View File

@ -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');

View File

@ -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');

View File

@ -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));

View File

@ -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');

View File

@ -5,9 +5,18 @@ es6id: 25.2.3.2
description: > description: >
The value of GeneratorFunction.prototype.prototype is the The value of GeneratorFunction.prototype.prototype is the
%GeneratorPrototype% intrinsic object. %GeneratorPrototype% intrinsic object.
This property has the attributes { [[Writable]]: false, [[Enumerable]]:
false, [[Configurable]]: true }.
includes: [propertyHelper.js]
---*/ ---*/
var GeneratorFunctionPrototype = Object.getPrototypeOf(function*() {});
assert.sameValue( assert.sameValue(
Object.getPrototypeOf(function*() {}).prototype, GeneratorFunctionPrototype.prototype,
Object.getPrototypeOf(function*() {}.prototype) Object.getPrototypeOf(function*() {}.prototype)
); );
verifyNotEnumerable(GeneratorFunctionPrototype, 'prototype');
verifyNotWritable(GeneratorFunctionPrototype, 'prototype');
verifyConfigurable(GeneratorFunctionPrototype, 'prototype');

View File

@ -1,12 +1,41 @@
// Copyright (C) 2013 the V8 project authors. All rights reserved. // Copyright (C) 2013 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file. // This code is governed by the BSD license found in the LICENSE file.
/*--- /*---
esid: sec-generatorvalidate
es6id: 25.3.3.2 es6id: 25.3.3.2
description: > 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() { function* withoutVal() {
iter.next(); iter.next();
} }
@ -17,9 +46,33 @@ function* withVal() {
iter = withoutVal(); iter = withoutVal();
assert.throws(TypeError, function() { assert.throws(TypeError, function() {
iter.next(); 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(); iter = withVal();
assert.throws(TypeError, function() { assert.throws(TypeError, function() {
iter.next(); 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'
);

View File

@ -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); });

View File

@ -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)'
);

View File

@ -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)'
);

View File

@ -13,9 +13,12 @@ var iter, result;
iter = G(); iter = G();
iter.next(); 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(); result = iter.next();
assert.sameValue(result.value, undefined, 'Result `value`'); assert.sameValue(result.value, undefined, 'next: result `value`');
assert.sameValue(result.done, true, 'Result `done` flag'); assert.sameValue(result.done, true, 'next: result `done` flag');

View File

@ -1,13 +1,41 @@
// Copyright (C) 2015 the V8 project authors. All rights reserved. // Copyright (C) 2015 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file. // This code is governed by the BSD license found in the LICENSE file.
/*--- /*---
esid: sec-generatorvalidate
es6id: 25.3.3.2 es6id: 25.3.3.2
description: > description: >
A TypeError should be thrown if the generator is resumed abruptly while A TypeError should be thrown if the generator is in the "executing" state,
running. 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() { function* g() {
iter.return(42); iter.return(42);
} }
@ -16,3 +44,9 @@ iter = g();
assert.throws(TypeError, function() { assert.throws(TypeError, function() {
iter.next(); iter.next();
}); });
result = iter.next();
assert.sameValue(typeof result, 'object');
assert.sameValue(result.value, undefined);
assert.sameValue(result.done, true);

View File

@ -8,8 +8,9 @@ description: >
state. state.
---*/ ---*/
var bodyCount = 0;
function* G() { function* G() {
yield 1; bodyCount += 1;
} }
var iter = G(); var iter = G();
var result; var result;
@ -18,8 +19,14 @@ result = iter.return(56);
assert.sameValue(result.value, 56); assert.sameValue(result.value, 56);
assert.sameValue(result.done, true); assert.sameValue(result.done, true);
assert.sameValue(
bodyCount, 0, 'body not evaluated during processing of `return` method'
);
result = iter.next(); result = iter.next();
assert.sameValue(result.value, undefined, 'Result `value`'); assert.sameValue(result.value, undefined, 'Result `value`');
assert.sameValue(result.done, true, 'Result `done` flag'); assert.sameValue(result.done, true, 'Result `done` flag');
assert.sameValue(
bodyCount, 0, 'body not evaluated when "completed" generator is advanced'
);

View File

@ -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); });

View File

@ -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)'
);

View File

@ -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)'
);

View File

@ -8,24 +8,34 @@ description: >
location in the function body. location in the function body.
---*/ ---*/
var unreachable = 0;
function* g() { function* g() {
yield; yield;
try { try {
$ERROR('This code is unreachable (within `try` block)'); unreachable += 1;
} catch (e) { } catch (e) {
throw e; throw e;
} }
$ERROR('This code is unreachable (following `try` statement)'); unreachable += 1;
} }
var iter = g(); var iter = g();
var result; var result;
iter.next(); iter.next();
assert.sameValue(
unreachable, 0, 'statement following `yield` not executed (paused at yield)'
);
result = iter.return(45); result = iter.return(45);
assert.sameValue(result.value, 45, 'Result `value` following `return`'); assert.sameValue(result.value, 45, 'Result `value` following `return`');
assert.sameValue(result.done, true, 'Result `done` flag 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(); result = iter.next();
assert.sameValue(result.value, assert.sameValue(result.value,
undefined, 'Result `value` is undefined when complete' undefined, 'Result `value` is undefined when complete'
@ -33,3 +43,6 @@ assert.sameValue(result.value,
assert.sameValue( assert.sameValue(
result.done, true, 'Result `done` flag is `true` when complete' result.done, true, 'Result `done` flag is `true` when complete'
); );
assert.sameValue(
unreachable, 0, 'statement following `yield` not executed (once "completed")'
);

View File

@ -8,27 +8,36 @@ description: >
location in the function body. location in the function body.
---*/ ---*/
var afterCatch = false; var afterCatch = 0;
var unreachable = 0;
function* g() { function* g() {
try { try {
throw new Error(); throw new Error();
} catch (e) {} } catch (e) {}
afterCatch = true; afterCatch += 1;
yield; yield;
$ERROR('This code is unreachable'); unreachable += 1;
} }
var iter = g(); var iter = g();
var result; var result;
result = iter.next(); 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); result = iter.return(45);
assert.sameValue( assert.sameValue(
result.value, 45, 'Result `value` following `return`' result.value, 45, 'Result `value` following `return`'
); );
assert.sameValue(result.done, true, 'Result `done` flag 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(); result = iter.next();
assert.sameValue( assert.sameValue(
@ -37,3 +46,6 @@ assert.sameValue(
assert.sameValue( assert.sameValue(
result.done, true, 'Result `done` flag is `true` when complete' result.done, true, 'Result `done` flag is `true` when complete'
); );
assert.sameValue(
unreachable, 0, 'statement following `yield` not executed (once "completed")'
);

View File

@ -8,29 +8,35 @@ description: >
statement had appeared at that location in the function body. statement had appeared at that location in the function body.
---*/ ---*/
var inCatch = false; var inCatch = 0;
var unreachable = 0;
function* g() { function* g() {
try { try {
throw new Error(); throw new Error();
} catch (e) { } catch (e) {
inCatch = true; inCatch += 1;
yield; 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 iter = g();
var result; var result;
result = iter.next(); result = iter.next();
assert.sameValue(inCatch, true); assert.sameValue(inCatch, 1);
result = iter.return(45); result = iter.return(45);
assert.sameValue( assert.sameValue(
result.value, 45, 'Result `value` following `return`' result.value, 45, 'Result `value` following `return`'
); );
assert.sameValue(result.done, true, 'Result `done` flag 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(); result = iter.next();
assert.sameValue( assert.sameValue(
@ -39,3 +45,6 @@ assert.sameValue(
assert.sameValue( assert.sameValue(
result.done, true, 'Result `done` flag is `true` when complete' result.done, true, 'Result `done` flag is `true` when complete'
); );
assert.sameValue(
unreachable, 0, 'statement following `yield` not executed (once "completed")'
);

View File

@ -8,27 +8,33 @@ description: >
statement had appeared at that location in the function body. statement had appeared at that location in the function body.
---*/ ---*/
var inTry = false; var inTry = 0;
var unreachable = 0;
function* g() { function* g() {
try { try {
inTry = true; inTry += 1;
yield; yield;
$ERROR('This code is unreachable (within `try` block)'); unreachable += 1;
} catch (e) { } catch (e) {
throw e; throw e;
} }
$ERROR('This code is unreachable (following `try` statement)'); unreachable += 1;
} }
var iter = g(); var iter = g();
var result; var result;
result = iter.next(); result = iter.next();
assert.sameValue(inTry, true); assert.sameValue(inTry, 1);
result = iter.return(44); result = iter.return(44);
assert.sameValue(result.value, 44, 'Result `value` following `return`'); assert.sameValue(result.value, 44, 'Result `value` following `return`');
assert.sameValue(result.done, true, 'Result `done` flag 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(); result = iter.next();
assert.sameValue( assert.sameValue(
@ -37,3 +43,6 @@ assert.sameValue(
assert.sameValue( assert.sameValue(
result.done, true, 'Result `done` flag is `true` when complete' result.done, true, 'Result `done` flag is `true` when complete'
); );
assert.sameValue(
unreachable, 0, 'statement following `yield` not executed (once "completed")'
);

View File

@ -8,23 +8,32 @@ description: >
that location in the function body. that location in the function body.
---*/ ---*/
var unreachable = 0;
function* g() { function* g() {
yield; yield;
unreachable += 1;
try { try {
$ERROR('This code is unreachable (within `try` block)');
} finally { } finally {
$ERROR('This code is unreachable (within `finally` block)');
} }
$ERROR('This code is unreachable (following `try` statement)');
} }
var iter = g(); var iter = g();
var result; var result;
iter.next(); iter.next();
assert.sameValue(
unreachable,
0,
'statement following `yield` not executed (paused at yield)'
);
result = iter.return(45); result = iter.return(45);
assert.sameValue(result.value, 45, 'Result `value` following `return`'); assert.sameValue(result.value, 45, 'Result `value` following `return`');
assert.sameValue(result.done, true, 'Result `done` flag 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(); result = iter.next();
assert.sameValue( assert.sameValue(
@ -33,3 +42,6 @@ assert.sameValue(
assert.sameValue( assert.sameValue(
result.done, true, 'Result `done` flag is `true` when complete' result.done, true, 'Result `done` flag is `true` when complete'
); );
assert.sameValue(
unreachable, 0, 'statement following `yield` not executed (once "completed")'
);

View File

@ -8,26 +8,37 @@ description: >
that location in the function body. that location in the function body.
---*/ ---*/
var afterFinally = false; var afterFinally = 0;
var unreachable = 0;
function* g() { function* g() {
try { try {
} finally {} } finally {}
afterFinally = true; afterFinally += 1;
yield; yield;
unreachable += 1;
} }
var iter = g(); var iter = g();
var result; var result;
iter.next(); iter.next();
assert.sameValue(afterFinally, true); assert.sameValue(afterFinally, 1);
result = iter.return(45); result = iter.return(45);
assert.sameValue(result.value, 45, 'Result `value` following `return`'); assert.sameValue(result.value, 45, 'Result `value` following `return`');
assert.sameValue(result.done, true, 'Result `done` flag 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(); result = iter.next();
assert.sameValue( assert.sameValue(
result.value, undefined, 'Result `value` is undefined when done' result.value, undefined, 'Result `value` is undefined when done'
); );
assert.sameValue(result.done, true, 'Result `done` flag is `true` 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")'
);

View File

@ -9,35 +9,41 @@ description: >
function body. function body.
---*/ ---*/
var inCatch = false; var inCatch = 0;
var inFinally = false; var inFinally = 0;
var unreachable = 0;
function* g() { function* g() {
try { try {
try { try {
throw new Error(); throw new Error();
} catch (e) { } catch (e) {
inCatch = true; inCatch += 1;
yield; yield;
$ERROR('This code is unreachable (within `catch` block)'); unreachable += 1;
} }
$ERROR('This code is unreachable (following nested `try` statement)'); unreachable += 1;
} finally { } finally {
inFinally = true; inFinally += 1;
} }
$ERROR('This code is unreachable (following outer `try` statement)'); unreachable += 1;
} }
var iter = g(); var iter = g();
var result; var result;
result = iter.next(); result = iter.next();
assert.sameValue(inCatch, true, '`catch` code patch executed'); assert.sameValue(inCatch, 1, '`catch` code patch executed');
assert.sameValue(inFinally, false, '`finally` code path not executed'); assert.sameValue(inFinally, 0, '`finally` code path not executed');
result = iter.return(45); result = iter.return(45);
assert.sameValue(result.value, 45, 'Result `value` following `return`'); assert.sameValue(result.value, 45, 'Result `value` following `return`');
assert.sameValue(result.done, true, 'Result `done` flag 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(); result = iter.next();
assert.sameValue( assert.sameValue(
@ -46,3 +52,6 @@ assert.sameValue(
assert.sameValue( assert.sameValue(
result.done, true, 'Result `done` flag is `true` when compelete' result.done, true, 'Result `done` flag is `true` when compelete'
); );
assert.sameValue(
unreachable, 0, 'statement following `yield` not executed (once "completed")'
);

View File

@ -8,30 +8,37 @@ description: >
statement had appeared at that location in the function body. statement had appeared at that location in the function body.
---*/ ---*/
var inFinally = false; var inFinally = 0;
var unreachable = 0;
function* g() { function* g() {
try { try {
throw new Error(); throw new Error();
try { try {
} catch (e) {} } catch (e) {}
} finally { } finally {
inFinally = true; inFinally += 1;
yield; 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 iter = g();
var result; var result;
result = iter.next(); result = iter.next();
assert.sameValue(inFinally, true, '`finally` code path executed'); assert.sameValue(inFinally, 1, '`finally` code path executed');
result = iter.return(45); result = iter.return(45);
assert.sameValue(result.value, 45, 'Result `value` following `return`'); assert.sameValue(result.value, 45, 'Result `value` following `return`');
assert.sameValue(result.done, true, 'Result `done` flag 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(); result = iter.next();
assert.sameValue( assert.sameValue(
result.value, undefined, 'Result `value` is undefined when complete' result.value, undefined, 'Result `value` is undefined when complete'
@ -39,3 +46,6 @@ assert.sameValue(
assert.sameValue( assert.sameValue(
result.done, true, 'Result `done` flag is `true` when complete' result.done, true, 'Result `done` flag is `true` when complete'
); );
assert.sameValue(
unreachable, 0, 'statement following `yield` not executed (once "completed")'
);

View File

@ -9,37 +9,43 @@ description: >
function body. function body.
---*/ ---*/
var inTry = false; var inTry = 0;
var inFinally = false; var inFinally = 0;
var unreachable = 0;
function* g() { function* g() {
try { try {
try { try {
inTry = true; inTry += 1;
yield; yield;
$ERROR('This code is unreachable (within nested `try` block)'); unreachable += 1;
} catch (e) { } catch (e) {
throw e; throw e;
} }
$ERROR('This code is unreachable (following nested `try` statement)'); unreachable += 1;
} finally { } finally {
inFinally = true; inFinally += 1;
} }
$ERROR('This code is unreachable (following outer `try` statement)'); unreachable += 1;
} }
var iter = g(); var iter = g();
var exception = new Error();
var result; var result;
iter.next(); iter.next();
assert.sameValue(inTry, true, 'Nested `try` code patch executed'); assert.sameValue(inTry, 1, 'Nested `try` code patch executed');
assert.sameValue(inFinally, false, '`finally` code path not executed'); assert.sameValue(inFinally, 0, '`finally` code path not executed');
result = iter.return(45); result = iter.return(45);
assert.sameValue(result.value, 45, 'Result `value` following `return`'); assert.sameValue(result.value, 45, 'Result `value` following `return`');
assert.sameValue(result.done, true, 'Result `done` flag 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(); result = iter.next();
assert.sameValue( assert.sameValue(
@ -48,3 +54,6 @@ assert.sameValue(
assert.sameValue( assert.sameValue(
result.done, true, 'Result `done` flag is `true` when complete' result.done, true, 'Result `done` flag is `true` when complete'
); );
assert.sameValue(
unreachable, 0, 'statement following `yield` not executed (once "completed")'
);

View File

@ -9,33 +9,40 @@ description: >
the function body. the function body.
---*/ ---*/
var inCatch = false; var inCatch = 0;
var inFinally = false; var inFinally = 0;
var unreachable = 0;
function* g() { function* g() {
try { try {
try { try {
throw new Error(); throw new Error();
} catch (e) { } catch (e) {
inCatch = true; inCatch += 1;
} }
} finally { } finally {
inFinally = true; inFinally += 1;
} }
yield; yield;
$ERROR('This code is unreachable'); unreachable += 1;
} }
var iter = g(); var iter = g();
var result; var result;
iter.next(); iter.next();
assert.sameValue(inCatch, true, '`catch` code path executed'); assert.sameValue(inCatch, 1, '`catch` code path executed');
assert.sameValue(inFinally, true, '`finally` code path executed'); assert.sameValue(inFinally, 1, '`finally` code path executed');
result = iter.return(45); result = iter.return(45);
assert.sameValue(result.value, 45, 'Result `value` following `return`'); assert.sameValue(result.value, 45, 'Result `value` following `return`');
assert.sameValue(result.done, true, 'Result `done` flag 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(); result = iter.next();
assert.sameValue( assert.sameValue(
result.value, undefined, 'Result `value` is undefined when complete' result.value, undefined, 'Result `value` is undefined when complete'
@ -43,3 +50,6 @@ assert.sameValue(
assert.sameValue( assert.sameValue(
result.done, true, 'Result `done` flag is `true` when complete' result.done, true, 'Result `done` flag is `true` when complete'
); );
assert.sameValue(
unreachable, 0, 'statement following `yield` not executed (once "completed")'
);

View File

@ -9,35 +9,42 @@ description: >
the function body. the function body.
---*/ ---*/
var inTry = false; var inTry = 0;
var inFinally = false; var inFinally = 0;
var unreachable = 0;
function* g() { function* g() {
try { try {
inTry = true; inTry += 1;
yield; yield;
try { try {
$ERROR('This code is unreachable (within nested `try` block)'); unreachable += 1;
} catch (e) { } catch (e) {
throw e; throw e;
} }
$ERROR('This code is unreacahable (following nested `try` statement)'); unreachable += 1;
} finally { } finally {
inFinally = true; inFinally += 1;
} }
$ERROR('This codeis unreachable (following outer `try` statement)'); unreachable += 1;
} }
var iter = g(); var iter = g();
var result; var result;
iter.next(); iter.next();
assert.sameValue(inTry, true, '`try` code path executed'); assert.sameValue(inTry, 1, '`try` code path executed');
assert.sameValue(inFinally, false, '`finally` code path not executed'); assert.sameValue(inFinally, 0, '`finally` code path not executed');
result = iter.return(45); result = iter.return(45);
assert.sameValue(result.value, 45, 'Second result `value`'); assert.sameValue(result.value, 45, 'Second result `value`');
assert.sameValue(result.done, true, 'Second result `done` flag'); 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(); result = iter.next();
assert.sameValue( assert.sameValue(
@ -46,3 +53,6 @@ assert.sameValue(
assert.sameValue( assert.sameValue(
result.done, true, 'Result `done` flag is `true` when complete' result.done, true, 'Result `done` flag is `true` when complete'
); );
assert.sameValue(
unreachable, 0, 'statement following `yield` not executed (once "completed")'
);

View File

@ -8,27 +8,34 @@ description: >
statement had appeared at that location in the function body. statement had appeared at that location in the function body.
---*/ ---*/
var inFinally = true; var inFinally = 0;
var unreachable = 0;
function* g() { function* g() {
try { try {
} finally { } finally {
inFinally = true; inFinally += 1;
yield; 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 iter = g();
var result; var result;
iter.next(); iter.next();
assert.sameValue(inFinally, true, '`finally` code path executed'); assert.sameValue(inFinally, 1, '`finally` code path executed');
result = iter.return(45); result = iter.return(45);
assert.sameValue(result.value, 45, 'Result `value` following `return`'); assert.sameValue(result.value, 45, 'Result `value` following `return`');
assert.sameValue(result.done, true, 'Result `done` flag 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(); result = iter.next();
assert.sameValue( assert.sameValue(
result.value, undefined, 'Result `value` is undefined when complete' result.value, undefined, 'Result `value` is undefined when complete'
@ -36,3 +43,6 @@ assert.sameValue(
assert.sameValue( assert.sameValue(
result.done, true, 'Result `done` flag is `true` when complete' result.done, true, 'Result `done` flag is `true` when complete'
); );
assert.sameValue(
unreachable, 0, 'statement following `yield` not executed (once "completed")'
);

View File

@ -8,30 +8,37 @@ description: >
statement had appeared at that location in the function body. statement had appeared at that location in the function body.
---*/ ---*/
var inTry = false; var inTry = 0;
var inFinally = false; var inFinally = 0;
var unreachable = 0;
function* g() { function* g() {
try { try {
inTry = true; inTry += 1;
yield; yield;
$ERROR('This code is unreachable (within `try` block)'); unreachable += 1;
} finally { } finally {
inFinally = true; inFinally += 1;
} }
$ERROR('This code is unreachable (following `try` statement)'); unreachable += 1;
} }
var iter = g(); var iter = g();
var result; var result;
iter.next(); iter.next();
assert.sameValue(inTry, true, '`try` block code path executed'); assert.sameValue(inTry, 1, '`try` block code path executed');
assert.sameValue(inFinally, false, '`finally` code path not executed'); assert.sameValue(inFinally, 0, '`finally` code path not executed');
result = iter.return(45); result = iter.return(45);
assert.sameValue(result.value, 45, 'Result `value` following `return`'); assert.sameValue(result.value, 45, 'Result `value` following `return`');
assert.sameValue(result.done, true, 'Result `done` flag 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(); result = iter.next();
assert.sameValue( assert.sameValue(
@ -40,3 +47,6 @@ assert.sameValue(
assert.sameValue( assert.sameValue(
result.done, true, 'Result `done` flag is `true` when complete' result.done, true, 'Result `done` flag is `true` when complete'
); );
assert.sameValue(
unreachable, 0, 'statement following `yield` not executed (once "completed")'
);

View File

@ -1,13 +1,41 @@
// Copyright (C) 2013 the V8 project authors. All rights reserved. // Copyright (C) 2013 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file. // This code is governed by the BSD license found in the LICENSE file.
/*--- /*---
esid: sec-generatorvalidate
es6id: 25.3.3.2 es6id: 25.3.3.2
description: > description: >
A TypeError should be thrown if the generator is resumed abruptly while A TypeError should be thrown if the generator is in the "executing" state,
running. 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() { function* g() {
iter.throw(42); iter.throw(42);
} }
@ -16,3 +44,9 @@ iter = g();
assert.throws(TypeError, function() { assert.throws(TypeError, function() {
iter.next(); iter.next();
}); });
result = iter.next();
assert.sameValue(typeof result, 'object');
assert.sameValue(result.value, undefined);
assert.sameValue(result.done, true);

View File

@ -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); });

View File

@ -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)'
);

View File

@ -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)'
);

View File

@ -8,8 +8,10 @@ description: >
location in the function body. location in the function body.
---*/ ---*/
var unreachable = 0;
function* g() { function* g() {
yield 1; yield 1;
unreachable += 1;
try { try {
yield 2; yield 2;
} catch (e) { } catch (e) {
@ -17,19 +19,32 @@ function* g() {
} }
yield 3; yield 3;
} }
var iter, result, exception; var iter, result;
iter = g(); iter = g();
result = iter.next(); result = iter.next();
assert.sameValue(result.value, 1, 'First result `value`'); assert.sameValue(result.value, 1, 'First result `value`');
assert.sameValue(result.done, false, 'First result `done` flag'); 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.throws(Test262Error, function() { iter.throw(new Test262Error()); });
assert.sameValue(
unreachable,
0,
'statement following `yield` not executed (following `throw`)'
);
result = iter.next(); result = iter.next();
assert.sameValue(result.value, assert.sameValue(result.value,
undefined, 'Result `value` is undefined when done' undefined, 'Result `value` is undefined when done'
); );
assert.sameValue(result.done, true, 'Result `done` flag is `true` 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(); iter.next();

View File

@ -9,6 +9,7 @@ description: >
---*/ ---*/
var obj = {}; var obj = {};
var unreachable = 0;
function* g() { function* g() {
yield 1; yield 1;
try { try {
@ -18,6 +19,7 @@ function* g() {
yield e; yield e;
} }
yield 3; yield 3;
unreachable += 1;
} }
var iter, result; 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.throws(Test262Error, function() { iter.throw(new Test262Error()); });
assert.sameValue(
unreachable,
0,
'statement following `yield` not executed (following `throw`)'
);
result = iter.next(); result = iter.next();
assert.sameValue( assert.sameValue(
result.value, undefined, 'Result `value` is undefined when done' result.value, undefined, 'Result `value` is undefined when done'
); );
assert.sameValue(result.done, true, 'Result `done` flag is `true` 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(); iter.next();

View File

@ -8,6 +8,7 @@ description: >
had appeared at that location in the function body. had appeared at that location in the function body.
---*/ ---*/
var unreachable = 0;
function* g() { function* g() {
yield 1; yield 1;
try { try {
@ -15,6 +16,7 @@ function* g() {
throw exception; throw exception;
} catch (e) { } catch (e) {
yield e; yield e;
unreachable += 1;
} }
yield 3; yield 3;
} }
@ -35,15 +37,21 @@ result = iter.next();
assert.sameValue(result.value, exception, 'Third result `value`'); assert.sameValue(result.value, exception, 'Third result `value`');
assert.sameValue(result.done, false, 'Third result `done` flag'); 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.throws(Test262Error, function() { iter.throw(new Test262Error()); });
assert.sameValue(
unreachable,
0,
'statement following `yield` not executed (following `throw`)'
);
result = iter.next(); result = iter.next();
assert.sameValue( assert.sameValue(
result.value, undefined, 'Result `value` is undefined when done' result.value, undefined, 'Result `value` is undefined when done'
); );
assert.sameValue(result.done, true, 'Result `done` flag is `true` 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(); iter.next();

View File

@ -8,10 +8,12 @@ description: >
had appeared at that location in the function body. had appeared at that location in the function body.
---*/ ---*/
var unreachable = 0;
function* g() { function* g() {
yield 1; yield 1;
try { try {
yield 2; yield 2;
unreachable += 1;
} catch (e) { } catch (e) {
yield e; yield e;
} }
@ -34,14 +36,28 @@ result = iter.throw(exception);
assert.sameValue(result.value, exception, 'Third result `value`'); assert.sameValue(result.value, exception, 'Third result `value`');
assert.sameValue(result.done, false, 'Third result `done` flag'); assert.sameValue(result.done, false, 'Third result `done` flag');
assert.sameValue(
unreachable,
0,
'statement following `yield` not executed (following `throw`)'
);
result = iter.next(); result = iter.next();
assert.sameValue(result.value, 3, 'Fourth result `done` flag'); assert.sameValue(result.value, 3, 'Fourth result `done` flag');
assert.sameValue(result.done, false, 'Fourth result `value`'); assert.sameValue(result.done, false, 'Fourth result `value`');
assert.sameValue(
unreachable,
0,
'statement following `yield` not executed (following `catch`)'
);
result = iter.next(); result = iter.next();
assert.sameValue( assert.sameValue(
result.value, undefined, 'Result `value` is undefined when done' result.value, undefined, 'Result `value` is undefined when done'
); );
assert.sameValue(result.done, true, 'Result `done` flag is `true` 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(); iter.next();

View File

@ -8,8 +8,10 @@ description: >
that location in the function body. that location in the function body.
---*/ ---*/
var unreachable = 0;
function* g() { function* g() {
yield 1; yield 1;
unreachable += 1;
try { try {
yield 2; yield 2;
} finally { } finally {
@ -26,13 +28,25 @@ assert.sameValue(result.value, 1, 'First result `value`');
assert.sameValue( assert.sameValue(
result.done, false, 'First result `done` flag' 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.throws(Test262Error, function() { iter.throw(new Test262Error()); });
assert.sameValue(
unreachable,
0,
'statement following `yield` not executed (following `throw`)'
);
result = iter.next(); result = iter.next();
assert.sameValue( assert.sameValue(
result.value, undefined, 'Result `value` is undefined when done' result.value, undefined, 'Result `value` is undefined when done'
); );
assert.sameValue( result.done, true, 'Result `done` flag is `true` 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(); iter.next();

View File

@ -8,6 +8,7 @@ description: >
location in the function body. location in the function body.
---*/ ---*/
var unreachable = 0;
function* g() { function* g() {
yield 1; yield 1;
try { try {
@ -16,7 +17,7 @@ function* g() {
yield 3; yield 3;
} }
yield 4; yield 4;
$ERROR('This code is unreachable'); unreachable += 1;
} }
var iter = g(); var iter = g();
var result; var result;
@ -39,10 +40,19 @@ assert.sameValue(result.done, false, 'Third result `done` flag');
assert.throws(Test262Error, function() { iter.throw(new Test262Error()); }); assert.throws(Test262Error, function() { iter.throw(new Test262Error()); });
assert.sameValue(
unreachable,
0,
'statement following `yield` not executed (following `throw`)'
);
result = iter.next(); result = iter.next();
assert.sameValue( assert.sameValue(
result.value, undefined, 'Result `value` is undefined when done' result.value, undefined, 'Result `value` is undefined when done'
); );
assert.sameValue(result.done, true, 'Result `done` flag is `true` 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(); iter.next();

View File

@ -9,6 +9,7 @@ description: >
function body. function body.
---*/ ---*/
var unreachable = 0;
function* g() { function* g() {
try { try {
yield 1; yield 1;
@ -17,6 +18,7 @@ function* g() {
throw exception; throw exception;
} catch (e) { } catch (e) {
yield e; yield e;
unreachable += 1;
} }
yield 3; yield 3;
} finally { } finally {
@ -46,10 +48,19 @@ assert.sameValue(result.done, false, 'Fourth result `done` flag');
assert.throws(Test262Error, function() { iter.next(); }); assert.throws(Test262Error, function() { iter.next(); });
assert.sameValue(
unreachable,
0,
'statement following `yield` not executed (following `throw`)'
);
result = iter.next(); result = iter.next();
assert.sameValue( assert.sameValue(
result.value, undefined, 'Result `value` is undefined when done' result.value, undefined, 'Result `value` is undefined when done'
); );
assert.sameValue(result.done, true, 'Result `done` flag is `true` 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(); iter.next();

View File

@ -8,6 +8,7 @@ description: >
had appeared at that location in the function body. had appeared at that location in the function body.
---*/ ---*/
var unreachable = 0;
function* g() { function* g() {
try { try {
yield 1; yield 1;
@ -20,7 +21,9 @@ function* g() {
yield 3; yield 3;
} finally { } finally {
yield 4; yield 4;
unreachable += 1;
} }
unreachable += 1;
yield 5; yield 5;
} }
var iter = g(); 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.throws(Test262Error, function() { iter.throw(new Test262Error()); });
assert.sameValue(
unreachable,
0,
'statement following `yield` not executed (following `throw`)'
);
result = iter.next(); result = iter.next();
assert.sameValue( assert.sameValue(
result.value, undefined, 'Result `value` is undefined when done' result.value, undefined, 'Result `value` is undefined when done'
); );
assert.sameValue(result.done, true, 'Result `done` flag is `true` 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(); iter.next();

View File

@ -9,11 +9,13 @@ description: >
function body. function body.
---*/ ---*/
var unreachable = 0;
function* g() { function* g() {
try { try {
yield 1; yield 1;
try { try {
yield 2; yield 2;
unreachable += 1;
} catch (e) { } catch (e) {
yield e; yield e;
} }
@ -39,6 +41,12 @@ result = iter.throw(exception);
assert.sameValue(result.value, exception, 'Third result `value`'); assert.sameValue(result.value, exception, 'Third result `value`');
assert.sameValue(result.done, false, 'Third result `done` flag'); assert.sameValue(result.done, false, 'Third result `done` flag');
assert.sameValue(
unreachable,
0,
'statement following `yield` not executed (following `throw`)'
);
result = iter.next(); result = iter.next();
assert.sameValue(result.value, 3, 'Fourth result `value'); assert.sameValue(result.value, 3, 'Fourth result `value');
assert.sameValue(result.done, false, 'Fourth result `done` flag'); assert.sameValue(result.done, false, 'Fourth result `done` flag');
@ -56,5 +64,8 @@ assert.sameValue(
result.value, undefined, 'Result `value` is undefined when done' result.value, undefined, 'Result `value` is undefined when done'
); );
assert.sameValue(result.done, true, 'Result `done` flag is `true` 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(); iter.next();

View File

@ -9,6 +9,7 @@ description: >
function body. function body.
---*/ ---*/
var unreachable = 0;
function* g() { function* g() {
try { try {
yield 1; yield 1;
@ -19,6 +20,7 @@ function* g() {
yield e; yield e;
} }
yield 3; yield 3;
unreachable += 1;
} finally { } finally {
yield 4; yield 4;
} }
@ -48,6 +50,12 @@ result = iter.throw(new Test262Error());
assert.sameValue(result.value, 4, 'Fifth result `value`'); assert.sameValue(result.value, 4, 'Fifth result `value`');
assert.sameValue(result.done, false, 'Fifth result `done` flag'); 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(); }); assert.throws(Test262Error, function() { iter.next(); });
result = iter.next(); result = iter.next();
@ -55,5 +63,8 @@ assert.sameValue(
result.value, undefined, 'Result `value` is undefined when done' result.value, undefined, 'Result `value` is undefined when done'
); );
assert.sameValue(result.done, true, 'Result `done` flag is `true` 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(); iter.next();

View File

@ -9,9 +9,11 @@ description: >
function body. function body.
---*/ ---*/
var unreachable = 0;
function* g() { function* g() {
try { try {
yield 1; yield 1;
unreachable += 1;
try { try {
yield 2; yield 2;
} catch (e) { } catch (e) {
@ -34,6 +36,12 @@ result = iter.throw(new Test262Error());
assert.sameValue(result.value, 4, 'Second result `value`'); assert.sameValue(result.value, 4, 'Second result `value`');
assert.sameValue(result.done, false, 'Second result `done` flag'); 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(); }); assert.throws(Test262Error, function() { iter.next(); });
result = iter.next(); result = iter.next();
@ -41,5 +49,8 @@ assert.sameValue(
result.value, undefined, 'Result `value` is undefined when done' result.value, undefined, 'Result `value` is undefined when done'
); );
assert.sameValue(result.done, true, 'Result `done` flag is `true` 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(); iter.next();

View File

@ -8,12 +8,14 @@ description: >
had appeared at that location in the function body. had appeared at that location in the function body.
---*/ ---*/
var unreachable = 0;
function* g() { function* g() {
yield 1; yield 1;
try { try {
yield 2; yield 2;
} finally { } finally {
yield 3; yield 3;
unreachable += 1;
} }
yield 4; yield 4;
} }
@ -32,16 +34,21 @@ result = iter.next();
assert.sameValue(result.value, 3, 'Third result `value`'); assert.sameValue(result.value, 3, 'Third result `value`');
assert.sameValue(result.done, false, 'Third result `done` flag'); 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.throws(Test262Error, function() { iter.throw(new Test262Error()); });
assert.sameValue(
unreachable,
0,
'statement following `yield` not executed (following `throw`)'
);
result = iter.next(); result = iter.next();
assert.sameValue( assert.sameValue(
result.value, undefined, 'Result `value` is undefined when done' result.value, undefined, 'Result `value` is undefined when done'
); );
assert.sameValue(result.done, true, 'Result `done` flag is `true` 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(); iter.next();

View File

@ -8,10 +8,12 @@ description: >
had appeared at that location in the function body. had appeared at that location in the function body.
---*/ ---*/
var unreachable = 0;
function* g() { function* g() {
yield 1; yield 1;
try { try {
yield 2; yield 2;
unreachable += 1;
} finally { } finally {
yield 3; yield 3;
} }
@ -28,16 +30,25 @@ result = iter.next();
assert.sameValue(result.value, 2, 'Second result `value`'); assert.sameValue(result.value, 2, 'Second result `value`');
assert.sameValue(result.done, false, 'Second result `done` flag'); 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.value, 3, 'Third result `value`');
assert.sameValue(result.done, false, 'Third result `done` flag'); 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(); result = iter.next();
assert.sameValue( assert.sameValue(
result.value, undefined, 'Result `value` is undefined when done' result.value, undefined, 'Result `value` is undefined when done'
); );
assert.sameValue(result.done, true, 'Result `done` flag is `true` 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(); iter.next();