Add test for "constructor" lookups and correct job order in for-await loop

This commit is contained in:
André Bargull 2019-03-11 10:34:40 -07:00
parent bb838d8d6b
commit 9d711fdf11
3 changed files with 260 additions and 0 deletions

View File

@ -0,0 +1,91 @@
// Copyright (C) 2019 André Bargull. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-runtime-semantics-forin-div-ofbodyevaluation-lhs-stmt-iterator-lhskind-labelset
description: >
Ensure the number of ticks and Promise constructor lookups is correct with custom async iterator.
info: |
13.7.5.13 Runtime Semantics: ForIn/OfBodyEvaluation ( lhs, stmt, iteratorRecord, iterationKind,
lhsKind, labelSet [ , iteratorKind ] )
25.6.4.5.1 PromiseResolve
6.2.3.1 Await
includes: [compareArray.js]
flags: [async]
features: [async-iteration]
---*/
// The expected event log.
var expected = [
// Before entering loop.
"pre",
// Await
// -> PromiseResolve
"constructor",
// Await promise resolved.
"tick 1",
// In loop body.
"loop",
// Await
// -> PromiseResolve
"constructor",
// Await promise resolved
"tick 2",
// After exiting loop.
"post",
];
// The actual event log.
var actual = [];
// Custom async iterator returning the result of the synchronous iterator wrapped in a Promise.
function toAsyncIterator(iterable) {
return {
[Symbol.asyncIterator]() {
var iter = iterable[Symbol.iterator]();
return {
next() {
return Promise.resolve(iter.next());
}
};
}
};
}
// Test function using for-await with a single, already resolved Promise.
async function f() {
var p = Promise.resolve(0);
actual.push("pre");
for await (var x of toAsyncIterator([p])) {
actual.push("loop");
}
actual.push("post");
}
// Count the number of ticks needed to complete the loop and compare the actual log.
Promise.resolve(0)
.then(() => actual.push("tick 1"))
.then(() => actual.push("tick 2"))
.then(() => {
assert.compareArray(actual, expected, "Ticks and constructor lookups");
}).then($DONE, $DONE);
// Redefine `Promise.constructor` in order to intercept "constructor" lookups from PromiseResolve.
// (Perform last so that the lookups from SpeciesConstructor in `then` aren't logged.)
Object.defineProperty(Promise.prototype, "constructor", {
get() {
actual.push("constructor");
return Promise;
},
configurable: true,
});
// Start the asynchronous function.
f();

View File

@ -0,0 +1,77 @@
// Copyright (C) 2019 André Bargull. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-runtime-semantics-forin-div-ofbodyevaluation-lhs-stmt-iterator-lhskind-labelset
description: >
Ensure the number of ticks and Promise constructor lookups is correct with custom async iterator.
info: |
13.7.5.13 Runtime Semantics: ForIn/OfBodyEvaluation ( lhs, stmt, iteratorRecord, iterationKind,
lhsKind, labelSet [ , iteratorKind ] )
6.2.3.1 Await
includes: [compareArray.js]
flags: [async]
features: [async-iteration]
---*/
// The expected event log.
var expected = [
// Before entering loop.
"pre",
// Await promise resolved.
"tick 1",
// In loop body.
"loop",
// Await promise resolved
"tick 2",
// After exiting loop.
"post",
];
// The actual event log.
var actual = [];
// Custom async iterator directly using a synchronous iterator.
function toAsyncIterator(iterable) {
return {
[Symbol.asyncIterator]() {
return iterable[Symbol.iterator]();
}
};
}
// Test function using for-await with a single, already resolved Promise.
async function f() {
var p = Promise.resolve(0);
actual.push("pre");
for await (var x of toAsyncIterator([p])) {
actual.push("loop");
}
actual.push("post");
}
// Count the number of ticks needed to complete the loop and compare the actual log.
Promise.resolve(0)
.then(() => actual.push("tick 1"))
.then(() => actual.push("tick 2"))
.then(() => {
assert.compareArray(actual, expected, "Ticks and constructor lookups");
}).then($DONE, $DONE);
// Redefine `Promise.constructor` in order to intercept "constructor" lookups from PromiseResolve.
// (Perform last so that the lookups from SpeciesConstructor in `then` aren't logged.)
Object.defineProperty(Promise.prototype, "constructor", {
get() {
actual.push("constructor");
return Promise;
},
configurable: true,
});
// Start the asynchronous function.
f();

View File

@ -0,0 +1,92 @@
// Copyright (C) 2019 André Bargull. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-runtime-semantics-forin-div-ofbodyevaluation-lhs-stmt-iterator-lhskind-labelset
description: >
Ensure the number of ticks and Promise constructor lookups is correct with a Async-from-Sync iterator.
info: |
13.7.5.13 Runtime Semantics: ForIn/OfBodyEvaluation ( lhs, stmt, iteratorRecord, iterationKind,
lhsKind, labelSet [ , iteratorKind ] )
25.1.4.2.1 %AsyncFromSyncIteratorPrototype%.next
25.1.4.4 AsyncFromSyncIteratorContinuation
25.6.4.5.1 PromiseResolve
6.2.3.1 Await
includes: [compareArray.js]
flags: [async]
features: [async-iteration]
---*/
// The expected event log.
var expected = [
// Before entering loop.
"pre",
// %AsyncFromSyncIteratorPrototype%.next
// -> AsyncFromSyncIteratorContinuation
// -> PromiseResolve
"constructor",
// Await
// -> PromiseResolve
"constructor",
// Async-from-Sync Iterator promise resolved.
"tick 1",
// Await promise resolved.
"tick 2",
// In loop body.
"loop",
// Await
// -> PromiseResolve
"constructor",
// Async-from-Sync Iterator promise resolved.
"tick 3",
// Await promise resolved
"tick 4",
// After exiting loop.
"post",
];
// The actual event log.
var actual = [];
// Test function using for-await with a single, already resolved Promise.
async function f() {
var p = Promise.resolve(0);
actual.push("pre");
for await (var x of [p]) {
actual.push("loop");
}
actual.push("post");
}
// Count the number of ticks needed to complete the loop and compare the actual log.
Promise.resolve(0)
.then(() => actual.push("tick 1"))
.then(() => actual.push("tick 2"))
.then(() => actual.push("tick 3"))
.then(() => actual.push("tick 4"))
.then(() => {
assert.compareArray(actual, expected, "Ticks and constructor lookups");
}).then($DONE, $DONE);
// Redefine `Promise.constructor` in order to intercept "constructor" lookups from PromiseResolve.
// (Perform last so that the lookups from SpeciesConstructor in `then` aren't logged.)
Object.defineProperty(Promise.prototype, "constructor", {
get() {
actual.push("constructor");
return Promise;
},
configurable: true,
});
// Start the asynchronous function.
f();