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