tor-browser

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

ObjectEmitter.h (30644B)


      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_ObjectEmitter_h
      8 #define frontend_ObjectEmitter_h
      9 
     10 #include "mozilla/Attributes.h"  // MOZ_STACK_CLASS, MOZ_ALWAYS_INLINE, MOZ_RAII
     11 #include "mozilla/Maybe.h"       // Maybe
     12 
     13 #include <stddef.h>  // size_t
     14 #include <stdint.h>  // uint32_t
     15 
     16 #include "frontend/EmitterScope.h"   // EmitterScope
     17 #include "frontend/NameOpEmitter.h"  // NameOpEmitter
     18 #include "frontend/ParseNode.h"      // AccessorType
     19 #include "frontend/ParserAtom.h"     // TaggedParserAtomIndex
     20 #include "frontend/TDZCheckCache.h"  // TDZCheckCache
     21 #include "vm/Opcodes.h"              // JSOp
     22 #include "vm/Scope.h"                // LexicalScope
     23 
     24 namespace js {
     25 
     26 namespace frontend {
     27 
     28 struct BytecodeEmitter;
     29 class SharedContext;
     30 
     31 // Class for emitting bytecode for object and class properties.
     32 // See ObjectEmitter and ClassEmitter for usage.
     33 class MOZ_STACK_CLASS PropertyEmitter {
     34 public:
     35  enum class Kind {
     36    // Prototype property.
     37    Prototype,
     38 
     39    // Class static property.
     40    Static
     41  };
     42 
     43 protected:
     44  BytecodeEmitter* bce_;
     45 
     46  // True if the object is class.
     47  // Set by ClassEmitter.
     48  bool isClass_ = false;
     49 
     50  // True if the property is class static method.
     51  bool isStatic_ = false;
     52 
     53  // True if the property has computed or index key.
     54  bool isIndexOrComputed_ = false;
     55 
     56 #ifdef DEBUG
     57  // The state of this emitter.
     58  //
     59  // +-------+
     60  // | Start |-+
     61  // +-------+ |
     62  //           |
     63  // +---------+
     64  // |
     65  // |  +------------------------------------------------------------+
     66  // |  |                                                            |
     67  // |  | [normal property/method/accessor]                          |
     68  // |  v   prepareForPropValue  +-----------+              +------+ |
     69  // +->+----------------------->| PropValue |-+         +->| Init |-+
     70  //    |                        +-----------+ |         |  +------+
     71  //    |                                      |         |
     72  //    |  +-----------------------------------+         +-----------+
     73  //    |  |                                                         |
     74  //    |  +-+---------------------------------------+               |
     75  //    |    |                                       |               |
     76  //    |    | [method with super]                   |               |
     77  //    |    |   emitInitHomeObject +-------------+  v               |
     78  //    |    +--------------------->| InitHomeObj |->+               |
     79  //    |                           +-------------+  |               |
     80  //    |                                            |               |
     81  //    |    +-------------------------------------- +               |
     82  //    |    |                                                       |
     83  //    |    | emitInit                                              |
     84  //    |    +------------------------------------------------------>+
     85  //    |                                                            ^
     86  //    | [optimized private non-static method]                      |
     87  //    |   prepareForPrivateMethod   +--------------------+         |
     88  //    +---------------------------->| PrivateMethodValue |-+       |
     89  //    |                             +--------------------+ |       |
     90  //    |                                                    |       |
     91  //    |  +-------------------------------------------------+       |
     92  //    |  |                                                         |
     93  //    |  +-+---------------------------------------------+         |
     94  //    |    |                                             |         |
     95  //    |    | [method with super                          |         |
     96  //    |    | emitInitHomeObject   +-----------------+    v         |
     97  //    |    +--------------------->| InitHomeObjFor- |----+         |
     98  //    |                           | PrivateMethod   |    |         |
     99  //    |                           +-----------------+    |         |
    100  //    |                                                  |         |
    101  //    |    +---------------------------------------------+         |
    102  //    |    |                                                       |
    103  //    |    | skipInit                                              |
    104  //    |    +------------------------------------------------------>+
    105  //    |                                                            ^
    106  //    | [private static method]                                    |
    107  //    |   prepareForPrivateStaticMethod  +---------------------+   |
    108  //    +--------------------------------->| PrivateStaticMethod |-+ |
    109  //    |                                  +---------------------+ | |
    110  //    |                                                          | |
    111  //    |  +-------------------------------------------------------+ |
    112  //    |  |                                                         |
    113  //    |  +-+-------------------------------------------------+     |
    114  //    |    |                                                 |     |
    115  //    |    | [method with super                              |     |
    116  //    |    | emitInitHomeObject   +---------------------+    v     |
    117  //    |    +--------------------->| InitHomeObjFor-     |----+     |
    118  //    |                           | PrivateStaticMethod |    |     |
    119  //    |                           +---------------------+    |     |
    120  //    |                                                      |     |
    121  //    |      +-----------------------------------------------+     |
    122  //    |      |                                                     |
    123  //    |      | emitPrivateStaticMethod                             |
    124  //    |      +---------------------------------------------------->+
    125  //    |                                                            ^
    126  //    | [index property/method/accessor]                           |
    127  //    |   prepareForIndexPropKey  +----------+                     |
    128  //    +-------------------------->| IndexKey |-+                   |
    129  //    |                           +----------+ |                   |
    130  //    |                                        |                   |
    131  //    |  +-------------------------------------+                   |
    132  //    |  |                                                         |
    133  //    |  | prepareForIndexPropValue +------------+                 |
    134  //    |  +------------------------->| IndexValue |-+               |
    135  //    |                             +------------+ |               |
    136  //    |                                            |               |
    137  //    |    +---------------------------------------+               |
    138  //    |    |                                                       |
    139  //    |    +-+--------------------------------------------------+  |
    140  //    |      |                                                  |  |
    141  //    |      | [method with super]                              |  |
    142  //    |      |   emitInitHomeObject +---------------------+     v  |
    143  //    |      +--------------------->| InitHomeObjForIndex |---->+  |
    144  //    |                             +---------------------+     |  |
    145  //    |                                                         |  |
    146  //    |      +--------------------------------------------------+  |
    147  //    |      |                                                     |
    148  //    |      | emitInitIndexOrComputed                             |
    149  //    |      +---------------------------------------------------->+
    150  //    |                                                            ^
    151  //    | [computed property/method/accessor]                        |
    152  //    |   prepareForComputedPropKey  +-------------+               |
    153  //    +----------------------------->| ComputedKey |-+             |
    154  //    |                              +-------------+ |             |
    155  //    |                                              |             |
    156  //    |  +-------------------------------------------+             |
    157  //    |  |                                                         |
    158  //    |  | prepareForComputedPropValue +---------------+           |
    159  //    |  +---------------------------->| ComputedValue |-+         |
    160  //    |                                +---------------+ |         |
    161  //    |                                                  |         |
    162  //    |    +---------------------------------------------+         |
    163  //    |    |                                                       |
    164  //    |    +-+--------------------------------------------------+  |
    165  //    |      |                                                  |  |
    166  //    |      | [method with super]                              |  |
    167  //    |      |   emitInitHomeObject +------------------------+  v  |
    168  //    |      +--------------------->| InitHomeObjForComputed |->+  |
    169  //    |                             +------------------------+  |  |
    170  //    |                                                         |  |
    171  //    |      +--------------------------------------------------+  |
    172  //    |      |                                                     |
    173  //    |      | emitInitIndexOrComputed                             |
    174  //    |      +---------------------------------------------------->+
    175  //    |                                                            ^
    176  //    |                                                            |
    177  //    | [__proto__]                                                |
    178  //    |   prepareForProtoValue  +------------+ emitMutateProto     |
    179  //    +------------------------>| ProtoValue |-------------------->+
    180  //    |                         +------------+                     ^
    181  //    |                                                            |
    182  //    | [...prop]                                                  |
    183  //    |   prepareForSpreadOperand +---------------+ emitSpread     |
    184  //    +-------------------------->| SpreadOperand |----------------+
    185  //                                +---------------+
    186  enum class PropertyState {
    187    // The initial state.
    188    Start,
    189 
    190    // After calling prepareForPropValue.
    191    PropValue,
    192 
    193    // After calling emitInitHomeObject, from PropValue.
    194    InitHomeObj,
    195 
    196    // After calling prepareForPrivateMethod.
    197    PrivateMethodValue,
    198 
    199    // After calling emitInitHomeObject, from PrivateMethod.
    200    InitHomeObjForPrivateMethod,
    201 
    202    // After calling prepareForPrivateStaticMethod.
    203    PrivateStaticMethod,
    204 
    205    // After calling emitInitHomeObject, from PrivateStaticMethod.
    206    InitHomeObjForPrivateStaticMethod,
    207 
    208    // After calling prepareForIndexPropKey.
    209    IndexKey,
    210 
    211    // prepareForIndexPropValue.
    212    IndexValue,
    213 
    214    // After calling emitInitHomeObject, from IndexValue.
    215    InitHomeObjForIndex,
    216 
    217    // After calling prepareForComputedPropKey.
    218    ComputedKey,
    219 
    220    // prepareForComputedPropValue.
    221    ComputedValue,
    222 
    223    // After calling emitInitHomeObject, from ComputedValue.
    224    InitHomeObjForComputed,
    225 
    226    // After calling prepareForProtoValue.
    227    ProtoValue,
    228 
    229    // After calling prepareForSpreadOperand.
    230    SpreadOperand,
    231 
    232    // After calling one of emitInit, emitInitIndexOrComputed, emitMutateProto,
    233    // or emitSpread.
    234    Init,
    235  };
    236  PropertyState propertyState_ = PropertyState::Start;
    237 #endif
    238 
    239 public:
    240  explicit PropertyEmitter(BytecodeEmitter* bce);
    241 
    242  // Parameters are the offset in the source code for each character below:
    243  //
    244  // { __proto__: protoValue }
    245  //   ^
    246  //   |
    247  //   keyPos
    248  [[nodiscard]] bool prepareForProtoValue(uint32_t keyPos);
    249  [[nodiscard]] bool emitMutateProto();
    250 
    251  // { ...obj }
    252  //   ^
    253  //   |
    254  //   spreadPos
    255  [[nodiscard]] bool prepareForSpreadOperand(uint32_t spreadPos);
    256  [[nodiscard]] bool emitSpread();
    257 
    258  // { key: value }
    259  //   ^
    260  //   |
    261  //   keyPos
    262  [[nodiscard]] bool prepareForPropValue(uint32_t keyPos, Kind kind);
    263 
    264  [[nodiscard]] bool prepareForPrivateMethod();
    265 
    266  [[nodiscard]] bool prepareForPrivateStaticMethod(uint32_t keyPos);
    267 
    268  // { 1: value }
    269  //   ^
    270  //   |
    271  //   keyPos
    272  [[nodiscard]] bool prepareForIndexPropKey(uint32_t keyPos, Kind kind);
    273  [[nodiscard]] bool prepareForIndexPropValue();
    274 
    275  // { [ key ]: value }
    276  //   ^
    277  //   |
    278  //   keyPos
    279  [[nodiscard]] bool prepareForComputedPropKey(uint32_t keyPos, Kind kind);
    280  [[nodiscard]] bool prepareForComputedPropValue();
    281 
    282  [[nodiscard]] bool emitInitHomeObject();
    283 
    284  // @param key
    285  //        Property key
    286  [[nodiscard]] bool emitInit(AccessorType accessorType,
    287                              TaggedParserAtomIndex key);
    288 
    289  [[nodiscard]] bool emitInitIndexOrComputed(AccessorType accessorType);
    290 
    291  [[nodiscard]] bool emitPrivateStaticMethod(AccessorType accessorType);
    292 
    293  [[nodiscard]] bool skipInit();
    294 
    295 private:
    296  [[nodiscard]] MOZ_ALWAYS_INLINE bool prepareForProp(uint32_t keyPos,
    297                                                      bool isStatic,
    298                                                      bool isComputed);
    299 
    300  // @param op
    301  //        Opcode for initializing property
    302  // @param key
    303  //        Atom of the property if the property key is not computed
    304  [[nodiscard]] bool emitInit(JSOp op, TaggedParserAtomIndex key);
    305  [[nodiscard]] bool emitInitIndexOrComputed(JSOp op);
    306 
    307  [[nodiscard]] bool emitPopClassConstructor();
    308 };
    309 
    310 // Class for emitting bytecode for object literal.
    311 //
    312 // Usage: (check for the return value is omitted for simplicity)
    313 //
    314 //   `{}`
    315 //     ObjectEmitter oe(this);
    316 //     oe.emitObject(0);
    317 //     oe.emitEnd();
    318 //
    319 //   `{ prop: 10 }`
    320 //     ObjectEmitter oe(this);
    321 //     oe.emitObject(1);
    322 //
    323 //     oe.prepareForPropValue(offset_of_prop);
    324 //     emit(10);
    325 //     oe.emitInitProp(atom_of_prop);
    326 //
    327 //     oe.emitEnd();
    328 //
    329 //   `{ prop: function() {} }`, when property value is anonymous function
    330 //     ObjectEmitter oe(this);
    331 //     oe.emitObject(1);
    332 //
    333 //     oe.prepareForPropValue(offset_of_prop);
    334 //     emit(function);
    335 //     oe.emitInitProp(atom_of_prop);
    336 //
    337 //     oe.emitEnd();
    338 //
    339 //   `{ get prop() { ... }, set prop(v) { ... } }`
    340 //     ObjectEmitter oe(this);
    341 //     oe.emitObject(2);
    342 //
    343 //     oe.prepareForPropValue(offset_of_prop);
    344 //     emit(function_for_getter);
    345 //     oe.emitInitGetter(atom_of_prop);
    346 //
    347 //     oe.prepareForPropValue(offset_of_prop);
    348 //     emit(function_for_setter);
    349 //     oe.emitInitSetter(atom_of_prop);
    350 //
    351 //     oe.emitEnd();
    352 //
    353 //   `{ 1: 10, get 2() { ... }, set 3(v) { ... } }`
    354 //     ObjectEmitter oe(this);
    355 //     oe.emitObject(3);
    356 //
    357 //     oe.prepareForIndexPropKey(offset_of_prop);
    358 //     emit(1);
    359 //     oe.prepareForIndexPropValue();
    360 //     emit(10);
    361 //     oe.emitInitIndexedProp();
    362 //
    363 //     oe.prepareForIndexPropKey(offset_of_opening_bracket);
    364 //     emit(2);
    365 //     oe.prepareForIndexPropValue();
    366 //     emit(function_for_getter);
    367 //     oe.emitInitIndexGetter();
    368 //
    369 //     oe.prepareForIndexPropKey(offset_of_opening_bracket);
    370 //     emit(3);
    371 //     oe.prepareForIndexPropValue();
    372 //     emit(function_for_setter);
    373 //     oe.emitInitIndexSetter();
    374 //
    375 //     oe.emitEnd();
    376 //
    377 //   `{ [prop1]: 10, get [prop2]() { ... }, set [prop3](v) { ... } }`
    378 //     ObjectEmitter oe(this);
    379 //     oe.emitObject(3);
    380 //
    381 //     oe.prepareForComputedPropKey(offset_of_opening_bracket);
    382 //     emit(prop1);
    383 //     oe.prepareForComputedPropValue();
    384 //     emit(10);
    385 //     oe.emitInitComputedProp();
    386 //
    387 //     oe.prepareForComputedPropKey(offset_of_opening_bracket);
    388 //     emit(prop2);
    389 //     oe.prepareForComputedPropValue();
    390 //     emit(function_for_getter);
    391 //     oe.emitInitComputedGetter();
    392 //
    393 //     oe.prepareForComputedPropKey(offset_of_opening_bracket);
    394 //     emit(prop3);
    395 //     oe.prepareForComputedPropValue();
    396 //     emit(function_for_setter);
    397 //     oe.emitInitComputedSetter();
    398 //
    399 //     oe.emitEnd();
    400 //
    401 //   `{ __proto__: obj }`
    402 //     ObjectEmitter oe(this);
    403 //     oe.emitObject(1);
    404 //     oe.prepareForProtoValue(offset_of___proto__);
    405 //     emit(obj);
    406 //     oe.emitMutateProto();
    407 //     oe.emitEnd();
    408 //
    409 //   `{ ...obj }`
    410 //     ObjectEmitter oe(this);
    411 //     oe.emitObject(1);
    412 //     oe.prepareForSpreadOperand(offset_of_triple_dots);
    413 //     emit(obj);
    414 //     oe.emitSpread();
    415 //     oe.emitEnd();
    416 //
    417 class MOZ_STACK_CLASS ObjectEmitter : public PropertyEmitter {
    418 private:
    419 #ifdef DEBUG
    420  // The state of this emitter.
    421  //
    422  // +-------+ emitObject +--------+
    423  // | Start |----------->| Object |-+
    424  // +-------+            +--------+ |
    425  //                                 |
    426  //   +-----------------------------+
    427  //   |
    428  //   | (do PropertyEmitter operation)  emitEnd  +-----+
    429  //   +-------------------------------+--------->| End |
    430  //                                              +-----+
    431  enum class ObjectState {
    432    // The initial state.
    433    Start,
    434 
    435    // After calling emitObject.
    436    Object,
    437 
    438    // After calling emitEnd.
    439    End,
    440  };
    441  ObjectState objectState_ = ObjectState::Start;
    442 #endif
    443 
    444 public:
    445  explicit ObjectEmitter(BytecodeEmitter* bce);
    446 
    447  [[nodiscard]] bool emitObject(size_t propertyCount);
    448  // Same as `emitObject()`, but start with an empty template object already on
    449  // the stack.
    450  [[nodiscard]] bool emitObjectWithTemplateOnStack();
    451  [[nodiscard]] bool emitEnd();
    452 };
    453 
    454 // Save and restore the strictness.
    455 // Used by class declaration/expression to temporarily enable strict mode.
    456 class MOZ_RAII AutoSaveLocalStrictMode {
    457  SharedContext* sc_;
    458  bool savedStrictness_;
    459 
    460 public:
    461  explicit AutoSaveLocalStrictMode(SharedContext* sc);
    462  ~AutoSaveLocalStrictMode();
    463 
    464  // Force restore the strictness now.
    465  void restore();
    466 };
    467 
    468 // Class for emitting bytecode for JS class.
    469 //
    470 // Usage: (check for the return value is omitted for simplicity)
    471 //
    472 //   `class { constructor() { ... } }`
    473 //     ClassEmitter ce(this);
    474 //     ce.emitScope(scopeBindings);
    475 //     ce.emitClass(nullptr, nullptr, false);
    476 //
    477 //     emit(function_for_constructor);
    478 //     ce.emitInitConstructor(/* needsHomeObject = */ false);
    479 //
    480 //     ce.emitEnd(ClassEmitter::Kind::Expression);
    481 //
    482 //   `class X { constructor() { ... } }`
    483 //     ClassEmitter ce(this);
    484 //     ce.emitScope(scopeBindings);
    485 //     ce.emitClass(atom_of_X, nullptr, false);
    486 //
    487 //     emit(function_for_constructor);
    488 //     ce.emitInitConstructor(/* needsHomeObject = */ false);
    489 //
    490 //     ce.emitEnd(ClassEmitter::Kind::Expression);
    491 //
    492 //   `class X extends Y { constructor() { ... } }`
    493 //     ClassEmitter ce(this);
    494 //     ce.emitScope(scopeBindings);
    495 //
    496 //     emit(Y);
    497 //     ce.emitDerivedClass(atom_of_X, nullptr, false);
    498 //
    499 //     emit(function_for_constructor);
    500 //     ce.emitInitConstructor(/* needsHomeObject = */ false);
    501 //
    502 //     ce.emitEnd(ClassEmitter::Kind::Expression);
    503 //
    504 //   `class X extends Y { constructor() { ... super.f(); ... } }`
    505 //     ClassEmitter ce(this);
    506 //     ce.emitScope(scopeBindings);
    507 //
    508 //     emit(Y);
    509 //     ce.emitDerivedClass(atom_of_X, nullptr, false);
    510 //
    511 //     emit(function_for_constructor);
    512 //     // pass true if constructor contains super.prop access
    513 //     ce.emitInitConstructor(/* needsHomeObject = */ true);
    514 //
    515 //     ce.emitEnd(ClassEmitter::Kind::Expression);
    516 //
    517 //   `class X extends Y { field0 = expr0; ... }`
    518 //     ClassEmitter ce(this);
    519 //     ce.emitScope(scopeBindings);
    520 //     emit(Y);
    521 //     ce.emitDerivedClass(atom_of_X, nullptr, false);
    522 //
    523 //     ce.prepareForMemberInitializers(fields.length());
    524 //     for (auto field : fields) {
    525 //       emit(field.initializer_method());
    526 //       ce.emitStoreMemberInitializer();
    527 //     }
    528 //     ce.emitMemberInitializersEnd();
    529 //
    530 //     emit(function_for_constructor);
    531 //     ce.emitInitConstructor(/* needsHomeObject = */ false);
    532 //     ce.emitEnd(ClassEmitter::Kind::Expression);
    533 //
    534 //   `class X { field0 = super.method(); ... }`
    535 //     // after emitClass/emitDerivedClass
    536 //     ce.prepareForMemberInitializers(1);
    537 //     for (auto field : fields) {
    538 //       emit(field.initializer_method());
    539 //       if (field.initializer_contains_super_or_eval()) {
    540 //         ce.emitMemberInitializerHomeObject();
    541 //       }
    542 //       ce.emitStoreMemberInitializer();
    543 //     }
    544 //     ce.emitMemberInitializersEnd();
    545 //
    546 //   `m() {}` in class
    547 //     // after emitInitConstructor
    548 //     ce.prepareForPropValue(offset_of_m);
    549 //     emit(function_for_m);
    550 //     ce.emitInitProp(atom_of_m);
    551 //
    552 //   `m() { super.f(); }` in class
    553 //     // after emitInitConstructor
    554 //     ce.prepareForPropValue(offset_of_m);
    555 //     emit(function_for_m);
    556 //     ce.emitInitHomeObject();
    557 //     ce.emitInitProp(atom_of_m);
    558 //
    559 //   `async m() { super.f(); }` in class
    560 //     // after emitInitConstructor
    561 //     ce.prepareForPropValue(offset_of_m);
    562 //     emit(function_for_m);
    563 //     ce.emitInitHomeObject();
    564 //     ce.emitInitProp(atom_of_m);
    565 //
    566 //   `get p() { super.f(); }` in class
    567 //     // after emitInitConstructor
    568 //     ce.prepareForPropValue(offset_of_p);
    569 //     emit(function_for_p);
    570 //     ce.emitInitHomeObject();
    571 //     ce.emitInitGetter(atom_of_m);
    572 //
    573 //   `static m() {}` in class
    574 //     // after emitInitConstructor
    575 //     ce.prepareForPropValue(offset_of_m,
    576 //                            PropertyEmitter::Kind::Static);
    577 //     emit(function_for_m);
    578 //     ce.emitInitProp(atom_of_m);
    579 //
    580 //   `static get [p]() { super.f(); }` in class
    581 //     // after emitInitConstructor
    582 //     ce.prepareForComputedPropValue(offset_of_m,
    583 //                                    PropertyEmitter::Kind::Static);
    584 //     emit(p);
    585 //     ce.prepareForComputedPropValue();
    586 //     emit(function_for_m);
    587 //     ce.emitInitHomeObject();
    588 //     ce.emitInitComputedGetter();
    589 //
    590 class MOZ_STACK_CLASS ClassEmitter : public PropertyEmitter {
    591 public:
    592  enum class Kind {
    593    // Class expression.
    594    Expression,
    595 
    596    // Class declaration.
    597    Declaration,
    598  };
    599 
    600 private:
    601  // Pseudocode for class declarations:
    602  //
    603  //     class extends BaseExpression {
    604  //       constructor() { ... }
    605  //       ...
    606  //       }
    607  //
    608  //
    609  //   if defined <BaseExpression> {
    610  //     let heritage = BaseExpression;
    611  //
    612  //     if (heritage !== null) {
    613  //       funProto = heritage;
    614  //       objProto = heritage.prototype;
    615  //     } else {
    616  //       funProto = %FunctionPrototype%;
    617  //       objProto = null;
    618  //     }
    619  //   } else {
    620  //     objProto = %ObjectPrototype%;
    621  //   }
    622  //
    623  //   let homeObject = ObjectCreate(objProto);
    624  //
    625  //   if defined <constructor> {
    626  //     if defined <BaseExpression> {
    627  //       cons = DefineMethod(<constructor>, proto=homeObject,
    628  //       funProto=funProto);
    629  //     } else {
    630  //       cons = DefineMethod(<constructor>, proto=homeObject);
    631  //     }
    632  //   } else {
    633  //     if defined <BaseExpression> {
    634  //       cons = DefaultDerivedConstructor(proto=homeObject,
    635  //       funProto=funProto);
    636  //     } else {
    637  //       cons = DefaultConstructor(proto=homeObject);
    638  //     }
    639  //   }
    640  //
    641  //   cons.prototype = homeObject;
    642  //   homeObject.constructor = cons;
    643  //
    644  //   EmitPropertyList(...)
    645 
    646  bool isDerived_ = false;
    647 
    648  mozilla::Maybe<TDZCheckCache> tdzCache_;
    649  mozilla::Maybe<EmitterScope> innerScope_;
    650  mozilla::Maybe<TDZCheckCache> bodyTdzCache_;
    651  mozilla::Maybe<EmitterScope> bodyScope_;
    652  AutoSaveLocalStrictMode strictMode_;
    653 
    654 #ifdef DEBUG
    655  // The state of this emitter.
    656  //
    657  // clang-format off
    658  // +-------+
    659  // | Start |-+------------------------>+--+------------------------------>+--+
    660  // +-------+ |                         ^  |                               ^  |
    661  //           | [has scope]             |  | [has body scope]              |  |
    662  //           |   emitScope   +-------+ |  |  emitBodyScope  +-----------+ |  |
    663  //           +-------------->| Scope |-+  +---------------->| BodyScope |-+  |
    664  //                           +-------+                      +-----------+    |
    665  //                                                                           |
    666  //   +-----------------------------------------------------------------------+
    667  //   |
    668  //   |   emitClass           +-------+
    669  //   +-+----------------->+->| Class |-+
    670  //     |                  ^  +-------+ |
    671  //     | emitDerivedClass |            |
    672  //     +------------------+            |
    673  //                                     |
    674  //     +-------------------------------+
    675  //     |
    676  //     |
    677  //     |  prepareForMemberInitializers(isStatic = false)
    678  //     +---------------+
    679  //     |               |
    680  //     |      +--------v-------------------+
    681  //     |      | InstanceMemberInitializers |
    682  //     |      +----------------------------+
    683  //     |               |
    684  //                     | emitMemberInitializersEnd
    685  //     |               |
    686  //     |      +--------v----------------------+
    687  //     |      | InstanceMemberInitializersEnd |
    688  //     |      +-------------------------------+
    689  //     |               |
    690  //     +<--------------+
    691  //     |
    692  //     |   emitInitConstructor           +-----------------+
    693  //     +-------------------------------->| InitConstructor |-+
    694  //                                       +-----------------+ |
    695  //                                                           |
    696  //                                                           |
    697  //                                                           |
    698  //     +-----------------------------------------------------+
    699  //     |
    700  //     |  prepareForMemberInitializers(isStatic = true)
    701  //     +---------------+
    702  //     |               |
    703  //     |      +--------v-----------------+
    704  //     |      | StaticMemberInitializers |
    705  //     |      +--------------------------+
    706  //     |               |
    707  //     |               | emitMemberInitializersEnd
    708  //     |               |
    709  //     |      +--------v--------------------+
    710  //     |      | StaticMemberInitializersEnd |
    711  //     |      +-----------------------------+
    712  //     |               |
    713  //     +<--------------+
    714  //     |
    715  //     | (do PropertyEmitter operation)
    716  //     +--------------------------------+
    717  //                                      |
    718  //     +-------------+    emitBinding   |
    719  //     |  BoundName  |<-----------------+
    720  //     +--+----------+
    721  //        |
    722  //        | emitEnd
    723  //        |
    724  //     +--v----+
    725  //     |  End  |
    726  //     +-------+
    727  //
    728  // clang-format on
    729  enum class ClassState {
    730    // The initial state.
    731    Start,
    732 
    733    // After calling emitScope.
    734    Scope,
    735 
    736    // After calling emitBodyScope.
    737    BodyScope,
    738 
    739    // After calling emitClass or emitDerivedClass.
    740    Class,
    741 
    742    // After calling emitInitConstructor.
    743    InitConstructor,
    744 
    745    // After calling prepareForMemberInitializers(isStatic = false).
    746    InstanceMemberInitializers,
    747 
    748    // After calling emitMemberInitializersEnd.
    749    InstanceMemberInitializersEnd,
    750 
    751    // After calling prepareForMemberInitializers(isStatic = true).
    752    StaticMemberInitializers,
    753 
    754    // After calling emitMemberInitializersEnd.
    755    StaticMemberInitializersEnd,
    756 
    757    // After calling emitBinding.
    758    BoundName,
    759 
    760    // After calling emitEnd.
    761    End,
    762  };
    763  ClassState classState_ = ClassState::Start;
    764 
    765  // The state of the members emitter.
    766  //
    767  // clang-format off
    768  //
    769  //   +-------+
    770  //   | Start +<-----------------------------+
    771  //   +-------+                              |
    772  //       |                                  |
    773  //       | prepareForMemberInitializer      | emitStoreMemberInitializer
    774  //       v                                  |
    775  // +-------------+                          |
    776  // | Initializer +------------------------->+
    777  // +-------------+                          |
    778  //       |                                  |
    779  //       | emitMemberInitializerHomeObject  |
    780  //       v                                  |
    781  // +---------------------------+            |
    782  // | InitializerWithHomeObject +------------+
    783  // +---------------------------+
    784  //
    785  // clang-format on
    786  enum class MemberState {
    787    // After calling prepareForMemberInitializers
    788    // and 0 or more calls to emitStoreMemberInitializer.
    789    Start,
    790 
    791    // After calling prepareForMemberInitializer
    792    Initializer,
    793 
    794    // After calling emitMemberInitializerHomeObject
    795    InitializerWithHomeObject,
    796  };
    797  MemberState memberState_ = MemberState::Start;
    798 
    799  size_t numInitializers_ = 0;
    800 #endif
    801 
    802  TaggedParserAtomIndex name_;
    803  TaggedParserAtomIndex nameForAnonymousClass_;
    804  bool hasNameOnStack_ = false;
    805  mozilla::Maybe<NameOpEmitter> initializersAssignment_;
    806  size_t initializerIndex_ = 0;
    807 
    808 public:
    809  explicit ClassEmitter(BytecodeEmitter* bce);
    810 
    811  bool emitScope(LexicalScope::ParserData* scopeBindings);
    812  bool emitBodyScope(ClassBodyScope::ParserData* scopeBindings);
    813 
    814  // @param name
    815  //        Name of the class (nullptr if this is anonymous class)
    816  // @param nameForAnonymousClass
    817  //        Statically inferred name of the class (only for anonymous classes)
    818  // @param hasNameOnStack
    819  //        If true the name is on the stack (only for anonymous classes)
    820  [[nodiscard]] bool emitClass(TaggedParserAtomIndex name,
    821                               TaggedParserAtomIndex nameForAnonymousClass,
    822                               bool hasNameOnStack, uint8_t membersCount);
    823  [[nodiscard]] bool emitDerivedClass(
    824      TaggedParserAtomIndex name, TaggedParserAtomIndex nameForAnonymousClass,
    825      bool hasNameOnStack);
    826 
    827  // @param needsHomeObject
    828  //        True if the constructor contains `super.foo`
    829  [[nodiscard]] bool emitInitConstructor(bool needsHomeObject);
    830 
    831  [[nodiscard]] bool prepareForMemberInitializers(size_t numInitializers,
    832                                                  bool isStatic);
    833  [[nodiscard]] bool prepareForMemberInitializer();
    834  [[nodiscard]] bool emitMemberInitializerHomeObject(bool isStatic);
    835  [[nodiscard]] bool emitStoreMemberInitializer();
    836  [[nodiscard]] bool emitMemberInitializersEnd();
    837 
    838 #ifdef ENABLE_DECORATORS
    839  // TODO!: When we've enabled decorators, update the states and transition
    840  //        diagram to reflect this new state.
    841  [[nodiscard]] bool prepareForExtraInitializers(
    842      TaggedParserAtomIndex initializers);
    843 #endif
    844 
    845  [[nodiscard]] bool emitBinding();
    846 
    847 #ifdef ENABLE_DECORATORS
    848  // TODO!: When we've enabled decorators, update the states and transition
    849  //        diagram to reflect this new state.
    850  [[nodiscard]] bool prepareForDecorators();
    851 #endif
    852 
    853  [[nodiscard]] bool emitEnd(Kind kind);
    854 
    855 private:
    856  [[nodiscard]] bool initProtoAndCtor();
    857 
    858  [[nodiscard]] bool leaveBodyAndInnerScope();
    859 };
    860 
    861 } /* namespace frontend */
    862 } /* namespace js */
    863 
    864 #endif /* frontend_ObjectEmitter_h */