Promise.any: coverage updates, R2

This commit is contained in:
Rick Waldron 2020-06-03 12:27:23 -04:00 committed by Leo Balter
parent 3604a65a29
commit 9999dff8fd
17 changed files with 806 additions and 11 deletions

View File

@ -19,16 +19,10 @@ let callCount = 0;
let errorArray;
function Constructor(executor) {
function reject(error) {
callCount += 1;
executor($ERROR, (error) => {
callCount++;
errorArray = error.errors;
assert(Array.isArray(error.errors), "error is array");
assert.sameValue(error.errors.length, 1, "error.length");
assert.sameValue(error.errors[0], "onRejectedValue", "error[0]");
assert(error instanceof AggregateError, "error instanceof AggregateError");
}
executor($ERROR, reject);
});
}
Constructor.resolve = function(v) {
return v;
@ -52,5 +46,4 @@ assert.sameValue(errorArray[0], "onRejectedValue", "errorArray after call to any
p1OnRejected("unexpectedonRejectedValue");
assert.sameValue(callCount, 1, "callCount after call to onRejected()");
assert.sameValue(errorArray[0], "onRejectedValue", "errorArray after call to onRejected()");
assert.sameValue(errorArray[0], "onRejectedValue", "errorArray[0] === 'onRejectedValue', after call to p1OnRejected()");

View File

@ -0,0 +1,44 @@
// Copyright (C) 2020 Rick Waldron. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-promise.any
description: >
Promise.any(new Test262Error()) rejects with TypeError.
info: |
Promise.any ( iterable )
...
Let iteratorRecord be GetIterator(iterable).
IfAbruptRejectPromise(iteratorRecord, promiseCapability).
...
GetIterator ( obj [ , hint [ , method ] ] )
...
Let iterator be ? Call(method, obj).
If Type(iterator) is not Object, throw a TypeError exception.
...
GetMethod
2. Let func be ? GetV(V, P).
3. If func is either undefined or null, return undefined.
4. If IsCallable(func) is false, throw a TypeError exception.
Call ( F, V [ , argumentsList ] )
2. If IsCallable(F) is false, throw a TypeError exception.
features: [Promise.any]
flags: [async]
---*/
try {
Promise.any(new Test262Error()).then(() => {
$DONE('The promise should be rejected, but was resolved');
}, (error) => {
assert(error instanceof TypeError);
}).then($DONE, $DONE);
} catch (error) {
$DONE(`The promise should be rejected, but threw an exception: ${error.message}`);
}

View File

@ -0,0 +1,63 @@
// Copyright (C) 2020 Rick Waldron. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-promise.any
description: >
Error when accessing an iterator result's `value` property (not closing
iterator)
info: |
Let result be PerformPromiseAny(iteratorRecord, C, promiseCapability).
If result is an abrupt completion, then
If iteratorRecord.[[Done]] is false, set result to IteratorClose(iteratorRecord, result).
IfAbruptRejectPromise(result, promiseCapability).
...
Runtime Semantics: PerformPromiseAny
...
Repeat
Let nextValue be IteratorValue(next).
If nextValue is an abrupt completion, set iteratorRecord.[[Done]] to true.
ReturnIfAbrupt(nextValue).
features: [Promise.any, Symbol.iterator]
flags: [async]
---*/
let callCount = 0;
let returnCount = 0;
let error = new Test262Error();
let poisoned = {
done: false
};
Object.defineProperty(poisoned, 'value', {
get() {
callCount++;
throw error;
}
});
let iterNextValThrows = {
[Symbol.iterator]() {
callCount++;
return {
next() {
callCount++;
return poisoned;
},
return() {
returnCount++;
return {};
}
};
}
};
Promise.any(iterNextValThrows).then(() => {
$DONE('The promise should be rejected, but was resolved');
}, (reason) => {
assert(error instanceof Test262Error);
assert.sameValue(reason, error);
assert.sameValue(callCount, 3, 'callCount === 3');
assert.sameValue(returnCount, 0);
}).then($DONE, $DONE);

View File

@ -0,0 +1,57 @@
// Copyright (C) 2020 Rick Waldron. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-promise.any
description: >
Error when accessing an iterator result's `value` property (rejecting
promise)
info: |
Let result be PerformPromiseAny(iteratorRecord, C, promiseCapability).
If result is an abrupt completion, then
If iteratorRecord.[[Done]] is false, set result to IteratorClose(iteratorRecord, result).
IfAbruptRejectPromise(result, promiseCapability).
...
Runtime Semantics: PerformPromiseAny
...
Repeat
Let nextValue be IteratorValue(next).
If nextValue is an abrupt completion, set iteratorRecord.[[Done]] to true.
ReturnIfAbrupt(nextValue).
features: [Promise.any, Symbol.iterator]
flags: [async]
---*/
let callCount = 0;
let error = new Test262Error();
let poisoned = {
done: false
};
Object.defineProperty(poisoned, 'value', {
get() {
callCount++;
throw error;
}
});
let iterNextValThrows = {
[Symbol.iterator]() {
callCount++;
return {
next() {
callCount++;
return poisoned;
}
};
}
};
Promise.any(iterNextValThrows).then(() => {
$DONE('The promise should be rejected, but was resolved');
}, (reason) => {
assert(error instanceof Test262Error);
assert.sameValue(reason, error);
assert.sameValue(callCount, 3, 'callCount === 3');
}).then($DONE, $DONE);

