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