tor-browser

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

ForOfLoopControl.h (4036B)


      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_ForOfLoopControl_h
      8 #define frontend_ForOfLoopControl_h
      9 
     10 #include "mozilla/Maybe.h"  // mozilla::Maybe
     11 
     12 #include <stdint.h>  // int32_t, uint32_t
     13 
     14 #include "frontend/BytecodeControlStructures.h"  // NestableControl, LoopControl
     15 #include "frontend/IteratorKind.h"               // IteratorKind
     16 #include "frontend/SelfHostedIter.h"             // SelfHostedIter
     17 #include "frontend/TryEmitter.h"                 // TryEmitter
     18 #ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT
     19 #  include "frontend/UsingEmitter.h"  // ForOfDisposalEmitter
     20 #endif
     21 #include "vm/CompletionKind.h"  // CompletionKind
     22 
     23 namespace js {
     24 namespace frontend {
     25 
     26 struct BytecodeEmitter;
     27 class BytecodeOffset;
     28 class EmitterScope;
     29 
     30 class ForOfLoopControl : public LoopControl {
     31  // The stack depth of the iterator.
     32  int32_t iterDepth_;
     33 
     34  // For-of loops, when throwing from non-iterator code (i.e. from the body
     35  // or from evaluating the LHS of the loop condition), need to call
     36  // IteratorClose.  This is done by enclosing the body of the loop with
     37  // try-catch and calling IteratorClose in the `catch` block.
     38  //
     39  // If IteratorClose itself throws, we must not re-call
     40  // IteratorClose. Since non-local jumps like break and return call
     41  // IteratorClose, whenever a non-local jump is emitted, we must
     42  // prevent the catch block from catching any exception thrown from
     43  // IteratorClose. We do this by wrapping the non-local jump in a
     44  // ForOfIterClose try-note.
     45  //
     46  //   for (x of y) {
     47  //     // Operations for iterator (IteratorNext etc) are outside of
     48  //     // try-block.
     49  //     try {
     50  //       ...
     51  //       if (...) {
     52  //         // Before non-local jump, close iterator.
     53  //         CloseIter(iter, CompletionKind::Return); // Covered by
     54  //         return;                                  // trynote
     55  //       }
     56  //       ...
     57  //     } catch (e) {
     58  //       // When propagating an exception, we swallow any exceptions
     59  //       // thrown while closing the iterator.
     60  //       CloseIter(iter, CompletionKind::Throw);
     61  //       throw e;
     62  //     }
     63  //   }
     64  mozilla::Maybe<TryEmitter> tryCatch_;
     65 
     66  // Used to track if any yields were emitted between calls to to
     67  // emitBeginCodeNeedingIteratorClose and emitEndCodeNeedingIteratorClose.
     68  uint32_t numYieldsAtBeginCodeNeedingIterClose_;
     69 
     70  SelfHostedIter selfHostedIter_;
     71 
     72  IteratorKind iterKind_;
     73 
     74 #ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT
     75  mozilla::Maybe<ForOfDisposalEmitter> forOfDisposalEmitter_;
     76 #endif
     77 
     78 public:
     79  ForOfLoopControl(BytecodeEmitter* bce, int32_t iterDepth,
     80                   SelfHostedIter selfHostedIter, IteratorKind iterKind);
     81 
     82 #ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT
     83  [[nodiscard]] bool prepareForForOfLoopIteration(
     84      BytecodeEmitter* bce, const EmitterScope* headLexicalEmitterScope,
     85      bool hasAwaitUsing);
     86 #endif
     87 
     88  [[nodiscard]] bool emitBeginCodeNeedingIteratorClose(BytecodeEmitter* bce);
     89  [[nodiscard]] bool emitEndCodeNeedingIteratorClose(BytecodeEmitter* bce);
     90 
     91  [[nodiscard]] bool emitIteratorCloseInInnermostScopeWithTryNote(
     92      BytecodeEmitter* bce, CompletionKind completionKind);
     93  [[nodiscard]] bool emitIteratorCloseInScope(BytecodeEmitter* bce,
     94                                              EmitterScope& currentScope,
     95                                              CompletionKind completionKind);
     96 
     97  [[nodiscard]] bool emitPrepareForNonLocalJumpFromScope(
     98      BytecodeEmitter* bce, EmitterScope& currentScope, bool isTarget,
     99      BytecodeOffset* tryNoteStart);
    100 };
    101 template <>
    102 inline bool NestableControl::is<ForOfLoopControl>() const {
    103  return kind_ == StatementKind::ForOfLoop;
    104 }
    105 
    106 } /* namespace frontend */
    107 } /* namespace js */
    108 
    109 #endif /* frontend_ForOfLoopControl_h */