Skip to content

Commit

Permalink
Adds NewPromiseCapability abstract operation (#43)
Browse files Browse the repository at this point in the history
This PR introduces the `NewPromiseCapability` abstract operation. As
part of this, it uses the new abstract operation in the
`Promise.withResolvers` polyfill.
  • Loading branch information
mhassan1 authored Jun 29, 2024
1 parent 1114a59 commit f5e9ab4
Show file tree
Hide file tree
Showing 4 changed files with 74 additions and 10 deletions.
2 changes: 1 addition & 1 deletion polyfills/Promise/withResolvers/config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ aliases = [ "es2024" ]
dependencies = [
"_ESAbstract.CreateDataPropertyOrThrow",
"_ESAbstract.CreateMethodProperty",
"_ESAbstract.IsConstructor",
"_ESAbstract.NewPromiseCapability",
"Promise",
]
license = "MIT"
Expand Down
11 changes: 2 additions & 9 deletions polyfills/Promise/withResolvers/polyfill.js
Original file line number Diff line number Diff line change
@@ -1,18 +1,11 @@
/* global CreateDataPropertyOrThrow, CreateMethodProperty, IsConstructor, Promise */
/* global CreateDataPropertyOrThrow, CreateMethodProperty, NewPromiseCapability, Promise */
(function () {
// 27.2.4.8 Promise.withResolvers ( )
CreateMethodProperty(Promise, "withResolvers", function withResolvers() {
// 1. Let C be the this value.
var C = this;
// 2. Let promiseCapability be ? NewPromiseCapability(C).
if (IsConstructor(C) === false) {
throw new TypeError("The `this` value must be a constructor");
}
var promiseCapability = {};
promiseCapability["[[Promise]]"] = new C(function (resolve, reject) {
promiseCapability["[[Resolve]]"] = resolve;
promiseCapability["[[Reject]]"] = reject;
});
var promiseCapability = NewPromiseCapability(C);
// 3. Let obj be OrdinaryObjectCreate(%Object.prototype%).
var obj = {};
// 4. Perform ! CreateDataPropertyOrThrow(obj, "promise", promiseCapability.[[Promise]]).
Expand Down
23 changes: 23 additions & 0 deletions polyfills/_ESAbstract/NewPromiseCapability/config.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
dependencies = [
"_ESAbstract.Construct",
"_ESAbstract.IsCallable",
"_ESAbstract.IsConstructor",
]
spec = "https://tc39.es/ecma262/#sec-newpromisecapability"

[browsers]
android = "*"
bb = "*"
chrome = "*"
edge = "*"
edge_mob = "*"
firefox = "*"
firefox_mob = "*"
ie = "*"
ie_mob = "*"
opera = "*"
op_mob = "*"
op_mini = "*"
safari = "*"
ios_saf = "*"
samsung_mob = "*"
48 changes: 48 additions & 0 deletions polyfills/_ESAbstract/NewPromiseCapability/polyfill.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/* global Construct, IsCallable, IsConstructor */
// 27.2.1.5 NewPromiseCapability ( C )
// eslint-disable-next-line no-unused-vars
function NewPromiseCapability(C) {
// 1. If IsConstructor(C) is false, throw a TypeError exception.
if (IsConstructor(C) === false) {
throw new TypeError("C must be a constructor");
}
// 2. NOTE: C is assumed to be a constructor function that supports the parameter conventions of the Promise constructor (see 27.2.3.1).
// 3. Let resolvingFunctions be the Record { [[Resolve]]: undefined, [[Reject]]: undefined }.
var resolvingFunctions = {
"[[Resolve]]": undefined,
"[[Reject]]": undefined
};
// 4. Let executorClosure be a new Abstract Closure with parameters (resolve, reject) that captures resolvingFunctions and performs the following steps when called:
// 5. Let executor be CreateBuiltinFunction(executorClosure, 2, "", « »).
var executor = function (resolve, reject) {
// a. If resolvingFunctions.[[Resolve]] is not undefined, throw a TypeError exception.
if (resolvingFunctions["[[Resolve]]"] !== undefined) {
throw new TypeError("[[Resolve]] is not undefined");
}
// b. If resolvingFunctions.[[Reject]] is not undefined, throw a TypeError exception.
if (resolvingFunctions["[[Reject]]"] !== undefined) {
throw new TypeError("[[Reject]] is not undefined");
}
// c. Set resolvingFunctions.[[Resolve]] to resolve.
resolvingFunctions["[[Resolve]]"] = resolve;
// d. Set resolvingFunctions.[[Reject]] to reject.
resolvingFunctions["[[Reject]]"] = reject;
// e. Return undefined.
};
// 6. Let promise be ? Construct(C, « executor »).
var promise = Construct(C, [executor]);
// 7. If IsCallable(resolvingFunctions.[[Resolve]]) is false, throw a TypeError exception.
if (IsCallable(resolvingFunctions["[[Resolve]]"]) === false) {
throw new TypeError("[[Resolve]] is not callable");
}
// 8. If IsCallable(resolvingFunctions.[[Reject]]) is false, throw a TypeError exception.
if (IsCallable(resolvingFunctions["[[Reject]]"]) === false) {
throw new TypeError("[[Reject]] is not callable");
}
// 9. Return the PromiseCapability Record { [[Promise]]: promise, [[Resolve]]: resolvingFunctions.[[Resolve]], [[Reject]]: resolvingFunctions.[[Reject]] }.
return {
"[[Promise]]": promise,
"[[Resolve]]": resolvingFunctions["[[Resolve]]"],
"[[Reject]]": resolvingFunctions["[[Reject]]"]
};
}

0 comments on commit f5e9ab4

Please sign in to comment.