1 // Copyright 2018 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 V8_OBJECTS_PROMISE_H_ 6 #define V8_OBJECTS_PROMISE_H_ 7 8 #include "src/objects/microtask.h" 9 10 // Has to be the last include (doesn't have include guards): 11 #include "src/objects/object-macros.h" 12 13 namespace v8 { 14 namespace internal { 15 16 // Struct to hold state required for PromiseReactionJob. See the comment on the 17 // PromiseReaction below for details on how this is being managed to reduce the 18 // memory and allocation overhead. This is the base class for the concrete 19 // 20 // - PromiseFulfillReactionJobTask 21 // - PromiseRejectReactionJobTask 22 // 23 // classes, which are used to represent either reactions, and we distinguish 24 // them by their instance types. 25 class PromiseReactionJobTask : public Microtask { 26 public: 27 DECL_ACCESSORS(argument, Object) 28 DECL_ACCESSORS(context, Context) 29 DECL_ACCESSORS(handler, HeapObject) 30 // [promise_or_capability]: Either a JSPromise or a PromiseCapability. 31 DECL_ACCESSORS(promise_or_capability, HeapObject) 32 33 static const int kArgumentOffset = Microtask::kHeaderSize; 34 static const int kContextOffset = kArgumentOffset + kPointerSize; 35 static const int kHandlerOffset = kContextOffset + kPointerSize; 36 static const int kPromiseOrCapabilityOffset = kHandlerOffset + kPointerSize; 37 static const int kSize = kPromiseOrCapabilityOffset + kPointerSize; 38 39 // Dispatched behavior. 40 DECL_CAST(PromiseReactionJobTask) 41 DECL_VERIFIER(PromiseReactionJobTask) 42 43 private: 44 DISALLOW_IMPLICIT_CONSTRUCTORS(PromiseReactionJobTask); 45 }; 46 47 // Struct to hold state required for a PromiseReactionJob of type "Fulfill". 48 class PromiseFulfillReactionJobTask : public PromiseReactionJobTask { 49 public: 50 // Dispatched behavior. 51 DECL_CAST(PromiseFulfillReactionJobTask) 52 DECL_PRINTER(PromiseFulfillReactionJobTask) 53 DECL_VERIFIER(PromiseFulfillReactionJobTask) 54 55 private: 56 DISALLOW_IMPLICIT_CONSTRUCTORS(PromiseFulfillReactionJobTask); 57 }; 58 59 // Struct to hold state required for a PromiseReactionJob of type "Reject". 60 class PromiseRejectReactionJobTask : public PromiseReactionJobTask { 61 public: 62 // Dispatched behavior. 63 DECL_CAST(PromiseRejectReactionJobTask) 64 DECL_PRINTER(PromiseRejectReactionJobTask) 65 DECL_VERIFIER(PromiseRejectReactionJobTask) 66 67 private: 68 DISALLOW_IMPLICIT_CONSTRUCTORS(PromiseRejectReactionJobTask); 69 }; 70 71 // A container struct to hold state required for PromiseResolveThenableJob. 72 class PromiseResolveThenableJobTask : public Microtask { 73 public: 74 DECL_ACCESSORS(context, Context) 75 DECL_ACCESSORS(promise_to_resolve, JSPromise) 76 DECL_ACCESSORS(then, JSReceiver) 77 DECL_ACCESSORS(thenable, JSReceiver) 78 79 static const int kContextOffset = Microtask::kHeaderSize; 80 static const int kPromiseToResolveOffset = kContextOffset + kPointerSize; 81 static const int kThenOffset = kPromiseToResolveOffset + kPointerSize; 82 static const int kThenableOffset = kThenOffset + kPointerSize; 83 static const int kSize = kThenableOffset + kPointerSize; 84 85 // Dispatched behavior. 86 DECL_CAST(PromiseResolveThenableJobTask) 87 DECL_PRINTER(PromiseResolveThenableJobTask) 88 DECL_VERIFIER(PromiseResolveThenableJobTask) 89 90 private: 91 DISALLOW_IMPLICIT_CONSTRUCTORS(PromiseResolveThenableJobTask); 92 }; 93 94 // Struct to hold the state of a PromiseCapability. 95 class PromiseCapability : public Struct { 96 public: 97 DECL_ACCESSORS(promise, HeapObject) 98 DECL_ACCESSORS(resolve, Object) 99 DECL_ACCESSORS(reject, Object) 100 101 static const int kPromiseOffset = Struct::kHeaderSize; 102 static const int kResolveOffset = kPromiseOffset + kPointerSize; 103 static const int kRejectOffset = kResolveOffset + kPointerSize; 104 static const int kSize = kRejectOffset + kPointerSize; 105 106 // Dispatched behavior. 107 DECL_CAST(PromiseCapability) 108 DECL_PRINTER(PromiseCapability) 109 DECL_VERIFIER(PromiseCapability) 110 111 private: 112 DISALLOW_IMPLICIT_CONSTRUCTORS(PromiseCapability); 113 }; 114 115 // A representation of promise reaction. This differs from the specification 116 // in that the PromiseReaction here holds both handlers for the fulfill and 117 // the reject case. When a JSPromise is eventually resolved (either via 118 // fulfilling it or rejecting it), we morph this PromiseReaction object in 119 // memory into a proper PromiseReactionJobTask and schedule it on the queue 120 // of microtasks. So the size of PromiseReaction and the size of the 121 // PromiseReactionJobTask has to be same for this to work. 122 // 123 // The PromiseReaction::promise_or_capability field can either hold a JSPromise 124 // instance (in the fast case of a native promise) or a PromiseCapability in 125 // case of a Promise subclass. 126 // 127 // We need to keep the context in the PromiseReaction so that we can run 128 // the default handlers (in case they are undefined) in the proper context. 129 // 130 // The PromiseReaction objects form a singly-linked list, terminated by 131 // Smi 0. On the JSPromise instance they are linked in reverse order, 132 // and are turned into the proper order again when scheduling them on 133 // the microtask queue. 134 class PromiseReaction : public Struct { 135 public: 136 enum Type { kFulfill, kReject }; 137 138 DECL_ACCESSORS(next, Object) 139 DECL_ACCESSORS(reject_handler, HeapObject) 140 DECL_ACCESSORS(fulfill_handler, HeapObject) 141 DECL_ACCESSORS(promise_or_capability, HeapObject) 142 143 static const int kNextOffset = Struct::kHeaderSize; 144 static const int kRejectHandlerOffset = kNextOffset + kPointerSize; 145 static const int kFulfillHandlerOffset = kRejectHandlerOffset + kPointerSize; 146 static const int kPromiseOrCapabilityOffset = 147 kFulfillHandlerOffset + kPointerSize; 148 static const int kSize = kPromiseOrCapabilityOffset + kPointerSize; 149 150 // Dispatched behavior. 151 DECL_CAST(PromiseReaction) 152 DECL_PRINTER(PromiseReaction) 153 DECL_VERIFIER(PromiseReaction) 154 155 private: 156 DISALLOW_IMPLICIT_CONSTRUCTORS(PromiseReaction); 157 }; 158 159 } // namespace internal 160 } // namespace v8 161 162 #include "src/objects/object-macros-undef.h" 163 164 #endif // V8_OBJECTS_PROMISE_H_ 165