mirror of
https://github.com/tc39/test262.git
synced 2025-07-25 23:14:47 +02:00
Test closing async-from-sync iterator when resolving result promise abrupt completes. (#3977)
* Test closing async-from-sync iterator when resolving result promise abrupt completes. These test new steps 6-6.a of AsyncFromSyncIteratorContinuation as per normative changes of ecma626 PR 2600 https://github.com/tc39/ecma262/pull/2600 * Apply suggestions from code review Co-authored-by: Kevin Gibbons <bakkot@gmail.com> * Apply suggestions from code review Co-authored-by: Nicolò Ribaudo <hello@nicr.dev> * Refactoring tests to use the Async Helpers. --------- Co-authored-by: Kevin Gibbons <bakkot@gmail.com> Co-authored-by: Nicolò Ribaudo <hello@nicr.dev>
This commit is contained in:
parent
2c58671789
commit
1f380f3750
@ -0,0 +1,67 @@
|
|||||||
|
// Copyright (C) 2023 Igalia, S.L. All rights reserved.
|
||||||
|
// This code is governed by the BSD license found in the LICENSE file.
|
||||||
|
|
||||||
|
/*---
|
||||||
|
esid: sec-%asyncfromsynciteratorprototype%.next
|
||||||
|
description: next() will reject promise if resolving result promise abrupt completes.
|
||||||
|
info: |
|
||||||
|
%AsyncFromSyncIteratorPrototype%.next ( value )
|
||||||
|
...
|
||||||
|
3. Let promiseCapability be ! NewPromiseCapability(%Promise%).
|
||||||
|
4. Let syncIteratorRecord be O.[[SyncIteratorRecord]].
|
||||||
|
5. If value is present, then
|
||||||
|
...
|
||||||
|
6. Else,
|
||||||
|
a. Let result be IteratorNext(syncIteratorRecord).
|
||||||
|
7. IfAbruptRejectPromise(result, promiseCapability).
|
||||||
|
8. Return ! AsyncFromSyncIteratorContinuation(result, promiseCapability, syncIteratorRecord, true).
|
||||||
|
|
||||||
|
AsyncFromSyncIteratorContinuation ( result, promiseCapability, syncIteratorRecord, closeOnRejection )
|
||||||
|
1. Let done be IteratorComplete(result).
|
||||||
|
2. IfAbruptRejectPromise(done, promiseCapability).
|
||||||
|
3. Let value be IteratorValue(result).
|
||||||
|
4. IfAbruptRejectPromise(value, promiseCapability).
|
||||||
|
5. Let valueWrapper be PromiseResolve(%Promise%, value).
|
||||||
|
6. If valueWrapper is an abrupt completion, done is false, and closeOnRejection is true, then
|
||||||
|
a. Set valueWrapper to IteratorClose(syncIteratorRecord, valueWrapper).
|
||||||
|
7. IfAbruptRejectPromise(valueWrapper, promiseCapability).
|
||||||
|
...
|
||||||
|
|
||||||
|
IfAbruptRejectPromise ( value, capability )
|
||||||
|
1. Assert: value is a Completion Record.
|
||||||
|
2. If value is an abrupt completion, then
|
||||||
|
a. Perform ? Call(capability.[[Reject]], undefined, « value.[[Value]] »).
|
||||||
|
b. Return capability.[[Promise]].
|
||||||
|
...
|
||||||
|
|
||||||
|
flags: [async]
|
||||||
|
features: [async-iteration]
|
||||||
|
includes: [asyncHelpers.js]
|
||||||
|
---*/
|
||||||
|
|
||||||
|
var finallyCount = 0;
|
||||||
|
function CatchError() {}
|
||||||
|
var thrownError = new CatchError();
|
||||||
|
|
||||||
|
function* gen() {
|
||||||
|
try {
|
||||||
|
const p = Promise.resolve('FAIL');
|
||||||
|
Object.defineProperty(p, 'constructor', {
|
||||||
|
get() {
|
||||||
|
throw thrownError;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
yield p;
|
||||||
|
} finally {
|
||||||
|
finallyCount += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function* iter() {
|
||||||
|
yield* gen();
|
||||||
|
}
|
||||||
|
|
||||||
|
asyncTest(async function () {
|
||||||
|
await assert.throwsAsync(CatchError, async () => iter().next(), "Promise should be rejected");
|
||||||
|
assert.sameValue(finallyCount, 1, 'iterator closed properly');
|
||||||
|
})
|
@ -0,0 +1,72 @@
|
|||||||
|
// Copyright (C) 2023 Igalia, S.L. All rights reserved.
|
||||||
|
// This code is governed by the BSD license found in the LICENSE file.
|
||||||
|
|
||||||
|
/*---
|
||||||
|
esid: sec-%asyncfromsynciteratorprototype%.next
|
||||||
|
description: next() will reject promise if resolving result promise abrupt completes.
|
||||||
|
info: |
|
||||||
|
%AsyncFromSyncIteratorPrototype%.next ( value )
|
||||||
|
...
|
||||||
|
3. Let promiseCapability be ! NewPromiseCapability(%Promise%).
|
||||||
|
4. Let syncIteratorRecord be O.[[SyncIteratorRecord]].
|
||||||
|
5. If value is present, then
|
||||||
|
...
|
||||||
|
6. Else,
|
||||||
|
a. Let result be IteratorNext(syncIteratorRecord).
|
||||||
|
7. IfAbruptRejectPromise(result, promiseCapability).
|
||||||
|
8. Return ! AsyncFromSyncIteratorContinuation(result, promiseCapability, syncIteratorRecord, true).
|
||||||
|
|
||||||
|
AsyncFromSyncIteratorContinuation ( result, promiseCapability, syncIteratorRecord, closeOnRejection )
|
||||||
|
1. Let done be IteratorComplete(result).
|
||||||
|
2. IfAbruptRejectPromise(done, promiseCapability).
|
||||||
|
3. Let value be IteratorValue(result).
|
||||||
|
4. IfAbruptRejectPromise(value, promiseCapability).
|
||||||
|
5. Let valueWrapper be PromiseResolve(%Promise%, value).
|
||||||
|
6. If valueWrapper is an abrupt completion, done is false, and closeOnRejection is true, then
|
||||||
|
a. Set valueWrapper to IteratorClose(syncIteratorRecord, valueWrapper).
|
||||||
|
7. IfAbruptRejectPromise(valueWrapper, promiseCapability).
|
||||||
|
...
|
||||||
|
|
||||||
|
IfAbruptRejectPromise ( value, capability )
|
||||||
|
1. Assert: value is a Completion Record.
|
||||||
|
2. If value is an abrupt completion, then
|
||||||
|
a. Perform ? Call(capability.[[Reject]], undefined, « value.[[Value]] »).
|
||||||
|
b. Return capability.[[Promise]].
|
||||||
|
...
|
||||||
|
|
||||||
|
flags: [async]
|
||||||
|
features: [async-iteration]
|
||||||
|
includes: [asyncHelpers.js]
|
||||||
|
---*/
|
||||||
|
|
||||||
|
var returnCount = 0;
|
||||||
|
function CatchError() {}
|
||||||
|
var thrownError = new CatchError();
|
||||||
|
|
||||||
|
const obj = {
|
||||||
|
[Symbol.iterator]() {
|
||||||
|
return {
|
||||||
|
next() {
|
||||||
|
const p = Promise.resolve('FAIL');
|
||||||
|
Object.defineProperty(p, 'constructor', {
|
||||||
|
get() {
|
||||||
|
throw thrownError;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return { value: p, done: false };
|
||||||
|
},
|
||||||
|
return() {
|
||||||
|
returnCount += 1;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
async function* iter() {
|
||||||
|
yield* obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
asyncTest(async function () {
|
||||||
|
await assert.throwsAsync(CatchError, async () => iter().next(), "Promise should be rejected");
|
||||||
|
assert.sameValue(returnCount, 1, 'iterator closed properly');
|
||||||
|
})
|
@ -0,0 +1,90 @@
|
|||||||
|
// Copyright (C) 2023 Igalia, S.L. All rights reserved.
|
||||||
|
// This code is governed by the BSD license found in the LICENSE file.
|
||||||
|
|
||||||
|
/*---
|
||||||
|
esid: sec-%asyncfromsynciteratorprototype%.throw
|
||||||
|
description: throw() will reject promise if resolving result promise abrupt completes.
|
||||||
|
info: |
|
||||||
|
%AsyncFromSyncIteratorPrototype%.throw ( value )
|
||||||
|
...
|
||||||
|
3. Let promiseCapability be ! NewPromiseCapability(%Promise%).
|
||||||
|
4. Let syncIteratorRecord be O.[[SyncIteratorRecord]].
|
||||||
|
5. Let syncIterator be syncIteratorRecord.[[Iterator]].
|
||||||
|
6. Let throw be GetMethod(syncIterator, "throw").
|
||||||
|
7. IfAbruptRejectPromise(throw, promiseCapability).
|
||||||
|
8. If throw is undefined, then
|
||||||
|
...
|
||||||
|
9. If value is present, then
|
||||||
|
...
|
||||||
|
10. Else,
|
||||||
|
a. Let result be Call(throw, syncIterator).
|
||||||
|
...
|
||||||
|
13. Return ! AsyncFromSyncIteratorContinuation(result, promiseCapability, syncIteratorRecord, true).
|
||||||
|
|
||||||
|
AsyncFromSyncIteratorContinuation ( result, promiseCapability, syncIteratorRecord, closeOnRejection )
|
||||||
|
1. Let done be IteratorComplete(result).
|
||||||
|
2. IfAbruptRejectPromise(done, promiseCapability).
|
||||||
|
3. Let value be IteratorValue(result).
|
||||||
|
4. IfAbruptRejectPromise(value, promiseCapability).
|
||||||
|
5. Let valueWrapper be PromiseResolve(%Promise%, value).
|
||||||
|
6. If valueWrapper is an abrupt completion, done is false, and closeOnRejection is true, then
|
||||||
|
a. Set valueWrapper to IteratorClose(syncIteratorRecord, valueWrapper).
|
||||||
|
7. IfAbruptRejectPromise(valueWrapper, promiseCapability).
|
||||||
|
...
|
||||||
|
|
||||||
|
IfAbruptRejectPromise ( value, capability )
|
||||||
|
1. Assert: value is a Completion Record.
|
||||||
|
2. If value is an abrupt completion, then
|
||||||
|
a. Perform ? Call(capability.[[Reject]], undefined, « value.[[Value]] »).
|
||||||
|
b. Return capability.[[Promise]].
|
||||||
|
...
|
||||||
|
|
||||||
|
flags: [async]
|
||||||
|
features: [async-iteration]
|
||||||
|
includes: [asyncHelpers.js]
|
||||||
|
---*/
|
||||||
|
|
||||||
|
var returnCount = 0;
|
||||||
|
function CatchError() {}
|
||||||
|
var thrownError = new CatchError();
|
||||||
|
var uncaughtError = new Error("Don't catch me");
|
||||||
|
|
||||||
|
const obj = {
|
||||||
|
[Symbol.iterator]() {
|
||||||
|
return {
|
||||||
|
next() {
|
||||||
|
return { value: 1, done: false };
|
||||||
|
},
|
||||||
|
throw() {
|
||||||
|
const p = Promise.resolve('FAIL');
|
||||||
|
Object.defineProperty(p, 'constructor', {
|
||||||
|
get() {
|
||||||
|
throw thrownError;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return { value: p, done: false };
|
||||||
|
},
|
||||||
|
return() {
|
||||||
|
returnCount += 1;
|
||||||
|
return { value: undefined, done: true };
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
async function* asyncg() {
|
||||||
|
return yield* obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
let iter = asyncg();
|
||||||
|
|
||||||
|
asyncTest(async function () {
|
||||||
|
await assert.throwsAsync(CatchError, async () => {
|
||||||
|
await iter.next();
|
||||||
|
return iter.throw(uncaughtError);
|
||||||
|
}, "Promise should be rejected");
|
||||||
|
assert.sameValue(returnCount, 1, 'iterator closed properly');
|
||||||
|
const result = await iter.next();
|
||||||
|
assert(result.done, "the iterator is completed");
|
||||||
|
assert.sameValue(result.value, undefined, "value is undefined");
|
||||||
|
})
|
Loading…
x
Reference in New Issue
Block a user