Browse Source

Implement Promise.try() (#3800)

See: https://github.com/tc39/proposal-promise-try
pull/3812/head
Linus Groh 8 months ago committed by GitHub
parent
commit
c0a961f650
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 56
      core/engine/src/builtins/promise/mod.rs

56
core/engine/src/builtins/promise/mod.rs

@ -347,6 +347,7 @@ impl IntrinsicObject for Promise {
.static_method(Self::race, js_string!("race"), 1)
.static_method(Self::reject, js_string!("reject"), 1)
.static_method(Self::resolve, js_string!("resolve"), 1)
.static_method(Self::r#try, js_string!("try"), 1)
.static_method(Self::with_resolvers, js_string!("withResolvers"), 0)
.static_accessor(
JsSymbol::species(),
@ -462,6 +463,59 @@ impl Promise {
&self.state
}
/// [`Promise.try ( callbackfn, ...args )`][spec]
///
/// Calls the given function and returns a new promise that is resolved if the function
/// completes normally and rejected if it throws.
///
/// [spec]: https://tc39.es/proposal-promise-try/#sec-promise.try
pub(crate) fn r#try(
this: &JsValue,
args: &[JsValue],
context: &mut Context,
) -> JsResult<JsValue> {
let callback = args.get_or_undefined(0);
let callback_args = args.get(1..).unwrap_or(&[]);
// 1. Let C be the this value.
// 2. If C is not an Object, throw a TypeError exception.
let c = this.as_object().ok_or_else(|| {
JsNativeError::typ().with_message("Promise.try() called on a non-object")
})?;
// 3. Let promiseCapability be ? NewPromiseCapability(C).
let promise_capability = PromiseCapability::new(c, context)?;
// 4. Let status be Completion(Call(callbackfn, undefined, args)).
let status = callback.call(&JsValue::undefined(), callback_args, context);
match status {
// 5. If status is an abrupt completion, then
Err(err) => {
let value = err.to_opaque(context);
// a. Perform ? Call(promiseCapability.[[Reject]], undefined, « status.[[Value]] »).
promise_capability.functions.reject.call(
&JsValue::undefined(),
&[value],
context,
)?;
}
// 6. Else,
Ok(value) => {
// a. Perform ? Call(promiseCapability.[[Resolve]], undefined, « status.[[Value]] »).
promise_capability.functions.resolve.call(
&JsValue::undefined(),
&[value],
context,
)?;
}
}
// 7. Return promiseCapability.[[Promise]].
Ok(promise_capability.promise.clone().into())
}
/// [`Promise.withResolvers ( )`][spec]
///
/// Creates a new promise that is pending, and returns that promise plus the resolve and reject
@ -477,7 +531,7 @@ impl Promise {
use super::OrdinaryObject;
let c = this.as_object().ok_or_else(|| {
JsNativeError::typ().with_message("Promise.all() called on a non-object")
JsNativeError::typ().with_message("Promise.withResolvers() called on a non-object")
})?;
// 2. Let promiseCapability be ? NewPromiseCapability(C).

Loading…
Cancel
Save