File: ForOfIterator.h

package info (click to toggle)
firefox 147.0.2-1
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 4,683,484 kB
  • sloc: cpp: 7,607,246; javascript: 6,533,185; ansic: 3,775,227; python: 1,415,393; xml: 634,561; asm: 438,951; java: 186,241; sh: 62,752; makefile: 18,079; objc: 13,092; perl: 12,808; yacc: 4,583; cs: 3,846; pascal: 3,448; lex: 1,720; ruby: 1,003; php: 436; lisp: 258; awk: 247; sql: 66; sed: 54; csh: 10; exp: 6
file content (118 lines) | stat: -rw-r--r-- 3,367 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
 * vim: set ts=8 sts=2 et sw=2 tw=80:
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

/*
 * A convenience class that makes it easy to perform the operations of a for-of
 * loop.
 */

#ifndef js_ForOfIterator_h
#define js_ForOfIterator_h

#include "mozilla/Attributes.h"  // MOZ_STACK_CLASS

#include <stdint.h>  // UINT32_MAX, uint32_t

#include "jstypes.h"  // JS_PUBLIC_API

#include "js/RootingAPI.h"  // JS::{Handle,Rooted}
#include "js/Value.h"       // JS::Value, JS::{,Mutable}Handle<JS::Value>

struct JS_PUBLIC_API JSContext;
class JS_PUBLIC_API JSObject;

namespace JS {

/**
 * A convenience class for imitating a JS for-of loop. Typical usage:
 *
 *     JS::ForOfIterator it(cx);
 *     if (!it.init(iterable)) {
 *       return false;
 *     }
 *     JS::Rooted<JS::Value> val(cx);
 *     while (true) {
 *       bool done;
 *       if (!it.next(&val, &done)) {
 *         return false;
 *       }
 *       if (done) {
 *         break;
 *       }
 *       if (!DoStuff(cx, val)) {
 *         return false;
 *       }
 *     }
 */
class MOZ_STACK_CLASS JS_PUBLIC_API ForOfIterator {
 protected:
  JSContext* cx_;

  // Use realm fuses (see `IsArrayWithDefaultIterator` in vm/Iteration.cpp) to
  // try to optimize iteration across arrays.
  //
  //  Case 1: Regular Iteration
  //      iterator - pointer to the iterator object.
  //      nextMethod - value of |iterator|.next.
  //      index - fixed to NOT_ARRAY (== UINT32_MAX)
  //
  //  Case 2: Optimized Array Iteration
  //      iterator - pointer to the array object.
  //      nextMethod - the undefined value.
  //      index - current position in array.
  //
  // The cases are distinguished by whether |index == NOT_ARRAY|.
  Rooted<JSObject*> iterator;
  Rooted<Value> nextMethod;

  static constexpr uint32_t NOT_ARRAY = UINT32_MAX;

  uint32_t index = NOT_ARRAY;

  ForOfIterator(const ForOfIterator&) = delete;
  ForOfIterator& operator=(const ForOfIterator&) = delete;

 public:
  explicit ForOfIterator(JSContext* cx)
      : cx_(cx), iterator(cx), nextMethod(cx) {}

  enum NonIterableBehavior { ThrowOnNonIterable, AllowNonIterable };

  /**
   * Initialize the iterator.  If AllowNonIterable is passed then if getting
   * the @@iterator property from iterable returns undefined init() will just
   * return true instead of throwing.  Callers must then check
   * valueIsIterable() before continuing with the iteration.
   */
  [[nodiscard]] bool init(
      Handle<Value> iterable,
      NonIterableBehavior nonIterableBehavior = ThrowOnNonIterable);

  /**
   * Get the next value from the iterator.  If false *done is true
   * after this call, do not examine val.
   */
  [[nodiscard]] bool next(MutableHandle<Value> val, bool* done);

  /**
   * Close the iterator.
   * For the case that completion type is throw.
   */
  void closeThrow();

  /**
   * If initialized with throwOnNonCallable = false, check whether
   * the value is iterable.
   */
  bool valueIsIterable() const { return iterator; }

 private:
  inline bool nextFromOptimizedArray(MutableHandle<Value> val, bool* done);
};

}  // namespace JS

#endif  // js_ForOfIterator_h