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/. */
8 * A convenience class that makes it easy to perform the operations of a for-of
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
;
30 * A convenience class for imitating a JS for-of loop. Typical usage:
32 * JS::ForOfIterator it(cx);
33 * if (!it.init(iterable)) {
36 * JS::Rooted<JS::Value> val(cx);
39 * if (!it.next(&val, &done)) {
45 * if (!DoStuff(cx, val)) {
50 class MOZ_STACK_CLASS JS_PUBLIC_API ForOfIterator
{
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;
79 explicit ForOfIterator(JSContext
* cx
)
80 : cx_(cx
), iterator(cx
), nextMethod(cx
) {}
82 enum NonIterableBehavior
{ ThrowOnNonIterable
, AllowNonIterable
};
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
);
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.
107 * If initialized with throwOnNonCallable = false, check whether
108 * the value is iterable.
110 bool valueIsIterable() const { return iterator
; }
113 inline bool nextFromOptimizedArray(MutableHandle
<Value
> val
, bool* done
);
118 #endif // js_ForOfIterator_h