-
Notifications
You must be signed in to change notification settings - Fork 474
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add test on handling broken promises in AsyncGenerator.prototype.retu…
…rn (#3472) * Add test on handling broken promises in AsyncGenerator.prototype.return * fixup! * fixup!
- Loading branch information
1 parent
2e7cdfb
commit 509363b
Showing
3 changed files
with
180 additions
and
0 deletions.
There are no files selected for viewing
62 changes: 62 additions & 0 deletions
62
test/built-ins/AsyncGeneratorPrototype/return/return-state-completed-broken-promise.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
// Copyright (C) 2022 Chengzhong Wu. All rights reserved. | ||
// This code is governed by the BSD license found in the LICENSE file. | ||
|
||
/*--- | ||
esid: sec-asyncgenerator-prototype-return | ||
description: > | ||
A broken promise should reject the returned promise of | ||
AsyncGenerator.prototype.return when the generator is completed. | ||
info: | | ||
AsyncGenerator.prototype.return ( value ) | ||
... | ||
8. If state is either suspendedStart or completed, then | ||
a. Set generator.[[AsyncGeneratorState]] to awaiting-return. | ||
b. Perform ! AsyncGeneratorAwaitReturn(generator). | ||
... | ||
AsyncGeneratorAwaitReturn ( generator ) | ||
... | ||
6. Let promise be Completion(PromiseResolve(%Promise%, completion.[[Value]])). | ||
7. If promiseCompletion is an abrupt completion, then | ||
a. Set generator.[[AsyncGeneratorState]] to completed. | ||
b. Perform AsyncGeneratorCompleteStep(generator, promiseCompletion, true). | ||
c. Perform AsyncGeneratorDrainQueue(generator). | ||
d. Return unused. | ||
8. Assert: promiseCompletion.[[Type]] is normal. | ||
9. Let promise be promiseCompletion.[[Value]]. | ||
... | ||
flags: [async] | ||
features: [async-iteration] | ||
---*/ | ||
|
||
let unblock; | ||
let blocking = new Promise(resolve => { unblock = resolve; }); | ||
let unblocked = false; | ||
var g = async function*() { | ||
await blocking; | ||
unblocked = true; | ||
}; | ||
|
||
var it = g(); | ||
let brokenPromise = Promise.resolve(42); | ||
Object.defineProperty(brokenPromise, 'constructor', { | ||
get: function () { | ||
throw new Error('broken promise'); | ||
} | ||
}); | ||
|
||
it.next(); | ||
it.return(brokenPromise) | ||
.then( | ||
() => { | ||
throw new Test262Error("Expected rejection"); | ||
}, | ||
err => { | ||
assert(unblocked, false, 'return should be rejected before generator is resumed'); | ||
assert.sameValue(err.message, 'broken promise'); | ||
} | ||
) | ||
.then($DONE, $DONE); | ||
|
||
unblock(); |
54 changes: 54 additions & 0 deletions
54
test/built-ins/AsyncGeneratorPrototype/return/return-suspendedStart-broken-promise.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
// Copyright (C) 2022 Chengzhong Wu. All rights reserved. | ||
// This code is governed by the BSD license found in the LICENSE file. | ||
|
||
/*--- | ||
esid: sec-asyncgenerator-prototype-return | ||
description: > | ||
A broken promise should reject the returned promise of | ||
AsyncGenerator.prototype.return when the generator's state is suspendedStart. | ||
info: | | ||
AsyncGenerator.prototype.return ( value ) | ||
... | ||
8. If state is either suspendedStart or completed, then | ||
a. Set generator.[[AsyncGeneratorState]] to awaiting-return. | ||
b. Perform AsyncGeneratorAwaitReturn(_generator_). | ||
... | ||
AsyncGeneratorAwaitReturn ( generator ) | ||
... | ||
6. Let promise be Completion(PromiseResolve(%Promise%, completion.[[Value]])). | ||
7. If promiseCompletion is an abrupt completion, then | ||
a. Set generator.[[AsyncGeneratorState]] to completed. | ||
b. Perform AsyncGeneratorCompleteStep(generator, promiseCompletion, true). | ||
c. Perform AsyncGeneratorDrainQueue(generator). | ||
d. Return unused. | ||
8. Assert: promiseCompletion.[[Type]] is normal. | ||
9. Let promise be promiseCompletion.[[Value]]. | ||
... | ||
flags: [async] | ||
features: [async-iteration] | ||
---*/ | ||
|
||
var g = async function*() { | ||
throw new Test262Error('Generator must not be resumed.'); | ||
}; | ||
|
||
var it = g(); | ||
let brokenPromise = Promise.resolve(42); | ||
Object.defineProperty(brokenPromise, 'constructor', { | ||
get: function () { | ||
throw new Error('broken promise'); | ||
} | ||
}); | ||
|
||
it.return(brokenPromise) | ||
.then( | ||
() => { | ||
throw new Test262Error("Expected rejection"); | ||
}, | ||
err => { | ||
assert.sameValue(err.message, 'broken promise'); | ||
} | ||
) | ||
.then($DONE, $DONE); |
64 changes: 64 additions & 0 deletions
64
...uilt-ins/AsyncGeneratorPrototype/return/return-suspendedYield-broken-promise-try-catch.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
// Copyright (C) 2022 Chengzhong Wu. All rights reserved. | ||
// This code is governed by the BSD license found in the LICENSE file. | ||
|
||
/*--- | ||
esid: sec-asyncgenerator-prototype-return | ||
description: > | ||
A broken promise should resume the generator and reject with | ||
the exception when the generator's state is suspendedYield. | ||
info: | | ||
AsyncGenerator.prototype.return ( value ) | ||
... | ||
9. Else if state is suspendedYield, then | ||
a. Perform AsyncGeneratorResume(generator, completion). | ||
... | ||
AsyncGeneratorCompleteStep ( generator, completion, done [ , realm ] ) | ||
Resumes the steps defined at AsyncGeneratorStart ( generator, generatorBody ) | ||
... | ||
4. Set the code evaluation state of genContext such that when evaluation is resumed for that execution context the following steps will be performed: | ||
... | ||
i. Perform AsyncGeneratorDrainQueue(generator). | ||
j. Return undefined. | ||
AsyncGeneratorDrainQueue ( generator ) | ||
... | ||
5. Repeat, while done is false, | ||
a. Let next be the first element of queue. | ||
b. Let completion be Completion(next.[[Completion]]). | ||
c. If completion.[[Type]] is return, then | ||
i. Set generator.[[AsyncGeneratorState]] to awaiting-return. | ||
ii. Perform AsyncGeneratorAwaitReturn(generator). | ||
iii. Set done to true. | ||
... | ||
flags: [async] | ||
features: [async-iteration] | ||
---*/ | ||
|
||
let caughtErr; | ||
var g = async function*() { | ||
try { | ||
yield; | ||
return 'this is never returned'; | ||
} catch (err) { | ||
caughtErr = err; | ||
return 1; | ||
} | ||
}; | ||
|
||
let brokenPromise = Promise.resolve(42); | ||
Object.defineProperty(brokenPromise, 'constructor', { | ||
get: function () { | ||
throw new Error('broken promise'); | ||
} | ||
}); | ||
|
||
var it = g(); | ||
it.next().then(() => { | ||
return it.return(brokenPromise); | ||
}).then(ret => { | ||
assert.sameValue(caughtErr.message, 'broken promise'); | ||
assert.sameValue(ret.value, 1, 'returned value'); | ||
assert.sameValue(ret.done, true, 'iterator is closed'); | ||
}).then($DONE, $DONE); |