Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

increase test coverage of Promise.withResolvers #3936

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions test/built-ins/Promise/withResolvers/builtin-prototype.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// Copyright (C) 2023 Peter Klecha. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.

/*---
esid: sec-promise.withresolvers
features: [promise-with-resolvers]
description: Promise.withResolvers meets the requirements for built-in objects
info: |
Built-in functions that are not constructors do not have a "prototype"
property unless otherwise specified in the description of a particular
function.
---*/

assert.sameValue(
Object.getOwnPropertyDescriptor(Promise.withResolvers, "prototype"),
undefined,
"Promise.withResolvers has no own prototype property"
);
27 changes: 27 additions & 0 deletions test/built-ins/Promise/withResolvers/builtin.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// Copyright (C) 2023 Peter Klecha. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.

/*---
esid: sec-promise.withresolvers
features: [promise-with-resolvers]
description: Promise.withResolvers meets the requirements for built-in objects
info: |
Unless specified otherwise, a built-in object that is callable as a function
is a built-in function object with the characteristics described in 10.3.
Unless specified otherwise, the [[Extensible]] internal slot of a built-in
object initially has the value *true*.

Unless otherwise specified every built-in function and every built-in
constructor has the Function prototype object, which is the initial value of
the expression Function.prototype (20.2.3), as the value of its [[Prototype]]
internal slot.

---*/

assert(Object.isExtensible(Promise.withResolvers), "Promise.withResolvers is extensible");

assert.sameValue(
Object.getPrototypeOf(Promise.withResolvers),
Function.prototype,
"Prototype of Promise.withResolvers is Function.prototype"
);
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
// Copyright (C) 2023 Peter Klecha. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.

/*---
esid: sec-promise.withresolvers
features: [promise-with-resolvers]
description: >
Throws a TypeError if capabilities executor already called with non-undefined values.
info: |
Promise.all ( iterable )

...
6. Let promiseCapability be NewPromiseCapability(C).
7. ReturnIfAbrupt(promiseCapability).
...

GetCapabilitiesExecutor Functions
...
3. If promiseCapability.[[Resolve]] is not undefined, throw a TypeError exception.
4. If promiseCapability.[[Reject]] is not undefined, throw a TypeError exception.
5. Set promiseCapability.[[Resolve]] to resolve.
6. Set promiseCapability.[[Reject]] to reject.
...

PerformPromiseAll ( iteratorRecord, constructor, resultCapability )

...
1. Let promiseResolve be ? Get(constructor, `"resolve"`).
1. If IsCallable(promiseResolve) is *false*, throw a *TypeError* exception.
...
---*/

var checkPoint = "";
function fn1(executor) {
checkPoint += "a";
executor();
checkPoint += "b";
executor(function() {}, function() {});
checkPoint += "c";
}
Promise.withResolvers.call(fn1);
assert.sameValue(checkPoint, "abc", "executor initially called with no arguments");

checkPoint = "";
function fn2(executor) {
checkPoint += "a";
executor(undefined, undefined);
checkPoint += "b";
executor(function() {}, function() {});
checkPoint += "c";
}
Promise.withResolvers.call(fn2);
assert.sameValue(checkPoint, "abc", "executor initially called with (undefined, undefined)");

checkPoint = "";
function fn3(executor) {
checkPoint += "a";
executor(undefined, function() {});
checkPoint += "b";
executor(function() {}, function() {});
checkPoint += "c";
}
assert.throws(TypeError, function() {
Promise.withResolvers.call(fn3);
}, "executor initially called with (undefined, function)");
assert.sameValue(checkPoint, "ab", "executor initially called with (undefined, function)");

checkPoint = "";
function fn4(executor) {
checkPoint += "a";
executor(function() {}, undefined);
checkPoint += "b";
executor(function() {}, function() {});
checkPoint += "c";
}
assert.throws(TypeError, function() {
Promise.withResolvers.call(fn4);
}, "executor initially called with (function, undefined)");
assert.sameValue(checkPoint, "ab", "executor initially called with (function, undefined)");

