1 // Copyright 2021 the V8 project authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef INCLUDE_V8_PROMISE_H_ 6 #define INCLUDE_V8_PROMISE_H_ 7 8 #include "v8-local-handle.h" // NOLINT(build/include_directory) 9 #include "v8-object.h" // NOLINT(build/include_directory) 10 #include "v8config.h" // NOLINT(build/include_directory) 11 12 namespace v8 { 13 14 class Context; 15 16 #ifndef V8_PROMISE_INTERNAL_FIELD_COUNT 17 // The number of required internal fields can be defined by embedder. 18 #define V8_PROMISE_INTERNAL_FIELD_COUNT 0 19 #endif 20 21 /** 22 * An instance of the built-in Promise constructor (ES6 draft). 23 */ 24 class V8_EXPORT Promise : public Object { 25 public: 26 /** 27 * State of the promise. Each value corresponds to one of the possible values 28 * of the [[PromiseState]] field. 29 */ 30 enum PromiseState { kPending, kFulfilled, kRejected }; 31 32 class V8_EXPORT Resolver : public Object { 33 public: 34 /** 35 * Create a new resolver, along with an associated promise in pending state. 36 */ 37 static V8_WARN_UNUSED_RESULT MaybeLocal<Resolver> New( 38 Local<Context> context); 39 40 /** 41 * Extract the associated promise. 42 */ 43 Local<Promise> GetPromise(); 44 45 /** 46 * Resolve/reject the associated promise with a given value. 47 * Ignored if the promise is no longer pending. 48 */ 49 V8_WARN_UNUSED_RESULT Maybe<bool> Resolve(Local<Context> context, 50 Local<Value> value); 51 52 V8_WARN_UNUSED_RESULT Maybe<bool> Reject(Local<Context> context, 53 Local<Value> value); 54 Cast(Value * value)55 V8_INLINE static Resolver* Cast(Value* value) { 56 #ifdef V8_ENABLE_CHECKS 57 CheckCast(value); 58 #endif 59 return static_cast<Promise::Resolver*>(value); 60 } 61 62 private: 63 Resolver(); 64 static void CheckCast(Value* obj); 65 }; 66 67 /** 68 * Register a resolution/rejection handler with a promise. 69 * The handler is given the respective resolution/rejection value as 70 * an argument. If the promise is already resolved/rejected, the handler is 71 * invoked at the end of turn. 72 */ 73 V8_WARN_UNUSED_RESULT MaybeLocal<Promise> Catch(Local<Context> context, 74 Local<Function> handler); 75 76 V8_WARN_UNUSED_RESULT MaybeLocal<Promise> Then(Local<Context> context, 77 Local<Function> handler); 78 79 V8_WARN_UNUSED_RESULT MaybeLocal<Promise> Then(Local<Context> context, 80 Local<Function> on_fulfilled, 81 Local<Function> on_rejected); 82 83 /** 84 * Returns true if the promise has at least one derived promise, and 85 * therefore resolve/reject handlers (including default handler). 86 */ 87 bool HasHandler() const; 88 89 /** 90 * Returns the content of the [[PromiseResult]] field. The Promise must not 91 * be pending. 92 */ 93 Local<Value> Result(); 94 95 /** 96 * Returns the value of the [[PromiseState]] field. 97 */ 98 PromiseState State(); 99 100 /** 101 * Marks this promise as handled to avoid reporting unhandled rejections. 102 */ 103 void MarkAsHandled(); 104 105 /** 106 * Marks this promise as silent to prevent pausing the debugger when the 107 * promise is rejected. 108 */ 109 void MarkAsSilent(); 110 Cast(Value * value)111 V8_INLINE static Promise* Cast(Value* value) { 112 #ifdef V8_ENABLE_CHECKS 113 CheckCast(value); 114 #endif 115 return static_cast<Promise*>(value); 116 } 117 118 static const int kEmbedderFieldCount = V8_PROMISE_INTERNAL_FIELD_COUNT; 119 120 private: 121 Promise(); 122 static void CheckCast(Value* obj); 123 }; 124 125 /** 126 * PromiseHook with type kInit is called when a new promise is 127 * created. When a new promise is created as part of the chain in the 128 * case of Promise.then or in the intermediate promises created by 129 * Promise.{race, all}/AsyncFunctionAwait, we pass the parent promise 130 * otherwise we pass undefined. 131 * 132 * PromiseHook with type kResolve is called at the beginning of 133 * resolve or reject function defined by CreateResolvingFunctions. 134 * 135 * PromiseHook with type kBefore is called at the beginning of the 136 * PromiseReactionJob. 137 * 138 * PromiseHook with type kAfter is called right at the end of the 139 * PromiseReactionJob. 140 */ 141 enum class PromiseHookType { kInit, kResolve, kBefore, kAfter }; 142 143 using PromiseHook = void (*)(PromiseHookType type, Local<Promise> promise, 144 Local<Value> parent); 145 146 // --- Promise Reject Callback --- 147 enum PromiseRejectEvent { 148 kPromiseRejectWithNoHandler = 0, 149 kPromiseHandlerAddedAfterReject = 1, 150 kPromiseRejectAfterResolved = 2, 151 kPromiseResolveAfterResolved = 3, 152 }; 153 154 class PromiseRejectMessage { 155 public: PromiseRejectMessage(Local<Promise> promise,PromiseRejectEvent event,Local<Value> value)156 PromiseRejectMessage(Local<Promise> promise, PromiseRejectEvent event, 157 Local<Value> value) 158 : promise_(promise), event_(event), value_(value) {} 159 GetPromise()160 V8_INLINE Local<Promise> GetPromise() const { return promise_; } GetEvent()161 V8_INLINE PromiseRejectEvent GetEvent() const { return event_; } GetValue()162 V8_INLINE Local<Value> GetValue() const { return value_; } 163 164 private: 165 Local<Promise> promise_; 166 PromiseRejectEvent event_; 167 Local<Value> value_; 168 }; 169 170 using PromiseRejectCallback = void (*)(PromiseRejectMessage message); 171 172 } // namespace v8 173 174 #endif // INCLUDE_V8_PROMISE_H_ 175