Implement changes for "avoid mostly-redundant `await` in async `yield*`" (#3619)

This commit is contained in:
Kevin Gibbons 2022-09-06 04:21:50 -07:00 committed by GitHub
parent f1870753fa
commit 746197355c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 63 additions and 23 deletions

View File

@ -0,0 +1,41 @@
// Copyright (C) 2022 Kevin Gibbons. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-generator-function-definitions-runtime-semantics-evaluation
description: >
`yield*` in an async generator does not await promises returned by a manually implemented async iterator.
flags: [async]
features: [async-iteration]
---*/
var innerPromise = Promise.resolve("unwrapped value");
var asyncIter = {
[Symbol.asyncIterator]() {
return this;
},
next() {
return {
done: false,
value: innerPromise,
};
},
get return() {
throw new Test262Error(".return should not be accessed");
},
get throw() {
throw new Test262Error(".throw should not be accessed");
},
};
async function* f() {
yield* asyncIter;
}
f()
.next()
.then(v => {
assert.sameValue(v.value, innerPromise, "yield* should not unwrap promises from manually-implemented async iterators");
})
.then($DONE, $DONE)

View File

@ -6,7 +6,7 @@ esid: sec-generator-function-definitions-runtime-semantics-evaluation
description: > description: >
Return resumption value is awaited upon and hence is treated as a thenable. Return resumption value is awaited upon and hence is treated as a thenable.
info: | info: |
14.4.14 Runtime Semantics: Evaluation 15.5.5 Runtime Semantics: Evaluation
YieldExpression : yield* AssignmentExpression YieldExpression : yield* AssignmentExpression
... ...
@ -27,46 +27,49 @@ info: |
2. Return Completion(received). 2. Return Completion(received).
... ...
25.5.3.7 AsyncGeneratorYield ( value ) 27.6.3.8 AsyncGeneratorYield ( value )
... ...
5. Set value to ? Await(value). 12. If queue is not empty, then
... ...
8. Set the code evaluation state of genContext such that when evaluation is resumed with a 13. Else,
...
c. Set the code evaluation state of genContext such that when evaluation is resumed with a
Completion resumptionValue the following steps will be performed: Completion resumptionValue the following steps will be performed:
... i. Return ? AsyncGeneratorUnwrapYieldResumption(resumptionValue).
b. Let awaited be Await(resumptionValue.[[Value]]).
... 27.6.3.7 AsyncGeneratorUnwrapYieldResumption ( resumptionValue )
e. Return Completion { [[Type]]: return, [[Value]]: awaited.[[Value]], [[Target]]: empty }. ...
... 2. Let awaited be Completion(Await(resumptionValue.[[Value]])).
...
6.2.3.1 Await 6.2.3.1 Await
... ...
2. Let promise be ? PromiseResolve(%Promise%, « value »). 2. Let promise be ? PromiseResolve(%Promise%, « value »).
... ...
25.6.4.5.1 PromiseResolve ( C, x ) 27.2.4.7.1 PromiseResolve ( C, x )
... ...
3. Let promiseCapability be ? NewPromiseCapability(C). 2. Let promiseCapability be ? NewPromiseCapability(C).
4. Perform ? Call(promiseCapability.[[Resolve]], undefined, « x »). 3. Perform ? Call(promiseCapability.[[Resolve]], undefined, « x »).
... ...
25.6.1.5 NewPromiseCapability ( C ) 27.2.1.5 NewPromiseCapability ( C )
... ...
7. Let promise be ? Construct(C, « executor »). 7. Let promise be ? Construct(C, « executor »).
... ...
25.6.3.1 Promise ( executor ) 27.2.3.1 Promise ( executor )
... ...
8. Let resolvingFunctions be CreateResolvingFunctions(promise). 8. Let resolvingFunctions be CreateResolvingFunctions(promise).
... ...
25.6.1.3 CreateResolvingFunctions ( promise ) 27.2.1.3 CreateResolvingFunctions ( promise )
... ...
2. Let stepsResolve be the algorithm steps defined in Promise Resolve Functions (25.6.1.3.2). 2. Let stepsResolve be the algorithm steps defined in Promise Resolve Functions (25.6.1.3.2).
3. Let resolve be CreateBuiltinFunction(stepsResolve, « [[Promise]], [[AlreadyResolved]] »). 3. Let resolve be CreateBuiltinFunction(stepsResolve, « [[Promise]], [[AlreadyResolved]] »).
... ...
25.6.1.3.2 Promise Resolve Functions 27.2.1.3.2 Promise Resolve Functions
... ...
9. Let then be Get(resolution, "then"). 9. Let then be Get(resolution, "then").
... ...
@ -82,14 +85,11 @@ var expected = [
// `Await(innerResult)` promise resolved. // `Await(innerResult)` promise resolved.
"tick 1", "tick 1",
// `Await(value)` promise resolved.
"tick 2",
// "then" of `resumptionValue.[[Value]]` accessed. // "then" of `resumptionValue.[[Value]]` accessed.
"get then", "get then",
// `Await(resumptionValue.[[Value]])` promise resolved. // `Await(resumptionValue.[[Value]])` promise resolved.
"tick 3", "tick 2",
// Get iterator "return" method. // Get iterator "return" method.
"get return", "get return",
@ -98,7 +98,7 @@ var expected = [
"get then", "get then",
// `Await(received.[[Value]])` promise resolved. // `Await(received.[[Value]])` promise resolved.
"tick 4", "tick 3",
]; ];
var actual = []; var actual = [];
@ -127,7 +127,6 @@ Promise.resolve(0)
.then(() => actual.push("tick 1")) .then(() => actual.push("tick 1"))
.then(() => actual.push("tick 2")) .then(() => actual.push("tick 2"))
.then(() => actual.push("tick 3")) .then(() => actual.push("tick 3"))
.then(() => actual.push("tick 4"))
.then(() => { .then(() => {
assert.compareArray(actual, expected, "Ticks for return with thenable getter"); assert.compareArray(actual, expected, "Ticks for return with thenable getter");
}).then($DONE, $DONE); }).then($DONE, $DONE);