Skip to content

Commit 0bb419a

Browse files
committed
Bug 2025779 - Implement Iterator Includes; r=arai
Differential Revision: https://phabricator.services.mozilla.com/D295349
1 parent 94ea010 commit 0bb419a

3 files changed

Lines changed: 75 additions & 0 deletions

File tree

js/public/friend/ErrorNumbers.msg

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -845,6 +845,7 @@ MSG_DEF(JSMSG_BAD_WEAKREF_TARGET, 0, JSEXN_TYPEERR, "cann
845845
MSG_DEF(JSMSG_NEGATIVE_LIMIT, 0, JSEXN_RANGEERR, "Iterator limits cannot be negative")
846846
MSG_DEF(JSMSG_INVALID_CHUNKSIZE, 0, JSEXN_RANGEERR, "Iterator chunkSize must be an integer between 1 and 2**32-1 inclusive")
847847
MSG_DEF(JSMSG_INVALID_WINDOWSIZE, 0, JSEXN_RANGEERR, "Iterator windowSize must be an integer between 1 and 2**32-1 inclusive")
848+
MSG_DEF(JSMSG_INVALID_SKIP_COUNT, 0, JSEXN_TYPEERR, "Iterator skippedElements must be +Infinity, -Infinity, or an integral Number")
848849
MSG_DEF(JSMSG_INVALID_UNDERSIZED_OPTION_VALUE, 2, JSEXN_TYPEERR, "invalid value for \"{0}\" option: {1}")
849850
MSG_DEF(JSMSG_ITERATOR_ZIP_INVALID_OPTION_TYPE, 2, JSEXN_TYPEERR, "invalid type for \"{0}\" option: {1}")
850851
MSG_DEF(JSMSG_ITERATOR_ZIP_INVALID_OPTION_VALUE, 2, JSEXN_TYPEERR, "invalid value for \"{0}\" option: {1}")

js/src/builtin/Iterator.js

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2168,4 +2168,77 @@ function* IteratorWindowsGenerator(iterator, nextMethod, windowSize, undersized)
21682168
function IteratorJoin(separator) {
21692169
return false;
21702170
}
2171+
2172+
/**
2173+
* Iterator.prototype.includes ( searchElement [ , skippedElements ] )
2174+
*
2175+
* https://tc39.es/proposal-iterator-includes
2176+
*/
2177+
function IteratorIncludes(searchElement, skippedElements = undefined) {
2178+
// Step 1. Let O be the this value.
2179+
var O = this;
2180+
2181+
// Step 2. If O is not an Object, throw a TypeError exception.
2182+
if (!IsObject(O)) {
2183+
ThrowTypeError(JSMSG_OBJECT_REQUIRED, O === null ? "null" : typeof O);
2184+
}
2185+
2186+
// Step 3. Let iterated be the Iterator Record
2187+
// { [[Iterator]]: O, [[NextMethod]]: undefined, [[Done]]: false }.
2188+
2189+
// Step 4. If skippedElements is undefined, then
2190+
// Step 4.a. Let toSkip be 0.
2191+
var toSkip = 0;
2192+
// Step 5. Else, (skippedElements is not undefined)
2193+
if (skippedElements !== undefined) {
2194+
// Step 5.a. If skippedElements is not one of +∞𝔽, -∞𝔽, or an integral Number, then
2195+
if (!(Number_isInteger(skippedElements) ||
2196+
(typeof skippedElements === "number" &&
2197+
!Number_isFinite(skippedElements) &&
2198+
!Number_isNaN(skippedElements)))) {
2199+
// Step 5.a.i-ii. Let error be ThrowCompletion(...). Return ? IteratorClose(iterated, error).
2200+
try {
2201+
IteratorClose(O);
2202+
} catch {}
2203+
ThrowTypeError(JSMSG_INVALID_SKIP_COUNT);
2204+
}
2205+
// Step 5.b. Let toSkip be the extended mathematical value of skippedElements.
2206+
toSkip = skippedElements;
2207+
}
2208+
2209+
// Step 6. If toSkip < 0, then
2210+
// Step 6.a. Let error be ThrowCompletion(a newly created RangeError object).
2211+
// Step 6.b. Return ? IteratorClose(iterated, error).
2212+
if (toSkip < 0) {
2213+
try {
2214+
IteratorClose(O);
2215+
} catch {}
2216+
ThrowRangeError(JSMSG_NEGATIVE_LIMIT);
2217+
}
2218+
2219+
// Step 7. Let skipped be 0.
2220+
var skipped = 0;
2221+
2222+
// Step 8. Set iterated to ? GetIteratorDirect(O).
2223+
// (Inlined call to GetIteratorDirect.)
2224+
var nextMethod = O.next;
2225+
2226+
// Step 9. Repeat,
2227+
// Step 9.a. Let value be ? IteratorStepValue(iterated).
2228+
for (var value of allowContentIterWithNext(O, nextMethod)) {
2229+
// Step 9.c. If skipped < toSkip, then
2230+
if (skipped < toSkip) {
2231+
// Step 9.c.i. Set skipped to skipped + 1.
2232+
skipped++;
2233+
// Step 9.d. Else if SameValueZero(value, searchElement) is true, then
2234+
} else if (value === searchElement || (Number_isNaN(value) && Number_isNaN(searchElement))) {
2235+
// Step 9.d.i. Return ? IteratorClose(iterated, NormalCompletion(true)).
2236+
return true;
2237+
}
2238+
}
2239+
2240+
// Step 9.b. If value is done, return false.
2241+
return false;
2242+
}
2243+
21712244
#endif

js/src/vm/Iteration.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1977,6 +1977,7 @@ static const JSFunctionSpec iterator_methods[] = {
19771977
JS_SELF_HOSTED_FN("chunks", "IteratorChunks", 1, 0),
19781978
JS_SELF_HOSTED_FN("windows", "IteratorWindows", 2, 0),
19791979
JS_SELF_HOSTED_FN("join", "IteratorJoin", 1, 0),
1980+
JS_SELF_HOSTED_FN("includes", "IteratorIncludes", 2, 0),
19801981
#endif
19811982
JS_FS_END,
19821983
};

0 commit comments

Comments
 (0)