Add coverage for IteratorClose in Promise combinators

SM doesn't pass these tests, whereas JSC and V8 passes them.
This commit is contained in:
André Bargull 2025-05-26 15:49:05 +02:00 committed by Ms2ger
parent 5920cb8e1b
commit c6ad284d99
8 changed files with 564 additions and 0 deletions

View File

@ -0,0 +1,70 @@
// Copyright (C) 2025 André Bargull. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-promise.all
description: >
Input throw-completion forwarded when IteratorClose returns abruptly because GetMethod throws.
info: |
27.2.4.1 Promise.all ( iterable )
...
7. Let result be Completion(PerformPromiseAll(iteratorRecord, C, promiseCapability, promiseResolve)).
8. If result is an abrupt completion, then
a. If iteratorRecord.[[Done]] is false, set result to Completion(IteratorClose(iteratorRecord, result)).
b. IfAbruptRejectPromise(result, promiseCapability).
...
7.4.11 IteratorClose ( iteratorRecord, completion )
...
3. Let innerResult be Completion(GetMethod(iterator, "return")).
...
5. If completion is a throw completion, return ? completion.
...
7.3.10 GetMethod ( V, P )
1. Let func be ? GetV(V, P).
2. If func is either undefined or null, return undefined.
3. If IsCallable(func) is false, throw a TypeError exception.
...
---*/
function resolve() {
throw new Test262Error("Unexpected call to resolve");
}
var rejectCallCount = 0;
function reject(e) {
rejectCallCount += 1;
assert.sameValue(e, "bad promise resolve");
}
class BadPromise {
constructor(executor) {
executor(resolve, reject);
}
static resolve() {
throw "bad promise resolve";
}
}
for (var returnMethod of [0, 0n, true, "string", {}, Symbol()]) {
var iterator = {
[Symbol.iterator]() {
return this;
},
next() {
return {done: false};
},
return: returnMethod,
};
// Reset counter.
rejectCallCount = 0;
Promise.all.call(BadPromise, iterator);
// Ensure `reject` was called exactly once.
assert.sameValue(rejectCallCount, 1);
}

View File

@ -0,0 +1,71 @@
// Copyright (C) 2025 André Bargull. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-promise.all
description: >
Input throw-completion forwarded when IteratorClose returns normally because GetMethod returns undefined.
info: |
27.2.4.1 Promise.all ( iterable )
...
7. Let result be Completion(PerformPromiseAll(iteratorRecord, C, promiseCapability, promiseResolve)).
8. If result is an abrupt completion, then
a. If iteratorRecord.[[Done]] is false, set result to Completion(IteratorClose(iteratorRecord, result)).
b. IfAbruptRejectPromise(result, promiseCapability).
...
7.4.11 IteratorClose ( iteratorRecord, completion )
...
3. Let innerResult be Completion(GetMethod(iterator, "return")).
4. If innerResult is a normal completion, then
a. Let return be innerResult.[[Value]].
b. If return is undefined, return ? completion.
...
...
7.3.10 GetMethod ( V, P )
1. Let func be ? GetV(V, P).
2. If func is either undefined or null, return undefined.
...
---*/
function resolve() {
throw new Test262Error("Unexpected call to resolve");
}
var rejectCallCount = 0;
function reject(e) {
rejectCallCount += 1;
assert.sameValue(e, "bad promise resolve");
}
class BadPromise {
constructor(executor) {
executor(resolve, reject);
}
static resolve() {
throw "bad promise resolve";
}
}
for (var returnMethod of [null, undefined]) {
var iterator = {
[Symbol.iterator]() {
return this;
},
next() {
return {done: false};
},
return: returnMethod,
};
// Reset counter.
rejectCallCount = 0;
Promise.all.call(BadPromise, iterator);
// Ensure `reject` was called exactly once.
assert.sameValue(rejectCallCount, 1);
}

View File

@ -0,0 +1,70 @@
// Copyright (C) 2025 André Bargull. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-promise.allsettled
description: >
Input throw-completion forwarded when IteratorClose returns abruptly because GetMethod throws.
info: |
27.2.4.2 Promise.allSettled ( iterable )
...
7. Let result be Completion(PerformPromiseAllSettled(iteratorRecord, C, promiseCapability, promiseResolve)).
8. If result is an abrupt completion, then
a. If iteratorRecord.[[Done]] is false, set result to Completion(IteratorClose(iteratorRecord, result)).
b. IfAbruptRejectPromise(result, promiseCapability).
...
7.4.11 IteratorClose ( iteratorRecord, completion )
...
3. Let innerResult be Completion(GetMethod(iterator, "return")).
...
5. If completion is a throw completion, return ? completion.
...
7.3.10 GetMethod ( V, P )
1. Let func be ? GetV(V, P).
2. If func is either undefined or null, return undefined.
3. If IsCallable(func) is false, throw a TypeError exception.
...
---*/
function resolve() {
throw new Test262Error("Unexpected call to resolve");
}
var rejectCallCount = 0;
function reject(e) {
rejectCallCount += 1;
assert.sameValue(e, "bad promise resolve");
}
class BadPromise {
constructor(executor) {
executor(resolve, reject);
}
static resolve() {
throw "bad promise resolve";
}
}
for (var returnMethod of [0, 0n, true, "string", {}, Symbol()]) {
var iterator = {
[Symbol.iterator]() {
return this;
},
next() {
return {done: false};
},
return: returnMethod,
};
// Reset counter.
rejectCallCount = 0;
Promise.allSettled.call(BadPromise, iterator);
// Ensure `reject` was called exactly once.
assert.sameValue(rejectCallCount, 1);
}

