tor-browser

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

DecoratorEmitter.cpp (45884B)


      1 /* This Source Code Form is subject to the terms of the Mozilla Public
      2 * License, v. 2.0. If a copy of the MPL was not distributed with this
      3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      4 
      5 #include "frontend/DecoratorEmitter.h"
      6 
      7 #include "mozilla/Assertions.h"
      8 
      9 #include "frontend/BytecodeEmitter.h"
     10 #include "frontend/CallOrNewEmitter.h"
     11 #include "frontend/FunctionEmitter.h"
     12 #include "frontend/IfEmitter.h"
     13 #include "frontend/LexicalScopeEmitter.h"
     14 #include "frontend/NameAnalysisTypes.h"
     15 #include "frontend/ObjectEmitter.h"
     16 #include "frontend/ParseNode.h"
     17 #include "frontend/ParserAtom.h"
     18 #include "frontend/WhileEmitter.h"
     19 #include "vm/ThrowMsgKind.h"
     20 
     21 using namespace js;
     22 using namespace js::frontend;
     23 
     24 DecoratorEmitter::DecoratorEmitter(BytecodeEmitter* bce) : bce_(bce) {}
     25 
     26 // A helper function to read the decorators in reverse order to how they were
     27 // parsed.
     28 bool DecoratorEmitter::reverseDecoratorsToApplicationOrder(
     29    const ListNode* decorators, DecoratorsVector& vec) const {
     30  MOZ_ASSERT(!decorators->empty());
     31  if (!vec.resize(decorators->count())) {
     32    ReportOutOfMemory(bce_->fc);
     33    return false;
     34  }
     35  int end = decorators->count() - 1;
     36  for (ParseNode* decorator : decorators->contents()) {
     37    vec[end--] = decorator;
     38  }
     39  return true;
     40 }
     41 
     42 bool DecoratorEmitter::emitApplyDecoratorsToElementDefinition(
     43    DecoratorEmitter::Kind kind, ParseNode* key, ListNode* decorators,
     44    bool isStatic) {
     45  MOZ_ASSERT(kind != Kind::Field && kind != Kind::Accessor);
     46 
     47  // The DecoratorEmitter expects the value to be decorated to be at the top
     48  // of the stack prior to this call. It will apply the decorators to this
     49  // value, possibly replacing the value with a value returned by a decorator.
     50  //          [stack] ADDINIT VAL
     51 
     52  // Decorators Proposal
     53  // https://arai-a.github.io/ecma262-compare/?pr=2417&id=sec-applydecoratorstoelementdefinition.
     54  // Step 1. Let decorators be elementRecord.[[Decorators]].
     55  // Step 2. If decorators is empty, return unused.
     56  // This is checked by the caller.
     57  MOZ_ASSERT(!decorators->empty());
     58 
     59  DecoratorsVector dec_vecs;
     60  if (!reverseDecoratorsToApplicationOrder(decorators, dec_vecs)) {
     61    return false;
     62  }
     63 
     64  // Step 3. Let key be elementRecord.[[Key]].
     65  // Step 4. Let kind be elementRecord.[[Kind]].
     66  // Step 5. For each element decorator of decorators, do
     67  for (auto decorator : dec_vecs) {
     68    // Step 5.a. Let decorationState be the Record { [[Finished]]: false }.
     69    if (!emitDecorationState()) {
     70      return false;
     71    }
     72 
     73    // TODO: See Bug 1869000 to support addInitializer for methods.
     74    if (!bce_->emitDupAt(1)) {
     75      //          [stack] ADDINIT VAL ADDINIT
     76      return false;
     77    }
     78 
     79    if (!emitCallDecoratorForElement(kind, key, isStatic, decorator)) {
     80      //          [stack] ADDINIT RETVAL
     81      return false;
     82    }
     83 
     84    // Step 5.i. Set decorationState.[[Finished]] to true.
     85    if (!emitUpdateDecorationState()) {
     86      return false;
     87    }
     88 
     89    // We need to check if the decorator returned undefined, a callable value,
     90    // or any other value.
     91    if (!emitCheckIsUndefined()) {
     92      //          [stack] ADDINIT VAL RETVAL ISUNDEFINED
     93      return false;
     94    }
     95 
     96    InternalIfEmitter ie(bce_);
     97    if (!ie.emitThenElse()) {
     98      //          [stack] ADDINIT VAL RETVAL
     99      return false;
    100    }
    101 
    102    // Pop the undefined RETVAL from the stack, leaving the original value in
    103    // place.
    104    if (!bce_->emitPopN(1)) {
    105      //          [stack] ADDINIT VAL
    106      return false;
    107    }
    108 
    109    if (!ie.emitElseIf(mozilla::Nothing())) {
    110      return false;
    111    }
    112 
    113    // Step 5.l.i. If IsCallable(newValue) is true, then
    114    if (!bce_->emitCheckIsCallable()) {
    115      //              [stack] ADDINIT VAL RETVAL ISCALLABLE_RESULT
    116      return false;
    117    }
    118 
    119    if (!ie.emitThenElse()) {
    120      //          [stack] ADDINIT VAL RETVAL
    121      return false;
    122    }
    123    // Step 5.l. Else,
    124    // Step 5.l.i.1. Perform MakeMethod(newValue, homeObject).
    125    // MakeMethod occurs in the caller, here we just drop the original method
    126    // which was an argument to the decorator, and leave the new method
    127    // returned by the decorator on the stack.
    128    if (!bce_->emit1(JSOp::Swap)) {
    129      //          [stack] ADDINIT RETVAL VAL
    130      return false;
    131    }
    132    if (!bce_->emitPopN(1)) {
    133      //          [stack] ADDINIT RETVAL
    134      return false;
    135    }
    136    // Step 5.j.ii. Else if initializer is not undefined, throw a TypeError
    137    //              exception.
    138    // Step 5.l.ii. Else if newValue is not undefined, throw a
    139    //              TypeError exception.
    140    if (!ie.emitElse()) {
    141      return false;
    142    }
    143 
    144    if (!bce_->emitPopN(1)) {
    145      //          [stack] ADDINIT RETVAL
    146      return false;
    147    }
    148 
    149    if (!bce_->emit2(JSOp::ThrowMsg,
    150                     uint8_t(ThrowMsgKind::DecoratorInvalidReturnType))) {
    151      return false;
    152    }
    153 
    154    if (!ie.emitEnd()) {
    155      return false;
    156    }
    157  }
    158 
    159  return true;
    160  //          [stack] ADDINIT RETVAL
    161 }
    162 
    163 bool DecoratorEmitter::emitApplyDecoratorsToFieldDefinition(
    164    ParseNode* key, ListNode* decorators, bool isStatic) {
    165  // This method creates a new array to contain initializers added by decorators
    166  // to the stack. start:
    167  //          [stack] ADDINIT
    168  // end:
    169  //          [stack] ADDINIT ARRAY
    170 
    171  // Decorators Proposal
    172  // https://arai-a.github.io/ecma262-compare/?pr=2417&id=sec-applydecoratorstoelementdefinition.
    173  // Step 1. Let decorators be elementRecord.[[Decorators]].
    174  // Step 2. If decorators is empty, return unused.
    175  // This is checked by the caller.
    176  MOZ_ASSERT(!decorators->empty());
    177 
    178  // If we're apply decorators to a field, we'll push a new array to the stack
    179  // to hold newly created initializers.
    180  if (!bce_->emitUint32Operand(JSOp::NewArray, 1)) {
    181    //          [stack] ADDINIT ARRAY
    182    return false;
    183  }
    184 
    185  if (!emitPropertyKey(key)) {
    186    //          [stack] ADDINIT ARRAY NAME
    187    return false;
    188  }
    189 
    190  if (!bce_->emitUint32Operand(JSOp::InitElemArray, 0)) {
    191    //          [stack] ADDINIT ARRAY
    192    return false;
    193  }
    194 
    195  if (!bce_->emit1(JSOp::One)) {
    196    //          [stack] ADDINIT ARRAY INDEX
    197    return false;
    198  }
    199 
    200  DecoratorsVector dec_vecs;
    201  if (!reverseDecoratorsToApplicationOrder(decorators, dec_vecs)) {
    202    return false;
    203  }
    204 
    205  // Step 3. Let key be elementRecord.[[Key]].
    206  // Step 4. Let kind be elementRecord.[[Kind]].
    207  // Step 5. For each element decorator of decorators, do
    208  for (auto it = dec_vecs.begin(); it != dec_vecs.end(); it++) {
    209    ParseNode* decorator = *it;
    210    // Step 5.a. Let decorationState be the Record { [[Finished]]: false }.
    211    if (!emitDecorationState()) {
    212      return false;
    213    }
    214 
    215    if (!bce_->emitDupAt(2)) {
    216      //          [stack] ADDINIT ARRAY INDEX ADDINIT
    217      return false;
    218    }
    219 
    220    if (!emitCallDecoratorForElement(Kind::Field, key, isStatic, decorator)) {
    221      //          [stack] ADDINIT ARRAY INDEX RETVAL
    222      return false;
    223    }
    224 
    225    // Step 5.i. Set decorationState.[[Finished]] to true.
    226    if (!emitUpdateDecorationState()) {
    227      //          [stack] ADDINIT ARRAY INDEX RETVAL
    228      return false;
    229    }
    230 
    231    // We need to check if the decorator returned undefined, a callable value,
    232    // or any other value.
    233    if (!emitCheckIsUndefined()) {
    234      //          [stack] ADDINIT ARRAY INDEX RETVAL ISUNDEFINED
    235      return false;
    236    }
    237 
    238    InternalIfEmitter ie(bce_);
    239    if (!ie.emitThenElse()) {
    240      //          [stack] ADDINIT ARRAY INDEX RETVAL
    241      return false;
    242    }
    243 
    244    // Pop the undefined RETVAL from the stack, leaving the original value in
    245    // place.
    246    if (!bce_->emitPopN(1)) {
    247      //          [stack] ADDINIT ARRAY INDEX
    248      return false;
    249    }
    250 
    251    if (!ie.emitElseIf(mozilla::Nothing())) {
    252      return false;
    253    }
    254 
    255    // Step 5.l.i. If IsCallable(newValue) is true, then
    256 
    257    if (!bce_->emitCheckIsCallable()) {
    258      //              [stack] ARRAY INDEX RETVAL ISCALLABLE_RESULT
    259      return false;
    260    }
    261 
    262    if (!ie.emitThenElse()) {
    263      //          [stack] ADDINIT ARRAY INDEX RETVAL
    264      return false;
    265    }
    266 
    267    // Step 5.j. If kind is field, then
    268    // Step 5.j.i. If IsCallable(initializer) is true, append initializer to
    269    //             elementRecord.[[Initializers]].
    270    if (!bce_->emit1(JSOp::InitElemInc)) {
    271      //          [stack] ADDINIT ARRAY INDEX
    272      return false;
    273    }
    274 
    275    // Step 5.j.ii. Else if initializer is not undefined, throw a TypeError
    276    //              exception.
    277    // Step 5.l.ii. Else if newValue is not undefined, throw a
    278    //              TypeError exception.
    279    if (!ie.emitElse()) {
    280      return false;
    281    }
    282 
    283    if (!bce_->emitPopN(1)) {
    284      //          [stack] ADDINIT ARRAY INDEX
    285      return false;
    286    }
    287 
    288    if (!bce_->emit2(JSOp::ThrowMsg,
    289                     uint8_t(ThrowMsgKind::DecoratorInvalidReturnType))) {
    290      return false;
    291    }
    292 
    293    if (!ie.emitEnd()) {
    294      return false;
    295    }
    296  }
    297 
    298  // Pop INDEX
    299  return bce_->emitPopN(1);
    300  //          [stack] ADDINIT ARRAY
    301 }
    302 
    303 bool DecoratorEmitter::emitApplyDecoratorsToAccessorDefinition(
    304    ParseNode* key, ListNode* decorators, bool isStatic) {
    305  // This method creates a new array to contain initializers added by decorators
    306  // to the stack. start:
    307  //          [stack] ADDINIT GETTER SETTER
    308  // end:
    309  //          [stack] ADDINIT GETTER SETTER ARRAY
    310  MOZ_ASSERT(key->is<NameNode>());
    311 
    312  // Decorators Proposal
    313  // https://arai-a.github.io/ecma262-compare/?pr=2417&id=sec-applydecoratorstoelementdefinition.
    314  // Step 1. Let decorators be elementRecord.[[Decorators]].
    315  // Step 2. If decorators is empty, return unused.
    316  // This is checked by the caller.
    317  MOZ_ASSERT(!decorators->empty());
    318 
    319  // If we're applying decorators to a field, we'll push a new array to the
    320  // stack to hold newly created initializers.
    321  if (!bce_->emitUint32Operand(JSOp::NewArray, 1)) {
    322    //          [stack] ADDINIT GETTER SETTER ARRAY
    323    return false;
    324  }
    325 
    326  if (!bce_->emitGetPrivateName(&key->as<NameNode>())) {
    327    //          [stack] ADDINIT GETTER SETTER ARRAY NAME
    328    return false;
    329  }
    330 
    331  if (!bce_->emitUint32Operand(JSOp::InitElemArray, 0)) {
    332    //          [stack] ADDINIT GETTER SETTER ARRAY
    333    return false;
    334  }
    335 
    336  if (!bce_->emit1(JSOp::One)) {
    337    //          [stack] ADDINIT GETTER SETTER ARRAY INDEX
    338    return false;
    339  }
    340 
    341  DecoratorsVector dec_vecs;
    342  if (!reverseDecoratorsToApplicationOrder(decorators, dec_vecs)) {
    343    return false;
    344  }
    345 
    346  // Step 3. Let key be elementRecord.[[Key]].
    347  // Step 4. Let kind be elementRecord.[[Kind]].
    348  // Step 5. For each element decorator of decorators, do
    349  for (auto it = dec_vecs.begin(); it != dec_vecs.end(); it++) {
    350    ParseNode* decorator = *it;
    351    // 5.a. Let decorationState be the Record { [[Finished]]: false }.
    352    if (!emitDecorationState()) {
    353      return false;
    354    }
    355 
    356    // Step 5.g.i. Set value to OrdinaryObjectCreate(%Object.prototype%).
    357    ObjectEmitter oe(bce_);
    358    if (!oe.emitObject(2)) {
    359      //          [stack] ADDINIT GETTER SETTER ARRAY INDEX VALUE
    360      return false;
    361    }
    362 
    363    // Step 5.g.ii. Perform ! CreateDataPropertyOrThrow(value, "get",
    364    //              elementRecord.[[Get]]).
    365    if (!oe.prepareForPropValue(decorator->pn_pos.begin,
    366                                PropertyEmitter::Kind::Prototype)) {
    367      return false;
    368    }
    369    if (!bce_->emitDupAt(4)) {
    370      //          [stack] ADDINIT GETTER SETTER ARRAY INDEX VALUE GETTER
    371      return false;
    372    }
    373    if (!oe.emitInit(frontend::AccessorType::None,
    374                     frontend::TaggedParserAtomIndex::WellKnown::get())) {
    375      //          [stack] ADDINIT GETTER SETTER ARRAY INDEX VALUE
    376      return false;
    377    }
    378 
    379    // Step 5.g.iii. Perform ! CreateDataPropertyOrThrow(value, "set",
    380    //               elementRecord.[[Set]]).
    381    if (!oe.prepareForPropValue(decorator->pn_pos.begin,
    382                                PropertyEmitter::Kind::Prototype)) {
    383      return false;
    384    }
    385    if (!bce_->emitDupAt(3)) {
    386      //          [stack] ADDINIT GETTER SETTER ARRAY INDEX VALUE SETTER
    387      return false;
    388    }
    389    if (!oe.emitInit(frontend::AccessorType::None,
    390                     frontend::TaggedParserAtomIndex::WellKnown::set())) {
    391      //          [stack] ADDINIT GETTER SETTER ARRAY INDEX VALUE
    392      return false;
    393    }
    394 
    395    if (!oe.emitEnd()) {
    396      //          [stack] ADDINIT GETTER SETTER ARRAY INDEX VALUE
    397      return false;
    398    }
    399 
    400    if (!bce_->emitDupAt(5)) {
    401      //          [stack] ADDINIT GETTER SETTER ARRAY INDEX VALUE ADDINIT
    402      return false;
    403    }
    404 
    405    // Step 5.j. Let newValue be ? Call(decorator, decoratorReceiver,
    406    //           « value, context »).
    407    if (!emitCallDecoratorForElement(Kind::Accessor, key, isStatic,
    408                                     decorator)) {
    409      //          [stack] ADDINIT GETTER SETTER ARRAY INDEX RETVAL
    410      return false;
    411    }
    412 
    413    // Step 5.k. Set decorationState.[[Finished]] to true.
    414    if (!emitUpdateDecorationState()) {
    415      //          [stack] ADDINIT GETTER SETTER ARRAY INDEX RETVAL
    416      return false;
    417    }
    418 
    419    // We need to check if the decorator returned undefined, a callable value,
    420    // or any other value.
    421    if (!emitCheckIsUndefined()) {
    422      //          [stack] ADDINIT GETTER SETTER ARRAY INDEX RETVAL ISUNDEFINED
    423      return false;
    424    }
    425 
    426    InternalIfEmitter ie(bce_);
    427    if (!ie.emitThenElse()) {
    428      //          [stack] ADDINIT GETTER SETTER ARRAY INDEX RETVAL
    429      return false;
    430    }
    431 
    432    // Pop the undefined RETVAL from the stack, leaving the original values in
    433    // place.
    434    if (!bce_->emitPopN(1)) {
    435      //          [stack] ADDINIT GETTER SETTER ARRAY INDEX
    436      return false;
    437    }
    438 
    439    if (!ie.emitElse()) {
    440      return false;
    441    }
    442 
    443    // Step 5.k. Else if kind is accessor, then
    444    // Step 5.k.ii. Else if newValue is not undefined, throw a TypeError
    445    //              exception. (Reordered)
    446    if (!bce_->emit2(JSOp::CheckIsObj,
    447                     uint8_t(CheckIsObjectKind::DecoratorReturn))) {
    448      //          [stack] ADDINIT GETTER SETTER ARRAY INDEX RETVAL
    449      return false;
    450    }
    451 
    452    // Step 5.k.i. If newValue is an Object, then
    453    // Step 5.k.i.1. Let newGetter be ? Get(newValue, "get").
    454    // Step 5.k.i.2. If IsCallable(newGetter) is true, set
    455    //               elementRecord.[[Get]] to newGetter.
    456    // Step 5.k.i.3. Else if newGetter is not undefined, throw a
    457    //               TypeError exception.
    458    if (!emitHandleNewValueField(
    459            frontend::TaggedParserAtomIndex::WellKnown::get(), 5)) {
    460      return false;
    461    }
    462 
    463    // Step 5.k.i.4. Let newSetter be ? Get(newValue, "set").
    464    // Step 5.k.i.5. If IsCallable(newSetter) is true, set
    465    //               elementRecord.[[Set]] to newSetter.
    466    // Step 5.k.i.6. Else if newSetter is not undefined, throw a
    467    //               TypeError exception.
    468    if (!emitHandleNewValueField(
    469            frontend::TaggedParserAtomIndex::WellKnown::set(), 4)) {
    470      return false;
    471    }
    472 
    473    // Step 5.k.i.7. Let initializer be ? Get(newValue, "init").
    474    // Step 5.k.i.8. If IsCallable(initializer) is true, append
    475    //               initializer to elementRecord.[[Initializers]].
    476    // Step 5.k.i.9. Else if initializer is not undefined, throw a
    477    //               TypeError exception.
    478    if (!emitHandleNewValueField(
    479            frontend::TaggedParserAtomIndex::WellKnown::init(), 0)) {
    480      return false;
    481    }
    482 
    483    // Pop RETVAL from stack
    484    if (!bce_->emitPopN(1)) {
    485      //          [stack] ADDINIT GETTER SETTER ARRAY INDEX
    486      return false;
    487    }
    488 
    489    if (!ie.emitEnd()) {
    490      return false;
    491    }
    492  }
    493 
    494  // Pop INDEX
    495  return bce_->emitPopN(1);
    496  //          [stack] ADDINIT GETTER SETTER ARRAY
    497 }
    498 
    499 bool DecoratorEmitter::emitApplyDecoratorsToClassDefinition(
    500    ParseNode* key, ListNode* decorators) {
    501  // This function expects a class constructor to already be on the stack. It
    502  // applies each decorator to the class constructor, possibly replacing it with
    503  // the return value of the decorator.
    504  //          [stack] CTOR
    505 
    506  DecoratorsVector dec_vecs;
    507  if (!reverseDecoratorsToApplicationOrder(decorators, dec_vecs)) {
    508    return false;
    509  }
    510 
    511  // https://arai-a.github.io/ecma262-compare/?pr=2417&id=sec-applydecoratorstoclassdefinition
    512  // Step 1. For each element decoratorRecord of decorators, do
    513  for (auto it = dec_vecs.begin(); it != dec_vecs.end(); it++) {
    514    ParseNode* decorator = *it;
    515    // Step 1.a. Let decorator be decoratorRecord.[[Decorator]].
    516    // Step 1.b. Let decoratorReceiver be decoratorRecord.[[Receiver]].
    517    // Step 1.c. Let decorationState be the Record { [[Finished]]: false }.
    518    if (!emitDecorationState()) {
    519      return false;
    520    }
    521 
    522    CallOrNewEmitter cone(bce_, JSOp::Call,
    523                          CallOrNewEmitter::ArgumentsKind::Other,
    524                          ValueUsage::WantValue);
    525 
    526    if (!bce_->emitCalleeAndThis(decorator, nullptr, cone)) {
    527      //          [stack] VAL? CALLEE THIS
    528      return false;
    529    }
    530 
    531    if (!cone.prepareForNonSpreadArguments()) {
    532      return false;
    533    }
    534 
    535    // Duplicate the class definition to pass it as an argument
    536    // to the decorator.
    537    if (!bce_->emitDupAt(2)) {
    538      //          [stack] CTOR CALLEE THIS CTOR
    539      return false;
    540    }
    541 
    542    // Step 1.d. Let context be CreateDecoratorContextObject(class, className,
    543    //           extraInitializers, decorationState).
    544    // TODO: See Bug 1868221 for support for addInitializer for class
    545    // decorators.
    546    if (!bce_->emit1(JSOp::Undefined)) {
    547      //          [stack] CTOR CALLEE THIS CTOR ADDINIT
    548      return false;
    549    }
    550    if (!emitCreateDecoratorContextObject(Kind::Class, key, false,
    551                                          decorator->pn_pos)) {
    552      //          [stack] CTOR CALLEE THIS CTOR context
    553      return false;
    554    }
    555 
    556    // Step 1.e. Let newDef be ? Call(decorator, decoratorReceiver, « classDef,
    557    //           context »).
    558    if (!cone.emitEnd(2, decorator->pn_pos.begin)) {
    559      //          [stack] CTOR NEWCTOR
    560      return false;
    561    }
    562 
    563    // Step 1.f. Set decorationState.[[Finished]] to true.
    564    if (!emitUpdateDecorationState()) {
    565      return false;
    566    }
    567 
    568    if (!emitCheckIsUndefined()) {
    569      //          [stack] CTOR NEWCTOR ISUNDEFINED
    570      return false;
    571    }
    572 
    573    InternalIfEmitter ie(bce_);
    574    if (!ie.emitThenElse()) {
    575      //          [stack] CTOR NEWCTOR
    576      return false;
    577    }
    578 
    579    // Pop the undefined NEWDEF from the stack, leaving the original value in
    580    // place.
    581    if (!bce_->emitPopN(1)) {
    582      //          [stack] CTOR
    583      return false;
    584    }
    585 
    586    if (!ie.emitElseIf(mozilla::Nothing())) {
    587      return false;
    588    }
    589 
    590    // Step 1.g. If IsCallable(newDef) is true, then
    591    // Step 1.g.i. Set classDef to newDef.
    592    if (!bce_->emitCheckIsCallable()) {
    593      //              [stack] CTOR NEWCTOR ISCALLABLE_RESULT
    594      return false;
    595    }
    596 
    597    if (!ie.emitThenElse()) {
    598      //          [stack] CTOR NEWCTOR
    599      return false;
    600    }
    601 
    602    if (!bce_->emit1(JSOp::Swap)) {
    603      //          [stack] NEWCTOR CTOR
    604      return false;
    605    }
    606    if (!bce_->emitPopN(1)) {
    607      //          [stack] NEWCTOR
    608      return false;
    609    }
    610 
    611    // Step 1.h. Else if newDef is not undefined, then
    612    // Step 1.h.i. Throw a TypeError exception.
    613    if (!ie.emitElse()) {
    614      return false;
    615    }
    616 
    617    if (!bce_->emitPopN(1)) {
    618      //          [stack] CTOR
    619      return false;
    620    }
    621    if (!bce_->emit2(JSOp::ThrowMsg,
    622                     uint8_t(ThrowMsgKind::DecoratorInvalidReturnType))) {
    623      return false;
    624    }
    625 
    626    if (!ie.emitEnd()) {
    627      return false;
    628    }
    629  }
    630 
    631  // Step 2. Return classDef.
    632  return true;
    633 }
    634 
    635 bool DecoratorEmitter::emitInitializeFieldOrAccessor() {
    636  //          [stack] THIS INITIALIZERS
    637 
    638  // Decorators Proposal
    639  // https://arai-a.github.io/ecma262-compare/?pr=2417&id=sec-applydecoratorstoelementdefinition.
    640  //
    641  // Step 1. Assert: elementRecord.[[Kind]] is field or accessor.
    642  // Step 2. If elementRecord.[[BackingStorageKey]] is present, let fieldName be
    643  //         elementRecord.[[BackingStorageKey]].
    644  // Step 3. Else, let fieldName be elementRecord.[[Key]].
    645  // We've stored the fieldname in the first element of the initializers array.
    646  if (!bce_->emit1(JSOp::Dup)) {
    647    //          [stack] THIS INITIALIZERS INITIALIZERS
    648    return false;
    649  }
    650 
    651  if (!bce_->emit1(JSOp::Zero)) {
    652    //          [stack] THIS INITIALIZERS INITIALIZERS INDEX
    653    return false;
    654  }
    655 
    656  if (!bce_->emit1(JSOp::GetElem)) {
    657    //          [stack] THIS INITIALIZERS FIELDNAME
    658    return false;
    659  }
    660 
    661  // Retrieve initial value of the field
    662  if (!bce_->emit1(JSOp::Dup)) {
    663    //          [stack] THIS INITIALIZERS FIELDNAME FIELDNAME
    664    return false;
    665  }
    666 
    667  if (!bce_->emitDupAt(3)) {
    668    //          [stack] THIS INITIALIZERS FIELDNAME FIELDNAME THIS
    669    return false;
    670  }
    671 
    672  if (!bce_->emit1(JSOp::Swap)) {
    673    //          [stack] THIS INITIALIZERS FIELDNAME THIS FIELDNAME
    674    return false;
    675  }
    676 
    677  // Step 4. Let initValue be undefined.
    678  // TODO: (See Bug 1817993) At the moment, we're applying the initialization
    679  // logic in two steps. The pre-decorator initialization code runs, stores
    680  // the initial value, and then we retrieve it here and apply the initializers
    681  // added by decorators. We should unify these two steps.
    682  if (!bce_->emit1(JSOp::GetElem)) {
    683    //          [stack] THIS INITIALIZERS FIELDNAME VALUE
    684    return false;
    685  }
    686 
    687  if (!bce_->emit2(JSOp::Pick, 2)) {
    688    //          [stack] THIS FIELDNAME VALUE INITIALIZERS
    689    return false;
    690  }
    691 
    692  // Retrieve the length of the initializers array.
    693  if (!bce_->emit1(JSOp::Dup)) {
    694    //          [stack] THIS FIELDNAME VALUE INITIALIZERS INITIALIZERS
    695    return false;
    696  }
    697 
    698  if (!bce_->emitAtomOp(JSOp::GetProp,
    699                        TaggedParserAtomIndex::WellKnown::length())) {
    700    //          [stack] THIS FIELDNAME VALUE INITIALIZERS LENGTH
    701    return false;
    702  }
    703 
    704  if (!bce_->emit1(JSOp::One)) {
    705    //          [stack] THIS FIELDNAME VALUE INITIALIZERS LENGTH INDEX
    706    return false;
    707  }
    708 
    709  // Step 5. For each element initializer of elementRecord.[[Initializers]], do
    710  InternalWhileEmitter wh(bce_);
    711  // At this point, we have no context to determine offsets in the
    712  // code for this while statement. Ideally, it would correspond to
    713  // the field we're initializing.
    714  if (!wh.emitCond()) {
    715    //          [stack] THIS FIELDNAME VALUE INITIALIZERS LENGTH INDEX
    716    return false;
    717  }
    718 
    719  if (!bce_->emit1(JSOp::Dup)) {
    720    //          [stack] THIS FIELDNAME VALUE INITIALIZERS LENGTH INDEX INDEX
    721    return false;
    722  }
    723 
    724  if (!bce_->emitDupAt(2)) {
    725    //          [stack] THIS FIELDNAME VALUE INITIALIZERS LENGTH INDEX INDEX
    726    //                  LENGTH
    727    return false;
    728  }
    729 
    730  if (!bce_->emit1(JSOp::Lt)) {
    731    //          [stack] THIS FIELDNAME VALUE INITIALIZERS LENGTH INDEX BOOL
    732    return false;
    733  }
    734 
    735  // Step 5.a. Set initValue to ? Call(initializer, receiver, « initValue»).
    736  if (!wh.emitBody()) {
    737    //          [stack] THIS FIELDNAME VALUE INITIALIZERS LENGTH INDEX
    738    return false;
    739  }
    740 
    741  if (!bce_->emitDupAt(2)) {
    742    //          [stack] THIS FIELDNAME VALUE INITIALIZERS LENGTH INDEX
    743    //                  INITIALIZERS
    744    return false;
    745  }
    746 
    747  if (!bce_->emitDupAt(1)) {
    748    //          [stack] THIS FIELDNAME VALUE INITIALIZERS LENGTH INDEX
    749    //                  INITIALIZERS INDEX
    750    return false;
    751  }
    752 
    753  if (!bce_->emit1(JSOp::GetElem)) {
    754    //          [stack] THIS FIELDNAME VALUE INITIALIZERS LENGTH INDEX FUNC
    755    return false;
    756  }
    757 
    758  if (!bce_->emitDupAt(6)) {
    759    //          [stack] THIS FIELDNAME VALUE INITIALIZERS LENGTH INDEX FUNC THIS
    760    return false;
    761  }
    762 
    763  // Pass value in as argument to the initializer
    764  if (!bce_->emit2(JSOp::Pick, 5)) {
    765    //          [stack] THIS FIELDNAME INITIALIZERS LENGTH INDEX FUNC THIS VALUE
    766    return false;
    767  }
    768 
    769  // Callee is always internal function.
    770  if (!bce_->emitCall(JSOp::Call, 1)) {
    771    //          [stack] THIS FIELDNAME INITIALIZERS LENGTH INDEX RVAL
    772    return false;
    773  }
    774 
    775  // Store returned value for next iteration
    776  if (!bce_->emit2(JSOp::Unpick, 3)) {
    777    //          [stack] THIS FIELDNAME VALUE INITIALIZERS LENGTH INDEX
    778    return false;
    779  }
    780 
    781  if (!bce_->emit1(JSOp::Inc)) {
    782    //          [stack] THIS FIELDNAME VALUE INITIALIZERS LENGTH INDEX
    783    return false;
    784  }
    785 
    786  if (!wh.emitEnd()) {
    787    //          [stack] THIS FIELDNAME VALUE INITIALIZERS LENGTH INDEX
    788    return false;
    789  }
    790 
    791  // Step 6. If fieldName is a Private Name, then
    792  // Step 6.a. Perform ? PrivateFieldAdd(receiver, fieldName, initValue).
    793  // Step 7. Else,
    794  // Step 7.a. Assert: IsPropertyKey(fieldName) is true.
    795  // Step 7.b. Perform ? CreateDataPropertyOrThrow(receiver, fieldName,
    796  //           initValue).
    797  // TODO: (See Bug 1817993) Because the field already exists, we just store the
    798  // updated value here.
    799  if (!bce_->emitPopN(3)) {
    800    //          [stack] THIS FIELDNAME VALUE
    801    return false;
    802  }
    803 
    804  if (!bce_->emit1(JSOp::InitElem)) {
    805    //          [stack] THIS
    806    return false;
    807  }
    808 
    809  // Step 8. Return unused.
    810  return bce_->emitPopN(1);
    811  //          [stack]
    812 }
    813 
    814 bool DecoratorEmitter::emitCallExtraInitializers(
    815    TaggedParserAtomIndex extraInitializers) {
    816  // Support for static and class extra initializers will be added in
    817  // bug 1868220 and bug 1868221.
    818  MOZ_ASSERT(
    819      extraInitializers ==
    820      TaggedParserAtomIndex::WellKnown::dot_instanceExtraInitializers_());
    821 
    822  if (!bce_->emitGetName(extraInitializers)) {
    823    //          [stack] ARRAY
    824    return false;
    825  }
    826 
    827  if (!bce_->emit1(JSOp::Dup)) {
    828    //          [stack] ARRAY ARRAY
    829    return false;
    830  }
    831 
    832  if (!bce_->emitAtomOp(JSOp::GetProp,
    833                        TaggedParserAtomIndex::WellKnown::length())) {
    834    //          [stack] ARRAY LENGTH
    835    return false;
    836  }
    837 
    838  if (!bce_->emit1(JSOp::Zero)) {
    839    //          [stack] ARRAY LENGTH INDEX
    840    return false;
    841  }
    842 
    843  InternalWhileEmitter wh(bce_);
    844  if (!wh.emitCond()) {
    845    //          [stack] ARRAY LENGTH INDEX
    846    return false;
    847  }
    848 
    849  if (!bce_->emit1(JSOp::Dup)) {
    850    //          [stack] ARRAY LENGTH INDEX INDEX
    851    return false;
    852  }
    853 
    854  if (!bce_->emitDupAt(2)) {
    855    //          [stack] ARRAY LENGTH INDEX INDEX LENGTH
    856    return false;
    857  }
    858 
    859  if (!bce_->emit1(JSOp::Lt)) {
    860    //          [stack] ARRAY LENGTH INDEX BOOL
    861    return false;
    862  }
    863 
    864  if (!wh.emitBody()) {
    865    //          [stack] ARRAY LENGTH INDEX
    866    return false;
    867  }
    868 
    869  if (!bce_->emitDupAt(2)) {
    870    //          [stack] ARRAY LENGTH INDEX ARRAY
    871    return false;
    872  }
    873 
    874  if (!bce_->emitDupAt(1)) {
    875    //          [stack] ARRAY LENGTH INDEX ARRAY INDEX
    876    return false;
    877  }
    878 
    879  // Retrieve initializer
    880  if (!bce_->emit1(JSOp::GetElem)) {
    881    //            [stack] ARRAY LENGTH INDEX INITIALIZER
    882    return false;
    883  }
    884 
    885  // This is guaranteed to run after super(), so we don't need TDZ checks.
    886  if (!bce_->emitGetName(TaggedParserAtomIndex::WellKnown::dot_this_())) {
    887    //            [stack] ARRAY LENGTH INDEX INITIALIZER THIS
    888    return false;
    889  }
    890 
    891  // Callee is always internal function.
    892  if (!bce_->emitCall(JSOp::CallIgnoresRv, 0)) {
    893    //            [stack] ARRAY LENGTH INDEX RVAL
    894    return false;
    895  }
    896 
    897  if (!bce_->emit1(JSOp::Pop)) {
    898    //            [stack] ARRAY LENGTH INDEX
    899    return false;
    900  }
    901 
    902  if (!bce_->emit1(JSOp::Inc)) {
    903    //            [stack] ARRAY LENGTH INDEX
    904    return false;
    905  }
    906 
    907  if (!wh.emitEnd()) {
    908    //          [stack] ARRAY LENGTH INDEX
    909    return false;
    910  }
    911 
    912  return bce_->emitPopN(3);
    913  //            [stack]
    914 }
    915 
    916 bool DecoratorEmitter::emitPropertyKey(ParseNode* key) {
    917  if (key->is<NameNode>()) {
    918    NameNode* keyAsNameNode = &key->as<NameNode>();
    919    if (keyAsNameNode->privateNameKind() == PrivateNameKind::None) {
    920      if (!bce_->emitStringOp(JSOp::String, keyAsNameNode->atom())) {
    921        //          [stack] NAME
    922        return false;
    923      }
    924    } else {
    925      MOZ_ASSERT(keyAsNameNode->privateNameKind() == PrivateNameKind::Field);
    926      if (!bce_->emitGetPrivateName(keyAsNameNode)) {
    927        //          [stack] NAME
    928        return false;
    929      }
    930    }
    931  } else if (key->isKind(ParseNodeKind::NumberExpr)) {
    932    if (!bce_->emitNumberOp(key->as<NumericLiteral>().value())) {
    933      //      [stack] NAME
    934      return false;
    935    }
    936  } else {
    937    // Otherwise this is a computed property name. BigInt keys are parsed
    938    // as (synthetic) computed property names, too.
    939    MOZ_ASSERT(key->isKind(ParseNodeKind::ComputedName));
    940 
    941    if (!bce_->emitComputedPropertyName(&key->as<UnaryNode>())) {
    942      //      [stack] NAME
    943      return false;
    944    }
    945  }
    946 
    947  return true;
    948 }
    949 
    950 bool DecoratorEmitter::emitDecorationState() {
    951  // TODO: See https://bugzilla.mozilla.org/show_bug.cgi?id=1868841
    952  return true;
    953 }
    954 
    955 bool DecoratorEmitter::emitUpdateDecorationState() {
    956  // TODO: See https://bugzilla.mozilla.org/show_bug.cgi?id=1868841.
    957  return true;
    958 }
    959 
    960 bool DecoratorEmitter::emitCallDecoratorForElement(Kind kind, ParseNode* key,
    961                                                   bool isStatic,
    962                                                   ParseNode* decorator) {
    963  MOZ_ASSERT(kind != Kind::Class);
    964  // Except for fields, this method expects the value to be passed
    965  // to the decorator to be on top of the stack. For methods, getters and
    966  // setters this is the method itself. For accessors it is an object
    967  // containing the getter and setter associated with the accessor.
    968  // This method also expects the addInitializerFunction to be present on
    969  // the top of the stack.
    970  //          [stack] VAL? ADDINIT
    971  // Prepare to call decorator
    972  CallOrNewEmitter cone(bce_, JSOp::Call,
    973                        CallOrNewEmitter::ArgumentsKind::Other,
    974                        ValueUsage::WantValue);
    975 
    976  if (!bce_->emitCalleeAndThis(decorator, nullptr, cone)) {
    977    //          [stack] VAL? ADDINIT CALLEE THIS
    978    return false;
    979  }
    980 
    981  if (!cone.prepareForNonSpreadArguments()) {
    982    return false;
    983  }
    984 
    985  if (kind == Kind::Field) {
    986    // Step 5.c. Let value be undefined.
    987    if (!bce_->emit1(JSOp::Undefined)) {
    988      //          [stack] ADDINIT CALLEE THIS undefined
    989      return false;
    990    }
    991  } else if (kind == Kind::Getter || kind == Kind::Method ||
    992             kind == Kind::Setter) {
    993    // Step 5.d. If kind is method, set value to elementRecord.[[Value]].
    994    // Step 5.e. Else if kind is getter, set value to elementRecord.[[Get]].
    995    // Step 5.f. Else if kind is setter, set value to elementRecord.[[Set]].
    996    // The DecoratorEmitter expects the method to already be on the stack.
    997    // We dup the value here so we can use it as an argument to the decorator.
    998    if (!bce_->emitDupAt(3)) {
    999      //          [stack] VAL ADDINIT CALLEE THIS VAL
   1000      return false;
   1001    }
   1002  } else {
   1003    // Step 5.g. Else if kind is accessor, then
   1004    // Step 5.g.i. Set value to OrdinaryObjectCreate(%Object.prototype%).
   1005    // For accessor decorators, we've already created the value object prior
   1006    // to calling this method.
   1007    MOZ_ASSERT(kind == Kind::Accessor);
   1008    if (!bce_->emitPickN(3)) {
   1009      //          [stack] ADDINIT CALLEE THIS VAL
   1010      return false;
   1011    }
   1012  }
   1013  // Step 5.b. Let context be CreateDecoratorContextObject(kind, key,
   1014  //           extraInitializers, decorationState, isStatic).
   1015  if (!bce_->emitPickN(3)) {
   1016    //          [stack] VAL? CALLEE THIS VAL ADDINIT
   1017    return false;
   1018  }
   1019  if (!emitCreateDecoratorContextObject(kind, key, isStatic,
   1020                                        decorator->pn_pos)) {
   1021    //          [stack] VAL? CALLEE THIS VAL context
   1022    return false;
   1023  }
   1024 
   1025  // Step 5.h. Let newValue be ? Call(decorator, undefined, « value, context»).
   1026  return cone.emitEnd(2, decorator->pn_pos.begin);
   1027  //          [stack] VAL? RETVAL
   1028 }
   1029 
   1030 bool DecoratorEmitter::emitCreateDecoratorAccessObject() {
   1031  // TODO: See https://bugzilla.mozilla.org/show_bug.cgi?id=1800725.
   1032  ObjectEmitter oe(bce_);
   1033  if (!oe.emitObject(0)) {
   1034    return false;
   1035  }
   1036  return oe.emitEnd();
   1037 }
   1038 
   1039 bool DecoratorEmitter::emitCheckIsUndefined() {
   1040  // This emits code to check if the value at the top of the stack is
   1041  // undefined. The value is left on the stack.
   1042  //          [stack] VAL
   1043  if (!bce_->emit1(JSOp::Dup)) {
   1044    //          [stack] VAL VAL
   1045    return false;
   1046  }
   1047  if (!bce_->emit1(JSOp::Undefined)) {
   1048    //          [stack] VAL VAL undefined
   1049    return false;
   1050  }
   1051  return bce_->emit1(JSOp::Eq);
   1052  //          [stack] VAL ISUNDEFINED
   1053 }
   1054 
   1055 bool DecoratorEmitter::emitCreateAddInitializerFunction(
   1056    FunctionNode* addInitializerFunction, TaggedParserAtomIndex initializers) {
   1057  // This synthesizes a function corresponding to this JavaScript code:
   1058  // function(initializer) {
   1059  //   if (IsCallable(initializer)) {
   1060  //     initializers[initializers.length++] = initializer;
   1061  //   } else {
   1062  //     throw DecoratorInvalidReturnType;
   1063  //   }
   1064  // }
   1065  MOZ_ASSERT(addInitializerFunction);
   1066  // TODO: Add support for static and class extra initializers, see bug 1868220
   1067  // and bug 1868221.
   1068  MOZ_ASSERT(
   1069      initializers ==
   1070      TaggedParserAtomIndex::WellKnown::dot_instanceExtraInitializers_());
   1071 
   1072  FunctionEmitter fe(bce_, addInitializerFunction->funbox(),
   1073                     FunctionSyntaxKind::Statement,
   1074                     FunctionEmitter::IsHoisted::No);
   1075  if (!fe.prepareForNonLazy()) {
   1076    return false;
   1077  }
   1078 
   1079  BytecodeEmitter bce2(bce_, addInitializerFunction->funbox());
   1080  if (!bce2.init()) {
   1081    return false;
   1082  }
   1083 
   1084  FunctionScriptEmitter fse(&bce2, addInitializerFunction->funbox(),
   1085                            mozilla::Nothing(), mozilla::Nothing());
   1086  if (!fse.prepareForParameters()) {
   1087    return false;
   1088  }
   1089 
   1090  if (!bce2.emitFunctionFormalParameters(addInitializerFunction->body())) {
   1091    return false;
   1092  }
   1093 
   1094  if (!fse.prepareForBody()) {
   1095    return false;
   1096  }
   1097 
   1098  LexicalScopeNode* lexicalScope = addInitializerFunction->body()->body();
   1099  LexicalScopeEmitter lse(&bce2);
   1100  if (lexicalScope->isEmptyScope()) {
   1101    if (!lse.emitEmptyScope()) {
   1102      return false;
   1103    }
   1104  } else {
   1105    if (!lse.emitScope(lexicalScope->kind(), lexicalScope->scopeBindings())) {
   1106      return false;
   1107    }
   1108  }
   1109 
   1110  NameLocation loc =
   1111      bce2.lookupName(TaggedParserAtomIndex::WellKnown::initializer());
   1112  MOZ_ASSERT(loc.kind() == NameLocation::Kind::ArgumentSlot);
   1113 
   1114  if (!bce2.emitArgOp(JSOp::GetArg, loc.argumentSlot())) {
   1115    //          [stack] INITIALIZER
   1116    return false;
   1117  }
   1118 
   1119  if (!bce2.emitCheckIsCallable()) {
   1120    //          [stack] INITIALIZER ISCALLABLE
   1121    return false;
   1122  }
   1123 
   1124  InternalIfEmitter ifCallable(&bce2);
   1125  if (!ifCallable.emitThenElse()) {
   1126    //          [stack] INITIALIZER
   1127    return false;
   1128  }
   1129 
   1130  loc = bce2.lookupName(initializers);
   1131  MOZ_ASSERT(loc.kind() == NameLocation::Kind::EnvironmentCoordinate);
   1132  if (!bce2.emitEnvCoordOp(JSOp::GetAliasedVar, loc.environmentCoordinate())) {
   1133    //          [stack] INITIALIZER ARRAY
   1134    return false;
   1135  }
   1136  if (!bce2.emitEnvCoordOp(JSOp::CheckAliasedLexical,
   1137                           loc.environmentCoordinate())) {
   1138    //          [stack] INITIALIZER ARRAY
   1139    return false;
   1140  }
   1141  if (!bce2.emit1(JSOp::Dup)) {
   1142    //          [stack] INITIALIZER ARRAY ARRAY
   1143    return false;
   1144  }
   1145  if (!bce2.emitAtomOp(JSOp::GetProp,
   1146                       TaggedParserAtomIndex::WellKnown::length())) {
   1147    //          [stack] INITIALIZER ARRAY LENGTH
   1148    return false;
   1149  }
   1150  if (!bce2.emitPickN(2)) {
   1151    //          [stack] ARRAY LENGTH INITIALIZER
   1152    return false;
   1153  }
   1154  if (!bce2.emit1(JSOp::InitElemInc)) {
   1155    //          [stack] ARRAY LENGTH
   1156    return false;
   1157  }
   1158  if (!bce2.emitPopN(2)) {
   1159    //          [stack]
   1160    return false;
   1161  }
   1162 
   1163  if (!ifCallable.emitElse()) {
   1164    //          [stack] INITIALIZER
   1165    return false;
   1166  }
   1167 
   1168  if (!bce2.emitPopN(1)) {
   1169    //          [stack]
   1170    return false;
   1171  }
   1172  if (!bce2.emit2(JSOp::ThrowMsg,
   1173                  uint8_t(ThrowMsgKind::DecoratorInvalidReturnType))) {
   1174    return false;
   1175  }
   1176 
   1177  if (!ifCallable.emitEnd()) {
   1178    return false;
   1179  }
   1180 
   1181  if (!lse.emitEnd()) {
   1182    return false;
   1183  }
   1184 
   1185  if (!fse.emitEndBody()) {
   1186    return false;
   1187  }
   1188 
   1189  if (!fse.intoStencil()) {
   1190    return false;
   1191  }
   1192 
   1193  return fe.emitNonLazyEnd();
   1194  //          [stack] ADDINIT
   1195 }
   1196 
   1197 bool DecoratorEmitter::emitCreateDecoratorContextObject(Kind kind,
   1198                                                        ParseNode* key,
   1199                                                        bool isStatic,
   1200                                                        TokenPos pos) {
   1201  // We expect the addInitializerFunction to already be on the stack.
   1202  //          [stack] ADDINIT
   1203 
   1204  // Step 1. Let contextObj be OrdinaryObjectCreate(%Object.prototype%).
   1205  ObjectEmitter oe(bce_);
   1206  size_t propertyCount = kind == Kind::Class ? 3 : 6;
   1207  if (!oe.emitObject(propertyCount)) {
   1208    //          [stack] ADDINIT context
   1209    return false;
   1210  }
   1211  if (!oe.prepareForPropValue(pos.begin, PropertyEmitter::Kind::Prototype)) {
   1212    return false;
   1213  }
   1214 
   1215  TaggedParserAtomIndex kindStr;
   1216  switch (kind) {
   1217    case Kind::Method:
   1218      // Step 2. If kind is method, let kindStr be "method".
   1219      kindStr = frontend::TaggedParserAtomIndex::WellKnown::method();
   1220      break;
   1221    case Kind::Getter:
   1222      // Step 3. Else if kind is getter, let kindStr be "getter".
   1223      kindStr = frontend::TaggedParserAtomIndex::WellKnown::getter();
   1224      break;
   1225    case Kind::Setter:
   1226      // Step 4. Else if kind is setter, let kindStr be "setter".
   1227      kindStr = frontend::TaggedParserAtomIndex::WellKnown::setter();
   1228      break;
   1229    case Kind::Accessor:
   1230      // Step 5. Else if kind is accessor, let kindStr be "accessor".
   1231      kindStr = frontend::TaggedParserAtomIndex::WellKnown::accessor();
   1232      break;
   1233    case Kind::Field:
   1234      // Step 6. Else if kind is field, let kindStr be "field".
   1235      kindStr = frontend::TaggedParserAtomIndex::WellKnown::field();
   1236      break;
   1237    case Kind::Class:
   1238      // Step 7. Else,
   1239      // Step 7.a. Assert: kind is class.
   1240      // Step 7.b. Let kindStr be "class".
   1241      kindStr = frontend::TaggedParserAtomIndex::WellKnown::class_();
   1242      break;
   1243    default:
   1244      MOZ_ASSERT_UNREACHABLE("Unknown kind");
   1245      break;
   1246  }
   1247  if (!bce_->emitStringOp(JSOp::String, kindStr)) {
   1248    //          [stack] ADDINIT context kindStr
   1249    return false;
   1250  }
   1251 
   1252  // Step 8. Perform ! CreateDataPropertyOrThrow(contextObj, "kind", kindStr).
   1253  if (!oe.emitInit(frontend::AccessorType::None,
   1254                   frontend::TaggedParserAtomIndex::WellKnown::kind())) {
   1255    //          [stack] ADDINIT context
   1256    return false;
   1257  }
   1258  // Step 9. If kind is not class, then
   1259  if (kind != Kind::Class) {
   1260    MOZ_ASSERT(key != nullptr, "Expect key to be present except for classes");
   1261 
   1262    // Step 9.a. Perform ! CreateDataPropertyOrThrow(contextObj, "access",
   1263    //           CreateDecoratorAccessObject(kind, name)).
   1264    if (!oe.prepareForPropValue(pos.begin, PropertyEmitter::Kind::Prototype)) {
   1265      return false;
   1266    }
   1267    if (!emitCreateDecoratorAccessObject()) {
   1268      return false;
   1269    }
   1270    if (!oe.emitInit(frontend::AccessorType::None,
   1271                     frontend::TaggedParserAtomIndex::WellKnown::access())) {
   1272      //          [stack] ADDINIT context
   1273      return false;
   1274    }
   1275    // Step 9.b. If isStatic is present, perform
   1276    //           ! CreateDataPropertyOrThrow(contextObj, "static", isStatic).
   1277    if (!oe.prepareForPropValue(pos.begin, PropertyEmitter::Kind::Prototype)) {
   1278      return false;
   1279    }
   1280    if (!bce_->emit1(isStatic ? JSOp::True : JSOp::False)) {
   1281      //          [stack] ADDINIT context isStatic
   1282      return false;
   1283    }
   1284    if (!oe.emitInit(frontend::AccessorType::None,
   1285                     frontend::TaggedParserAtomIndex::WellKnown::static_())) {
   1286      //          [stack] ADDINIT context
   1287      return false;
   1288    }
   1289    // Step 9.c. If name is a Private Name, then
   1290    // Step 9.c.i. Perform ! CreateDataPropertyOrThrow(contextObj, "private",
   1291    //             true).
   1292    // Step 9.d. Else, Step 9.d.i. Perform
   1293    //           ! CreateDataPropertyOrThrow(contextObj, "private", false).
   1294    if (!oe.prepareForPropValue(pos.begin, PropertyEmitter::Kind::Prototype)) {
   1295      return false;
   1296    }
   1297    if (!bce_->emit1(key->isKind(ParseNodeKind::PrivateName) ? JSOp::True
   1298                                                             : JSOp::False)) {
   1299      //          [stack] ADDINIT context private
   1300      return false;
   1301    }
   1302    if (!oe.emitInit(frontend::AccessorType::None,
   1303                     frontend::TaggedParserAtomIndex::WellKnown::private_())) {
   1304      //          [stack] ADDINIT context
   1305      return false;
   1306    }
   1307    // Step 9.c.ii. Perform ! CreateDataPropertyOrThrow(contextObj,
   1308    //              "name", name.[[Description]]).
   1309    //
   1310    // Step 9.d.ii. Perform ! CreateDataPropertyOrThrow(contextObj,
   1311    //              "name", name.[[Description]]).)
   1312    if (!oe.prepareForPropValue(pos.begin, PropertyEmitter::Kind::Prototype)) {
   1313      return false;
   1314    }
   1315    if (key->is<NameNode>()) {
   1316      if (!bce_->emitStringOp(JSOp::String, key->as<NameNode>().atom())) {
   1317        return false;
   1318      }
   1319    } else {
   1320      if (!emitPropertyKey(key)) {
   1321        return false;
   1322      }
   1323    }
   1324    if (!oe.emitInit(frontend::AccessorType::None,
   1325                     frontend::TaggedParserAtomIndex::WellKnown::name())) {
   1326      //          [stack] ADDINIT context
   1327      return false;
   1328    }
   1329  } else {
   1330    // Step 10. Else,
   1331    // Step 10.a. Perform ! CreateDataPropertyOrThrow(contextObj, "name", name).
   1332    if (!oe.prepareForPropValue(pos.begin, PropertyEmitter::Kind::Prototype)) {
   1333      return false;
   1334    }
   1335    if (key != nullptr) {
   1336      if (!bce_->emitStringOp(JSOp::String, key->as<NameNode>().atom())) {
   1337        return false;
   1338      }
   1339    } else {
   1340      if (!bce_->emit1(JSOp::Undefined)) {
   1341        return false;
   1342      }
   1343    }
   1344    if (!oe.emitInit(frontend::AccessorType::None,
   1345                     frontend::TaggedParserAtomIndex::WellKnown::name())) {
   1346      //          [stack] ADDINIT context
   1347      return false;
   1348    }
   1349  }
   1350  // Step 11. Let addInitializer be CreateAddInitializerFunction(initializers,
   1351  //          decorationState).
   1352  if (!oe.prepareForPropValue(pos.begin, PropertyEmitter::Kind::Prototype)) {
   1353    return false;
   1354  }
   1355 
   1356  if (!bce_->emitPickN(1)) {
   1357    //          [stack] context ADDINIT
   1358    return false;
   1359  }
   1360  // Step 12. Perform ! CreateDataPropertyOrThrow(contextObj, "addInitializer",
   1361  //          addInitializer).
   1362  if (!oe.emitInit(
   1363          frontend::AccessorType::None,
   1364          frontend::TaggedParserAtomIndex::WellKnown::addInitializer())) {
   1365    //          [stack] context
   1366    return false;
   1367  }
   1368  // Step 13. Return contextObj.
   1369  return oe.emitEnd();
   1370 }
   1371 
   1372 bool DecoratorEmitter::emitHandleNewValueField(TaggedParserAtomIndex atom,
   1373                                               int8_t offset) {
   1374  // This function handles retrieving the new value from a field in the RETVAL
   1375  // object returned by the decorator. The `atom` is the atom of the field to be
   1376  // examined. The offset is the offset of the existing value on the stack,
   1377  // which will be replaced by the new value. If the offset is zero, we're
   1378  // handling the initializer which will be added to the array of initializers
   1379  // already on the stack.
   1380  //            [stack] GETTER SETTER ARRAY INDEX RETVAL
   1381 
   1382  if (!bce_->emit1(JSOp::Dup)) {
   1383    //          [stack] GETTER SETTER ARRAY INDEX RETVAL RETVAL
   1384    return false;
   1385  }
   1386  if (!bce_->emitStringOp(JSOp::String, atom)) {
   1387    //          [stack] GETTER SETTER ARRAY INDEX RETVAL RETVAL ATOM
   1388    return false;
   1389  }
   1390  if (!bce_->emit1(JSOp::GetElem)) {
   1391    //          [stack] GETTER SETTER ARRAY INDEX RETVAL
   1392    //          NEW_VALUE
   1393    return false;
   1394  }
   1395 
   1396  if (!emitCheckIsUndefined()) {
   1397    //          [stack] GETTER SETTER ARRAY INDEX RETVAL
   1398    //                  NEW_VALUE ISUNDEFINED
   1399    return false;
   1400  }
   1401 
   1402  InternalIfEmitter ifCallable(bce_);
   1403  if (!ifCallable.emitThenElse()) {
   1404    //          [stack] GETTER SETTER ARRAY INDEX RETVAL
   1405    //                  NEW_VALUE
   1406    return false;
   1407  }
   1408 
   1409  // Pop the undefined getter or setter from the stack, leaving the original
   1410  // values in place.
   1411  if (!bce_->emitPopN(1)) {
   1412    //          [stack] GETTER SETTER ARRAY INDEX RETVAL
   1413    return false;
   1414  }
   1415 
   1416  if (!ifCallable.emitElseIf(mozilla::Nothing())) {
   1417    return false;
   1418  }
   1419  if (!bce_->emitCheckIsCallable()) {
   1420    //          [stack] GETTER SETTER ARRAY INDEX RETVAL
   1421    //                  NEW_VALUE ISCALLABLE_RESULT
   1422    return false;
   1423  }
   1424  if (!ifCallable.emitThenElse()) {
   1425    //          [stack] GETTER SETTER ARRAY INDEX RETVAL
   1426    //                  NEW_VALUE
   1427    return false;
   1428  }
   1429  if (offset != 0) {
   1430    if (!bce_->emitPickN(offset)) {
   1431      //          [stack] GETTER? SETTER? ARRAY INDEX RETVAL
   1432      //                  NEW_VALUE GETTER_OR_SETTER
   1433      return false;
   1434    }
   1435    if (!bce_->emitPopN(1)) {
   1436      //          [stack] GETTER? SETTER? ARRAY INDEX RETVAL
   1437      //                  NEW_VALUE
   1438      return false;
   1439    }
   1440    if (!bce_->emitUnpickN(offset - 1)) {
   1441      //          [stack] GETTER SETTER ARRAY INDEX RETVAL
   1442      return false;
   1443    }
   1444  } else {
   1445    // Offset == 0 means we're retrieving the initializer, this is
   1446    // stored in the initializer array on the stack.
   1447    if (!bce_->emit1(JSOp::Swap)) {
   1448      //          [stack] GETTER SETTER ARRAY INDEX NEW_VALUE RETVAL
   1449      return false;
   1450    }
   1451 
   1452    if (!bce_->emitUnpickN(3)) {
   1453      //          [stack] GETTER SETTER RETVAL ARRAY INDEX NEW_VALUE
   1454      return false;
   1455    }
   1456 
   1457    if (!bce_->emit1(JSOp::InitElemInc)) {
   1458      //          [stack] GETTER SETTER RETVAL ARRAY INDEX
   1459      return false;
   1460    }
   1461 
   1462    if (!bce_->emitPickN(2)) {
   1463      //          [stack] GETTER SETTER ARRAY INDEX RETVAL
   1464      return false;
   1465    }
   1466  }
   1467 
   1468  if (!ifCallable.emitElse()) {
   1469    return false;
   1470  }
   1471 
   1472  if (!bce_->emitPopN(1)) {
   1473    //          [stack] GETTER SETTER ARRAY INDEX
   1474    return false;
   1475  }
   1476 
   1477  if (!bce_->emit2(JSOp::ThrowMsg,
   1478                   uint8_t(ThrowMsgKind::DecoratorInvalidReturnType))) {
   1479    return false;
   1480  }
   1481 
   1482  return ifCallable.emitEnd();
   1483 }