View File

@ -0,0 +1,36 @@
// Copyright (C) 2020 Rick Waldron. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-promise.any
description: >
Reject when argument's Symbol.iterator returns false
info: |
...
Let iteratorRecord be GetIterator(iterable).
IfAbruptRejectPromise(iteratorRecord, promiseCapability).
...
GetIterator ( obj [ , hint [ , method ] ] )
...
Let iterator be ? Call(method, obj).
If Type(iterator) is not Object, throw a TypeError exception.
...
features: [Promise.any, Symbol.iterator]
flags: [async]
---*/
let callCount = 0;
Promise.any({
[Symbol.iterator]() {
callCount++;
return false;
}
}).then(() => {
$DONE('The promise should be rejected, but was resolved');
}, (error) => {
assert.sameValue(callCount, 1, 'callCount === 1');
assert(error instanceof TypeError);
}).then($DONE, $DONE);

View File

@ -0,0 +1,36 @@
// Copyright (C) 2020 Rick Waldron. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-promise.any
description: >
Reject when argument's Symbol.iterator returns null
info: |
...
Let iteratorRecord be GetIterator(iterable).
IfAbruptRejectPromise(iteratorRecord, promiseCapability).
...
GetIterator ( obj [ , hint [ , method ] ] )
...
Let iterator be ? Call(method, obj).
If Type(iterator) is not Object, throw a TypeError exception.
...
features: [Promise.any, Symbol.iterator]
flags: [async]
---*/
let callCount = 0;
Promise.any({
[Symbol.iterator]() {
callCount++;
return null;
}
}).then(() => {
$DONE('The promise should be rejected, but was resolved');
}, (error) => {
assert.sameValue(callCount, 1, 'callCount === 1');
assert(error instanceof TypeError);
}).then($DONE, $DONE);

View File

@ -0,0 +1,35 @@
// Copyright (C) 2020 Rick Waldron. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-promise.any
description: >
Reject when argument's Symbol.iterator returns number
info: |
...
Let iteratorRecord be GetIterator(iterable).
IfAbruptRejectPromise(iteratorRecord, promiseCapability).
...
GetIterator ( obj [ , hint [ , method ] ] )
...
Let iterator be ? Call(method, obj).
If Type(iterator) is not Object, throw a TypeError exception.
...
features: [Promise.any, Symbol.iterator]
flags: [async]
---*/
let callCount = 0;
Promise.any({
[Symbol.iterator]() {
callCount++;
return 1;
}
}).then(() => {
$DONE('The promise should be rejected, but was resolved');
}, (error) => {
assert.sameValue(callCount, 1, 'callCount === 1');
assert(error instanceof TypeError);
}).then($DONE, $DONE);

View File

@ -0,0 +1,35 @@
// Copyright (C) 2020 Rick Waldron. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-promise.any
description: >
Reject when argument's Symbol.iterator returns string
info: |
...
Let iteratorRecord be GetIterator(iterable).
IfAbruptRejectPromise(iteratorRecord, promiseCapability).
...
GetIterator ( obj [ , hint [ , method ] ] )
...
Let iterator be ? Call(method, obj).
If Type(iterator) is not Object, throw a TypeError exception.
...
features: [Promise.any, Symbol.iterator]
flags: [async]
---*/
let callCount = 0;
Promise.any({
[Symbol.iterator]() {
callCount++;
return '';
}
}).then(() => {
$DONE('The promise should be rejected, but was resolved');
}, (error) => {
assert.sameValue(callCount, 1, 'callCount === 1');
assert(error instanceof TypeError);
}).then($DONE, $DONE);

View File