View File

@ -0,0 +1,71 @@
// Copyright (C) 2025 André Bargull. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-promise.allsettled
description: >
Input throw-completion forwarded when IteratorClose returns normally because GetMethod returns undefined.
info: |
27.2.4.2 Promise.allSettled ( iterable )
...
7. Let result be Completion(PerformPromiseAllSettled(iteratorRecord, C, promiseCapability, promiseResolve)).
8. If result is an abrupt completion, then
a. If iteratorRecord.[[Done]] is false, set result to Completion(IteratorClose(iteratorRecord, result)).
b. IfAbruptRejectPromise(result, promiseCapability).
...
7.4.11 IteratorClose ( iteratorRecord, completion )
...
3. Let innerResult be Completion(GetMethod(iterator, "return")).
4. If innerResult is a normal completion, then
a. Let return be innerResult.[[Value]].
b. If return is undefined, return ? completion.
...
...
7.3.10 GetMethod ( V, P )
1. Let func be ? GetV(V, P).
2. If func is either undefined or null, return undefined.
...
---*/
function resolve() {
throw new Test262Error("Unexpected call to resolve");
}
var rejectCallCount = 0;
function reject(e) {
rejectCallCount += 1;
assert.sameValue(e, "bad promise resolve");
}
class BadPromise {
constructor(executor) {
executor(resolve, reject);
}
static resolve() {
throw "bad promise resolve";
}
}
for (var returnMethod of [null, undefined]) {
var iterator = {
[Symbol.iterator]() {
return this;
},
next() {
return {done: false};
},
return: returnMethod,
};
// Reset counter.
rejectCallCount = 0;
Promise.allSettled.call(BadPromise, iterator);
// Ensure `reject` was called exactly once.
assert.sameValue(rejectCallCount, 1);
}

View File

@ -0,0 +1,70 @@
// Copyright (C) 2025 André Bargull. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-promise.any
description: >
Input throw-completion forwarded when IteratorClose returns abruptly because GetMethod throws.
info: |
27.2.4.3 Promise.any ( iterable )
...
7. Let result be Completion(PerformPromiseAny(iteratorRecord, C, promiseCapability, promiseResolve)).
8. If result is an abrupt completion, then
a. If iteratorRecord.[[Done]] is false, set result to Completion(IteratorClose(iteratorRecord, result)).
b. IfAbruptRejectPromise(result, promiseCapability).
...
7.4.11 IteratorClose ( iteratorRecord, completion )
...
3. Let innerResult be Completion(GetMethod(iterator, "return")).
...
5. If completion is a throw completion, return ? completion.
...
7.3.10 GetMethod ( V, P )
1. Let func be ? GetV(V, P).
2. If func is either undefined or null, return undefined.
3. If IsCallable(func) is false, throw a TypeError exception.
...
---*/
function resolve() {
throw new Test262Error("Unexpected call to resolve");
}
var rejectCallCount = 0;
function reject(e) {
rejectCallCount += 1;
assert.sameValue(e, "bad promise resolve");
}
class BadPromise {
constructor(executor) {
executor(resolve, reject);
}
static resolve() {
throw "bad promise resolve";
}
}
for (var returnMethod of [0, 0n, true, "string", {}, Symbol()]) {
var iterator = {
[Symbol.iterator]() {
return this;
},
next() {
return {done: false};
},
return: returnMethod,
};
// Reset counter.
rejectCallCount = 0;
Promise.any.call(BadPromise, iterator);
// Ensure `reject` was called exactly once.
assert.sameValue(rejectCallCount, 1);
}

View File

