tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

AsyncEmitter.h (5709B)


      1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
      2 * vim: set ts=8 sts=2 et sw=2 tw=80:
      3 * This Source Code Form is subject to the terms of the Mozilla Public
      4 * License, v. 2.0. If a copy of the MPL was not distributed with this
      5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 
      7 #ifndef frontend_AsyncEmitter_h
      8 #define frontend_AsyncEmitter_h
      9 
     10 #include "mozilla/Attributes.h"  // MOZ_STACK_CLASS
     11 
     12 #include "frontend/TryEmitter.h"  // TryEmitter
     13 
     14 namespace js {
     15 namespace frontend {
     16 
     17 struct BytecodeEmitter;
     18 
     19 // Class for emitting Bytecode associated with the AsyncFunctionGenerator.
     20 //
     21 // Usage:
     22 //
     23 //   For an async function, the params have to be handled separately,
     24 //   because the body may have pushed an additional var environment, changing
     25 //   the number of hops required to reach the |.generator| variable. In order
     26 //   to handle this, we can't reuse the same TryCatch emitter.
     27 //
     28 //   Simple case - For a function without expression or destructuring
     29 //   parameters:
     30 //   `async function f(<params>) {<body>}`,
     31 //     AsyncEmitter ae(this);
     32 //
     33 //     ae.prepareForParamsWithoutExpressionOrDestructuring();
     34 //     // Emit Params.
     35 //     ...
     36 //     ae.paramsEpilogue(); // We need to emit the epilogue before the extra
     37 //     VarScope emitExtraBodyVarScope();
     38 //
     39 //     // Emit new scope
     40 //     ae.prepareForBody();
     41 //
     42 //     // Emit body of the Function.
     43 //     ...
     44 //
     45 //     ae.emitEndFunction();
     46 //
     47 //   Complex case - For a function with expression or destructuring parameters:
     48 //   `async function f(<expression>) {<body>}`,
     49 //     AsyncEmitter ae(this);
     50 //
     51 //     ae.prepareForParamsWithExpressionOrDestructuring();
     52 //
     53 //     // Emit Params.
     54 //     ...
     55 //     ae.paramsEpilogue(); // We need to emit the epilogue before the extra
     56 //                          // VarScope
     57 //     emitExtraBodyVarScope();
     58 //
     59 //     // Emit new scope
     60 //     ae.prepareForBody();
     61 //
     62 //     // Emit body of the Function.
     63 //     ...
     64 //
     65 //     // The final yield is emitted in FunctionScriptEmitter::emitEndBody().
     66 //     ae.emitEndFunction();
     67 //
     68 //
     69 //   Async Module case - For a module with `await` in the top level:
     70 //     AsyncEmitter ae(this);
     71 //     ae.prepareForModule(); // prepareForModule is used to setup the generator
     72 //                            // for the async module.
     73 //     switchToMain();
     74 //     ...
     75 //
     76 //     // Emit new scope
     77 //     ae.prepareForBody();
     78 //
     79 //     // Emit body of the Script.
     80 //
     81 //     ae.emitEndModule();
     82 //
     83 
     84 class MOZ_STACK_CLASS AsyncEmitter {
     85 private:
     86  BytecodeEmitter* bce_;
     87 
     88  // try-catch block for async function parameter and body.
     89  mozilla::Maybe<TryEmitter> rejectTryCatch_;
     90 
     91 #ifdef DEBUG
     92  // The state of this emitter.
     93  //
     94  //    +-------+
     95  //    | Start |-+
     96  //    +-------+ |
     97  //              |
     98  //   +----------+
     99  //   |
    100  //   | [Parameters with Expression or Destructuring]
    101  //   |   prepareForParamsWithExpressionOrDestructuring    +------------+
    102  //   +----------------------------------------------------| Parameters |-->+
    103  //   |                                                    +------------+   |
    104  //   |                                                                     |
    105  //   | [Parameters Without Expression or Destructuring]                    |
    106  //   |   prepareForParamsWithoutExpressionOrDestructuring +------------+   |
    107  //   +----------------------------------------------------| Parameters |-->+
    108  //   |                                                    +------------+   |
    109  //   | [Modules]                                                           |
    110  //   |   prepareForModule  +----------------+                              |
    111  //   +-------------------->| ModulePrologue |--+                           |
    112  //                         +----------------+  |                           |
    113  //                                             |                           |
    114  //                                             |                           |
    115  //   +-----------------------------------------+                           |
    116  //   |                                                                     |
    117  //   |                                                                     |
    118  //   V                     +------------+  paramsEpilogue                  |
    119  //   +<--------------------| PostParams |<---------------------------------+
    120  //   |                     +------------+
    121  //   |
    122  //   | [Script body]
    123  //   |   prepareForBody    +---------+
    124  //   +-------------------->|  Body   |--------+
    125  //                         +---------+        |  <emit script body>
    126  //   +----------------------------------------+
    127  //   |
    128  //   |  [Functions]
    129  //   |  emitEndFunction     +-----+
    130  //   +--------------------->| End |
    131  //   |                      +-----+
    132  //   |
    133  //   |  [Modules]
    134  //   |  emitEndModule       +-----+
    135  //   +--------------------->| End |
    136  //                          +-----+
    137 
    138  enum class State {
    139    // The initial state.
    140    Start,
    141 
    142    Parameters,
    143 
    144    ModulePrologue,
    145 
    146    PostParams,
    147 
    148    Body,
    149 
    150    End,
    151  };
    152 
    153  State state_ = State::Start;
    154 #endif
    155 
    156  [[nodiscard]] bool emitRejectCatch();
    157  [[nodiscard]] bool emitFinalYield();
    158 
    159 public:
    160  explicit AsyncEmitter(BytecodeEmitter* bce) : bce_(bce) {};
    161 
    162  [[nodiscard]] bool prepareForParamsWithoutExpressionOrDestructuring();
    163  [[nodiscard]] bool prepareForParamsWithExpressionOrDestructuring();
    164  [[nodiscard]] bool prepareForModule();
    165  [[nodiscard]] bool emitParamsEpilogue();
    166  [[nodiscard]] bool prepareForBody();
    167  [[nodiscard]] bool emitEndFunction();
    168  [[nodiscard]] bool emitEndModule();
    169 };
    170 
    171 } /* namespace frontend */
    172 } /* namespace js */
    173 
    174 #endif /* frontend_AsyncEmitter_h */