Home | History | Annotate | Download | only in objects
      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