@ -0,0 +1,35 @@
// Copyright (C) 2020 Rick Waldron. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-promise.any
description: >
Reject when argument's Symbol.iterator returns symbol
info: |
...
Let iteratorRecord be GetIterator(iterable).
IfAbruptRejectPromise(iteratorRecord, promiseCapability).
...
GetIterator ( obj [ , hint [ , method ] ] )
...
Let iterator be ? Call(method, obj).
If Type(iterator) is not Object, throw a TypeError exception.
...
features: [Promise.any, Symbol.iterator]
flags: [async]
---*/
let callCount = 0;
Promise.any({
[Symbol.iterator]() {
callCount++;
return Symbol();
}
}).then(() => {
$DONE('The promise should be rejected, but was resolved');
}, (error) => {
assert.sameValue(callCount, 1, 'callCount === 1');
assert(error instanceof TypeError);
}).then($DONE, $DONE);

View File

@ -0,0 +1,35 @@
// Copyright (C) 2020 Rick Waldron. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-promise.any
description: >
Reject when argument's Symbol.iterator returns true
info: |
...
Let iteratorRecord be GetIterator(iterable).
IfAbruptRejectPromise(iteratorRecord, promiseCapability).
...
GetIterator ( obj [ , hint [ , method ] ] )
...
Let iterator be ? Call(method, obj).
If Type(iterator) is not Object, throw a TypeError exception.
...
features: [Symbol.iterator]
flags: [async]
---*/
let callCount = 0;
Promise.any({
[Symbol.iterator]() {
callCount++;
return true;
}
}).then(() => {
$DONE('The promise should be rejected, but was resolved');
}, (error) => {
assert.sameValue(callCount, 1, 'callCount === 1');
assert(error instanceof TypeError);
}).then($DONE, $DONE);

View File

@ -0,0 +1,35 @@
// Copyright (C) 2020 Rick Waldron. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-promise.any
description: >
Reject when argument's Symbol.iterator returns undefined
info: |
...
Let iteratorRecord be GetIterator(iterable).
IfAbruptRejectPromise(iteratorRecord, promiseCapability).
...
GetIterator ( obj [ , hint [ , method ] ] )
...
Let iterator be ? Call(method, obj).
If Type(iterator) is not Object, throw a TypeError exception.
...
features: [Symbol.iterator]
flags: [async]
---*/
let callCount = 0;
Promise.any({
[Symbol.iterator]() {
callCount++;
return undefined;
}
}).then(() => {
$DONE('The promise should be rejected, but was resolved');
}, (error) => {
assert.sameValue(callCount, 1, 'callCount === 1');
assert(error instanceof TypeError);
}).then($DONE, $DONE);

View File

@ -0,0 +1,68 @@
// Copyright (C) 2020 Rick Waldron. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-promise.any
description: >
Resolved promises ignore rejections through deferred invocation of the
provided resolving function
info: |
Let result be PerformPromiseAny(iteratorRecord, C, promiseCapability).
Runtime Semantics: PerformPromiseAny
...
Let remainingElementsCount be a new Record { [[value]]: 1 }.
...
8.d ...
ii. Set remainingElementsCount.[[value]] to remainingElementsCount.[[value]] 1.
iii. If remainingElementsCount.[[value]] is 0,
1. Let error be a newly created AggregateError object.
2. Perform ! DefinePropertyOrThrow(error, "errors", Property Descriptor { [[Configurable]]: true, [[Enumerable]]: false, [[Writable]]: true, [[Value]]: errors }).
3. Return ThrowCompletion(error).
...
Promise.any Reject Element Functions
...
Let alreadyCalled be the value of F's [[AlreadyCalled]] internal slot.
If alreadyCalled.[[value]] is true, return undefined.
Set alreadyCalled.[[value]] to true.
...
flags: [async]
features: [Promise.any, arrow-function]
---*/
let callCount = 0;
let fulfiller = {
then(resolve) {
new Promise((resolve) => {
callCount++;
resolve();
})
.then(() => {
callCount++;
resolve();
});
}
};
let rejector = {
then(resolve, reject) {
new Promise((resolve) => {
callCount++;
resolve();
})
.then(() => {
callCount++;
resolve();
reject();
});
}
};
Promise.all([fulfiller, rejector])
.then(() => {
assert.sameValue(callCount, 4, "callCount === 4");
$DONE();
}, () => {
$DONE("The promise should not be rejected.");
});

View File

