v8/test/mjsunit/harmony/for-await-of.js
caitp 76ab55e3d3 [async-iteration] add support for for-await-of loops in Async Functions
When --harmony-async-iteration is enabled, it is now possible to
use the for-await-of loop, which uses the Async Iteration protocol
rather than the ordinary ES6 Iteration protocol.

the Async-from-Sync Iterator object is not implemented in this CL,
and so for-await-of loops will abort execution if the iterated object
does not have a Symbol.asyncIterator() method. Async-from-Sync
Iterators are implemented seperately in https://codereview.chromium.org/2645313003/

BUG=v8:5855, v8:4483
R=neis@chromium.org, littledan@chromium.org, adamk@chromium.org

Review-Url: https://codereview.chromium.org/2637403008
Cr-Commit-Position: refs/heads/master@{#43224}
2017-02-15 19:39:06 +00:00

1265 lines
36 KiB
JavaScript

// Copyright 2017 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --harmony-async-iteration --allow-natives-syntax
let testFailed = false;
let testFailure;
(async function() {
const kNext = 1;
const kThrow = 2;
const kReturn = 4;
const kReturnPrimitive = kReturn | 32;
function async(iterable, features = kNext, log = []) {
// Helper to turn a synchronous iterable into an asynchronous iterable,
// without using the [Async-from-Sync Iterator].
let it = iterable[Symbol.iterator]();
let methods = {
next(sentValue) {
return new Promise(function(resolve, reject) {
let {value, done} = it.next(sentValue);
Promise.resolve(value).then(function(value) {
log.push('.next() -> resolved ' + value);
resolve({value, done});
}, function(value) {
log.push('.next() -> rejected ' + value);
reject(value);
});
});
},
throw(sentValue) {
return new Promise(function(resolve, reject) {
let throwMethod = it.throw;
if (typeof throwMethod !== 'function') {
log.push('.throw(' + sentValue + ')');
return reject(sentValue);
}
let {value, done} = throwMethod.call(it, sentValue);
Promise.resolve(value).then(function(value) {
log.push('.throw() -> resolved ' + value);
resolve({ value, done });
}, function(value) {
log.push('.throw() -> rejected ' + value);
reject(value);
});
});
},
return(sentValue) {
return new Promise(function(resolve, reject) {
let returnMethod = it.return;
if (typeof returnMethod !== 'function') {
log.push('.return(' + sentValue + ')');
if ((features & kReturnPrimitive) === kReturnPrimitive)
return resolve(sentValue);
return resolve({value: sentValue, done: true});
}
let {value, done} = returnMethod.call(it, sentValue);
Promise.resolve(value).then(function(value) {
log.push('.return() -> resolved ' + value);
if ((features & kReturnPrimitive) === kReturnPrimitive)
return resolve(value);
resolve({ value, done });
}, function(value) {
log.push('.return() -> rejected ' + value);
reject(value);
});
});
}
};
return {
[Symbol.asyncIterator]() {
log.push('[Symbol.asyncIterator]()')
return this;
},
next: (features & kNext) ? methods.next : undefined,
throw: (features & kThrow) ? methods.throw : undefined,
return: (features & kReturn) ? methods.return : undefined
};
}
let testDone;
let test;
async function testBindingIdentifierVarDeclarationStatement() {
let sum = 0;
testDone = false;
for await (var value of async([100, 200, 300, 400, 500])) sum += value;
testDone = true;
return sum;
}
test = testBindingIdentifierVarDeclarationStatement();
assertFalse(testDone);
assertEquals(1500, await test);
assertTrue(testDone);
async function testBindingIdentifierVarDeclarationBlockStatement() {
let sum = 0;
testDone = false;
for await (var value of async([100, 200, 300, 400, 500])) {
'use strict';
let strict = (function() { return this === undefined; })();
assertFalse(strict);
sum += value;
}
testDone = true;
return sum;
}
test = testBindingIdentifierVarDeclarationBlockStatement();
assertFalse(testDone);
assertEquals(1500, await test);
assertTrue(testDone);
async function testObjectBindingPatternVarDeclarationStatement() {
let sum = 0, keys = [];
let collection = [
{key: 'first', value: 10}, {key: undefined, value: 20}, {value: 30},
{key: 'last', value: 40}
];
testDone = false;
for await (var {key = 'unknown', value} of async(collection))
keys.push(key), sum += value;
testDone = true;
return {keys, sum};
}
test = testObjectBindingPatternVarDeclarationStatement();
assertFalse(testDone);
assertEquals(
{keys: ['first', 'unknown', 'unknown', 'last'], sum: 100}, await test);
assertTrue(testDone);
async function testObjectBindingPatternVarDeclarationBlockStatement() {
let sum = 0, keys = [];
let collection = [
{key: 'first', value: 10}, {key: undefined, value: 20}, {value: 30},
{key: 'last', value: 40}
];
testDone = false;
for await (var {key = 'unknown', value} of async(collection)) {
'use strict';
let strict = (function() { return this === undefined; })();
assertFalse(strict);
keys.push(key);
sum += value;
}
testDone = true;
return {keys, sum};
}
test = testObjectBindingPatternVarDeclarationBlockStatement();
assertFalse(testDone);
assertEquals(
{keys: ['first', 'unknown', 'unknown', 'last'], sum: 100}, await test);
assertTrue(testDone);
async function testArrayBindingPatternVarDeclarationStatement() {
let sum = 0, keys = [];
let collection = [['first', 10], [undefined, 20], [, 30], ['last', 40]];
testDone = false;
for await (var [key = 'unknown', value] of async(collection))
keys.push(key), sum += value;
testDone = true;
return {keys, sum};
}
test = testArrayBindingPatternVarDeclarationStatement();
assertFalse(testDone);
assertEquals(
{keys: ['first', 'unknown', 'unknown', 'last'], sum: 100}, await test);
assertTrue(testDone);
async function testArrayBindingPatternVarDeclarationBlockStatement() {
let sum = 0, keys = [];
let collection = [['first', 10], [undefined, 20], [, 30], ['last', 40]];
testDone = false;
for await (var [key = 'unknown', value] of async(collection)) {
'use strict';
let strict = (function() { return this === undefined; })();
assertFalse(strict);
keys.push(key);
sum += value;
}
testDone = true;
return {keys, sum};
}
test = testArrayBindingPatternVarDeclarationBlockStatement();
assertFalse(testDone);
assertEquals(
{keys: ['first', 'unknown', 'unknown', 'last'], sum: 100}, await test);
assertTrue(testDone);
// --------------------------------------------------------------------------
async function testBindingIdentifierLetDeclarationStatement() {
let sum = 0;
testDone = false;
for await (let value of async([100, 200, 300, 400, 500])) sum += value;
testDone = true;
return sum;
}
test = testBindingIdentifierLetDeclarationStatement();
assertFalse(testDone);
assertEquals(1500, await test);
assertTrue(testDone);
async function testBindingIdentifierLetDeclarationBlockStatement() {
let sum = 0;
testDone = false;
for await (let value of async([100, 200, 300, 400, 500])) {
'use strict';
let strict = (function() { return this === undefined; })();
assertFalse(strict);
sum += value;
}
testDone = true;
return sum;
}
test = testBindingIdentifierLetDeclarationBlockStatement();
assertFalse(testDone);
assertEquals(1500, await test);
assertTrue(testDone);
async function testObjectBindingPatternLetDeclarationStatement() {
let sum = 0, keys = [];
let collection = [
{key: 'first', value: 10}, {key: undefined, value: 20}, {value: 30},
{key: 'last', value: 40}
];
testDone = false;
for await (let {key = 'unknown', value} of async(collection))
keys.push(key), sum += value;
testDone = true;
return {keys, sum};
}
test = testObjectBindingPatternLetDeclarationStatement();
assertFalse(testDone);
assertEquals(
{keys: ['first', 'unknown', 'unknown', 'last'], sum: 100}, await test);
assertTrue(testDone);
async function testObjectBindingPatternLetDeclarationBlockStatement() {
let sum = 0, keys = [];
let collection = [
{key: 'first', value: 10}, {key: undefined, value: 20}, {value: 30},
{key: 'last', value: 40}
];
testDone = false;
for await (let {key = 'unknown', value} of async(collection)) {
'use strict';
let strict = (function() { return this === undefined; })();
assertFalse(strict);
keys.push(key);
sum += value;
}
testDone = true;
return {keys, sum};
}
let threwEarly = false;
test = testObjectBindingPatternLetDeclarationBlockStatement();
assertFalse(testDone);
assertEquals(
{keys: ['first', 'unknown', 'unknown', 'last'], sum: 100}, await test);
assertTrue(testDone);
async function testObjectBindingPatternTDZLetDeclarationStatement() {
// See https://codereview.chromium.org/1218543003
let sum = 0;
testDone = false;
let value = { value: 1 };
try {
for await (let {value} of async([value])) sum += value;
} catch (error) {
threwEarly = true;
throw { sum, error, toString() { return 'TestError' } };
}
}
test = testObjectBindingPatternTDZLetDeclarationStatement();
assertTrue(threwEarly, 'Async function promise should be rejected');
try {
await test;
} catch (e) {
assertEquals('TestError', e.toString());
assertEquals(0, e.sum);
assertInstanceof(e.error, ReferenceError);
testDone = true;
}
assertTrue(testDone, 'Awaited promise should be rejected');
async function testObjectBindingPatternTDZLetDeclarationBlockStatement() {
// See https://codereview.chromium.org/1218543003
let sum = 0;
testDone = false;
let value = { value: 1 };
try {
for await (let {value} of async([value])) {
sum += value;
}
} catch (error) {
threwEarly = true;
throw { sum, error, toString() { return 'TestError' } };
}
}
threwEarly = false;
test = testObjectBindingPatternTDZLetDeclarationBlockStatement();
assertTrue(threwEarly, 'Async function promise should be rejected');
try {
await test;
} catch (e) {
assertEquals('TestError', e.toString());
assertEquals(0, e.sum);
assertInstanceof(e.error, ReferenceError);
testDone = true;
}
assertTrue(testDone, 'Awaited promise should be rejected');
async function testArrayBindingPatternLetDeclarationStatement() {
let sum = 0, keys = [];
let collection = [['first', 10], [undefined, 20], [, 30], ['last', 40]];
testDone = false;
for await (let [key = 'unknown', value] of async(collection))
keys.push(key), sum += value;
testDone = true;
return {keys, sum};
}
test = testArrayBindingPatternLetDeclarationStatement();
assertFalse(testDone);
assertEquals(
{keys: ['first', 'unknown', 'unknown', 'last'], sum: 100}, await test);
assertTrue(testDone);
async function testArrayBindingPatternLetDeclarationBlockStatement() {
let sum = 0, keys = [];
let collection = [['first', 10], [undefined, 20], [, 30], ['last', 40]];
testDone = false;
for await (let [key = 'unknown', value] of async(collection)) {
'use strict';
let strict = (function() { return this === undefined; })();
assertFalse(strict);
keys.push(key);
sum += value;
}
testDone = true;
return {keys, sum};
}
test = testArrayBindingPatternLetDeclarationBlockStatement();
assertFalse(testDone);
assertEquals(
{keys: ['first', 'unknown', 'unknown', 'last'], sum: 100}, await test);
assertTrue(testDone);
async function testArrayBindingPatternTDZLetDeclarationStatement() {
// See https://codereview.chromium.org/1218543003
let sum = 0;
testDone = false;
let value = [1];
try {
for await (let [value] of async([value])) sum += value;
} catch (error) {
threwEarly = true;
throw { sum, error, toString() { return 'TestError' } };
}
}
threwEarly = false;
test = testArrayBindingPatternTDZLetDeclarationStatement();
assertTrue(threwEarly, 'Async function promise should be rejected');
try {
await test;
} catch (e) {
assertEquals('TestError', e.toString());
assertEquals(0, e.sum);
assertInstanceof(e.error, ReferenceError);
testDone = true;
}
assertTrue(testDone, 'Awaited promise should be rejected');
async function testArrayBindingPatternTDZLetDeclarationBlockStatement() {
// See https://codereview.chromium.org/1218543003
let sum = 0;
testDone = false;
let value = [1];
try {
for await (let [value] of async([value])) {
sum += value;
}
} catch (error) {
threwEarly = true;
throw { sum, error, toString() { return 'TestError' } };
}
}
threwEarly = false;
test = testArrayBindingPatternTDZLetDeclarationBlockStatement();
assertTrue(threwEarly, 'Async function promise should be rejected');
try {
await test;
} catch (e) {
assertEquals('TestError', e.toString());
assertEquals(0, e.sum);
assertInstanceof(e.error, ReferenceError);
testDone = true;
}
assertTrue(testDone, 'Awaited promise should be rejected');
// --------------------------------------------------------------------------
async function testBindingIdentifierConstDeclarationStatement() {
let sum = 0;
testDone = false;
for await (let value of async([100, 200, 300, 400, 500])) sum += value;
testDone = true;
return sum;
}
test = testBindingIdentifierConstDeclarationStatement();
assertFalse(testDone);
assertEquals(1500, await test);
assertTrue(testDone);
async function testBindingIdentifierConstDeclarationBlockStatement() {
let sum = 0;
testDone = false;
for await (const value of async([100, 200, 300, 400, 500])) {
'use strict';
let strict = (function() { return this === undefined; })();
assertFalse(strict);
sum += value;
}
testDone = true;
return sum;
}
test = testBindingIdentifierConstDeclarationBlockStatement();
assertFalse(testDone);
assertEquals(1500, await test);
assertTrue(testDone);
async function testObjectBindingPatternConstDeclarationStatement() {
let sum = 0, keys = [];
let collection = [
{key: 'first', value: 10}, {key: undefined, value: 20}, {value: 30},
{key: 'last', value: 40}
];
testDone = false;
for await (const {key = 'unknown', value} of async(collection))
keys.push(key), sum += value;
testDone = true;
return {keys, sum};
}
test = testObjectBindingPatternConstDeclarationStatement();
assertFalse(testDone);
assertEquals(
{keys: ['first', 'unknown', 'unknown', 'last'], sum: 100}, await test);
assertTrue(testDone);
async function testObjectBindingPatternConstDeclarationBlockStatement() {
let sum = 0, keys = [];
let collection = [
{key: 'first', value: 10}, {key: undefined, value: 20}, {value: 30},
{key: 'last', value: 40}
];
testDone = false;
for await (const {key = 'unknown', value} of async(collection)) {
'use strict';
let strict = (function() { return this === undefined; })();
assertFalse(strict);
keys.push(key);
sum += value;
}
testDone = true;
return {keys, sum};
}
test = testObjectBindingPatternConstDeclarationBlockStatement();
assertFalse(testDone);
assertEquals(
{keys: ['first', 'unknown', 'unknown', 'last'], sum: 100}, await test);
assertTrue(testDone);
async function testObjectBindingPatternTDZConstDeclarationStatement() {
// See https://codereview.chromium.org/1218543003
let sum = 0;
testDone = false;
const value = { value: 1 };
try {
for await (const {value} of async([value])) sum += value;
} catch (error) {
threwEarly = true;
throw { sum, error, toString() { return 'TestError' } };
}
}
threwEarly = false;
test = testObjectBindingPatternTDZConstDeclarationStatement();
assertTrue(threwEarly, 'Async function promise should be rejected');
try {
await test;
} catch (e) {
assertEquals('TestError', e.toString());
assertEquals(0, e.sum);
assertInstanceof(e.error, ReferenceError);
testDone = true;
}
assertTrue(testDone, 'Awaited promise should be rejected');
async function testObjectBindingPatternTDZConstDeclarationBlockStatement() {
// See https://codereview.chromium.org/1218543003
let sum = 0;
testDone = false;
const value = { value: 1 };
try {
for await (const {value} of async([value])) {
sum += value;
}
} catch (error) {
threwEarly = true;
throw { sum, error, toString() { return 'TestError' } };
}
}
threwEarly = false;
test = testObjectBindingPatternTDZConstDeclarationBlockStatement();
assertTrue(threwEarly, 'Async function promise should be rejected');
try {
await test;
} catch (e) {
assertEquals('TestError', e.toString());
assertEquals(0, e.sum);
assertInstanceof(e.error, ReferenceError);
testDone = true;
}
assertTrue(testDone, 'Awaited promise should be rejected');
async function testArrayBindingPatternConstDeclarationStatement() {
let sum = 0, keys = [];
let collection = [['first', 10], [undefined, 20], [, 30], ['last', 40]];
testDone = false;
for await (const [key = 'unknown', value] of async(collection))
keys.push(key), sum += value;
testDone = true;
return {keys, sum};
}
test = testArrayBindingPatternConstDeclarationStatement();
assertFalse(testDone);
assertEquals(
{keys: ['first', 'unknown', 'unknown', 'last'], sum: 100}, await test);
assertTrue(testDone);
async function testArrayBindingPatternConstDeclarationBlockStatement() {
let sum = 0, keys = [];
let collection = [['first', 10], [undefined, 20], [, 30], ['last', 40]];
testDone = false;
for await (const [key = 'unknown', value] of async(collection)) {
'use strict';
let strict = (function() { return this === undefined; })();
assertFalse(strict);
keys.push(key);
sum += value;
}
testDone = true;
return {keys, sum};
}
test = testArrayBindingPatternLetDeclarationBlockStatement();
assertFalse(testDone);
assertEquals(
{keys: ['first', 'unknown', 'unknown', 'last'], sum: 100}, await test);
assertTrue(testDone);
async function testArrayBindingPatternTDZConstDeclarationStatement() {
// See https://codereview.chromium.org/1218543003
let sum = 0;
testDone = false;
const value = [1];
try {
for await (const [value] of async([value])) sum += value;
} catch (error) {
threwEarly = true;
throw { sum, error, toString() { return 'TestError' } };
}
}
threwEarly = false;
test = testArrayBindingPatternTDZConstDeclarationStatement();
assertTrue(threwEarly, 'Async function promise should be rejected');
try {
await test;
} catch (e) {
assertEquals('TestError', e.toString());
assertEquals(0, e.sum);
assertInstanceof(e.error, ReferenceError);
testDone = true;
}
assertTrue(testDone, 'Awaited promise should be rejected');
async function testArrayBindingPatternTDZConstDeclarationBlockStatement() {
// See https://codereview.chromium.org/1218543003
let sum = 0;
testDone = false;
const value = [1];
try {
for await (const [value] of async([value])) {
sum += value;
}
} catch (error) {
threwEarly = true;
throw { sum, error, toString() { return 'TestError' } };
}
}
threwEarly = false;
test = testArrayBindingPatternTDZConstDeclarationBlockStatement();
assertTrue(threwEarly, 'Async function promise should be rejected');
try {
await test;
} catch (e) {
assertEquals('TestError', e.toString());
assertEquals(0, e.sum);
assertInstanceof(e.error, ReferenceError);
testDone = true;
}
assertTrue(testDone, 'Awaited promise should be rejected');
// --------------------------------------------------------------------------
async function testBindingIdentifierLHSStatement() {
let sum = 0;
let value;
testDone = false;
for await (value of async([100, 200, 300, 400, 500])) sum += value;
testDone = true;
return sum;
}
test = testBindingIdentifierLHSStatement();
assertFalse(testDone);
assertEquals(1500, await test);
assertTrue(testDone);
async function testBindingIdentifierLHSBlockStatement() {
let sum = 0;
let value;
testDone = false;
for await (value of async([100, 200, 300, 400, 500])) {
'use strict';
let strict = (function() { return this === undefined; })();
assertFalse(strict);
sum += value;
}
testDone = true;
return sum;
}
test = testBindingIdentifierLHSStatement();
assertFalse(testDone);
assertEquals(1500, await test);
assertTrue(testDone);
async function testObjectBindingPatternLHSStatement() {
let sum = 0;
let keys = [];
let value;
let key;
let collection = [
{key: 'first', value: 1}, {key: undefined, value: 2}, {value: 3},
{key: 'last', value: 4}
];
testDone = false;
for await ({key = 'unknown', value} of async(collection))
keys.push(key), sum += value;
testDone = true;
return {keys, sum};
}
test = testObjectBindingPatternLHSStatement();
assertFalse(testDone);
assertEquals(
{keys: ['first', 'unknown', 'unknown', 'last'], sum: 10}, await test);
assertTrue(testDone);
async function testObjectBindingPatternLHSBlockStatement() {
let sum = 0;
let keys = [];
let value;
let key;
let collection = [
{key: 'first', value: 1}, {key: undefined, value: 2}, {value: 3},
{key: 'last', value: 4}
];
testDone = false;
for await ({key = 'unknown', value} of async(collection)) {
'use strict';
let strict = (function() { return this === undefined; })();
assertFalse(strict);
keys.push(key);
sum += value;
}
testDone = true;
return {keys, sum};
}
test = testObjectBindingPatternLHSBlockStatement();
assertFalse(testDone);
assertEquals(
{keys: ['first', 'unknown', 'unknown', 'last'], sum: 10}, await test);
assertTrue(testDone);
async function testArrayBindingPatternLHSStatement() {
let sum = 0;
let keys = [];
let value;
let key;
let collection = [['first', 1], [undefined, 2], [, 3], ['last', 4]];
testDone = false;
for await ([key = 'unknown', value] of async(collection)) {
'use strict';
let strict = (function() { return this === undefined; })();
assertFalse(strict);
keys.push(key);
sum += value;
}
testDone = true;
return {keys, sum};
}
test = testArrayBindingPatternLHSStatement();
assertFalse(testDone);
assertEquals(
{keys: ['first', 'unknown', 'unknown', 'last'], sum: 10}, await test);
assertTrue(testDone);
async function testArrayBindingPatternLHSBlockStatement() {
let sum = 0;
let keys = [];
let value;
let key;
let collection = [
{key: 'first', value: 1}, {key: undefined, value: 2}, {value: 3},
{key: 'last', value: 4}
];
testDone = false;
for await ({key = 'unknown', value} of async(collection)) {
'use strict';
let strict = (function() { return this === undefined; })();
assertFalse(strict);
keys.push(key);
sum += value;
}
testDone = true;
return {keys, sum};
}
test = testArrayBindingPatternLHSBlockStatement();
assertFalse(testDone);
assertEquals(
{keys: ['first', 'unknown', 'unknown', 'last'], sum: 10}, await test);
assertTrue(testDone);
// --------------------------------------------------------------------------
async function testBreakStatementReturnMethodNotPresent() {
let log = [];
let collection = [1, 2, 3, 4, 5];
let sum = 0;
let i = 0;
testDone = false;
for await (var x of async(collection, kNext, log)) {
sum += x;
if (++i === 3) break;
}
testDone = true;
return { sum, log };
}
test = testBreakStatementReturnMethodNotPresent();
assertFalse(testDone);
assertEquals({sum: 6, log: ['[Symbol.asyncIterator]()',
'.next() -> resolved 1',
'.next() -> resolved 2',
'.next() -> resolved 3']},
await test);
assertTrue(testDone);
async function testBreakStatementReturnMethodPresent() {
let log = [];
let collection = [1, 2, 3, 4, 5];
let sum = 0;
let i = 0;
testDone = false;
for await (var x of async(collection, kNext|kReturn, log)) {
sum += x;
if (++i === 2) break;
}
testDone = true;
return { sum, log };
}
test = testBreakStatementReturnMethodPresent();
assertFalse(testDone);
assertEquals({sum: 3, log: ['[Symbol.asyncIterator]()',
'.next() -> resolved 1',
'.next() -> resolved 2',
'.return(undefined)']},
await test);
assertTrue(testDone);
async function testBreakStatementReturnMethodAwaitIterResult() {
let log = [];
let collection = [1, 2, 3, 4, 5];
let sync_iter = collection[Symbol.iterator]();
sync_iter.return = function() {
return {
value: new Promise(function(resolve, reject) {
Promise.resolve().then(function() {
resolve('break!');
});
}),
done: true
};
};
let sum = 0;
let i = 0;
testDone = false;
for await (var x of async(sync_iter, kNext|kReturn, log)) {
sum += x;
if (++i === 2) break;
}
testDone = true;
return { sum, log };
}
test = testBreakStatementReturnMethodAwaitIterResult();
assertFalse(testDone);
assertEquals({sum: 3,
log: ['[Symbol.asyncIterator]()',
'.next() -> resolved 1',
'.next() -> resolved 2',
'.return() -> resolved break!' ]},
await test);
assertTrue(testDone);
async function testBreakStatementReturnMethodAwaitRejection(log) {
let collection = [1, 2, 3, 4, 5];
let sync_iter = collection[Symbol.iterator]();
let sum = 0;
sync_iter.return = function() {
return {
value: new Promise(function(resolve, reject) {
Promise.resolve().then(function() {
reject('break! ' + sum);
});
}),
done: true
};
};
let i = 0;
testDone = false;
for await (var x of async(sync_iter, kNext|kReturn, log)) {
sum += x;
if (++i === 2) break;
}
return { sum, log };
}
let log = [];
test = testBreakStatementReturnMethodAwaitRejection(log);
assertFalse(testDone);
try {
await test;
} catch (e) {
assertEquals(log, ['[Symbol.asyncIterator]()',
'.next() -> resolved 1',
'.next() -> resolved 2',
'.return() -> rejected break! 3']);
assertEquals('break! 3', e);
testDone = true;
}
assertTrue(testDone, 'Promise should be rejected');
async function testBreakStatementReturnMethodPrimitiveValue(log) {
let collection = [1, 2, 3, 4, 5];
let sync_iter = collection[Symbol.iterator]();
sync_iter.return = function() {
return { value: 'break! primitive!', done: true };
}
let sum = 0;
let i = 0;
testDone = false;
for await (var x of async(sync_iter, kNext|kReturnPrimitive, log)) {
sum += x;
if (++i === 2) break;
}
return { sum, log };
}
log = [];
test = testBreakStatementReturnMethodPrimitiveValue(log);
assertFalse(testDone);
try {
await test;
} catch (e) {
assertEquals(['[Symbol.asyncIterator]()',
'.next() -> resolved 1',
'.next() -> resolved 2',
'.return() -> resolved break! primitive!'],
log);
assertInstanceof(e, TypeError);
testDone = true;
}
assertTrue(testDone, 'Promise should be rejected');
async function testReturnStatementReturnMethodNotPresent() {
let log = [];
let collection = [1, 2, 3, 4, 5];
let sum = 0;
let i = 0;
testDone = false;
for await (var x of async(collection, kNext, log)) {
sum += x;
if (++i === 3) {
testDone = true;
return { sum, log };
}
}
}
test = testReturnStatementReturnMethodNotPresent();
assertFalse(testDone);
assertEquals({sum: 6, log: ['[Symbol.asyncIterator]()',
'.next() -> resolved 1',
'.next() -> resolved 2',
'.next() -> resolved 3']},
await test);
assertTrue(testDone);
async function testReturnStatementReturnMethodPresent() {
let log = [];
let collection = [1, 2, 3, 4, 5];
let sum = 0;
let i = 0;
testDone = false;
for await (var x of async(collection, kNext|kReturn, log)) {
sum += x;
if (++i === 2) {
testDone = true;
return { sum, log };
}
}
}
test = testReturnStatementReturnMethodPresent();
assertFalse(testDone);
assertEquals({sum: 3, log: ['[Symbol.asyncIterator]()',
'.next() -> resolved 1',
'.next() -> resolved 2',
'.return(undefined)']},
await test);
assertTrue(testDone);
async function testReturnStatementReturnMethodAwaitIterResult() {
let log = [];
let collection = [1, 2, 3, 4, 5];
let sync_iter = collection[Symbol.iterator]();
sync_iter.return = function() {
return {
value: new Promise(function(resolve, reject) {
Promise.resolve().then(function() {
testDone = true;
resolve('return!');
});
}),
done: true
};
};
let sum = 0;
let i = 0;
testDone = false;
for await (var x of async(sync_iter, kNext|kReturn, log)) {
sum += x;
if (++i === 2) return { sum, log };
}
}
test = testReturnStatementReturnMethodAwaitIterResult();
assertFalse(testDone);
assertEquals({sum: 3,
log: ['[Symbol.asyncIterator]()',
'.next() -> resolved 1',
'.next() -> resolved 2',
'.return() -> resolved return!' ]},
await test);
assertTrue(testDone);
async function testReturnStatementReturnMethodAwaitRejection(log) {
let collection = [1, 2, 3, 4, 5];
let sync_iter = collection[Symbol.iterator]();
let sum = 0;
sync_iter.return = function() {
return {
value: new Promise(function(resolve, reject) {
Promise.resolve().then(function() {
reject('return! ' + sum);
});
}),
done: true
};
};
let i = 0;
testDone = false;
for await (var x of async(sync_iter, kNext|kReturn, log)) {
sum += x;
if (++i === 2) return { sum, log };
}
}
log = [];
test = testReturnStatementReturnMethodAwaitRejection(log);
assertFalse(testDone);
try {
await test;
} catch (e) {
assertEquals('return! 3', e);
assertEquals(['[Symbol.asyncIterator]()',
'.next() -> resolved 1',
'.next() -> resolved 2',
'.return() -> rejected return! 3'],
log);
testDone = true;
}
assertTrue(testDone, 'Promise should be rejected');
async function testReturnStatementReturnMethodPrimitiveValue(log) {
let collection = [1, 2, 3, 4, 5];
let sync_iter = collection[Symbol.iterator]();
sync_iter.return = function() {
return { value: 'return! primitive!', done: true };
}
let sum = 0;
let i = 0;
testDone = false;
for await (var x of async(sync_iter, kNext|kReturnPrimitive, log)) {
sum += x;
if (++i === 2) break;
}
return { sum, log };
}
log = [];
test = testReturnStatementReturnMethodPrimitiveValue(log);
assertFalse(testDone);
try {
await test;
} catch (e) {
assertEquals(['[Symbol.asyncIterator]()',
'.next() -> resolved 1',
'.next() -> resolved 2',
'.return() -> resolved return! primitive!'],
log);
assertInstanceof(e, TypeError);
testDone = true;
}
assertTrue(testDone, 'Promise should be rejected');
async function testThrowStatementReturnMethodNotPresent() {
let log = [];
let collection = [1, 2, 3, 4, 5];
let sum = 0;
let i = 0;
testDone = false;
for await (var x of async(collection, kNext|kThrow, log)) {
sum += x;
if (++i === 3) {
throw { sum, log, toString() { return 'TestError'; } };
}
}
return { sum, log };
}
test = testThrowStatementReturnMethodNotPresent();
assertFalse(testDone);
try {
await test;
} catch (e) {
assertEquals('TestError', e.toString());
assertEquals(6, e.sum);
assertEquals(['[Symbol.asyncIterator]()', '.next() -> resolved 1',
'.next() -> resolved 2', '.next() -> resolved 3'
], e.log);
testDone = true;
}
assertTrue(testDone, 'Awaited Promise should be rejected');
async function testThrowStatementReturnMethodPresent() {
let log = [];
let collection = [1, 2, 3, 4, 5];
let sum = 0;
let i = 0;
testDone = false;
for await (var x of async(collection, kNext|kThrow|kReturn, log)) {
sum += x;
if (++i === 2) {
throw { sum, log, toString() { return 'TestError2'; } };
}
}
return { sum, log };
}
test = testThrowStatementReturnMethodPresent();
assertFalse(testDone);
try {
await test;
} catch (e) {
assertEquals('TestError2', e.toString());
assertEquals(3, e.sum);
assertEquals(['[Symbol.asyncIterator]()', '.next() -> resolved 1',
'.next() -> resolved 2', '.return(undefined)'
], e.log);
testDone = true;
}
assertTrue(testDone, 'Awaited Promise should be rejected');
async function testThrowStatementReturnMethodAwaitIterResult(log) {
let collection = [1, 2, 3, 4, 5];
let sync_iter = collection[Symbol.iterator]();
sync_iter.return = function() {
return {
value: new Promise(function(resolve, reject) {
Promise.resolve().then(function() {
testDone = true;
resolve('throw!');
});
}),
done: true
};
};
let sum = 0;
let i = 0;
testDone = false;
for await (var x of async(sync_iter, kNext|kReturn, log)) {
sum += x;
if (++i === 2) throw 'Boo!!';
}
}
log = [];
test = testThrowStatementReturnMethodAwaitIterResult(log);
assertFalse(testDone);
try {
await test;
} catch (e) {
assertEquals('Boo!!', e);
assertEquals(['[Symbol.asyncIterator]()',
'.next() -> resolved 1',
'.next() -> resolved 2',
'.return() -> resolved throw!' ], log);
testDone = true;
}
assertTrue(testDone, 'Awaited Promise should be rejected');
async function testThrowStatementReturnMethodAwaitRejection(log) {
let collection = [1, 2, 3, 4, 5];
let sync_iter = collection[Symbol.iterator]();
let sum = 0;
sync_iter.return = function() {
return {
value: new Promise(function(resolve, reject) {
Promise.resolve().then(function() {
reject('return! ' + sum);
});
}),
done: true
};
};
let i = 0;
testDone = false;
for await (var x of async(sync_iter, kNext|kReturn, log)) {
sum += x;
if (++i === 2) throw 'Boo!!';
}
}
log = [];
test = testThrowStatementReturnMethodAwaitRejection(log);
assertFalse(testDone);
try {
await test;
} catch (e) {
assertEquals('Boo!!', e);
assertEquals(['[Symbol.asyncIterator]()',
'.next() -> resolved 1',
'.next() -> resolved 2',
'.return() -> rejected return! 3'],
log);
testDone = true;
}
assertTrue(testDone, 'Promise should be rejected');
async function testThrowStatementReturnMethodPrimitiveValue(log) {
let collection = [1, 2, 3, 4, 5];
let sync_iter = collection[Symbol.iterator]();
sync_iter.return = function() {
return { value: 'return! primitive!', done: true };
}
let sum = 0;
let i = 0;
testDone = false;
for await (var x of async(sync_iter, kNext|kReturnPrimitive, log)) {
sum += x;
if (++i === 2) throw 'Boo!!';
}
}
log = [];
test = testThrowStatementReturnMethodPrimitiveValue(log);
assertFalse(testDone);
try {
await test;
} catch (e) {
assertEquals(['[Symbol.asyncIterator]()',
'.next() -> resolved 1',
'.next() -> resolved 2',
'.return() -> resolved return! primitive!'],
log);
// AsyncIteratorClose does not require Throw completions to be of type
// Object
assertEquals('Boo!!', e);
testDone = true;
}
assertTrue(testDone, 'Promise should be rejected');
})().catch(function(error) {
testFailed = true;
testFailure = error;
});
%RunMicrotasks();
if (testFailed) {
throw testFailure;
}