Skip to main content

v8/
promise.rs

1use std::marker::PhantomData;
2
3use crate::Context;
4use crate::Function;
5use crate::Local;
6use crate::Promise;
7use crate::PromiseResolver;
8use crate::Value;
9use crate::scope::PinScope;
10use crate::support::MaybeBool;
11
12unsafe extern "C" {
13  fn v8__Promise__Resolver__New(
14    context: *const Context,
15  ) -> *const PromiseResolver;
16  fn v8__Promise__Resolver__GetPromise(
17    this: *const PromiseResolver,
18  ) -> *const Promise;
19  fn v8__Promise__Resolver__Resolve(
20    this: *const PromiseResolver,
21    context: *const Context,
22    value: *const Value,
23  ) -> MaybeBool;
24  fn v8__Promise__Resolver__Reject(
25    this: *const PromiseResolver,
26    context: *const Context,
27    value: *const Value,
28  ) -> MaybeBool;
29  fn v8__Promise__State(this: *const Promise) -> PromiseState;
30  fn v8__Promise__HasHandler(this: *const Promise) -> bool;
31  fn v8__Promise__MarkAsHandled(this: *const Promise);
32  fn v8__Promise__Result(this: *const Promise) -> *const Value;
33  fn v8__Promise__Catch(
34    this: *const Promise,
35    context: *const Context,
36    handler: *const Function,
37  ) -> *const Promise;
38  fn v8__Promise__Then(
39    this: *const Promise,
40    context: *const Context,
41    handler: *const Function,
42  ) -> *const Promise;
43  fn v8__Promise__Then2(
44    this: *const Promise,
45    context: *const Context,
46    on_fulfilled: *const Function,
47    on_rejected: *const Function,
48  ) -> *const Promise;
49
50  fn v8__PromiseRejectMessage__GetPromise(
51    this: *const PromiseRejectMessage,
52  ) -> *const Promise;
53  fn v8__PromiseRejectMessage__GetValue(
54    this: *const PromiseRejectMessage,
55  ) -> *const Value;
56  fn v8__PromiseRejectMessage__GetEvent(
57    this: *const PromiseRejectMessage,
58  ) -> PromiseRejectEvent;
59}
60
61#[derive(Debug, PartialEq, Eq)]
62#[repr(C)]
63pub enum PromiseState {
64  Pending,
65  Fulfilled,
66  Rejected,
67}
68
69impl Promise {
70  /// Returns the value of the [[PromiseState]] field.
71  #[inline(always)]
72  pub fn state(&self) -> PromiseState {
73    unsafe { v8__Promise__State(self) }
74  }
75
76  /// Returns true if the promise has at least one derived promise, and
77  /// therefore resolve/reject handlers (including default handler).
78  #[inline(always)]
79  pub fn has_handler(&self) -> bool {
80    unsafe { v8__Promise__HasHandler(self) }
81  }
82
83  /// Marks this promise as handled to avoid reporting unhandled rejections.
84  #[inline(always)]
85  pub fn mark_as_handled(&self) {
86    unsafe { v8__Promise__MarkAsHandled(self) }
87  }
88
89  /// Returns the content of the [[PromiseResult]] field. The Promise must not
90  /// be pending.
91  #[inline(always)]
92  pub fn result<'s>(&self, scope: &PinScope<'s, '_>) -> Local<'s, Value> {
93    unsafe { scope.cast_local(|_| v8__Promise__Result(self)) }.unwrap()
94  }
95
96  /// Register a rejection handler with a promise.
97  ///
98  /// See `Self::then2`.
99  #[inline(always)]
100  pub fn catch<'s>(
101    &self,
102    scope: &PinScope<'s, '_>,
103    handler: Local<Function>,
104  ) -> Option<Local<'s, Promise>> {
105    unsafe {
106      scope.cast_local(|sd| {
107        v8__Promise__Catch(self, sd.get_current_context(), &*handler)
108      })
109    }
110  }
111
112  /// Register a resolution handler with a promise.
113  ///
114  /// See `Self::then2`.
115  #[inline(always)]
116  pub fn then<'s>(
117    &self,
118    scope: &PinScope<'s, '_>,
119    handler: Local<Function>,
120  ) -> Option<Local<'s, Promise>> {
121    unsafe {
122      scope.cast_local(|sd| {
123        v8__Promise__Then(self, sd.get_current_context(), &*handler)
124      })
125    }
126  }
127
128  /// Register a resolution/rejection handler with a promise.
129  /// The handler is given the respective resolution/rejection value as
130  /// an argument. If the promise is already resolved/rejected, the handler is
131  /// invoked at the end of turn.
132  #[inline(always)]
133  pub fn then2<'s>(
134    &self,
135    scope: &PinScope<'s, '_>,
136    on_fulfilled: Local<Function>,
137    on_rejected: Local<Function>,
138  ) -> Option<Local<'s, Promise>> {
139    unsafe {
140      scope.cast_local(|sd| {
141        v8__Promise__Then2(
142          self,
143          sd.get_current_context(),
144          &*on_fulfilled,
145          &*on_rejected,
146        )
147      })
148    }
149  }
150}
151
152impl PromiseResolver {
153  /// Create a new resolver, along with an associated promise in pending state.
154  #[inline(always)]
155  pub fn new<'s>(
156    scope: &PinScope<'s, '_>,
157  ) -> Option<Local<'s, PromiseResolver>> {
158    unsafe {
159      scope
160        .cast_local(|sd| v8__Promise__Resolver__New(sd.get_current_context()))
161    }
162  }
163
164  /// Extract the associated promise.
165  #[inline(always)]
166  pub fn get_promise<'s>(
167    &self,
168    scope: &PinScope<'s, '_>,
169  ) -> Local<'s, Promise> {
170    unsafe { scope.cast_local(|_| v8__Promise__Resolver__GetPromise(self)) }
171      .unwrap()
172  }
173
174  /// Resolve the associated promise with a given value.
175  /// Ignored if the promise is no longer pending.
176  #[inline(always)]
177  pub fn resolve(
178    &self,
179    scope: &PinScope<'_, '_>,
180    value: Local<'_, Value>,
181  ) -> Option<bool> {
182    unsafe {
183      v8__Promise__Resolver__Resolve(
184        self,
185        &*scope.get_current_context(),
186        &*value,
187      )
188      .into()
189    }
190  }
191
192  /// Reject the associated promise with a given value.
193  /// Ignored if the promise is no longer pending.
194  #[inline(always)]
195  pub fn reject(
196    &self,
197    scope: &PinScope<'_, '_>,
198    value: Local<'_, Value>,
199  ) -> Option<bool> {
200    unsafe {
201      v8__Promise__Resolver__Reject(
202        self,
203        &*scope.get_current_context(),
204        &*value,
205      )
206      .into()
207    }
208  }
209}
210
211#[derive(Debug, Clone, Copy, PartialEq, Eq)]
212#[repr(C)]
213pub enum PromiseRejectEvent {
214  PromiseRejectWithNoHandler,
215  PromiseHandlerAddedAfterReject,
216  PromiseRejectAfterResolved,
217  PromiseResolveAfterResolved,
218}
219
220#[derive(Clone, Copy, Debug)]
221#[repr(C)]
222pub struct PromiseRejectMessage<'msg>([usize; 3], PhantomData<&'msg ()>);
223
224impl<'msg> PromiseRejectMessage<'msg> {
225  #[inline(always)]
226  pub fn get_promise(&self) -> Local<'msg, Promise> {
227    unsafe { Local::from_raw(v8__PromiseRejectMessage__GetPromise(self)) }
228      .unwrap()
229  }
230
231  #[inline(always)]
232  pub fn get_event(&self) -> PromiseRejectEvent {
233    unsafe { v8__PromiseRejectMessage__GetEvent(self) }
234  }
235
236  #[inline(always)]
237  pub fn get_value(&self) -> Option<Local<'msg, Value>> {
238    unsafe { Local::from_raw(v8__PromiseRejectMessage__GetValue(self)) }
239  }
240}