checkPoint = "";
function fn5(executor) {
checkPoint += "a";
executor("invalid value", 123);
checkPoint += "b";
executor(function() {}, function() {});
checkPoint += "c";
}
assert.throws(TypeError, function() {
Promise.withResolvers.call(fn5);
}, "executor initially called with (String, Number)");
assert.sameValue(checkPoint, "ab", "executor initially called with (String, Number)");
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
// Copyright (C) 2023 Peter Klecha. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.

/*---
esid: sec-promise.withresolvers
features: [promise-with-resolvers]
description: >
Throws a TypeError if either resolve or reject capability is not callable.
info: |
Promise.withResolvers ( )

...
2. Let promiseCapability be ? NewPromiseCapability(C).
...

25.4.1.5 NewPromiseCapability ( C )
...
4. Let executor be a new built-in function object as defined in GetCapabilitiesExecutor Functions (25.4.1.5.1).
5. Set the [[Capability]] internal slot of executor to promiseCapability.
6. Let promise be Construct(C, «executor»).
7. ReturnIfAbrupt(promise).
8. If IsCallable(promiseCapability.[[Resolve]]) is false, throw a TypeError exception.
9. If IsCallable(promiseCapability.[[Reject]]) is false, throw a TypeError exception.
...
---*/

var checkPoint = "";
function fn1(executor) {
checkPoint += "a";
}
assert.throws(TypeError, function() {
Promise.withResolvers.call(fn1);
}, "executor not called at all");
assert.sameValue(checkPoint, "a", "executor not called at all");

checkPoint = "";
function fn2(executor) {
checkPoint += "a";
executor();
checkPoint += "b";
}
assert.throws(TypeError, function() {
Promise.withResolvers.call(fn2);
}, "executor called with no arguments");
assert.sameValue(checkPoint, "ab", "executor called with no arguments");

checkPoint = "";
function fn3(executor) {
checkPoint += "a";
executor(undefined, undefined);
checkPoint += "b";
}
assert.throws(TypeError, function() {
Promise.withResolvers.call(fn3);
}, "executor called with (undefined, undefined)");
assert.sameValue(checkPoint, "ab", "executor called with (undefined, undefined)");

checkPoint = "";
function fn4(executor) {
checkPoint += "a";
executor(undefined, function() {});
checkPoint += "b";
}
assert.throws(TypeError, function() {
Promise.withResolvers.call(fn4);
}, "executor called with (undefined, function)");
assert.sameValue(checkPoint, "ab", "executor called with (undefined, function)");

checkPoint = "";
function fn5(executor) {
checkPoint += "a";
executor(function() {}, undefined);
checkPoint += "b";
}
assert.throws(TypeError, function() {
Promise.withResolvers.call(fn5);
}, "executor called with (function, undefined)");
assert.sameValue(checkPoint, "ab", "executor called with (function, undefined)");

checkPoint = "";
function fn6(executor) {
checkPoint += "a";
executor(123, "invalid value");
checkPoint += "b";
}
assert.throws(TypeError, function() {
Promise.withResolvers.call(fn6);
}, "executor called with (Number, String)");
assert.sameValue(checkPoint, "ab", "executor called with (Number, String)");
28 changes: 28 additions & 0 deletions test/built-ins/Promise/withResolvers/length.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// Copyright (C) 2023 Peter Klecha. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-promise.withresolvers
features: [promise-with-resolvers]
description: Promise.withResolvers `length` property
info: |
ES6 Section 17:
Every built-in Function object, including constructors, has a length
property whose value is an integer. Unless otherwise specified, this value
is equal to the largest number of named arguments shown in the subclause
headings for the function description, including optional parameters.

[...]

Unless otherwise specified, the length property of a built-in Function
object has the attributes { [[Writable]]: false, [[Enumerable]]: false,
[[Configurable]]: true }.
includes: [propertyHelper.js]
---*/

assert.sameValue(Promise.withResolvers.length, 0);