@ -0,0 +1,52 @@
// Copyright (C) 2020 Rick Waldron. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-promise.any
description: >
Resolved promises ignore rejections through immediate invocation of the
provided resolving function
info: |
Let result be PerformPromiseAny(iteratorRecord, C, promiseCapability).
Runtime Semantics: PerformPromiseAny
...
Let remainingElementsCount be a new Record { [[value]]: 1 }.
...
8.d ...
ii. Set remainingElementsCount.[[value]] to remainingElementsCount.[[value]] 1.
iii. If remainingElementsCount.[[value]] is 0,
1. Let error be a newly created AggregateError object.
2. Perform ! DefinePropertyOrThrow(error, "errors", Property Descriptor { [[Configurable]]: true, [[Enumerable]]: false, [[Writable]]: true, [[Value]]: errors }).
3. Return ThrowCompletion(error).
...
Promise.any Reject Element Functions
...
Let alreadyCalled be the value of F's [[AlreadyCalled]] internal slot.
If alreadyCalled.[[value]] is true, return undefined.
Set alreadyCalled.[[value]] to true.
...
flags: [async]
features: [Promise.any, arrow-function]
---*/
let fulfiller = {
then(resolve) {
resolve();
}
};
let lateRejector = {
then(resolve, reject) {
resolve();
reject();
}
};
Promise.any([fulfiller, lateRejector])
.then(() => {
$DONE();
}, () => {
$DONE('The promise should not be rejected.');
});

View File

@ -0,0 +1,44 @@
// Copyright (C) 2016 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-promise.any
description: Rejecting through immediate invocation of the provided resolving function
info: |
...
Let promiseCapability be NewPromiseCapability(C).
...
Let result be PerformPromiseAny(iteratorRecord, promiseCapability, C).
...
Runtime Semantics: PerformPromiseAny
...
8. Repeat
...
r. Perform ? Invoke(nextPromise, "then",
« resultCapability.[[Resolve]], rejectElement »).
Promise.any Reject Element Functions
...
6. Return RejectPromise(promise, reason).
flags: [async]
features: [Promise.any, arrow-function]
---*/
let callCount = 0;
let thenable = {
then(_, reject) {
callCount++;
reject('reason');
}
};
Promise.any([thenable])
.then(() => {
$DONE('The promise should not be fulfilled.');
}, (error) => {
assert.sameValue(callCount, 1, "callCount === 1");
assert(error instanceof AggregateError, "error instanceof AggregateError");
assert.sameValue(error.errors[0], "reason", "error.errors[0] === 'reason'");
$DONE();
});

View File

@ -0,0 +1,99 @@
// Copyright (C) 2020 Rick Waldron. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-promise.any
description: >
Cannot tamper remainingElementsCount when Promise.all resolve element function is called twice in a row.
info: |
Let result be PerformPromiseAny(iteratorRecord, C, promiseCapability).
Runtime Semantics: PerformPromiseAny
...
Let remainingElementsCount be a new Record { [[value]]: 1 }.
...
8.d ...
ii. Set remainingElementsCount.[[value]] to remainingElementsCount.[[value]] 1.
iii. If remainingElementsCount.[[value]] is 0,
1. Let error be a newly created AggregateError object.
2. Perform ! DefinePropertyOrThrow(error, "errors", Property Descriptor { [[Configurable]]: true, [[Enumerable]]: false, [[Writable]]: true, [[Value]]: errors }).
3. Return ThrowCompletion(error).
...
Promise.any Reject Element Functions
...
Let alreadyCalled be the value of F's [[AlreadyCalled]] internal slot.
If alreadyCalled.[[value]] is true, return undefined.
Set alreadyCalled.[[value]] to true.
...
features: [Promise.any, arrow-function]
---*/
let callCount = 0;
let errorArray;
function Constructor(executor) {
function reject(error) {
callCount += 1;
errorArray = error.errors;
assert(Array.isArray(error.errors), "error is array");
assert.sameValue(error.errors.length, 3, "error.length");
assert.sameValue(error.errors[0], "p1-rejection", "error.errors[0] === 'p1-rejection'");
assert.sameValue(error.errors[1], "p2-rejection", "error.errors[1] === 'p2-rejection'");
assert.sameValue(error.errors[2], "p3-rejection", "error.errors[2] === 'p3-rejection'");
assert(error instanceof AggregateError, "error instanceof AggregateError");
}
executor($ERROR, reject);
}
Constructor.resolve = function(v) {
return v;
};
let p1OnRejected;
let p1 = {
then(onResolved, onRejected) {
p1OnRejected = onRejected;
}
};
let p2 = {
then(onResolved, onRejected) {
onRejected("p2-rejection");
onRejected("unexpectedonRejectedValue");
}
};
let p3 = {
then(onResolved, onRejected) {
onRejected("p3-rejection");
}
};
assert.sameValue(callCount, 0, "callCount before call to any()");
Promise.any.call(Constructor, [p1, p2, p3]);
assert.sameValue(callCount, 0, "callCount after call to any()");
p1OnRejected("p1-rejection");
assert.sameValue(callCount, 1, "callCount after call to p1OnRejected()");
assert.sameValue(
errorArray[0],
"p1-rejection",
"errorArray[0] === 'p1-rejection', after call to p1OnRejected(...)"
);
assert.sameValue(
errorArray[1],
"p2-rejection",
"errorArray[1] === 'p2-rejection', after call to p1OnRejected(...)"
);
assert.sameValue(
errorArray[2],
"p3-rejection",
"errorArray[2] === 'p3-rejection', after call to p1OnRejected(...)"
);

