tor-browser

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

ForOfIterator.h (3367B)


      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 /*
      8 * A convenience class that makes it easy to perform the operations of a for-of
      9 * loop.
     10 */
     11 
     12 #ifndef js_ForOfIterator_h
     13 #define js_ForOfIterator_h
     14 
     15 #include "mozilla/Attributes.h"  // MOZ_STACK_CLASS
     16 
     17 #include <stdint.h>  // UINT32_MAX, uint32_t
     18 
     19 #include "jstypes.h"  // JS_PUBLIC_API
     20 
     21 #include "js/RootingAPI.h"  // JS::{Handle,Rooted}
     22 #include "js/Value.h"       // JS::Value, JS::{,Mutable}Handle<JS::Value>
     23 
     24 struct JS_PUBLIC_API JSContext;
     25 class JS_PUBLIC_API JSObject;
     26 
     27 namespace JS {
     28 
     29 /**
     30 * A convenience class for imitating a JS for-of loop. Typical usage:
     31 *
     32 *     JS::ForOfIterator it(cx);
     33 *     if (!it.init(iterable)) {
     34 *       return false;
     35 *     }
     36 *     JS::Rooted<JS::Value> val(cx);
     37 *     while (true) {
     38 *       bool done;
     39 *       if (!it.next(&val, &done)) {
     40 *         return false;
     41 *       }
     42 *       if (done) {
     43 *         break;
     44 *       }
     45 *       if (!DoStuff(cx, val)) {
     46 *         return false;
     47 *       }
     48 *     }
     49 */
     50 class MOZ_STACK_CLASS JS_PUBLIC_API ForOfIterator {
     51 protected:
     52  JSContext* cx_;
     53 
     54  // Use realm fuses (see `IsArrayWithDefaultIterator` in vm/Iteration.cpp) to
     55  // try to optimize iteration across arrays.
     56  //
     57  //  Case 1: Regular Iteration
     58  //      iterator - pointer to the iterator object.
     59  //      nextMethod - value of |iterator|.next.
     60  //      index - fixed to NOT_ARRAY (== UINT32_MAX)
     61  //
     62  //  Case 2: Optimized Array Iteration
     63  //      iterator - pointer to the array object.
     64  //      nextMethod - the undefined value.
     65  //      index - current position in array.
     66  //
     67  // The cases are distinguished by whether |index == NOT_ARRAY|.
     68  Rooted<JSObject*> iterator;
     69  Rooted<Value> nextMethod;
     70 
     71  static constexpr uint32_t NOT_ARRAY = UINT32_MAX;
     72 
     73  uint32_t index = NOT_ARRAY;
     74 
     75  ForOfIterator(const ForOfIterator&) = delete;
     76  ForOfIterator& operator=(const ForOfIterator&) = delete;
     77 
     78 public:
     79  explicit ForOfIterator(JSContext* cx)
     80      : cx_(cx), iterator(cx), nextMethod(cx) {}
     81 
     82  enum NonIterableBehavior { ThrowOnNonIterable, AllowNonIterable };
     83 
     84  /**
     85   * Initialize the iterator.  If AllowNonIterable is passed then if getting
     86   * the @@iterator property from iterable returns undefined init() will just
     87   * return true instead of throwing.  Callers must then check
     88   * valueIsIterable() before continuing with the iteration.
     89   */
     90  [[nodiscard]] bool init(
     91      Handle<Value> iterable,
     92      NonIterableBehavior nonIterableBehavior = ThrowOnNonIterable);
     93 
     94  /**
     95   * Get the next value from the iterator.  If false *done is true
     96   * after this call, do not examine val.
     97   */
     98  [[nodiscard]] bool next(MutableHandle<Value> val, bool* done);
     99 
    100  /**
    101   * Close the iterator.
    102   * For the case that completion type is throw.
    103   */
    104  void closeThrow();
    105 
    106  /**
    107   * If initialized with throwOnNonCallable = false, check whether
    108   * the value is iterable.
    109   */
    110  bool valueIsIterable() const { return iterator; }
    111 
    112 private:
    113  inline bool nextFromOptimizedArray(MutableHandle<Value> val, bool* done);
    114 };
    115 
    116 }  // namespace JS
    117 
    118 #endif  // js_ForOfIterator_h