verifyProperty(Promise.withResolvers, 'length', {
enumerable: false,
writable: false,
configurable: true,
})
29 changes: 29 additions & 0 deletions test/built-ins/Promise/withResolvers/name.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// Copyright (C) 2023 Peter Klecha. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-promise.withresolvers
features: [promise-with-resolvers]
description: Promise.withResolvers `name` property
info: |
ES6 Section 17:

Every built-in Function object, including constructors, that is not
identified as an anonymous function has a name property whose value is a
String. Unless otherwise specified, this value is the name that is given to
the function in this specification.

[...]

Unless otherwise specified, the name property of a built-in Function
object, if it exists, has the attributes { [[Writable]]: false,
[[Enumerable]]: false, [[Configurable]]: true }.
includes: [propertyHelper.js]
---*/

assert.sameValue(Promise.withResolvers.name, 'withResolvers');

verifyProperty(Promise.withResolvers, 'name', {
enumerable: false,
writable: false,
configurable: true,
})
28 changes: 28 additions & 0 deletions test/built-ins/Promise/withResolvers/not-a-constructor.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// Copyright (C) 2023 Peter Klecha. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-promise.withresolvers
description: >
Promise.withResolvers does not implement [[Construct]], is not new-able
info: |
ECMAScript Function Objects

Built-in function objects that are not identified as constructors do not
implement the [[Construct]] internal method unless otherwise specified in
the description of a particular function.

sec-evaluatenew

...
7. If IsConstructor(constructor) is false, throw a TypeError exception.
...
includes: [isConstructor.js]
features: [promise-with-resolvers, Reflect.construct, arrow-function]
---*/

assert.sameValue(isConstructor(Promise.withResolvers), false, 'isConstructor(Promise.withResolvers) must return false');

assert.throws(TypeError, () => {
new Promise.withResolvers();
}, '`new Promise.withResolvers()` throws TypeError');

21 changes: 21 additions & 0 deletions test/built-ins/Promise/withResolvers/prop-desc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// Copyright (C) 2023 Peter Klecha. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-promise.withresolvers
features: [promise-with-resolvers]
author: Jordan Harband
description: Promise.withResolvers should be non-enumerable
info: |
ES6 Section 17

Every other data property described in clauses 18 through 26 and in Annex
B.2 has the attributes { [[Writable]]: true, [[Enumerable]]: false,
[[Configurable]]: true } unless otherwise specified.
includes: [propertyHelper.js]
---*/

verifyProperty(Promise, 'withResolvers', {
enumerable: false,
writable: true,
configurable: true,
})
21 changes: 21 additions & 0 deletions test/built-ins/Promise/withResolvers/rejection.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// Copyright (C) 2023 Peter Klecha. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.

/*---
description: Promise.withResolvers `reject` function rejects the corresponding promise correctly
esid: sec-promise.withresolvers
features: [promise-with-resolvers]
flags: [async]
---*/


var instance = Promise.withResolvers();

var rejectString = "reject";

instance.promise.catch(err => {
assert.sameValue(err, rejectString);
$DONE();
});

instance.reject(rejectString);
21 changes: 21 additions & 0 deletions test/built-ins/Promise/withResolvers/resolution.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// Copyright (C) 2023 Peter Klecha. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.

/*---
description: Promise.withResolvers `resolve` function resolves the corresponding promise correctly
esid: sec-promise.withresolvers
features: [promise-with-resolvers]
flags: [async]
---*/


var instance = Promise.withResolvers();

var resolveValue = {};

instance.promise.then(res => {
assert.sameValue(res, resolveValue);
$DONE();
});

instance.resolve(resolveValue);
2 changes: 2 additions & 0 deletions test/built-ins/Promise/withResolvers/result.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@ var instance = Promise.withResolvers();

assert.sameValue(typeof instance, "object");
assert.notSameValue(instance, null);

assert(instance instanceof Object);
assert.sameValue(Object.getPrototypeOf(instance), Object.prototype);

verifyProperty(instance, "promise", {
writable: true,
Expand Down