View File

@ -0,0 +1,100 @@
// Copyright (C) 2020 Rick Waldron. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-promise.any
description: >
Cannot tamper remainingElementsCount when two Promise.any Reject Element Function are called in succession.
info: |
Let result be PerformPromiseAny(iteratorRecord, C, promiseCapability).
Runtime Semantics: PerformPromiseAny
...
Let remainingElementsCount be a new Record { [[value]]: 1 }.
...
8.d ...
ii. Set remainingElementsCount.[[value]] to remainingElementsCount.[[value]] 1.
iii. If remainingElementsCount.[[value]] is 0,
1. Let error be a newly created AggregateError object.
2. Perform ! DefinePropertyOrThrow(error, "errors", Property Descriptor { [[Configurable]]: true, [[Enumerable]]: false, [[Writable]]: true, [[Value]]: errors }).
3. Return ThrowCompletion(error).
...
Promise.any Reject Element Functions
...
Let alreadyCalled be the value of F's [[AlreadyCalled]] internal slot.
If alreadyCalled.[[value]] is true, return undefined.
Set alreadyCalled.[[value]] to true.
...
features: [Promise.any, arrow-function]
---*/
let callCount = 0;
let errorArray;
function Constructor(executor) {
function reject(error) {
callCount += 1;
errorArray = error.errors;
assert(Array.isArray(error.errors), "error is array");
assert.sameValue(error.errors.length, 3, "error.length");
assert.sameValue(error.errors[0], "p1-rejection", "error.errors[0] === 'p1-rejection'");
assert.sameValue(error.errors[1], "p2-rejection", "error.errors[1] === 'p2-rejection'");
assert.sameValue(error.errors[2], "p3-rejection", "error.errors[2] === 'p3-rejection'");
assert(error instanceof AggregateError, "error instanceof AggregateError");
}
executor($ERROR, reject);
}
Constructor.resolve = function(v) {
return v;
};
let p1OnRejected;
let p1 = {
then(onResolved, onRejected) {
p1OnRejected = onRejected;
}
};
let p2 = {
then(onResolved, onRejected) {
p1OnRejected("p1-rejection");
onRejected("p2-rejection");
}
};
let p3 = {
then(onResolved, onRejected) {
onRejected("p3-rejection");
}
};
assert.sameValue(callCount, 0, "callCount before call to any()");
Promise.any.call(Constructor, [p1, p2, p3]);
assert.sameValue(callCount, 1, "callCount after call to any()");
assert.sameValue(errorArray[0], "p1-rejection", "errorArray[0] === 'p1-rejection'");
assert.sameValue(errorArray[1], "p2-rejection", "errorArray[1] === 'p2-rejection'");
assert.sameValue(errorArray[2], "p3-rejection", "errorArray[2] === 'p3-rejection'");
p1OnRejected("unexpectedonRejectedValue");
assert.sameValue(callCount, 1, "callCount after call to p1OnRejected()");
assert.sameValue(
errorArray[0],
"p1-rejection",
"errorArray[0] === 'p1-rejection', after call to p1OnRejected(...)"
);
assert.sameValue(
errorArray[1],
"p2-rejection",
"errorArray[1] === 'p2-rejection', after call to p1OnRejected(...)"
);
assert.sameValue(
errorArray[2],
"p3-rejection",
"errorArray[2] === 'p3-rejection', after call to p1OnRejected(...)"
);

View File

@ -0,0 +1,28 @@
// Copyright (C) 2020 Rick Waldron. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-promise.any
description: >
If the constructor's `resolve` method is not callable, reject with a TypeError.
info: |
Let result be PerformPromiseAny(iteratorRecord, C, promiseCapability).
Runtime Semantics: PerformPromiseAny
Let promiseResolve be ? Get(constructor, "resolve").
If ! IsCallable(promiseResolve) is false, throw a TypeError exception.
flags: [async]
features: [Promise.any, arrow-function]
---*/
Promise.resolve = null;
Promise.any([1])
.then(
() => $DONE('The promise should not be resolved.'),
error => {
assert(error instanceof TypeError);
}
).then($DONE, $DONE);