07011cc4f0
This replaces Runtime_RunMicrotasks with Runtime_PerformMicrotaskCheckpoint. RunMicrotasks forcibly runs Microtasks even when the microtasks are suppressed, and may causes nested Microtasks in a problematic way. E.g. that confuses v8::MicrotasksScope::IsRunningMicrotasks() and GetEnteredOrMicrotaskContext(). OTOH, PerformMicrotaskCheckpoint() doesn't run cause the failure as it respects the microtask suppressions. As all existing tests don't call RunMicrotasks() in the suppressed situation (like Promise.resolve().then(()=>{%RunMicrotasks();})), this change should not affect to these tests. Change-Id: Ib043a0cc8e482e022d375084d65ea98a6f54ef3d Reviewed-on: https://chromium-review.googlesource.com/c/1360095 Reviewed-by: Yang Guo <yangguo@chromium.org> Commit-Queue: Taiju Tsuiki <tzik@chromium.org> Cr-Commit-Position: refs/heads/master@{#58068}
1265 lines
36 KiB
JavaScript
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: --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;
|
|
});
|
|
|
|
%PerformMicrotaskCheckpoint();
|
|
|
|
if (testFailed) {
|
|
throw testFailure;
|
|
}
|