mirror of https://github.com/tc39/test262.git
Improve coverage for YieldExpression (#681)
* Re-organize coverage for YieldExpression * Extend test coverge for YieldExpression * fixup! Extend test coverge for YieldExpression Remove unused variables
This commit is contained in:
parent
720c3cc8cc
commit
c9569a7e7e
|
@ -1,115 +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.
|
||||
|
||||
/*---
|
||||
description: >
|
||||
`yield` is a valid expression within generator function bodies.
|
||||
es6id: 14.4
|
||||
---*/
|
||||
|
||||
var result, iter;
|
||||
var g1 = function*() { (yield 1) };
|
||||
var g2 = function*() { [yield 1] };
|
||||
var g3 = function*() { {yield 1} };
|
||||
var g4 = function*() { yield 1, yield 2; };
|
||||
var g5 = function*() { (yield 1) ? yield 2 : yield 3; };
|
||||
|
||||
iter = g1();
|
||||
result = iter.next();
|
||||
assert.sameValue(result.value, 1, 'Within grouping operator: result `value`');
|
||||
assert.sameValue(
|
||||
result.done, false, 'Within grouping operator: result `done` flag'
|
||||
);
|
||||
result = iter.next();
|
||||
assert.sameValue(
|
||||
result.value, undefined, 'Following grouping operator: result `value`'
|
||||
);
|
||||
assert.sameValue(
|
||||
result.done, true, 'Following grouping operator: result `done` flag'
|
||||
);
|
||||
|
||||
iter = g2();
|
||||
result = iter.next();
|
||||
assert.sameValue(result.value, 1, 'Within array literal: result `value`');
|
||||
assert.sameValue(
|
||||
result.done, false, 'Within array literal: result `done` flag'
|
||||
);
|
||||
result = iter.next();
|
||||
assert.sameValue(
|
||||
result.value, undefined, 'Following array literal: result `value`'
|
||||
);
|
||||
assert.sameValue(
|
||||
result.done, true, 'Following array literal: result `done` flag'
|
||||
);
|
||||
|
||||
iter = g3();
|
||||
result = iter.next();
|
||||
assert.sameValue(result.value, 1, 'Within object literal: result `value`');
|
||||
assert.sameValue(
|
||||
result.done, false, 'Within object literal: result `done` flag'
|
||||
);
|
||||
result = iter.next();
|
||||
assert.sameValue(
|
||||
result.value, undefined, 'Following object literal: result `value`'
|
||||
);
|
||||
assert.sameValue(
|
||||
result.done, true, 'Following object literal: result `done` flag'
|
||||
);
|
||||
|
||||
iter = g4();
|
||||
result = iter.next();
|
||||
assert.sameValue(
|
||||
result.value, 1, 'First expression in comma expression: result `value`'
|
||||
);
|
||||
assert.sameValue(
|
||||
result.done,
|
||||
false,
|
||||
'First expression in comma expression: result `done` flag'
|
||||
);
|
||||
result = iter.next();
|
||||
assert.sameValue(
|
||||
result.value, 2, 'Second expression in comma expression: result `value`'
|
||||
);
|
||||
assert.sameValue(
|
||||
result.done,
|
||||
false,
|
||||
'Second expression in comma expression: result `done` flag'
|
||||
);
|
||||
result = iter.next();
|
||||
assert.sameValue(
|
||||
result.value, undefined, 'Following comma expression: result `value`'
|
||||
);
|
||||
assert.sameValue(
|
||||
result.done, true, 'Following comma expression: result `done` flag'
|
||||
);
|
||||
|
||||
iter = g5();
|
||||
result = iter.next();
|
||||
assert.sameValue(
|
||||
result.value,
|
||||
1,
|
||||
'Conditional expression in conditional operator: result `value`'
|
||||
);
|
||||
assert.sameValue(
|
||||
result.done,
|
||||
false,
|
||||
'Conditional expression in conditional operator: result `done` flag'
|
||||
);
|
||||
result = iter.next();
|
||||
assert.sameValue(
|
||||
result.value,
|
||||
3,
|
||||
'Branch in conditional operator: result `value`'
|
||||
);
|
||||
assert.sameValue(
|
||||
result.done,
|
||||
false,
|
||||
'Branch in conditional operator: result `done` flag'
|
||||
);
|
||||
result = iter.next();
|
||||
assert.sameValue(
|
||||
result.value, undefined, 'Following conditional operator: result `value`'
|
||||
);
|
||||
assert.sameValue(
|
||||
result.done, true, 'Following conditional operator: result `done` flag'
|
||||
);
|
|
@ -1,125 +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.
|
||||
|
||||
/*---
|
||||
description: >
|
||||
`yield` is a valid expression within generator function bodies.
|
||||
es6id: 14.4
|
||||
---*/
|
||||
|
||||
var iter, result;
|
||||
var g1 = function*() { (yield) };
|
||||
var g2 = function*() { [yield] };
|
||||
var g3 = function*() { {yield} };
|
||||
var g4 = function*() { yield, yield; };
|
||||
var g5 = function*() { (yield) ? yield : yield; };
|
||||
|
||||
iter = g1();
|
||||
result = iter.next();
|
||||
assert.sameValue(
|
||||
result.value, undefined, 'Within grouping operator: result `value`'
|
||||
);
|
||||
assert.sameValue(
|
||||
result.done, false, 'Within grouping operator: result `done` flag'
|
||||
);
|
||||
result = iter.next();
|
||||
assert.sameValue(
|
||||
result.value, undefined, 'Following grouping operator: result `value`'
|
||||
);
|
||||
assert.sameValue(
|
||||
result.done, true, 'Following grouping operator: result `done` flag'
|
||||
);
|
||||
|
||||
iter = g2();
|
||||
result = iter.next();
|
||||
assert.sameValue(
|
||||
result.value, undefined, 'Within array literal: result `value`'
|
||||
);
|
||||
assert.sameValue(
|
||||
result.done, false, 'Within array literal: result `done` flag'
|
||||
);
|
||||
result = iter.next();
|
||||
assert.sameValue(
|
||||
result.value, undefined, 'Following array literal: result `value`'
|
||||
);
|
||||
assert.sameValue(
|
||||
result.done, true, 'Following array literal: result `done` flag'
|
||||
);
|
||||
|
||||
iter = g3();
|
||||
result = iter.next();
|
||||
assert.sameValue(
|
||||
result.value, undefined, 'Within object literal: result `value`'
|
||||
);
|
||||
assert.sameValue(
|
||||
result.done, false, 'Within object literal: result `done` flag'
|
||||
);
|
||||
result = iter.next();
|
||||
assert.sameValue(
|
||||
result.value, undefined, 'Following object literal: result `value`'
|
||||
);
|
||||
assert.sameValue(
|
||||
result.done, true, 'Following object literal: result `done` flag'
|
||||
);
|
||||
|
||||
iter = g4();
|
||||
result = iter.next();
|
||||
assert.sameValue(
|
||||
result.value,
|
||||
undefined,
|
||||
'First expression in comma expression: result `value`'
|
||||
);
|
||||
assert.sameValue(
|
||||
result.done,
|
||||
false,
|
||||
'First expression in comma expression: result `done` flag'
|
||||
);
|
||||
result = iter.next();
|
||||
assert.sameValue(
|
||||
result.value,
|
||||
undefined,
|
||||
'Second expression in comma expression: result `value`'
|
||||
);
|
||||
assert.sameValue(
|
||||
result.done,
|
||||
false,
|
||||
'Second expression in comma expression: result `done` flag'
|
||||
);
|
||||
result = iter.next();
|
||||
assert.sameValue(
|
||||
result.value, undefined, 'Following comma expression: result `value`'
|
||||
);
|
||||
assert.sameValue(
|
||||
result.done, true, 'Following comma expression: result `done` flag'
|
||||
);
|
||||
|
||||
iter = g5();
|
||||
result = iter.next();
|
||||
assert.sameValue(
|
||||
result.value,
|
||||
undefined,
|
||||
'Conditional expression in conditional operator: result `value`'
|
||||
);
|
||||
assert.sameValue(
|
||||
result.done,
|
||||
false,
|
||||
'Conditional expression in conditional operator: result `done` flag'
|
||||
);
|
||||
result = iter.next();
|
||||
assert.sameValue(
|
||||
result.value,
|
||||
undefined,
|
||||
'Branch in conditional operator: result `value`'
|
||||
);
|
||||
assert.sameValue(
|
||||
result.done,
|
||||
false,
|
||||
'Branch in conditional operator: result `done` flag'
|
||||
);
|
||||
result = iter.next();
|
||||
assert.sameValue(
|
||||
result.value, undefined, 'Following conditional operator: result `value`'
|
||||
);
|
||||
assert.sameValue(
|
||||
result.done, true, 'Following conditional operator: result `done` flag'
|
||||
);
|
|
@ -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-generator-function-definitions
|
||||
es6id: 14.4
|
||||
description: >
|
||||
YieldExpression operand may not include the `in` keyword in contexts where it
|
||||
is disallowed
|
||||
info: |
|
||||
Syntax
|
||||
|
||||
yield [no LineTerminator here] AssignmentExpression[?In, +Yield]
|
||||
negative: SyntaxError
|
||||
---*/
|
||||
|
||||
function* g() {
|
||||
for (yield '' in {}; ; ) ;
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
// Copyright (C) 2016 the V8 project authors. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
/*---
|
||||
esid: sec-generator-function-definitions
|
||||
es6id: 14.4
|
||||
description: >
|
||||
YieldExpression contextually recognizes the `in` keyword as part of a
|
||||
RelationalExpression
|
||||
info: |
|
||||
Syntax
|
||||
|
||||
yield [no LineTerminator here] AssignmentExpression[?In, +Yield]
|
||||
---*/
|
||||
|
||||
var obj = Object.create(null);
|
||||
var iter, iterResult, value;
|
||||
function* g() {
|
||||
value = yield 'hit' in obj;
|
||||
value = yield 'miss' in obj;
|
||||
}
|
||||
obj.hit = true;
|
||||
|
||||
iter = g();
|
||||
|
||||
iterResult = iter.next('first');
|
||||
|
||||
assert.sameValue(iterResult.done, false, '`done` property (first iteration)');
|
||||
assert.sameValue(iterResult.value, true, '`value` property (first iteration)');
|
||||
assert.sameValue(
|
||||
value, undefined, 'generator paused prior to evaluating AssignmentExpression'
|
||||
);
|
||||
|
||||
iterResult = iter.next('second');
|
||||
|
||||
assert.sameValue(iterResult.done, false, '`done` property (second iteration)');
|
||||
assert.sameValue(
|
||||
iterResult.value, false, '`value` property (second iteration)'
|
||||
);
|
||||
assert.sameValue(value, 'second', 'value of first AssignmentExpression');
|
||||
|
||||
iterResult = iter.next('third');
|
||||
|
||||
assert.sameValue(iterResult.done, true, '`done` property (third iteration)');
|
||||
assert.sameValue(
|
||||
iterResult.value, undefined, '`value` property (third iteration)'
|
||||
);
|
||||
assert.sameValue(value, 'third', 'value of second AssignmentExpression');
|
|
@ -0,0 +1,39 @@
|
|||
// Copyright (C) 2016 the V8 project authors. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
/*---
|
||||
esid: sec-generator-function-definitions-runtime-semantics-evaluation
|
||||
es6id: 14.4.14
|
||||
description: >
|
||||
Iteration protocol is not initiated for non-delegating YieldExpression
|
||||
info: |
|
||||
YieldExpression:yieldAssignmentExpression
|
||||
|
||||
1. Let exprRef be the result of evaluating AssignmentExpression.
|
||||
2. Let value be ? GetValue(exprRef).
|
||||
3. Return ? GeneratorYield(CreateIterResultObject(value, false)).
|
||||
features: [Symbol.iterator]
|
||||
---*/
|
||||
|
||||
var callCount = 0;
|
||||
var iterSpy = Object.defineProperty({}, Symbol.iterator, {
|
||||
get: function() {
|
||||
callCount += 1;
|
||||
}
|
||||
});
|
||||
function* g() {
|
||||
yield iterSpy;
|
||||
}
|
||||
var iter = g();
|
||||
var result;
|
||||
|
||||
result = iter.next();
|
||||
|
||||
assert.sameValue(result.value, iterSpy);
|
||||
assert.sameValue(result.done, false);
|
||||
assert.sameValue(callCount, 0);
|
||||
|
||||
result = iter.next();
|
||||
|
||||
assert.sameValue(result.value, undefined);
|
||||
assert.sameValue(result.done, true);
|
||||
assert.sameValue(callCount, 0);
|
|
@ -0,0 +1,42 @@
|
|||
// Copyright (C) 2016 the V8 project authors. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
/*---
|
||||
esid: sec-generator-function-definitions
|
||||
es6id: 14.4
|
||||
description: >
|
||||
YieldExpression accepts a regular expression literal as its right-hand side
|
||||
info: >
|
||||
The syntactic context immediately following yield requires use of the
|
||||
InputElementRegExpOrTemplateTail lexical goal.
|
||||
---*/
|
||||
|
||||
var complete = false;
|
||||
var sent = {};
|
||||
var iter, iterResult, received;
|
||||
// Unused variables declared to improve error messages in incorrect parsing
|
||||
// scenarios.
|
||||
var abc, i;
|
||||
function* g() {
|
||||
received = yield/abc/i;
|
||||
complete = true;
|
||||
}
|
||||
|
||||
iter = g();
|
||||
|
||||
assert.sameValue(complete, false, 'generator initially paused');
|
||||
assert.sameValue(received, undefined, 'first statement no executed');
|
||||
|
||||
iterResult = iter.next();
|
||||
|
||||
assert.sameValue(complete, false, 'generator paused following expression');
|
||||
assert.sameValue(received, undefined, 'first statement not executed');
|
||||
|
||||
assert.sameValue(iterResult.done, false, 'iteration not complete');
|
||||
assert.sameValue(iterResult.value.test('ABC'), true, 'first iterated value');
|
||||
|
||||
iterResult = iter.next(sent);
|
||||
|
||||
assert.sameValue(received, sent, 'YieldExpression value');
|
||||
assert.sameValue(complete, true, 'generator correctly re-started');
|
||||
assert.sameValue(iterResult.done, true, 'iteration complete');
|
||||
assert.sameValue(iterResult.value, undefined, 'second iterated value');
|
|
@ -0,0 +1,37 @@
|
|||
// Copyright (C) 2016 the V8 project authors. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
/*---
|
||||
esid: sec-generator-function-definitions
|
||||
es6id: 14.4
|
||||
description: YieldExpression may be followed by a TemplateMiddle construct
|
||||
info: >
|
||||
The syntactic context immediately following yield requires use of the
|
||||
InputElementRegExpOrTemplateTail lexical goal.
|
||||
---*/
|
||||
|
||||
var complete = false;
|
||||
var iter, iterResult, str;
|
||||
function* g() {
|
||||
str = `1${ yield }3${ 4 }5`;
|
||||
complete = true;
|
||||
}
|
||||
|
||||
iter = g();
|
||||
|
||||
assert.sameValue(complete, false, 'generator initially paused');
|
||||
assert.sameValue(str, undefined, 'first statement not executed');
|
||||
|
||||
iterResult = iter.next();
|
||||
|
||||
assert.sameValue(complete, false, 'generator paused following expression');
|
||||
assert.sameValue(str, undefined, 'first statement not executed');
|
||||
|
||||
assert.sameValue(iterResult.done, false, 'iteration not complete');
|
||||
assert.sameValue(iterResult.value, undefined, 'first iterated value');
|
||||
|
||||
iterResult = iter.next(2);
|
||||
|
||||
assert.sameValue(str, '12345', 'YieldExpression value');
|
||||
assert.sameValue(complete, true, 'generator correctly re-started');
|
||||
assert.sameValue(iterResult.done, true, 'iteration complete');
|
||||
assert.sameValue(iterResult.value, undefined, 'second iterated value');
|
|
@ -0,0 +1,30 @@
|
|||
// Copyright (C) 2016 the V8 project authors. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
/*---
|
||||
esid: sec-generator-function-definitions-runtime-semantics-evaluation
|
||||
es6id: 14.4.14
|
||||
description: GetValue invoked on Reference value
|
||||
info: |
|
||||
YieldExpression : yield AssignmentExpression
|
||||
|
||||
1. Let exprRef be the result of evaluating AssignmentExpression.
|
||||
2. Let value be ? GetValue(exprRef).
|
||||
---*/
|
||||
|
||||
var err;
|
||||
function* g() {
|
||||
try {
|
||||
yield test262unresolvable;
|
||||
} catch (_err) {
|
||||
err = _err;
|
||||
}
|
||||
}
|
||||
var iter = g();
|
||||
var result;
|
||||
|
||||
result = iter.next();
|
||||
|
||||
assert.sameValue(result.value, undefined);
|
||||
assert.sameValue(result.done, true);
|
||||
assert.sameValue(typeof err, 'object');
|
||||
assert.sameValue(err.constructor, ReferenceError);
|
|
@ -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-generator-function-definitions
|
||||
es6id: 14.4
|
||||
description: >
|
||||
YieldExpression operand may not include the `in` keyword in contexts where it
|
||||
is disallowed
|
||||
info: |
|
||||
Syntax
|
||||
|
||||
yield [no LineTerminator here] * AssignmentExpression[?In, +Yield]
|
||||
negative: SyntaxError
|
||||
---*/
|
||||
|
||||
function* g() {
|
||||
for (yield * '' in {}; ; ) ;
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
// Copyright (C) 2016 the V8 project authors. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
/*---
|
||||
esid: sec-generator-function-definitions
|
||||
es6id: 14.4
|
||||
description: >
|
||||
YieldExpression contextually recognizes the `in` keyword as part of a
|
||||
RelationalExpression
|
||||
info: |
|
||||
Syntax
|
||||
|
||||
yield [no LineTerminator here] AssignmentExpression[?In, +Yield]
|
||||
features: [Symbol.iterator]
|
||||
---*/
|
||||
|
||||
var obj = Object.create({ hit: true });
|
||||
var iter, iterResult, value;
|
||||
Boolean.prototype[Symbol.iterator] = function* () { yield this.valueOf(); };
|
||||
function* g() {
|
||||
value = yield * 'hit' in obj;
|
||||
value = yield * 'miss' in obj;
|
||||
}
|
||||
|
||||
iter = g();
|
||||
|
||||
iterResult = iter.next('first');
|
||||
|
||||
assert.sameValue(iterResult.done, false, '`done` property (first iteration)');
|
||||
assert.sameValue(iterResult.value, true, '`value` property (first iteration)');
|
||||
assert.sameValue(
|
||||
value, undefined, 'generator paused prior to evaluating AssignmentExpression'
|
||||
);
|
||||
|
||||
iterResult = iter.next('second');
|
||||
|
||||
assert.sameValue(iterResult.done, false, '`done` property (second iteration)');
|
||||
assert.sameValue(
|
||||
iterResult.value, false, '`value` property (second iteration)'
|
||||
);
|
||||
assert.sameValue(value, undefined, 'value of first AssignmentExpression');
|
||||
|
||||
iterResult = iter.next('third');
|
||||
|
||||
assert.sameValue(iterResult.done, true, '`done` property (third iteration)');
|
||||
assert.sameValue(
|
||||
iterResult.value, undefined, '`value` property (third iteration)'
|
||||
);
|
||||
assert.sameValue(value, undefined, 'value of second AssignmentExpression');
|
|
@ -0,0 +1,43 @@
|
|||
// Copyright (C) 2016 the V8 project authors. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
/*---
|
||||
esid: sec-generator-function-definitions-runtime-semantics-evaluation
|
||||
es6id: 14.4.14
|
||||
description: Abrupt completion returned when invoking the @@iterator method
|
||||
info: |
|
||||
YieldExpression : yield * AssignmentExpression
|
||||
|
||||
1. Let exprRef be the result of evaluating AssignmentExpression.
|
||||
2. Let value be ? GetValue(exprRef).
|
||||
3. Let iterator be ? GetIterator(value).
|
||||
|
||||
7.4.1 GetIterator
|
||||
|
||||
1. If method was not passed, then
|
||||
a. Let method be ? GetMethod(obj, @@iterator).
|
||||
2. Let iterator be ? Call(method, obj).
|
||||
features: [Symbol.iterator]
|
||||
---*/
|
||||
|
||||
var thrown = new Test262Error();
|
||||
var badIter = {};
|
||||
badIter[Symbol.iterator] = function() {
|
||||
throw thrown;
|
||||
};
|
||||
function* g() {
|
||||
try {
|
||||
yield * badIter;
|
||||
} catch (err) {
|
||||
caught = err;
|
||||
}
|
||||
}
|
||||
var iter = g();
|
||||
var result, caught;
|
||||
|
||||
assert.sameValue(caught, undefined, 'method is not invoked eagerly');
|
||||
|
||||
result = iter.next();
|
||||
|
||||
assert.sameValue(result.value, undefined, 'iteration value');
|
||||
assert.sameValue(result.done, true, 'iteration status');
|
||||
assert.sameValue(caught, thrown, 'error value');
|
|
@ -0,0 +1,42 @@
|
|||
// Copyright (C) 2016 the V8 project authors. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
/*---
|
||||
esid: sec-generator-function-definitions-runtime-semantics-evaluation
|
||||
es6id: 14.4.14
|
||||
description: TypeError thrown when @@iterator method returns a non-object value
|
||||
info: |
|
||||
YieldExpression : yield * AssignmentExpression
|
||||
|
||||
1. Let exprRef be the result of evaluating AssignmentExpression.
|
||||
2. Let value be ? GetValue(exprRef).
|
||||
3. Let iterator be ? GetIterator(value).
|
||||
|
||||
7.4.1 GetIterator
|
||||
|
||||
1. If method was not passed, then
|
||||
a. Let method be ? GetMethod(obj, @@iterator).
|
||||
2. Let iterator be ? Call(method, obj).
|
||||
3. If Type(iterator) is not Object, throw a TypeError exception.
|
||||
features: [Symbol.iterator]
|
||||
---*/
|
||||
|
||||
var badIter = {};
|
||||
badIter[Symbol.iterator] = function() {
|
||||
return 7;
|
||||
};
|
||||
function* g() {
|
||||
try {
|
||||
yield * badIter;
|
||||
} catch (err) {
|
||||
caught = err;
|
||||
}
|
||||
}
|
||||
var iter = g();
|
||||
var result, caught;
|
||||
|
||||
result = iter.next();
|
||||
|
||||
assert.sameValue(result.value, undefined);
|
||||
assert.sameValue(result.done, true);
|
||||
assert.sameValue(typeof caught, 'object');
|
||||
assert.sameValue(caught.constructor, TypeError);
|
|
@ -0,0 +1,43 @@
|
|||
// Copyright (C) 2016 the V8 project authors. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
/*---
|
||||
esid: sec-generator-function-definitions-runtime-semantics-evaluation
|
||||
es6id: 14.4.14
|
||||
description: Abrupt completion returned when accessing the @@iterator property
|
||||
info: |
|
||||
YieldExpression : yield * AssignmentExpression
|
||||
|
||||
1. Let exprRef be the result of evaluating AssignmentExpression.
|
||||
2. Let value be ? GetValue(exprRef).
|
||||
3. Let iterator be ? GetIterator(value).
|
||||
|
||||
7.4.1 GetIterator
|
||||
|
||||
1. If method was not passed, then
|
||||
a. Let method be ? GetMethod(obj, @@iterator).
|
||||
features: [Symbol.iterator]
|
||||
---*/
|
||||
|
||||
var thrown = new Test262Error();
|
||||
var poisonedIter = Object.defineProperty({}, Symbol.iterator, {
|
||||
get: function() {
|
||||
throw thrown;
|
||||
}
|
||||
});
|
||||
function* g() {
|
||||
try {
|
||||
yield * poisonedIter;
|
||||
} catch (err) {
|
||||
caught = err;
|
||||
}
|
||||
}
|
||||
var iter = g();
|
||||
var result, caught;
|
||||
|
||||
assert.sameValue(caught, undefined, 'property is not accessed eagerly');
|
||||
|
||||
result = iter.next();
|
||||
|
||||
assert.sameValue(result.value, undefined, 'iteration value');
|
||||
assert.sameValue(result.done, true, 'iteration status');
|
||||
assert.sameValue(caught, thrown, 'error value');
|
|
@ -0,0 +1,50 @@
|
|||
// Copyright (C) 2016 the V8 project authors. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
/*---
|
||||
esid: sec-generator-function-definitions-runtime-semantics-evaluation
|
||||
es6id: 14.4.14
|
||||
description: Abrupt completion returned when invoking iterator `next` method
|
||||
info: |
|
||||
YieldExpression : yield * AssignmentExpression
|
||||
|
||||
1. Let exprRef be the result of evaluating AssignmentExpression.
|
||||
2. Let value be ? GetValue(exprRef).
|
||||
3. Let iterator be ? GetIterator(value).
|
||||
4. Let received be NormalCompletion(undefined).
|
||||
5. Repeat
|
||||
a. If received.[[Type]] is normal, then
|
||||
i. Let innerResult be ? IteratorNext(iterator, received.[[Value]]).
|
||||
|
||||
7.4.2 IteratorNext
|
||||
|
||||
1. If value was not passed, then
|
||||
[...]
|
||||
2. Else,
|
||||
a. Let result be ? Invoke(iterator, "next", « value »).
|
||||
features: [Symbol.iterator]
|
||||
---*/
|
||||
|
||||
var thrown = new Test262Error();
|
||||
var badIter = {};
|
||||
badIter[Symbol.iterator] = function() {
|
||||
return {
|
||||
next: function() {
|
||||
throw thrown;
|
||||
}
|
||||
};
|
||||
};
|
||||
function* g() {
|
||||
try {
|
||||
yield * badIter;
|
||||
} catch (err) {
|
||||
caught = err;
|
||||
}
|
||||
}
|
||||
var iter = g();
|
||||
var result, caught;
|
||||
|
||||
result = iter.next();
|
||||
|
||||
assert.sameValue(result.value, undefined);
|
||||
assert.sameValue(result.done, true);
|
||||
assert.sameValue(caught, thrown);
|
|
@ -0,0 +1,51 @@
|
|||
// Copyright (C) 2016 the V8 project authors. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
/*---
|
||||
esid: sec-generator-function-definitions-runtime-semantics-evaluation
|
||||
es6id: 14.4.14
|
||||
description: >
|
||||
TypeError thrown when iterator `next` method returns a non-object value
|
||||
info: |
|
||||
YieldExpression : yield * AssignmentExpression
|
||||
|
||||
1. Let exprRef be the result of evaluating AssignmentExpression.
|
||||
2. Let value be ? GetValue(exprRef).
|
||||
3. Let iterator be ? GetIterator(value).
|
||||
4. Let received be NormalCompletion(undefined).
|
||||
5. Repeat
|
||||
a. If received.[[Type]] is normal, then
|
||||
i. Let innerResult be ? IteratorNext(iterator, received.[[Value]]).
|
||||
|
||||
7.4.2 IteratorNext
|
||||
|
||||
1. If value was not passed, then
|
||||
[...]
|
||||
2. Else,
|
||||
a. Let result be ? Invoke(iterator, "next", « value »).
|
||||
features: [Symbol.iterator]
|
||||
---*/
|
||||
|
||||
var badIter = {};
|
||||
badIter[Symbol.iterator] = function() {
|
||||
return {
|
||||
next: function() {
|
||||
return 8;
|
||||
}
|
||||
};
|
||||
};
|
||||
function* g() {
|
||||
try {
|
||||
yield * badIter;
|
||||
} catch (err) {
|
||||
caught = err;
|
||||
}
|
||||
}
|
||||
var iter = g();
|
||||
var result, caught;
|
||||
|
||||
result = iter.next();
|
||||
|
||||
assert.sameValue(result.value, undefined);
|
||||
assert.sameValue(result.done, true);
|
||||
assert.sameValue(typeof caught, 'object');
|
||||
assert.sameValue(caught.constructor, TypeError);
|
|
@ -0,0 +1,51 @@
|
|||
// Copyright (C) 2016 the V8 project authors. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
/*---
|
||||
esid: sec-generator-function-definitions-runtime-semantics-evaluation
|
||||
es6id: 14.4.14
|
||||
description: Abrupt completion returned when accessing iterator `next` method
|
||||
info: |
|
||||
YieldExpression : yield * AssignmentExpression
|
||||
|
||||
1. Let exprRef be the result of evaluating AssignmentExpression.
|
||||
2. Let value be ? GetValue(exprRef).
|
||||
3. Let iterator be ? GetIterator(value).
|
||||
4. Let received be NormalCompletion(undefined).
|
||||
5. Repeat
|
||||
a. If received.[[Type]] is normal, then
|
||||
i. Let innerResult be ? IteratorNext(iterator, received.[[Value]]).
|
||||
|
||||
7.4.2 IteratorNext
|
||||
|
||||
1. If value was not passed, then
|
||||
[...]
|
||||
2. Else,
|
||||
a. Let result be ? Invoke(iterator, "next", « value »).
|
||||
features: [Symbol.iterator]
|
||||
---*/
|
||||
|
||||
var thrown = new Test262Error();
|
||||
var badIter = {};
|
||||
var poisonedNext = Object.defineProperty({}, 'next', {
|
||||
get: function() {
|
||||
throw thrown;
|
||||
}
|
||||
});
|
||||
badIter[Symbol.iterator] = function() {
|
||||
return poisonedNext;
|
||||
};
|
||||
function* g() {
|
||||
try {
|
||||
yield * badIter;
|
||||
} catch (err) {
|
||||
caught = err;
|
||||
}
|
||||
}
|
||||
var iter = g();
|
||||
var result, caught;
|
||||
|
||||
result = iter.next();
|
||||
|
||||
assert.sameValue(result.value, undefined);
|
||||
assert.sameValue(result.done, true);
|
||||
assert.sameValue(caught, thrown);
|
|
@ -0,0 +1,52 @@
|
|||
// Copyright (C) 2016 the V8 project authors. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
/*---
|
||||
esid: sec-generator-function-definitions-runtime-semantics-evaluation
|
||||
es6id: 14.4.14
|
||||
description: Invocation of iterator `next` method
|
||||
info: |
|
||||
YieldExpression : yield * AssignmentExpression
|
||||
|
||||
1. Let exprRef be the result of evaluating AssignmentExpression.
|
||||
2. Let value be ? GetValue(exprRef).
|
||||
3. Let iterator be ? GetIterator(value).
|
||||
4. Let received be NormalCompletion(undefined).
|
||||
5. Repeat
|
||||
a. If received.[[Type]] is normal, then
|
||||
i. Let innerResult be ? IteratorNext(iterator, received.[[Value]]).
|
||||
|
||||
7.4.2 IteratorNext
|
||||
|
||||
1. If value was not passed, then
|
||||
[...]
|
||||
2. Else,
|
||||
a. Let result be ? Invoke(iterator, "next", « value »).
|
||||
[...]
|
||||
features: [Symbol.iterator]
|
||||
---*/
|
||||
|
||||
var args, thisValue;
|
||||
var callCount = 0;
|
||||
var spyIterator = {
|
||||
next: function() {
|
||||
callCount += 1;
|
||||
args = arguments;
|
||||
thisValue = this;
|
||||
return { done: true };
|
||||
}
|
||||
};
|
||||
var spyIterable = {};
|
||||
spyIterable[Symbol.iterator] = function() {
|
||||
return spyIterator;
|
||||
};
|
||||
function* g() {
|
||||
yield * spyIterable;
|
||||
}
|
||||
var iter = g();
|
||||
|
||||
iter.next(9876);
|
||||
|
||||
assert.sameValue(callCount, 1);
|
||||
assert.sameValue(args.length, 1);
|
||||
assert.sameValue(args[0], undefined);
|
||||
assert.sameValue(thisValue, spyIterator);
|
|
@ -0,0 +1,53 @@
|
|||
// Copyright (C) 2016 the V8 project authors. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
/*---
|
||||
esid: sec-generator-function-definitions-runtime-semantics-evaluation
|
||||
es6id: 14.4.14
|
||||
description: >
|
||||
Abrupt completion returned when accessing `done` property of iteration result
|
||||
info: |
|
||||
YieldExpression : yield * AssignmentExpression
|
||||
|
||||
1. Let exprRef be the result of evaluating AssignmentExpression.
|
||||
2. Let value be ? GetValue(exprRef).
|
||||
3. Let iterator be ? GetIterator(value).
|
||||
4. Let received be NormalCompletion(undefined).
|
||||
5. Repeat
|
||||
a. If received.[[Type]] is normal, then
|
||||
i. Let innerResult be ? IteratorNext(iterator, received.[[Value]]).
|
||||
ii. Let done be ? IteratorComplete(innerResult).
|
||||
|
||||
7.4.3 IteratorComplete
|
||||
|
||||
1. Assert: Type(iterResult) is Object.
|
||||
2. Return ToBoolean(? Get(iterResult, "done")).
|
||||
features: [Symbol.iterator]
|
||||
---*/
|
||||
|
||||
var thrown = new Test262Error();
|
||||
var badIter = {};
|
||||
var poisonedDone = Object.defineProperty({}, 'done', {
|
||||
get: function() {
|
||||
throw thrown;
|
||||
}
|
||||
});
|
||||
badIter[Symbol.iterator] = function() {
|
||||
return {
|
||||
next: function() {
|
||||
return poisonedDone;
|
||||
}
|
||||
};
|
||||
};
|
||||
function* g() {
|
||||
try {
|
||||
yield * badIter;
|
||||
} catch (err) {
|
||||
caught = err;
|
||||
}
|
||||
}
|
||||
var iter = g();
|
||||
var result, caught;
|
||||
|
||||
result = iter.next();
|
||||
|
||||
assert.sameValue(caught, thrown);
|
|
@ -0,0 +1,60 @@
|
|||
// Copyright (C) 2016 the V8 project authors. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
/*---
|
||||
esid: sec-generator-function-definitions-runtime-semantics-evaluation
|
||||
es6id: 14.4.14
|
||||
description: >
|
||||
`value` property is not accessed when iteration is incomplete
|
||||
info: |
|
||||
YieldExpression : yield * AssignmentExpression
|
||||
|
||||
1. Let exprRef be the result of evaluating AssignmentExpression.
|
||||
2. Let value be ? GetValue(exprRef).
|
||||
3. Let iterator be ? GetIterator(value).
|
||||
4. Let received be NormalCompletion(undefined).
|
||||
5. Repeat
|
||||
a. If received.[[Type]] is normal, then
|
||||
i. Let innerResult be ? IteratorNext(iterator, received.[[Value]]).
|
||||
ii. Let done be ? IteratorComplete(innerResult).
|
||||
iii. If done is true, then
|
||||
1. Return ? IteratorValue(innerResult).
|
||||
features: [Symbol.iterator]
|
||||
---*/
|
||||
|
||||
var badIter = {};
|
||||
var callCount = 0;
|
||||
var spyValue = Object.defineProperty({ done: false }, 'value', {
|
||||
get: function() {
|
||||
callCount += 1;
|
||||
}
|
||||
});
|
||||
badIter[Symbol.iterator] = function() {
|
||||
return {
|
||||
next: function() {
|
||||
return spyValue;
|
||||
}
|
||||
};
|
||||
};
|
||||
var delegationComplete = false;
|
||||
function* g() {
|
||||
yield * badIter;
|
||||
delegationComplete = true;
|
||||
}
|
||||
var iter = g();
|
||||
|
||||
iter.next();
|
||||
assert.sameValue(callCount, 0, 'access count (first iteration)');
|
||||
assert.sameValue(
|
||||
delegationComplete, false, 'delegation ongoing (first iteration)'
|
||||
);
|
||||
|
||||
iter.next();
|
||||
assert.sameValue(callCount, 0, 'access count (second iteration)');
|
||||
assert.sameValue(
|
||||
delegationComplete, false, 'delegation ongoing (second iteration)'
|
||||
);
|
||||
|
||||
spyValue.done = true;
|
||||
iter.next();
|
||||
assert.sameValue(callCount, 1, 'access count (final iteration)');
|
||||
assert.sameValue(delegationComplete, true, 'delegation complete');
|
|
@ -0,0 +1,56 @@
|
|||
// Copyright (C) 2016 the V8 project authors. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
/*---
|
||||
esid: sec-generator-function-definitions-runtime-semantics-evaluation
|
||||
es6id: 14.4.14
|
||||
description: >
|
||||
Abrupt completion returned when accessing `value` property of iteration
|
||||
result
|
||||
info: |
|
||||
YieldExpression : yield * AssignmentExpression
|
||||
|
||||
1. Let exprRef be the result of evaluating AssignmentExpression.
|
||||
2. Let value be ? GetValue(exprRef).
|
||||
3. Let iterator be ? GetIterator(value).
|
||||
4. Let received be NormalCompletion(undefined).
|
||||
5. Repeat
|
||||
a. If received.[[Type]] is normal, then
|
||||
i. Let innerResult be ? IteratorNext(iterator, received.[[Value]]).
|
||||
ii. Let done be ? IteratorComplete(innerResult).
|
||||
iii. If done is true, then
|
||||
1. Return ? IteratorValue(innerResult).
|
||||
|
||||
7.4.4 IteratorValue
|
||||
|
||||
1. Assert: Type(iterResult) is Object.
|
||||
2. Return ? Get(iterResult, "value").
|
||||
features: [Symbol.iterator]
|
||||
---*/
|
||||
|
||||
var thrown = new Test262Error();
|
||||
var badIter = {};
|
||||
var poisonedValue = Object.defineProperty({ done: true }, 'value', {
|
||||
get: function() {
|
||||
throw thrown;
|
||||
}
|
||||
});
|
||||
badIter[Symbol.iterator] = function() {
|
||||
return {
|
||||
next: function() {
|
||||
return poisonedValue;
|
||||
}
|
||||
};
|
||||
};
|
||||
function* g() {
|
||||
try {
|
||||
yield * badIter;
|
||||
} catch (err) {
|
||||
caught = err;
|
||||
}
|
||||
}
|
||||
var iter = g();
|
||||
var result, caught;
|
||||
|
||||
result = iter.next();
|
||||
|
||||
assert.sameValue(caught, thrown);
|
|
@ -0,0 +1,62 @@
|
|||
// Copyright (C) 2016 the V8 project authors. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
/*---
|
||||
esid: sec-generator-function-definitions-runtime-semantics-evaluation
|
||||
es6id: 14.4.14
|
||||
description: Value received from invocation of generator's `next` method
|
||||
info: |
|
||||
YieldExpression : yield * AssignmentExpression
|
||||
|
||||
1. Let exprRef be the result of evaluating AssignmentExpression.
|
||||
2. Let value be ? GetValue(exprRef).
|
||||
3. Let iterator be ? GetIterator(value).
|
||||
4. Let received be NormalCompletion(undefined).
|
||||
5. Repeat
|
||||
a. If received.[[Type]] is normal, then
|
||||
i. Let innerResult be ? IteratorNext(iterator, received.[[Value]]).
|
||||
ii. Let done be ? IteratorComplete(innerResult).
|
||||
iii. If done is true, then
|
||||
1. Return ? IteratorValue(innerResult).
|
||||
|
||||
7.4.4 IteratorValue
|
||||
|
||||
1. Assert: Type(iterResult) is Object.
|
||||
2. Return ? Get(iterResult, "value").
|
||||
features: [Symbol.iterator]
|
||||
---*/
|
||||
|
||||
var quickIter = {};
|
||||
var exprValue, nextReceived, done, iter;
|
||||
quickIter[Symbol.iterator] = function() {
|
||||
return {
|
||||
next: function(x) {
|
||||
nextReceived = x;
|
||||
return {
|
||||
done: done,
|
||||
value: 3333
|
||||
};
|
||||
}
|
||||
};
|
||||
};
|
||||
function* g() {
|
||||
exprValue = yield * quickIter;
|
||||
}
|
||||
|
||||
done = true;
|
||||
iter = g();
|
||||
iter.next(4444);
|
||||
|
||||
assert.sameValue(
|
||||
nextReceived, undefined, 'received value (previously-exhausted iterator)'
|
||||
);
|
||||
assert.sameValue(exprValue, 3333, 'expression value (previously-exhausted iterator)');
|
||||
|
||||
done = false;
|
||||
exprValue = null;
|
||||
iter = g();
|
||||
iter.next(2222);
|
||||
done = true;
|
||||
iter.next(5555);
|
||||
|
||||
assert.sameValue(nextReceived, 5555, 'received value');
|
||||
assert.sameValue(exprValue, 3333, 'expression value');
|
|
@ -0,0 +1,76 @@
|
|||
// Copyright (C) 2016 the V8 project authors. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
/*---
|
||||
esid: sec-generator-function-definitions-runtime-semantics-evaluation
|
||||
es6id: 14.4.14
|
||||
description: >
|
||||
"Return" completion returned when `return` method is not defined
|
||||
info: |
|
||||
YieldExpression : yield * AssignmentExpression
|
||||
|
||||
1. Let exprRef be the result of evaluating AssignmentExpression.
|
||||
2. Let value be ? GetValue(exprRef).
|
||||
3. Let iterator be ? GetIterator(value).
|
||||
4. Let received be NormalCompletion(undefined).
|
||||
5. Repeat
|
||||
a. If received.[[Type]] is normal, then
|
||||
[...]
|
||||
b. Else if received.[[Type]] is throw, then
|
||||
[...]
|
||||
c. Else,
|
||||
i. Assert: received.[[Type]] is return.
|
||||
ii. Let return be ? GetMethod(iterator, "return").
|
||||
iii. If return is undefined, return Completion(received).
|
||||
features: [Symbol.iterator]
|
||||
---*/
|
||||
|
||||
var badIter = {};
|
||||
var throwCount = 0;
|
||||
var returnCount = 0;
|
||||
var hitNextStatement = false;
|
||||
var hitCatch = false;
|
||||
var hitFinally = false;
|
||||
var spyResult = {
|
||||
next: function() {
|
||||
return { done: false };
|
||||
}
|
||||
};
|
||||
Object.defineProperty(spyResult, 'throw', {
|
||||
get: function() {
|
||||
throwCount += 1;
|
||||
}
|
||||
});
|
||||
Object.defineProperty(spyResult, 'return', {
|
||||
get: function() {
|
||||
returnCount += 1;
|
||||
}
|
||||
});
|
||||
badIter[Symbol.iterator] = function() {
|
||||
return spyResult;
|
||||
};
|
||||
function* g() {
|
||||
try {
|
||||
yield * badIter;
|
||||
hitNextStatement = true;
|
||||
} catch (_) {
|
||||
hitCatch = true;
|
||||
} finally {
|
||||
hitFinally = true;
|
||||
}
|
||||
}
|
||||
var iter = g();
|
||||
|
||||
iter.next();
|
||||
iter.return();
|
||||
|
||||
assert.sameValue(throwCount, 0, '`throw` property access');
|
||||
assert.sameValue(returnCount, 1, '`return` property access');
|
||||
assert.sameValue(
|
||||
hitFinally, true, 'Generator execution was resumed'
|
||||
);
|
||||
assert.sameValue(
|
||||
hitNextStatement, false, 'Abrupt completion interrupted control flow'
|
||||
);
|
||||
assert.sameValue(
|
||||
hitCatch, false, 'Abrupt completion not interpreted as "throw"'
|
||||
);
|
|
@ -0,0 +1,67 @@
|
|||
// Copyright (C) 2016 the V8 project authors. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
/*---
|
||||
esid: sec-generator-function-definitions-runtime-semantics-evaluation
|
||||
es6id: 14.4.14
|
||||
description: >
|
||||
Abrupt completion returned when accessing `done` property of iteration result
|
||||
info: |
|
||||
YieldExpression : yield * AssignmentExpression
|
||||
|
||||
1. Let exprRef be the result of evaluating AssignmentExpression.
|
||||
2. Let value be ? GetValue(exprRef).
|
||||
3. Let iterator be ? GetIterator(value).
|
||||
4. Let received be NormalCompletion(undefined).
|
||||
5. Repeat
|
||||
a. If received.[[Type]] is normal, then
|
||||
[...]
|
||||
b. Else if received.[[Type]] is throw, then
|
||||
[...]
|
||||
c. Else,
|
||||
i. Assert: received.[[Type]] is return.
|
||||
ii. Let return be ? GetMethod(iterator, "return").
|
||||
iii. If return is undefined, return Completion(received).
|
||||
iv. Let innerReturnResult be ? Call(return, iterator, «
|
||||
received.[[Value]] »).
|
||||
v. If Type(innerReturnResult) is not Object, throw a TypeError
|
||||
exception.
|
||||
vi. Let done be ? IteratorComplete(innerReturnResult).
|
||||
|
||||
7.4.3 IteratorComplete
|
||||
|
||||
1. Assert: Type(iterResult) is Object.
|
||||
2. Return ToBoolean(? Get(iterResult, "done")).
|
||||
features: [Symbol.iterator]
|
||||
---*/
|
||||
|
||||
var thrown = new Test262Error();
|
||||
var badIter = {};
|
||||
var poisonedDone = Object.defineProperty({}, 'done', {
|
||||
get: function() {
|
||||
throw thrown;
|
||||
}
|
||||
});
|
||||
badIter[Symbol.iterator] = function() {
|
||||
return {
|
||||
next: function() {
|
||||
return { done: false };
|
||||
},
|
||||
return: function() {
|
||||
return poisonedDone;
|
||||
}
|
||||
};
|
||||
};
|
||||
function* g() {
|
||||
try {
|
||||
yield * badIter;
|
||||
} catch (err) {
|
||||
caught = err;
|
||||
}
|
||||
}
|
||||
var iter = g();
|
||||
var caught;
|
||||
|
||||
iter.next();
|
||||
iter.return();
|
||||
|
||||
assert.sameValue(caught, thrown);
|
|
@ -0,0 +1,91 @@
|
|||
// Copyright (C) 2016 the V8 project authors. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
/*---
|
||||
esid: sec-generator-function-definitions-runtime-semantics-evaluation
|
||||
es6id: 14.4.14
|
||||
description: >
|
||||
`value` property is not accessed when iteration is incomplete
|
||||
info: |
|
||||
YieldExpression : yield * AssignmentExpression
|
||||
|
||||
1. Let exprRef be the result of evaluating AssignmentExpression.
|
||||
2. Let value be ? GetValue(exprRef).
|
||||
3. Let iterator be ? GetIterator(value).
|
||||
4. Let received be NormalCompletion(undefined).
|
||||
5. Repeat
|
||||
a. If received.[[Type]] is normal, then
|
||||
[...]
|
||||
b. Else if received.[[Type]] is throw, then
|
||||
[...]
|
||||
c. Else,
|
||||
i. Assert: received.[[Type]] is return.
|
||||
ii. Let return be ? GetMethod(iterator, "return").
|
||||
iii. If return is undefined, return Completion(received).
|
||||
iv. Let innerReturnResult be ? Call(return, iterator, «
|
||||
received.[[Value]] »).
|
||||
v. If Type(innerReturnResult) is not Object, throw a TypeError
|
||||
exception.
|
||||
vi. Let done be ? IteratorComplete(innerReturnResult).
|
||||
vii. If done is true, then
|
||||
1. Let value be ? IteratorValue(innerReturnResult).
|
||||
2. Return Completion{[[Type]]: return, [[Value]]: value,
|
||||
[[Target]]: empty}.
|
||||
viii. Let received be GeneratorYield(innerReturnResult).
|
||||
|
||||
7.4.3 IteratorComplete
|
||||
|
||||
1. Assert: Type(iterResult) is Object.
|
||||
2. Return ToBoolean(? Get(iterResult, "done")).
|
||||
features: [Symbol.iterator]
|
||||
---*/
|
||||
|
||||
var badIter = {};
|
||||
var callCount = 0;
|
||||
var spyValue = Object.defineProperty({ done: false }, 'value', {
|
||||
get: function() {
|
||||
callCount += 1;
|
||||
}
|
||||
});
|
||||
badIter[Symbol.iterator] = function() {
|
||||
return {
|
||||
next: function() {
|
||||
return { done: false };
|
||||
},
|
||||
return: function() {
|
||||
return spyValue;
|
||||
}
|
||||
};
|
||||
};
|
||||
var normalCompletion = false;
|
||||
var errorCompletion = false;
|
||||
var delegationComplete = false;
|
||||
function* g() {
|
||||
try {
|
||||
yield * badIter;
|
||||
normalCompletion = true;
|
||||
} catch (_) {
|
||||
errorCompletion = true;
|
||||
} finally {
|
||||
delegationComplete = true;
|
||||
}
|
||||
}
|
||||
var iter = g();
|
||||
|
||||
iter.next();
|
||||
assert.sameValue(callCount, 0, 'access count (first iteration)');
|
||||
assert.sameValue(
|
||||
delegationComplete, false, 'delegation ongoing (first iteration)'
|
||||
);
|
||||
|
||||
iter.return();
|
||||
assert.sameValue(callCount, 0, 'access count (second iteration)');
|
||||
assert.sameValue(
|
||||
delegationComplete, false, 'delegation ongoing (second iteration)'
|
||||
);
|
||||
|
||||
spyValue.done = true;
|
||||
iter.return();
|
||||
assert.sameValue(callCount, 1, 'access count (final iteration)');
|
||||
assert.sameValue(delegationComplete, true, 'delegation complete');
|
||||
assert.sameValue(normalCompletion, false, 'completion was abrupt');
|
||||
assert.sameValue(errorCompletion, false, 'completion was not of type "throw"');
|
|
@ -0,0 +1,70 @@
|
|||
// Copyright (C) 2016 the V8 project authors. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
/*---
|
||||
esid: sec-generator-function-definitions-runtime-semantics-evaluation
|
||||
es6id: 14.4.14
|
||||
description: >
|
||||
Abrupt completion returned when accessing `value` property of iteration
|
||||
result
|
||||
info: |
|
||||
YieldExpression : yield * AssignmentExpression
|
||||
|
||||
1. Let exprRef be the result of evaluating AssignmentExpression.
|
||||
2. Let value be ? GetValue(exprRef).
|
||||
3. Let iterator be ? GetIterator(value).
|
||||
4. Let received be NormalCompletion(undefined).
|
||||
5. Repeat
|
||||
a. If received.[[Type]] is normal, then
|
||||
[...]
|
||||
b. Else if received.[[Type]] is throw, then
|
||||
[...]
|
||||
c. Else,
|
||||
i. Assert: received.[[Type]] is return.
|
||||
ii. Let return be ? GetMethod(iterator, "return").
|
||||
iii. If return is undefined, return Completion(received).
|
||||
iv. Let innerReturnResult be ? Call(return, iterator, «
|
||||
received.[[Value]] »).
|
||||
v. If Type(innerReturnResult) is not Object, throw a TypeError
|
||||
exception.
|
||||
vi. Let done be ? IteratorComplete(innerReturnResult).
|
||||
vii. If done is true, then
|
||||
1. Let value be ? IteratorValue(innerReturnResult).
|
||||
|
||||
7.4.4 IteratorValue
|
||||
|
||||
1. Assert: Type(iterResult) is Object.
|
||||
2. Return ? Get(iterResult, "value").
|
||||
features: [Symbol.iterator]
|
||||
---*/
|
||||
|
||||
var thrown = new Test262Error();
|
||||
var badIter = {};
|
||||
var poisonedValue = Object.defineProperty({ done: true }, 'value', {
|
||||
get: function() {
|
||||
throw thrown;
|
||||
}
|
||||
});
|
||||
badIter[Symbol.iterator] = function() {
|
||||
return {
|
||||
next: function() {
|
||||
return { done: false };
|
||||
},
|
||||
return: function() {
|
||||
return poisonedValue;
|
||||
}
|
||||
};
|
||||
};
|
||||
function* g() {
|
||||
try {
|
||||
yield * badIter;
|
||||
} catch (err) {
|
||||
caught = err;
|
||||
}
|
||||
}
|
||||
var iter = g();
|
||||
var caught;
|
||||
|
||||
iter.next();
|
||||
iter.return();
|
||||
|
||||
assert.sameValue(caught, thrown);
|
|
@ -0,0 +1,71 @@
|
|||
// Copyright (C) 2016 the V8 project authors. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
/*---
|
||||
esid: sec-generator-function-definitions-runtime-semantics-evaluation
|
||||
es6id: 14.4.14
|
||||
description: Value received from invocation of generator's `return` method
|
||||
info: |
|
||||
YieldExpression : yield * AssignmentExpression
|
||||
|
||||
1. Let exprRef be the result of evaluating AssignmentExpression.
|
||||
2. Let value be ? GetValue(exprRef).
|
||||
3. Let iterator be ? GetIterator(value).
|
||||
4. Let received be NormalCompletion(undefined).
|
||||
5. Repeat
|
||||
a. If received.[[Type]] is normal, then
|
||||
[...]
|
||||
b. Else if received.[[Type]] is throw, then
|
||||
[...]
|
||||
c. Else,
|
||||
i. Assert: received.[[Type]] is return.
|
||||
ii. Let return be ? GetMethod(iterator, "return").
|
||||
iii. If return is undefined, return Completion(received).
|
||||
iv. Let innerReturnResult be ? Call(return, iterator, «
|
||||
received.[[Value]] »).
|
||||
v. If Type(innerReturnResult) is not Object, throw a TypeError
|
||||
exception.
|
||||
vi. Let done be ? IteratorComplete(innerReturnResult).
|
||||
vii. If done is true, then
|
||||
1. Let value be ? IteratorValue(innerReturnResult).
|
||||
2. Return Completion{[[Type]]: return, [[Value]]: value,
|
||||
[[Target]]: empty}.
|
||||
viii. Let received be GeneratorYield(innerReturnResult).
|
||||
|
||||
features: [Symbol.iterator]
|
||||
---*/
|
||||
|
||||
var quickIter = {};
|
||||
var normalCompletion = false;
|
||||
var errorCompletion = false;
|
||||
var delegationComplete = false;
|
||||
var iter, returnReceived;
|
||||
quickIter[Symbol.iterator] = function() {
|
||||
return {
|
||||
next: function() {
|
||||
return { done: false };
|
||||
},
|
||||
return: function(x) {
|
||||
returnReceived = x;
|
||||
return { done: true, value: 3333 };
|
||||
}
|
||||
};
|
||||
};
|
||||
function* g() {
|
||||
try {
|
||||
yield * quickIter;
|
||||
normalCompletion = true;
|
||||
} catch (e) {
|
||||
errorCompletion = true;
|
||||
} finally {
|
||||
delegationComplete = true;
|
||||
}
|
||||
}
|
||||
|
||||
iter = g();
|
||||
|
||||
iter.next();
|
||||
iter.return(2222);
|
||||
assert.sameValue(returnReceived, 2222);
|
||||
assert.sameValue(delegationComplete, true, 'delegation complete');
|
||||
assert.sameValue(normalCompletion, false, 'completion was abrupt');
|
||||
assert.sameValue(errorCompletion, false, 'completion was not of type "throw"');
|
|
@ -0,0 +1,55 @@
|
|||
// Copyright (C) 2016 the V8 project authors. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
/*---
|
||||
esid: sec-generator-function-definitions-runtime-semantics-evaluation
|
||||
es6id: 14.4.14
|
||||
description: Abrupt completion returned when invoking iterator `return` method
|
||||
info: |
|
||||
YieldExpression : yield * AssignmentExpression
|
||||
|
||||
1. Let exprRef be the result of evaluating AssignmentExpression.
|
||||
2. Let value be ? GetValue(exprRef).
|
||||
3. Let iterator be ? GetIterator(value).
|
||||
4. Let received be NormalCompletion(undefined).
|
||||
5. Repeat
|
||||
a. If received.[[Type]] is normal, then
|
||||
[...]
|
||||
b. Else if received.[[Type]] is throw, then
|
||||
[...]
|
||||
c. Else,
|
||||
i. Assert: received.[[Type]] is return.
|
||||
ii. Let return be ? GetMethod(iterator, "return").
|
||||
iii. If return is undefined, return Completion(received).
|
||||
iv. Let innerReturnResult be ? Call(return, iterator, «
|
||||
received.[[Value]] »).
|
||||
features: [Symbol.iterator]
|
||||
---*/
|
||||
|
||||
var thrown = new Test262Error();
|
||||
var badIter = {};
|
||||
badIter[Symbol.iterator] = function() {
|
||||
return {
|
||||
next: function() {
|
||||
return { done: false };
|
||||
},
|
||||
return: function() {
|
||||
throw thrown;
|
||||
}
|
||||
};
|
||||
};
|
||||
function* g() {
|
||||
try {
|
||||
yield * badIter;
|
||||
} catch (err) {
|
||||
caught = err;
|
||||
}
|
||||
}
|
||||
var iter = g();
|
||||
var result, caught;
|
||||
|
||||
iter.next();
|
||||
result = iter.return();
|
||||
|
||||
assert.sameValue(result.value, undefined);
|
||||
assert.sameValue(result.done, true);
|
||||
assert.sameValue(caught, thrown);
|
|
@ -0,0 +1,58 @@
|
|||
// Copyright (C) 2016 the V8 project authors. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
/*---
|
||||
esid: sec-generator-function-definitions-runtime-semantics-evaluation
|
||||
es6id: 14.4.14
|
||||
description: >
|
||||
TypeError thrown when iterator `return` method returns a non-object value
|
||||
info: |
|
||||
YieldExpression : yield * AssignmentExpression
|
||||
|
||||
1. Let exprRef be the result of evaluating AssignmentExpression.
|
||||
2. Let value be ? GetValue(exprRef).
|
||||
3. Let iterator be ? GetIterator(value).
|
||||
4. Let received be NormalCompletion(undefined).
|
||||
5. Repeat
|
||||
a. If received.[[Type]] is normal, then
|
||||
[...]
|
||||
b. Else if received.[[Type]] is throw, then
|
||||
[...]
|
||||
c. Else,
|
||||
i. Assert: received.[[Type]] is return.
|
||||
ii. Let return be ? GetMethod(iterator, "return").
|
||||
iii. If return is undefined, return Completion(received).
|
||||
iv. Let innerReturnResult be ? Call(return, iterator, «
|
||||
received.[[Value]] »).
|
||||
v. If Type(innerReturnResult) is not Object, throw a TypeError
|
||||
exception.
|
||||
features: [Symbol.iterator]
|
||||
---*/
|
||||
|
||||
var badIter = {};
|
||||
badIter[Symbol.iterator] = function() {
|
||||
return {
|
||||
next: function() {
|
||||
return { done: false };
|
||||
},
|
||||
return: function() {
|
||||
return 23;
|
||||
}
|
||||
};
|
||||
};
|
||||
function* g() {
|
||||
try {
|
||||
yield * badIter;
|
||||
} catch (err) {
|
||||
caught = err;
|
||||
}
|
||||
}
|
||||
var iter = g();
|
||||
var result, caught;
|
||||
|
||||
iter.next();
|
||||
result = iter.return();
|
||||
|
||||
assert.sameValue(result.value, undefined);
|
||||
assert.sameValue(result.done, true);
|
||||
assert.sameValue(typeof caught, 'object');
|
||||
assert.sameValue(caught.constructor, TypeError);
|
|
@ -0,0 +1,65 @@
|
|||
// Copyright (C) 2016 the V8 project authors. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
/*---
|
||||
esid: sec-generator-function-definitions-runtime-semantics-evaluation
|
||||
es6id: 14.4.14
|
||||
description: Abrupt completion returned when accessing iterator `return` method
|
||||
info: |
|
||||
YieldExpression : yield * AssignmentExpression
|
||||
|
||||
1. Let exprRef be the result of evaluating AssignmentExpression.
|
||||
2. Let value be ? GetValue(exprRef).
|
||||
3. Let iterator be ? GetIterator(value).
|
||||
4. Let received be NormalCompletion(undefined).
|
||||
5. Repeat
|
||||
a. If received.[[Type]] is normal, then
|
||||
[...]
|
||||
b. Else if received.[[Type]] is throw, then
|
||||
[...]
|
||||
c. Else,
|
||||
i. Assert: received.[[Type]] is return.
|
||||
ii. Let return be ? GetMethod(iterator, "return").
|
||||
features: [Symbol.iterator]
|
||||
---*/
|
||||
|
||||
var thrown = new Test262Error();
|
||||
var badIter = {};
|
||||
var callCount = 0;
|
||||
var poisonedReturn = {
|
||||
next: function() {
|
||||
return { done: false };
|
||||
}
|
||||
};
|
||||
Object.defineProperty(poisonedReturn, 'throw', {
|
||||
get: function() {
|
||||
callCount += 1;
|
||||
}
|
||||
});
|
||||
Object.defineProperty(poisonedReturn, 'return', {
|
||||
get: function() {
|
||||
throw thrown;
|
||||
}
|
||||
});
|
||||
badIter[Symbol.iterator] = function() {
|
||||
return poisonedReturn;
|
||||
};
|
||||
function* g() {
|
||||
try {
|
||||
yield * badIter;
|
||||
} catch (err) {
|
||||
caught = err;
|
||||
}
|
||||
}
|
||||
var iter = g();
|
||||
var result, caught;
|
||||
|
||||
iter.next();
|
||||
|
||||
assert.sameValue(caught, undefined, '`return` property not accessed eagerly');
|
||||
|
||||
result = iter.return();
|
||||
|
||||
assert.sameValue(result.value, undefined);
|
||||
assert.sameValue(result.done, true);
|
||||
assert.sameValue(caught, thrown);
|
||||
assert.sameValue(callCount, 0, 'iterator `throw` property is not accessed');
|
|
@ -0,0 +1,57 @@
|
|||
// Copyright (C) 2016 the V8 project authors. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
/*---
|
||||
esid: sec-generator-function-definitions-runtime-semantics-evaluation
|
||||
es6id: 14.4.14
|
||||
description: Invocation of iterator `return` method
|
||||
info: |
|
||||
YieldExpression : yield * AssignmentExpression
|
||||
|
||||
1. Let exprRef be the result of evaluating AssignmentExpression.
|
||||
2. Let value be ? GetValue(exprRef).
|
||||
3. Let iterator be ? GetIterator(value).
|
||||
4. Let received be NormalCompletion(undefined).
|
||||
5. Repeat
|
||||
a. If received.[[Type]] is normal, then
|
||||
[...]
|
||||
b. Else if received.[[Type]] is throw, then
|
||||
[...]
|
||||
c. Else,
|
||||
i. Assert: received.[[Type]] is return.
|
||||
ii. Let return be ? GetMethod(iterator, "return").
|
||||
iii. If return is undefined, return Completion(received).
|
||||
iv. Let innerReturnResult be ? Call(return, iterator, «
|
||||
received.[[Value]] »).
|
||||
[...]
|
||||
features: [Symbol.iterator]
|
||||
---*/
|
||||
|
||||
var args, thisValue;
|
||||
var callCount = 0;
|
||||
var spyIterator = {
|
||||
next: function() {
|
||||
return { done: false };
|
||||
},
|
||||
return: function() {
|
||||
callCount += 1;
|
||||
args = arguments;
|
||||
thisValue = this;
|
||||
return { done: true };
|
||||
}
|
||||
};
|
||||
var spyIterable = {};
|
||||
spyIterable[Symbol.iterator] = function() {
|
||||
return spyIterator;
|
||||
};
|
||||
function* g() {
|
||||
yield * spyIterable;
|
||||
}
|
||||
var iter = g();
|
||||
|
||||
iter.next(8888);
|
||||
iter.return(7777);
|
||||
|
||||
assert.sameValue(callCount, 1);
|
||||
assert.sameValue(args.length, 1);
|
||||
assert.sameValue(args[0], 7777);
|
||||
assert.sameValue(thisValue, spyIterator);
|
|
@ -0,0 +1,66 @@
|
|||
// Copyright (C) 2016 the V8 project authors. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
/*---
|
||||
esid: sec-generator-function-definitions-runtime-semantics-evaluation
|
||||
es6id: 14.4.14
|
||||
description: >
|
||||
Abrupt completion returned when accessing `done` property of iteration result
|
||||
info: |
|
||||
YieldExpression : yield * AssignmentExpression
|
||||
|
||||
1. Let exprRef be the result of evaluating AssignmentExpression.
|
||||
2. Let value be ? GetValue(exprRef).
|
||||
3. Let iterator be ? GetIterator(value).
|
||||
4. Let received be NormalCompletion(undefined).
|
||||
5. Repeat
|
||||
a. If received.[[Type]] is normal, then
|
||||
[...]
|
||||
b. Else if received.[[Type]] is throw, then
|
||||
i. Let throw be ? GetMethod(iterator, "throw").
|
||||
ii. If throw is not undefined, then
|
||||
1. Let innerResult be ? Call(throw, iterator, « received.[[Value]]
|
||||
»).
|
||||
2. NOTE: Exceptions from the inner iterator throw method are
|
||||
propagated. Normal completions from an inner throw method are
|
||||
processed similarly to an inner next.
|
||||
3. If Type(innerResult) is not Object, throw a TypeError exception.
|
||||
4. Let done be ? IteratorComplete(innerResult).
|
||||
|
||||
7.4.3 IteratorComplete
|
||||
|
||||
1. Assert: Type(iterResult) is Object.
|
||||
2. Return ToBoolean(? Get(iterResult, "done")).
|
||||
features: [Symbol.iterator]
|
||||
---*/
|
||||
|
||||
var thrown = new Test262Error();
|
||||
var badIter = {};
|
||||
var poisonedDone = Object.defineProperty({}, 'done', {
|
||||
get: function() {
|
||||
throw thrown;
|
||||
}
|
||||
});
|
||||
badIter[Symbol.iterator] = function() {
|
||||
return {
|
||||
next: function() {
|
||||
return { done: false };
|
||||
},
|
||||
throw: function() {
|
||||
return poisonedDone;
|
||||
}
|
||||
};
|
||||
};
|
||||
function* g() {
|
||||
try {
|
||||
yield * badIter;
|
||||
} catch (err) {
|
||||
caught = err;
|
||||
}
|
||||
}
|
||||
var iter = g();
|
||||
var caught;
|
||||
|
||||
iter.next();
|
||||
iter.throw();
|
||||
|
||||
assert.sameValue(caught, thrown);
|
|
@ -0,0 +1,76 @@
|
|||
// Copyright (C) 2016 the V8 project authors. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
/*---
|
||||
esid: sec-generator-function-definitions-runtime-semantics-evaluation
|
||||
description: >
|
||||
`value` property is not accessed when iteration is complete
|
||||
info: |
|
||||
YieldExpression : yield * AssignmentExpression
|
||||
|
||||
1. Let exprRef be the result of evaluating AssignmentExpression.
|
||||
2. Let value be ? GetValue(exprRef).
|
||||
3. Let iterator be ? GetIterator(value).
|
||||
4. Let received be NormalCompletion(undefined).
|
||||
5. Repeat
|
||||
a. If received.[[Type]] is normal, then
|
||||
[...]
|
||||
b. Else if received.[[Type]] is throw, then
|
||||
i. Let throw be ? GetMethod(iterator, "throw").
|
||||
ii. If throw is not undefined, then
|
||||
1. Let innerResult be ? Call(throw, iterator, « received.[[Value]]
|
||||
»).
|
||||
2. NOTE: Exceptions from the inner iterator throw method are
|
||||
propagated. Normal completions from an inner throw method are
|
||||
processed similarly to an inner next.
|
||||
3. If Type(innerResult) is not Object, throw a TypeError exception.
|
||||
4. Let done be ? IteratorComplete(innerResult).
|
||||
5. If done is true, then
|
||||
a. Return ? IteratorValue(innerResult).
|
||||
|
||||
7.4.3 IteratorComplete
|
||||
|
||||
1. Assert: Type(iterResult) is Object.
|
||||
2. Return ToBoolean(? Get(iterResult, "done")).
|
||||
features: [Symbol.iterator]
|
||||
---*/
|
||||
|
||||
var badIter = {};
|
||||
var callCount = 0;
|
||||
var spyValue = Object.defineProperty({ done: false }, 'value', {
|
||||
get: function() {
|
||||
callCount += 1;
|
||||
}
|
||||
});
|
||||
badIter[Symbol.iterator] = function() {
|
||||
return {
|
||||
next: function() {
|
||||
return { done: false };
|
||||
},
|
||||
throw: function() {
|
||||
return spyValue;
|
||||
}
|
||||
};
|
||||
};
|
||||
var delegationComplete = false;
|
||||
function* g() {
|
||||
yield * badIter;
|
||||
delegationComplete = true;
|
||||
}
|
||||
var iter = g();
|
||||
|
||||
iter.next();
|
||||
assert.sameValue(callCount, 0, 'access count (first iteration)');
|
||||
assert.sameValue(
|
||||
delegationComplete, false, 'delegation ongoing (first iteration)'
|
||||
);
|
||||
|
||||
iter.throw();
|
||||
assert.sameValue(callCount, 0, 'access count (second iteration)');
|
||||
assert.sameValue(
|
||||
delegationComplete, false, 'delegation ongoing (second iteration)'
|
||||
);
|
||||
|
||||
spyValue.done = true;
|
||||
iter.throw();
|
||||
assert.sameValue(callCount, 1, 'access count (final iteration)');
|
||||
assert.sameValue(delegationComplete, true, 'delegation complete');
|
|
@ -0,0 +1,69 @@
|
|||
// Copyright (C) 2016 the V8 project authors. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
/*---
|
||||
esid: sec-generator-function-definitions-runtime-semantics-evaluation
|
||||
es6id: 14.4.14
|
||||
description: >
|
||||
Abrupt completion returned when accessing `value` property of iteration
|
||||
result
|
||||
info: |
|
||||
YieldExpression : yield * AssignmentExpression
|
||||
|
||||
1. Let exprRef be the result of evaluating AssignmentExpression.
|
||||
2. Let value be ? GetValue(exprRef).
|
||||
3. Let iterator be ? GetIterator(value).
|
||||
4. Let received be NormalCompletion(undefined).
|
||||
5. Repeat
|
||||
a. If received.[[Type]] is normal, then
|
||||
[...]
|
||||
b. Else if received.[[Type]] is throw, then
|
||||
i. Let throw be ? GetMethod(iterator, "throw").
|
||||
ii. If throw is not undefined, then
|
||||
1. Let innerResult be ? Call(throw, iterator, « received.[[Value]]
|
||||
»).
|
||||
2. NOTE: Exceptions from the inner iterator throw method are
|
||||
propagated. Normal completions from an inner throw method are
|
||||
processed similarly to an inner next.
|
||||
3. If Type(innerResult) is not Object, throw a TypeError exception.
|
||||
4. Let done be ? IteratorComplete(innerResult).
|
||||
5. If done is true, then
|
||||
a. Return ? IteratorValue(innerResult).
|
||||
|
||||
7.4.4 IteratorValue
|
||||
|
||||
1. Assert: Type(iterResult) is Object.
|
||||
2. Return ? Get(iterResult, "value").
|
||||
features: [Symbol.iterator]
|
||||
---*/
|
||||
|
||||
var thrown = new Test262Error();
|
||||
var badIter = {};
|
||||
var poisonedValue = Object.defineProperty({ done: true }, 'value', {
|
||||
get: function() {
|
||||
throw thrown;
|
||||
}
|
||||
});
|
||||
badIter[Symbol.iterator] = function() {
|
||||
return {
|
||||
next: function() {
|
||||
return { done: false };
|
||||
},
|
||||
throw: function() {
|
||||
return poisonedValue;
|
||||
}
|
||||
};
|
||||
};
|
||||
function* g() {
|
||||
try {
|
||||
yield * badIter;
|
||||
} catch (err) {
|
||||
caught = err;
|
||||
}
|
||||
}
|
||||
var iter = g();
|
||||
var caught;
|
||||
|
||||
iter.next();
|
||||
iter.throw();
|
||||
|
||||
assert.sameValue(caught, thrown);
|
|
@ -0,0 +1,54 @@
|
|||
// Copyright (C) 2016 the V8 project authors. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
/*---
|
||||
esid: sec-generator-function-definitions-runtime-semantics-evaluation
|
||||
description: Value received from invocation of generator's `throw` method
|
||||
info: |
|
||||
YieldExpression : yield * AssignmentExpression
|
||||
|
||||
1. Let exprRef be the result of evaluating AssignmentExpression.
|
||||
2. Let value be ? GetValue(exprRef).
|
||||
3. Let iterator be ? GetIterator(value).
|
||||
4. Let received be NormalCompletion(undefined).
|
||||
5. Repeat
|
||||
a. If received.[[Type]] is normal, then
|
||||
[...]
|
||||
b. Else if received.[[Type]] is throw, then
|
||||
i. Let throw be ? GetMethod(iterator, "throw").
|
||||
ii. If throw is not undefined, then
|
||||
1. Let innerResult be ? Call(throw, iterator, « received.[[Value]]
|
||||
»).
|
||||
2. NOTE: Exceptions from the inner iterator throw method are
|
||||
propagated. Normal completions from an inner throw method are
|
||||
processed similarly to an inner next.
|
||||
3. If Type(innerResult) is not Object, throw a TypeError exception.
|
||||
4. Let done be ? IteratorComplete(innerResult).
|
||||
5. If done is true, then
|
||||
[...]
|
||||
6. Let received be GeneratorYield(innerResult).
|
||||
features: [Symbol.iterator]
|
||||
---*/
|
||||
|
||||
var quickIter = {};
|
||||
var iter, exprValue, throwReceived;
|
||||
quickIter[Symbol.iterator] = function() {
|
||||
return {
|
||||
next: function() {
|
||||
return { done: false };
|
||||
},
|
||||
throw: function(x) {
|
||||
throwReceived = x;
|
||||
return { done: true, value: 3333 };
|
||||
}
|
||||
};
|
||||
};
|
||||
function* g() {
|
||||
exprValue = yield * quickIter;
|
||||
}
|
||||
|
||||
iter = g();
|
||||
|
||||
iter.next();
|
||||
iter.throw(2222);
|
||||
assert.sameValue(throwReceived, 2222);
|
||||
assert.sameValue(exprValue, 3333);
|
|
@ -0,0 +1,52 @@
|
|||
// Copyright (C) 2016 the V8 project authors. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
/*---
|
||||
esid: sec-generator-function-definitions-runtime-semantics-evaluation
|
||||
es6id: 14.4.14
|
||||
description: Abrupt completion returned when invoking iterator `throw` method
|
||||
info: |
|
||||
YieldExpression : yield * AssignmentExpression
|
||||
|
||||
1. Let exprRef be the result of evaluating AssignmentExpression.
|
||||
2. Let value be ? GetValue(exprRef).
|
||||
3. Let iterator be ? GetIterator(value).
|
||||
4. Let received be NormalCompletion(undefined).
|
||||
5. Repeat
|
||||
a. If received.[[Type]] is normal, then
|
||||
[...]
|
||||
b. Else if received.[[Type]] is throw, then
|
||||
i. Let throw be ? GetMethod(iterator, "throw").
|
||||
ii. If throw is not undefined, then
|
||||
1. Let innerResult be ? Call(throw, iterator, « received.[[Value]]
|
||||
»).
|
||||
features: [Symbol.iterator]
|
||||
---*/
|
||||
|
||||
var thrown = new Test262Error();
|
||||
var badIter = {};
|
||||
badIter[Symbol.iterator] = function() {
|
||||
return {
|
||||
next: function() {
|
||||
return { done: false };
|
||||
},
|
||||
throw: function() {
|
||||
throw thrown;
|
||||
}
|
||||
};
|
||||
};
|
||||
function* g() {
|
||||
try {
|
||||
yield * badIter;
|
||||
} catch (err) {
|
||||
caught = err;
|
||||
}
|
||||
}
|
||||
var iter = g();
|
||||
var result, caught;
|
||||
|
||||
iter.next();
|
||||
result = iter.throw();
|
||||
|
||||
assert.sameValue(result.value, undefined);
|
||||
assert.sameValue(result.done, true);
|
||||
assert.sameValue(caught, thrown);
|
|
@ -0,0 +1,57 @@
|
|||
// Copyright (C) 2016 the V8 project authors. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
/*---
|
||||
esid: sec-generator-function-definitions-runtime-semantics-evaluation
|
||||
es6id: 14.4.14
|
||||
description: >
|
||||
TypeError thrown when iterator `throw` method returns a non-object value
|
||||
info: |
|
||||
YieldExpression : yield * AssignmentExpression
|
||||
|
||||
1. Let exprRef be the result of evaluating AssignmentExpression.
|
||||
2. Let value be ? GetValue(exprRef).
|
||||
3. Let iterator be ? GetIterator(value).
|
||||
4. Let received be NormalCompletion(undefined).
|
||||
5. Repeat
|
||||
a. If received.[[Type]] is normal, then
|
||||
[...]
|
||||
b. Else if received.[[Type]] is throw, then
|
||||
i. Let throw be ? GetMethod(iterator, "throw").
|
||||
ii. If throw is not undefined, then
|
||||
1. Let innerResult be ? Call(throw, iterator, « received.[[Value]]
|
||||
»).
|
||||
2. NOTE: Exceptions from the inner iterator throw method are
|
||||
propagated. Normal completions from an inner throw method are
|
||||
processed similarly to an inner next.
|
||||
3. If Type(innerResult) is not Object, throw a TypeError exception.
|
||||
features: [Symbol.iterator]
|
||||
---*/
|
||||
|
||||
var badIter = {};
|
||||
badIter[Symbol.iterator] = function() {
|
||||
return {
|
||||
next: function() {
|
||||
return { done: false };
|
||||
},
|
||||
throw: function() {
|
||||
return 23;
|
||||
}
|
||||
};
|
||||
};
|
||||
function* g() {
|
||||
try {
|
||||
yield * badIter;
|
||||
} catch (err) {
|
||||
caught = err;
|
||||
}
|
||||
}
|
||||
var iter = g();
|
||||
var result, caught;
|
||||
|
||||
iter.next();
|
||||
result = iter.throw();
|
||||
|
||||
assert.sameValue(result.value, undefined);
|
||||
assert.sameValue(result.done, true);
|
||||
assert.sameValue(typeof caught, 'object');
|
||||
assert.sameValue(caught.constructor, TypeError);
|
|
@ -0,0 +1,55 @@
|
|||
// Copyright (C) 2016 the V8 project authors. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
/*---
|
||||
esid: sec-generator-function-definitions-runtime-semantics-evaluation
|
||||
es6id: 14.4.14
|
||||
description: Abrupt completion returned when accessing iterator `throw` method
|
||||
info: |
|
||||
YieldExpression : yield * AssignmentExpression
|
||||
|
||||
1. Let exprRef be the result of evaluating AssignmentExpression.
|
||||
2. Let value be ? GetValue(exprRef).
|
||||
3. Let iterator be ? GetIterator(value).
|
||||
4. Let received be NormalCompletion(undefined).
|
||||
5. Repeat
|
||||
a. If received.[[Type]] is normal, then
|
||||
[...]
|
||||
b. Else if received.[[Type]] is throw, then
|
||||
i. Let throw be ? GetMethod(iterator, "throw").
|
||||
features: [Symbol.iterator]
|
||||
---*/
|
||||
|
||||
var thrown = new Test262Error();
|
||||
var badIter = {};
|
||||
var poisonedThrow = {
|
||||
next: function() {
|
||||
return { done: false };
|
||||
}
|
||||
};
|
||||
Object.defineProperty(poisonedThrow, 'throw', {
|
||||
get: function() {
|
||||
throw thrown;
|
||||
}
|
||||
});
|
||||
badIter[Symbol.iterator] = function() {
|
||||
return poisonedThrow;
|
||||
};
|
||||
function* g() {
|
||||
try {
|
||||
yield * badIter;
|
||||
} catch (err) {
|
||||
caught = err;
|
||||
}
|
||||
}
|
||||
var iter = g();
|
||||
var result, caught;
|
||||
|
||||
iter.next();
|
||||
|
||||
assert.sameValue(caught, undefined, '`throw` property not accesed eagerly');
|
||||
|
||||
result = iter.throw();
|
||||
|
||||
assert.sameValue(result.value, undefined);
|
||||
assert.sameValue(result.done, true);
|
||||
assert.sameValue(caught, thrown);
|
|
@ -0,0 +1,54 @@
|
|||
// Copyright (C) 2016 the V8 project authors. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
/*---
|
||||
esid: sec-generator-function-definitions-runtime-semantics-evaluation
|
||||
es6id: 14.4.14
|
||||
description: Invocation of iterator `throw` method
|
||||
info: |
|
||||
YieldExpression : yield * AssignmentExpression
|
||||
|
||||
1. Let exprRef be the result of evaluating AssignmentExpression.
|
||||
2. Let value be ? GetValue(exprRef).
|
||||
3. Let iterator be ? GetIterator(value).
|
||||
4. Let received be NormalCompletion(undefined).
|
||||
5. Repeat
|
||||
a. If received.[[Type]] is normal, then
|
||||
[...]
|
||||
b. Else if received.[[Type]] is throw, then
|
||||
i. Let throw be ? GetMethod(iterator, "throw").
|
||||
ii. If throw is not undefined, then
|
||||
1. Let innerResult be ? Call(throw, iterator, « received.[[Value]]
|
||||
»).
|
||||
[...]
|
||||
features: [Symbol.iterator]
|
||||
---*/
|
||||
|
||||
var args, thisValue;
|
||||
var callCount = 0;
|
||||
var spyIterator = {
|
||||
next: function() {
|
||||
return { done: false };
|
||||
},
|
||||
throw: function() {
|
||||
callCount += 1;
|
||||
args = arguments;
|
||||
thisValue = this;
|
||||
return { done: true };
|
||||
}
|
||||
};
|
||||
var spyIterable = {};
|
||||
spyIterable[Symbol.iterator] = function() {
|
||||
return spyIterator;
|
||||
};
|
||||
function* g() {
|
||||
yield * spyIterable;
|
||||
}
|
||||
var iter = g();
|
||||
|
||||
iter.next(8888);
|
||||
iter.throw(7777);
|
||||
|
||||
assert.sameValue(callCount, 1);
|
||||
assert.sameValue(args.length, 1);
|
||||
assert.sameValue(args[0], 7777);
|
||||
assert.sameValue(thisValue, spyIterator);
|
|
@ -0,0 +1,80 @@
|
|||
// Copyright (C) 2016 the V8 project authors. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
/*---
|
||||
esid: sec-generator-function-definitions-runtime-semantics-evaluation
|
||||
es6id: 14.4.14
|
||||
description: >
|
||||
Abrupt completion returned after protocol violation (and a `return` method
|
||||
is not defined)
|
||||
info: |
|
||||
YieldExpression : yield * AssignmentExpression
|
||||
|
||||
1. Let exprRef be the result of evaluating AssignmentExpression.
|
||||
2. Let value be ? GetValue(exprRef).
|
||||
3. Let iterator be ? GetIterator(value).
|
||||
4. Let received be NormalCompletion(undefined).
|
||||
5. Repeat
|
||||
a. If received.[[Type]] is normal, then
|
||||
[...]
|
||||
b. Else if received.[[Type]] is throw, then
|
||||
i. Let throw be ? GetMethod(iterator, "throw").
|
||||
ii. If throw is not undefined, then
|
||||
[...]
|
||||
iii. Else,
|
||||
1. NOTE: If iterator does not have a throw method, this throw is
|
||||
going to terminate the yield* loop. But first we need to give
|
||||
iterator a chance to clean up.
|
||||
2. Perform ? IteratorClose(iterator, Completion{[[Type]]: normal,
|
||||
[[Value]]: empty, [[Target]]: empty}).
|
||||
3. NOTE: The next step throws a TypeError to indicate that there
|
||||
was a yield* protocol violation: iterator does not have a throw
|
||||
method.
|
||||
4. Throw a TypeError exception.
|
||||
|
||||
7.4.6 IteratorClose
|
||||
|
||||
1. Assert: Type(iterator) is Object.
|
||||
2. Assert: completion is a Completion Record.
|
||||
3. Let return be ? GetMethod(iterator, "return").
|
||||
4. If return is undefined, return Completion(completion).
|
||||
features: [Symbol.iterator]
|
||||
---*/
|
||||
|
||||
var badIter = {};
|
||||
var throwCount = 0;
|
||||
var returnCount = 0;
|
||||
var spyResult = {
|
||||
next: function() {
|
||||
return { done: false };
|
||||
}
|
||||
};
|
||||
Object.defineProperty(spyResult, 'throw', {
|
||||
get: function() {
|
||||
throwCount += 1;
|
||||
}
|
||||
});
|
||||
Object.defineProperty(spyResult, 'return', {
|
||||
get: function() {
|
||||
returnCount += 1;
|
||||
}
|
||||
});
|
||||
badIter[Symbol.iterator] = function() {
|
||||
return spyResult;
|
||||
};
|
||||
function* g() {
|
||||
try {
|
||||
yield * badIter;
|
||||
} catch (err) {
|
||||
caught = err;
|
||||
}
|
||||
}
|
||||
var iter = g();
|
||||
var caught;
|
||||
|
||||
iter.next();
|
||||
iter.throw();
|
||||
|
||||
assert.sameValue(throwCount, 1, '`throw` property access');
|
||||
assert.sameValue(returnCount, 1, '`return` property access');
|
||||
assert.sameValue(typeof caught, 'object');
|
||||
assert.sameValue(caught.constructor, TypeError);
|
|
@ -0,0 +1,71 @@
|
|||
// Copyright (C) 2016 the V8 project authors. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
/*---
|
||||
esid: sec-generator-function-definitions-runtime-semantics-evaluation
|
||||
es6id: 14.4.14
|
||||
description: >
|
||||
Abrupt completion returned when invoking iterator `return` method following
|
||||
protocol violation
|
||||
info: |
|
||||
YieldExpression : yield * AssignmentExpression
|
||||
|
||||
1. Let exprRef be the result of evaluating AssignmentExpression.
|
||||
2. Let value be ? GetValue(exprRef).
|
||||
3. Let iterator be ? GetIterator(value).
|
||||
4. Let received be NormalCompletion(undefined).
|
||||
5. Repeat
|
||||
a. If received.[[Type]] is normal, then
|
||||
[...]
|
||||
b. Else if received.[[Type]] is throw, then
|
||||
i. Let throw be ? GetMethod(iterator, "throw").
|
||||
ii. If throw is not undefined, then
|
||||
[...]
|
||||
iii. Else,
|
||||
1. NOTE: If iterator does not have a throw method, this throw is
|
||||
going to terminate the yield* loop. But first we need to give
|
||||
iterator a chance to clean up.
|
||||
2. Perform ? IteratorClose(iterator, Completion{[[Type]]: normal,
|
||||
[[Value]]: empty, [[Target]]: empty}).
|
||||
|
||||
7.4.6 IteratorClose
|
||||
|
||||
1. Assert: Type(iterator) is Object.
|
||||
2. Assert: completion is a Completion Record.
|
||||
3. Let return be ? GetMethod(iterator, "return").
|
||||
4. If return is undefined, return Completion(completion).
|
||||
5. Let innerResult be Call(return, iterator, « »).
|
||||
6. If completion.[[Type]] is throw, return Completion(completion).
|
||||
7. If innerResult.[[Type]] is throw, return Completion(innerResult).
|
||||
8. If Type(innerResult.[[Value]]) is not Object, throw a TypeError exception.
|
||||
features: [Symbol.iterator]
|
||||
---*/
|
||||
|
||||
var badIter = {};
|
||||
badIter[Symbol.iterator] = function() {
|
||||
return {
|
||||
next: function() {
|
||||
return { done: false };
|
||||
},
|
||||
return: function() {
|
||||
// Using a primitive completion value ensures that the check for the type
|
||||
// of the completion value (and resulting TypeError) occurs *after* the
|
||||
// check for the type of the completion itself (which is the behavior
|
||||
// under test).
|
||||
throw 87;
|
||||
}
|
||||
};
|
||||
};
|
||||
function* g() {
|
||||
try {
|
||||
yield * badIter;
|
||||
} catch (err) {
|
||||
caught = err;
|
||||
}
|
||||
}
|
||||
var iter = g();
|
||||
var caught;
|
||||
|
||||
iter.next();
|
||||
iter.throw();
|
||||
|
||||
assert.sameValue(caught, 87);
|
|
@ -0,0 +1,68 @@
|
|||
// Copyright (C) 2016 the V8 project authors. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
/*---
|
||||
esid: sec-generator-function-definitions-runtime-semantics-evaluation
|
||||
es6id: 14.4.14
|
||||
description: >
|
||||
Non-object value returned by iterator `return` method following protocol
|
||||
violation
|
||||
info: |
|
||||
YieldExpression : yield * AssignmentExpression
|
||||
|
||||
1. Let exprRef be the result of evaluating AssignmentExpression.
|
||||
2. Let value be ? GetValue(exprRef).
|
||||
3. Let iterator be ? GetIterator(value).
|
||||
4. Let received be NormalCompletion(undefined).
|
||||
5. Repeat
|
||||
a. If received.[[Type]] is normal, then
|
||||
[...]
|
||||
b. Else if received.[[Type]] is throw, then
|
||||
i. Let throw be ? GetMethod(iterator, "throw").
|
||||
ii. If throw is not undefined, then
|
||||
[...]
|
||||
iii. Else,
|
||||
1. NOTE: If iterator does not have a throw method, this throw is
|
||||
going to terminate the yield* loop. But first we need to give
|
||||
iterator a chance to clean up.
|
||||
2. Perform ? IteratorClose(iterator, Completion{[[Type]]: normal,
|
||||
[[Value]]: empty, [[Target]]: empty}).
|
||||
|
||||
7.4.6 IteratorClose
|
||||
|
||||
1. Assert: Type(iterator) is Object.
|
||||
2. Assert: completion is a Completion Record.
|
||||
3. Let return be ? GetMethod(iterator, "return").
|
||||
4. If return is undefined, return Completion(completion).
|
||||
5. Let innerResult be Call(return, iterator, « »).
|
||||
6. If completion.[[Type]] is throw, return Completion(completion).
|
||||
7. If innerResult.[[Type]] is throw, return Completion(innerResult).
|
||||
8. If Type(innerResult.[[Value]]) is not Object, throw a TypeError exception.
|
||||
features: [Symbol.iterator]
|
||||
---*/
|
||||
|
||||
var badIter = {};
|
||||
badIter[Symbol.iterator] = function() {
|
||||
return {
|
||||
next: function() {
|
||||
return { done: false };
|
||||
},
|
||||
return: function() {
|
||||
return 87;
|
||||
}
|
||||
};
|
||||
};
|
||||
function* g() {
|
||||
try {
|
||||
yield * badIter;
|
||||
} catch (err) {
|
||||
caught = err;
|
||||
}
|
||||
}
|
||||
var iter = g();
|
||||
var caught;
|
||||
|
||||
iter.next();
|
||||
iter.throw();
|
||||
|
||||
assert.sameValue(typeof caught, 'object');
|
||||
assert.sameValue(caught.constructor, TypeError);
|
|
@ -0,0 +1,73 @@
|
|||
// Copyright (C) 2016 the V8 project authors. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
/*---
|
||||
esid: sec-generator-function-definitions-runtime-semantics-evaluation
|
||||
es6id: 14.4.14
|
||||
description: >
|
||||
Abrupt completion returned when accessing iterator `return` property after
|
||||
protocol violation
|
||||
info: |
|
||||
YieldExpression : yield * AssignmentExpression
|
||||
|
||||
1. Let exprRef be the result of evaluating AssignmentExpression.
|
||||
2. Let value be ? GetValue(exprRef).
|
||||
3. Let iterator be ? GetIterator(value).
|
||||
4. Let received be NormalCompletion(undefined).
|
||||
5. Repeat
|
||||
a. If received.[[Type]] is normal, then
|
||||
[...]
|
||||
b. Else if received.[[Type]] is throw, then
|
||||
i. Let throw be ? GetMethod(iterator, "throw").
|
||||
ii. If throw is not undefined, then
|
||||
[...]
|
||||
iii. Else,
|
||||
1. NOTE: If iterator does not have a throw method, this throw is
|
||||
going to terminate the yield* loop. But first we need to give
|
||||
iterator a chance to clean up.
|
||||
2. Perform ? IteratorClose(iterator, Completion{[[Type]]: normal,
|
||||
[[Value]]: empty, [[Target]]: empty}).
|
||||
|
||||
7.4.6 IteratorClose
|
||||
|
||||
1. Assert: Type(iterator) is Object.
|
||||
2. Assert: completion is a Completion Record.
|
||||
3. Let return be ? GetMethod(iterator, "return").
|
||||
features: [Symbol.iterator]
|
||||
---*/
|
||||
|
||||
var thrown = new Test262Error();
|
||||
var badIter = {};
|
||||
var callCount = 0;
|
||||
var poisonedReturn = {
|
||||
next: function() {
|
||||
return { done: false };
|
||||
}
|
||||
};
|
||||
Object.defineProperty(poisonedReturn, 'throw', {
|
||||
get: function() {
|
||||
callCount += 1;
|
||||
}
|
||||
});
|
||||
Object.defineProperty(poisonedReturn, 'return', {
|
||||
get: function() {
|
||||
throw thrown;
|
||||
}
|
||||
});
|
||||
badIter[Symbol.iterator] = function() {
|
||||
return poisonedReturn;
|
||||
};
|
||||
function* g() {
|
||||
try {
|
||||
yield * badIter;
|
||||
} catch (err) {
|
||||
caught = err;
|
||||
}
|
||||
}
|
||||
var iter = g();
|
||||
var caught;
|
||||
|
||||
iter.next();
|
||||
iter.throw();
|
||||
|
||||
assert.sameValue(callCount, 1);
|
||||
assert.sameValue(caught, thrown);
|
|
@ -0,0 +1,89 @@
|
|||
// Copyright (C) 2016 the V8 project authors. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
/*---
|
||||
esid: sec-generator-function-definitions-runtime-semantics-evaluation
|
||||
es6id: 14.4.14
|
||||
description: >
|
||||
Abrupt completion returned after protocol violation (and a `return` method
|
||||
is defined)
|
||||
info: |
|
||||
YieldExpression : yield * AssignmentExpression
|
||||
|
||||
1. Let exprRef be the result of evaluating AssignmentExpression.
|
||||
2. Let value be ? GetValue(exprRef).
|
||||
3. Let iterator be ? GetIterator(value).
|
||||
4. Let received be NormalCompletion(undefined).
|
||||
5. Repeat
|
||||
a. If received.[[Type]] is normal, then
|
||||
[...]
|
||||
b. Else if received.[[Type]] is throw, then
|
||||
i. Let throw be ? GetMethod(iterator, "throw").
|
||||
ii. If throw is not undefined, then
|
||||
[...]
|
||||
iii. Else,
|
||||
1. NOTE: If iterator does not have a throw method, this throw is
|
||||
going to terminate the yield* loop. But first we need to give
|
||||
iterator a chance to clean up.
|
||||
2. Perform ? IteratorClose(iterator, Completion{[[Type]]: normal,
|
||||
[[Value]]: empty, [[Target]]: empty}).
|
||||
3. NOTE: The next step throws a TypeError to indicate that there
|
||||
was a yield* protocol violation: iterator does not have a throw
|
||||
method.
|
||||
4. Throw a TypeError exception.
|
||||
|
||||
7.4.6 IteratorClose
|
||||
|
||||
1. Assert: Type(iterator) is Object.
|
||||
2. Assert: completion is a Completion Record.
|
||||
3. Let return be ? GetMethod(iterator, "return").
|
||||
4. If return is undefined, return Completion(completion).
|
||||
5. Let innerResult be Call(return, iterator, « »).
|
||||
6. If completion.[[Type]] is throw, return Completion(completion).
|
||||
7. If innerResult.[[Type]] is throw, return Completion(innerResult).
|
||||
8. If Type(innerResult.[[Value]]) is not Object, throw a TypeError exception.
|
||||
9. Return Completion(completion).
|
||||
features: [Symbol.iterator]
|
||||
---*/
|
||||
|
||||
var badIter = {};
|
||||
var throwCount = 0;
|
||||
var thisValue, args;
|
||||
var poisonedReturn = {
|
||||
next: function() {
|
||||
return { done: false };
|
||||
},
|
||||
return: function() {
|
||||
thisValue = this;
|
||||
args = arguments;
|
||||
return 'this value has no effect on the protocol';
|
||||
}
|
||||
};
|
||||
Object.defineProperty(poisonedReturn, 'throw', {
|
||||
get: function() {
|
||||
throwCount += 1;
|
||||
}
|
||||
});
|
||||
badIter[Symbol.iterator] = function() {
|
||||
return poisonedReturn;
|
||||
};
|
||||
function* g() {
|
||||
try {
|
||||
yield * badIter;
|
||||
} catch (err) {
|
||||
caught = err;
|
||||
}
|
||||
}
|
||||
var iter = g();
|
||||
var caught;
|
||||
|
||||
iter.next();
|
||||
iter.throw();
|
||||
|
||||
assert.sameValue(throwCount, 1);
|
||||
assert.sameValue(thisValue, poisonedReturn, '"this" value');
|
||||
assert.sameValue(
|
||||
typeof args, 'object', 'method invoked, arguments object provided'
|
||||
);
|
||||
assert.sameValue(args.length, 0);
|
||||
assert.sameValue(typeof caught, 'object', 'object value thrown');
|
||||
assert.sameValue(caught.constructor, TypeError);
|
|
@ -0,0 +1,30 @@
|
|||
// Copyright (C) 2016 the V8 project authors. All rights reserved.
|
||||
// This code is governed by the BSD license found in the LICENSE file.
|
||||
/*---
|
||||
esid: sec-generator-function-definitions-runtime-semantics-evaluation
|
||||
es6id: 14.4.14
|
||||
description: GetValue invoked on Reference value
|
||||
info: |
|
||||
YieldExpression : yield * AssignmentExpression
|
||||
|
||||
1. Let exprRef be the result of evaluating AssignmentExpression.
|
||||
2. Let value be ? GetValue(exprRef).
|
||||
---*/
|
||||
|
||||
var err;
|
||||
function* g() {
|
||||
try {
|
||||
yield * test262unresolvable;
|
||||
} catch (_err) {
|
||||
err = _err;
|
||||
}
|
||||
}
|
||||
var iter = g();
|
||||
var result;
|
||||
|
||||
result = iter.next();
|
||||
|
||||
assert.sameValue(result.value, undefined);
|
||||
assert.sameValue(result.done, true);
|
||||
assert.sameValue(typeof err, 'object');
|
||||
assert.sameValue(err.constructor, ReferenceError);
|
Loading…
Reference in New Issue