Merge mozilla-central to autoland. a=merge CLOSED TREE
[gecko.git] / js / public / ForOfIterator.h
blobdb0a099e5efac5a6faa0264ef6a4432d53d7da07
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/. */
7 /*
8 * A convenience class that makes it easy to perform the operations of a for-of
9 * loop.
12 #ifndef js_ForOfIterator_h
13 #define js_ForOfIterator_h
15 #include "mozilla/Attributes.h" // MOZ_STACK_CLASS
17 #include <stdint.h> // UINT32_MAX, uint32_t
19 #include "jstypes.h" // JS_PUBLIC_API
21 #include "js/RootingAPI.h" // JS::{Handle,Rooted}
22 #include "js/Value.h" // JS::Value, JS::{,Mutable}Handle<JS::Value>
24 struct JS_PUBLIC_API JSContext;
25 class JS_PUBLIC_API JSObject;
27 namespace JS {
29 /**
30 * A convenience class for imitating a JS for-of loop. Typical usage:
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 * }
50 class MOZ_STACK_CLASS JS_PUBLIC_API ForOfIterator {
51 protected:
52 JSContext* cx_;
54 // Use the ForOfPIC on the global object (see vm/GlobalObject.h) to try to
55 // optimize iteration across arrays.
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)
62 // Case 2: Optimized Array Iteration
63 // iterator - pointer to the array object.
64 // nextMethod - the undefined value.
65 // index - current position in array.
67 // The cases are distinguished by whether |index == NOT_ARRAY|.
68 Rooted<JSObject*> iterator;
69 Rooted<Value> nextMethod;
71 static constexpr uint32_t NOT_ARRAY = UINT32_MAX;
73 uint32_t index = NOT_ARRAY;
75 ForOfIterator(const ForOfIterator&) = delete;
76 ForOfIterator& operator=(const ForOfIterator&) = delete;
78 public:
79 explicit ForOfIterator(JSContext* cx)
80 : cx_(cx), iterator(cx), nextMethod(cx) {}
82 enum NonIterableBehavior { ThrowOnNonIterable, AllowNonIterable };
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.
90 [[nodiscard]] bool init(
91 Handle<Value> iterable,
92 NonIterableBehavior nonIterableBehavior = ThrowOnNonIterable);
94 /**
95 * Get the next value from the iterator. If false *done is true
96 * after this call, do not examine val.
98 [[nodiscard]] bool next(MutableHandle<Value> val, bool* done);
101 * Close the iterator.
102 * For the case that completion type is throw.
104 void closeThrow();
107 * If initialized with throwOnNonCallable = false, check whether
108 * the value is iterable.
110 bool valueIsIterable() const { return iterator; }
112 private:
113 inline bool nextFromOptimizedArray(MutableHandle<Value> val, bool* done);
116 } // namespace JS
118 #endif // js_ForOfIterator_h