| // 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; |
| } |