@ -0,0 +1,71 @@
// Copyright (C) 2025 André Bargull. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-promise.any
description: >
Input throw-completion forwarded when IteratorClose returns normally because GetMethod returns undefined.
info: |
27.2.4.3 Promise.any ( iterable )
...
7. Let result be Completion(PerformPromiseAny(iteratorRecord, C, promiseCapability, promiseResolve)).
8. If result is an abrupt completion, then
a. If iteratorRecord.[[Done]] is false, set result to Completion(IteratorClose(iteratorRecord, result)).
b. IfAbruptRejectPromise(result, promiseCapability).
...
7.4.11 IteratorClose ( iteratorRecord, completion )
...
3. Let innerResult be Completion(GetMethod(iterator, "return")).
4. If innerResult is a normal completion, then
a. Let return be innerResult.[[Value]].
b. If return is undefined, return ? completion.
...
...
7.3.10 GetMethod ( V, P )
1. Let func be ? GetV(V, P).
2. If func is either undefined or null, return undefined.
...
---*/
function resolve() {
throw new Test262Error("Unexpected call to resolve");
}
var rejectCallCount = 0;
function reject(e) {
rejectCallCount += 1;
assert.sameValue(e, "bad promise resolve");
}
class BadPromise {
constructor(executor) {
executor(resolve, reject);
}
static resolve() {
throw "bad promise resolve";
}
}
for (var returnMethod of [null, undefined]) {
var iterator = {
[Symbol.iterator]() {
return this;
},
next() {
return {done: false};
},
return: returnMethod,
};
// Reset counter.
rejectCallCount = 0;
Promise.any.call(BadPromise, iterator);
// Ensure `reject` was called exactly once.
assert.sameValue(rejectCallCount, 1);
}

View File

@ -0,0 +1,70 @@
// Copyright (C) 2025 André Bargull. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-promise.race
description: >
Input throw-completion forwarded when IteratorClose returns abruptly because GetMethod throws.
info: |
27.2.4.5 Promise.race ( iterable )
...
7. Let result be Completion(PerformPromiseRace(iteratorRecord, C, promiseCapability, promiseResolve)).
8. If result is an abrupt completion, then
a. If iteratorRecord.[[Done]] is false, set result to Completion(IteratorClose(iteratorRecord, result)).
b. IfAbruptRejectPromise(result, promiseCapability).
...
7.4.11 IteratorClose ( iteratorRecord, completion )
...
3. Let innerResult be Completion(GetMethod(iterator, "return")).
...
5. If completion is a throw completion, return ? completion.
...
7.3.10 GetMethod ( V, P )
1. Let func be ? GetV(V, P).
2. If func is either undefined or null, return undefined.
3. If IsCallable(func) is false, throw a TypeError exception.
...
---*/
function resolve() {
throw new Test262Error("Unexpected call to resolve");
}
var rejectCallCount = 0;
function reject(e) {
rejectCallCount += 1;
assert.sameValue(e, "bad promise resolve");
}
class BadPromise {
constructor(executor) {
executor(resolve, reject);
}
static resolve() {
throw "bad promise resolve";
}
}
for (var returnMethod of [0, 0n, true, "string", {}, Symbol()]) {
var iterator = {
[Symbol.iterator]() {
return this;
},
next() {
return {done: false};
},
return: returnMethod,
};
// Reset counter.
rejectCallCount = 0;
Promise.race.call(BadPromise, iterator);
// Ensure `reject` was called exactly once.
assert.sameValue(rejectCallCount, 1);
}

View File

@ -0,0 +1,71 @@
// Copyright (C) 2025 André Bargull. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-promise.race
description: >
Input throw-completion forwarded when IteratorClose returns normally because GetMethod returns undefined.
info: |
27.2.4.5 Promise.race ( iterable )
...
7. Let result be Completion(PerformPromiseRace(iteratorRecord, C, promiseCapability, promiseResolve)).
8. If result is an abrupt completion, then
a. If iteratorRecord.[[Done]] is false, set result to Completion(IteratorClose(iteratorRecord, result)).
b. IfAbruptRejectPromise(result, promiseCapability).
...
7.4.11 IteratorClose ( iteratorRecord, completion )
...
3. Let innerResult be Completion(GetMethod(iterator, "return")).
4. If innerResult is a normal completion, then
a. Let return be innerResult.[[Value]].
b. If return is undefined, return ? completion.
...
...
7.3.10 GetMethod ( V, P )
1. Let func be ? GetV(V, P).
2. If func is either undefined or null, return undefined.
...
---*/
function resolve() {
throw new Test262Error("Unexpected call to resolve");
}
var rejectCallCount = 0;
function reject(e) {
rejectCallCount += 1;
assert.sameValue(e, "bad promise resolve");
}
class BadPromise {
constructor(executor) {
executor(resolve, reject);
}
static resolve() {
throw "bad promise resolve";
}
}
for (var returnMethod of [null, undefined]) {
var iterator = {
[Symbol.iterator]() {
return this;
},
next() {
return {done: false};
},
return: returnMethod,
};
// Reset counter.
rejectCallCount = 0;
Promise.race.call(BadPromise, iterator);
// Ensure `reject` was called exactly once.
assert.sameValue(rejectCallCount, 1);
}