/* This Source Code Form is subject to the terms of the Mozilla Public *License,v.2.0.IfacopyoftheMPLwasnotdistributedwiththis
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
function IteratorIdentity() { returnthis;
}
/* ECMA262 7.2.7 */ function IteratorNext(iteratorRecord, value) { // Steps 1-2. var result =
ArgumentsLength() < 2
? callContentFunction(iteratorRecord.nextMethod, iteratorRecord.iterator)
: callContentFunction(
iteratorRecord.nextMethod,
iteratorRecord.iterator,
value
); // Step 3. if (!IsObject(result)) {
ThrowTypeError(JSMSG_OBJECT_REQUIRED, result);
} // Step 4. return result;
}
// https://tc39.es/ecma262/#sec-getiterator function GetIterator(obj, isAsync, method) { // Step 1. If hint is not present, set hint to sync. // Step 2. If method is not present, then if (!method) { // Step 2.a. If hint is async, then if (isAsync) { // Step 2.a.i. Set method to ? GetMethod(obj, @@asyncIterator).
method = GetMethod(obj, GetBuiltinSymbol("asyncIterator"));
// Step 2.a.ii. If method is undefined, then if (!method) { // Step 2.a.ii.1. Let syncMethod be ? GetMethod(obj, @@iterator). var syncMethod = GetMethod(obj, GetBuiltinSymbol("iterator"));
// Step 2.a.ii.2. Let syncIteratorRecord be ? GetIterator(obj, sync, syncMethod). var syncIteratorRecord = GetIterator(obj, false, syncMethod);
// Step 3. Let iterator be ? Call(method, obj). var iterator = callContentFunction(method, obj);
// Step 4. If Type(iterator) is not Object, throw a TypeError exception. if (!IsObject(iterator)) {
ThrowTypeError(JSMSG_NOT_ITERABLE, obj === null ? "null" : typeof obj);
}
// Step 5. Let nextMethod be ? GetV(iterator, "next"). var nextMethod = iterator.next;
// Step 6. Let iteratorRecord be the Record { [[Iterator]]: iterator, [[NextMethod]]: nextMethod, [[Done]]: false }. var iteratorRecord = {
__proto__: null,
iterator,
nextMethod,
done: false,
};
#ifdef ENABLE_EXPLICIT_RESOURCE_MANAGEMENT /** *ExplicitResourceManagementProposal *27.1.2.1%IteratorPrototype%[@@dispose]() *https://arai-a.github.io/ecma262-compare/?pr=3000&id=sec-%25iteratorprototype%25-%40%40dispose
*/ function IteratorDispose() { // Step 1. Let O be the this value. var O = this;
// Step 2. Let return be ? GetMethod(O, "return"). var returnMethod = GetMethod(O, "return");
// Step 3. If return is not undefined, then if (returnMethod !== undefined) { // Step 3.a. Perform ? Call(return, O, « »).
callContentFunction(returnMethod, O);
}
/** *%IteratorHelperPrototype%.next() * *https://tc39.es/ecma262/#sec-%iteratorhelperprototype%.next *ES2026draftrevd14670224281909f5bb552e8ebe4a8e958646c16
*/ function IteratorHelperNext() { // Step 1. var O = this; if (!IsObject(O) || (O = GuardToIteratorHelper(O)) === null) { return callFunction(
CallIteratorHelperMethodIfWrapped, this, "IteratorHelperNext"
);
} var generator = UnsafeGetReservedSlot(O, ITERATOR_HELPER_GENERATOR_SLOT); return callFunction(GeneratorNext, generator, undefined);
}
/** *%IteratorHelperPrototype%.return() * *https://tc39.es/ecma262/#sec-%iteratorhelperprototype%.return *ES2026draftrevd14670224281909f5bb552e8ebe4a8e958646c16
*/ function IteratorHelperReturn() { // Step 1. var O = this;
// Step 2. if (!IsObject(O) || (O = GuardToIteratorHelper(O)) === null) { return callFunction(
CallIteratorHelperMethodIfWrapped, this, "IteratorHelperReturn"
);
}
// Step 3. (Implicit)
// Step 4 (Partial). If O.[[GeneratorState]] is suspended-start, then // // Retrieve the current resume index before calling GeneratorReturn. var generator = UnsafeGetReservedSlot(O, ITERATOR_HELPER_GENERATOR_SLOT); var resumeIndex = UnsafeGetReservedSlot(generator, GENERATOR_RESUME_INDEX_SLOT); assert(
resumeIndex === undefined ||
resumeIndex === null || typeof resumeIndex === "number", "unexpected resumeIndex value"
);
// If the generator was suspended at the initial yield, then the generator // state is "suspended-start". var isSuspendedStart = resumeIndex === GENERATOR_RESUME_INDEX_INITIAL_YIELD; assert(
!isSuspendedStart || IsSuspendedGenerator(generator), "unexpected 'suspended-start' state for non-suspended generator"
);
// Step 4.a. Set O.[[GeneratorState]] to completed. // Step 4.b. NOTE: (elided) // Step 4.d. Return CreateIteratorResultObject(undefined, true). // Step 5. Let C be ReturnCompletion(undefined). // Step 6. Return ? GeneratorResumeAbrupt(O, C, "Iterator Helper"). var result = callFunction(GeneratorReturn, generator, undefined);
// Step 4 (Cont'ed). If O.[[GeneratorState]] is suspended-start, then // // Performed after GeneratorReturn, so even if IteratorClose throws an error, // it's not possible to re-enter the generator. if (isSuspendedStart) { var underlyingIterator = UnsafeGetReservedSlot(O, ITERATOR_HELPER_UNDERLYING_ITERATOR_SLOT); assert(
underlyingIterator === undefined || IsObject(underlyingIterator), "underlyingIterator is undefined or an object"
);
// Step 4.c. Perform ? IteratorClose(O.[[UnderlyingIterator]], NormalCompletion(unused)). // // NB: |underlyingIterator| can be `undefined` for IteratorConcat. if (IsObject(underlyingIterator)) {
IteratorClose(underlyingIterator);
}
}
return result;
}
// Lazy %Iterator.prototype% methods // // In order to match the semantics of the built-in generator objects, we use a // reserved slot on the IteratorHelper objects to store a regular generator that // is called from the %IteratorHelper.prototype% methods. // // Each of the lazy methods is divided into a prelude and a body, with the // eager prelude steps being contained in the corresponding IteratorX method // and the lazy body steps inside the IteratorXGenerator generator functions. // // Each prelude method initializes and returns a new IteratorHelper object. // As part of this initialization process, the appropriate generator function // is called and stored in the IteratorHelper object, alongside the underlying // iterator object.
/** *Iterator.prototype.map(mapper) * *https://tc39.es/ecma262/#sec-iterator.prototype.map *ES2026draftrevd14670224281909f5bb552e8ebe4a8e958646c16
*/ function IteratorMap(mapper) { // Step 1. var iterator = this;
// Step 5. (Inlined call to GetIteratorDirect.) var nextMethod = iterator.next;
// Steps 6-7. var accumulator; var counter; if (ArgumentsLength() === 1) { // Steps 6.a-d. (Moved below.)
counter = -1;
} else { // Step 7.a.
accumulator = GetArgument(1);
// Step 7.b.
counter = 0;
}
// Step 8. for (var value of allowContentIterWithNext(iterator, nextMethod)) { if (counter < 0) { // Step 6. (Reordered steps to compute initial accumulator.)
// Step 6.c.
accumulator = value;
// Step 6.d.
counter = 1;
} else { // Steps 8.a-b and 8.d. (Implicit through for-of loop)
/** *Iterator.concat(...items) * *https://tc39.es/proposal-iterator-sequencing/
*/ function IteratorConcat() { // Step 1. // // Stored in reversed order to simplify removing processed items. var index = ArgumentsLength() * 2; var iterables = std_Array(index);
// Step 2. for (var i = 0; i < ArgumentsLength(); i++) { var item = GetArgument(i);
// Step 2.a. if (!IsObject(item)) {
ThrowTypeError(JSMSG_OBJECT_REQUIRED, typeof item);
}
// Step 2.b. (Inlined GetMethod) var method = item[GetBuiltinSymbol("iterator")];
// Step 2.c. if (!IsCallable(method)) {
ThrowTypeError(JSMSG_NOT_ITERABLE, ToSource(item));
}
// Steps 3-5. var result = NewIteratorHelper(); var generator = IteratorConcatGenerator(iterables);
UnsafeSetReservedSlot(
result,
ITERATOR_HELPER_GENERATOR_SLOT,
generator
); // ITERATOR_HELPER_UNDERLYING_ITERATOR_SLOT is unused because IteratorConcat // doesn't have an underlying iterator.
// Step 14. if (mode === "longest") { // Step 9. (Reordered) var padding = [];
// Step 13. (Reordered) var iterCount = iters.length;
// Steps 14.b. if (paddingOption !== undefined) { // Steps 14.b.i-v. try { // Take care to not execute IteratorStepValue when |iterCount| is zero. if (iterCount > 0) { for (var paddingValue of allowContentIter(paddingOption)) {
DefineDataProperty(padding, padding.length, paddingValue);
// Steps 14.a.i and 14.b.iv.2. // // Fill with |undefined| up to |iterCount|. for (var i = padding.length; i < iterCount; i++) {
DefineDataProperty(padding, i, undefined);
}
}
// Steps 15-16. var result = NewIteratorHelper(); var generator = IteratorZipGenerator(iters, nextMethods, mode, padding); var closeIterator = { return() {
IteratorCloseAllForReturn(iters); return {};
}
};
UnsafeSetReservedSlot(
result,
ITERATOR_HELPER_GENERATOR_SLOT,
generator
);
UnsafeSetReservedSlot(
result,
ITERATOR_HELPER_UNDERLYING_ITERATOR_SLOT,
closeIterator
);
// Step 14. if (mode === "longest") { // Step 9. (Reordered) var padding = [];
// Steps 14.a-b. if (paddingOption === undefined) { // Step 13. (Reordered) var iterCount = iters.length;
// Step 14.1.i. for (var i = 0; i < iterCount; i++) {
DefineDataProperty(padding, i, undefined);
}
} else { try { // Step 14.b.i. for (var i = 0; i < keys.length; i++) {
DefineDataProperty(padding, i, paddingOption[keys[i]]);
}
} catch (e) { // Step 14.b.i.2.
IteratorCloseAllForException(iters); throw e;
}
}
}
// Steps 15-16. var result = NewIteratorHelper(); var generator = IteratorZipGenerator(iters, nextMethods, mode, padding, keys); var closeIterator = { return() {
IteratorCloseAllForReturn(iters); return {};
}
};
UnsafeSetReservedSlot(
result,
ITERATOR_HELPER_GENERATOR_SLOT,
generator
);
UnsafeSetReservedSlot(
result,
ITERATOR_HELPER_UNDERLYING_ITERATOR_SLOT,
closeIterator
);
return result;
}
/** *IteratorZip(iters,mode,padding,finishResults) * *https://tc39.es/proposal-joint-iteration/#sec-IteratorZip
*/ function* IteratorZipGenerator(iters, nextMethods, mode, padding, keys) { assert(
iters.length === nextMethods.length, "iters and nextMethods have the same number of entries"
); assert(
mode === "shortest" || mode === "longest" || mode === "strict", "invalid mode"
); assert(
mode !== "longest" || (IsArray(padding) && padding.length === iters.length), "iters and padding have the same number of entries"
); assert(
keys === undefined || (IsArray(keys) && keys.length === iters.length), "keys is undefined or an array with iters.length entries"
);
// Step 1. var iterCount = iters.length;
// Step 2. // // Our implementation reuses |iters| instead of using another list. This // counter is the number of non-null entries in |iters|. var openIterCount = iterCount;
// Step 3.a. if (iterCount === 0) { return;
}
// Step 3.b. while (true) { // Step 3.b.i. var results = [];
// Step 3.b.ii. assert(openIterCount > 0, "at least one open iterator");
// Step 3.b.iii. for (var i = 0; i < iterCount; i++) { // Step 3.b.iii.1. var iter = iters[i]; var nextMethod = nextMethods[i];
// Steps 3.b.iii.2-3. var result; if (iter === null) { // Step 3.b.iii.2.a. assert(mode === "longest", "padding only applied when mode is longest");
// Step 3.b.iii.2.b.
result = padding[i];
} else { // Steps 3.b.iii.3.a-c. try { // Step 3.b.iii.3.a. var iterResult = callContentFunction(nextMethod, iter); if (!IsObject(iterResult)) {
ThrowTypeError(JSMSG_ITER_METHOD_RETURNED_PRIMITIVE, "next");
} var done = !!iterResult.done; if (!done) {
result = iterResult.value;
}
} catch (e) { // Step 3.b.iii.3.b.i.
iters[i] = null;
returnCompletion = false;
} finally { // Step 3.b.vi. // // IteratorHelper iterators can't continue execution with a Throw // completion, so this must be a Return completion. if (returnCompletion) {
IteratorCloseAllForReturn(iters);
}
}
}
}
/** *IteratorCloseAll(iters,completion) * *When|completion|isaReturncompletion. * *https://tc39.es/proposal-joint-iteration/#sec-closeall
*/ function IteratorCloseAllForReturn(iters) { assert(IsArray(iters), "iters is an array");
var exception; var hasException = false;
// Step 1. for (var i = iters.length - 1; i >= 0; i--) { var iter = iters[i]; assert(IsObject(iter) || iter === null, "iter is an object or null");
if (IsObject(iter)) { try {
IteratorClose(iter);
} catch (e) { // Store the first exception and then ignore any later exceptions. if (!hasException) {
hasException = true;
exception = e;
}
}
}
}
// Step 2. if (hasException) { throw exception;
}
}
/** *IteratorCloseAll(iters,completion) * *When|completion|isaThrowcompletion. * *https://tc39.es/proposal-joint-iteration/#sec-closeall
*/ function IteratorCloseAllForException(iters) { assert(IsArray(iters), "iters is an array");
// Step 1. for (var i = iters.length - 1; i >= 0; i--) { var iter = iters[i]; assert(IsObject(iter) || iter === null, "iter is an object or null");
if (IsObject(iter)) { try {
IteratorClose(iter);
} catch { // Ignore any inner exceptions.
}
}
}
// Step 2. (Performed in caller)
}
#ifdef NIGHTLY_BUILD /** *CreateNumericRangeIterator(start,end,optionOrStep,type) *Step18 * *https://tc39.es/proposal-iterator.range/#sec-create-numeric-range-iterator
*/ function IteratorRangeNext() { var obj = this; // Step 18. Let closure be a new Abstract Closure with no parameters // that captures start, end, step, inclusiveEnd, zero, one and performs the following steps when called:
// Retrieve values from reserved slots var start = UnsafeGetReservedSlot(obj, ITERATOR_RANGE_SLOT_START); var end = UnsafeGetReservedSlot(obj, ITERATOR_RANGE_SLOT_END); var step = UnsafeGetReservedSlot(obj, ITERATOR_RANGE_SLOT_STEP); var inclusiveEnd = UnsafeGetReservedSlot(obj, ITERATOR_RANGE_SLOT_INCLUSIVE_END); var zero = UnsafeGetReservedSlot(obj, ITERATOR_RANGE_SLOT_ZERO); var one = UnsafeGetReservedSlot(obj, ITERATOR_RANGE_SLOT_ONE); var currentCount = UnsafeGetReservedSlot(obj, ITERATOR_RANGE_SLOT_CURRENT_COUNT);
// Step 18.a: If end > start, let ifIncrease be true // Step 18.b: Else let ifIncrease be false var ifIncrease = end > start;
// Step 18.c: If step > zero, let ifStepIncrease be true // Step 18.d: Else let ifStepIncrease be false var ifStepIncrease = step > zero;
// Step 18.e: If ifIncrease is not ifStepIncrease, return undefined. if (ifIncrease !== ifStepIncrease) { return { value: undefined, done: true };
}
// Step 18.f: Let hitsEnd be false var hitsEnd = false;
// Step 18.g: Let currentCount be zero (already handled via slots)
// Step 18.i.i: Let currentYieldingValue be start + (step × currentCount) var currentYieldingValue = start + (step * currentCount);
// Step 18.i.ii: If currentYieldingValue is equal to end, set hitsEnd to true
hitsEnd = currentYieldingValue === end && !inclusiveEnd;
// Step 18.i.iii: Set currentCount to currentCount + one
currentCount = currentCount + one;
// Step 18.i.iv: If ifIncrease is true, then if (ifIncrease) { // Step 18.i.iv.1: If inclusiveEnd is true, then if (inclusiveEnd) { // Step 18.i.iv.1.a: If currentYieldingValue > end, return undefined. if (currentYieldingValue > end) { return { value: undefined, done: true };
}
} else { // Step 18.i.iv.2: If currentYieldingValue >= end, return undefined if (currentYieldingValue >= end) { return { value: undefined, done: true };
}
}
} else { // Step 18.i.v: Else // Step 18.i.v.1: If inclusiveEnd is true, then if (inclusiveEnd) { //Step 18.i.v.1.a.a. If end > currentYieldingValue, return undefined. if (end > currentYieldingValue) { return { value: undefined, done: true };
}
} else { // Step 18.i.v.2: Else if (end >= currentYieldingValue) { // Step 18i.v.2.a: If end >= currentYieldingValue, return undefined return { value: undefined, done: true };
}
}
}
// Step 1: If start is NaN, throw a RangeError exception. if (isNumberRange && Number_isNaN(start)) {
ThrowRangeError(JSMSG_ITERATOR_RANGE_INVALID_START_RANGEERR);
}
// Step 2: If end is NaN, throw a RangeError exception. if (isNumberRange && Number_isNaN(end)) {
ThrowRangeError(JSMSG_ITERATOR_RANGE_INVALID_END_RANGEERR);
}
// Step 3: If type is NUMBER-RANGE, then if (isNumberRange) { // Step 3.a. Assert: start is a Number. assert(typeof start === 'number', "The 'start' argument must be a number");
// Step 3.b. If end is not a Number, throw a TypeError exception. if (typeof end !== 'number') {
ThrowTypeError(JSMSG_ITERATOR_RANGE_INVALID_END);
}
// Step 3.c. Let zero be 0ℤ. var zero = 0;
// Step 3.d. Let one be 1ℤ. var one = 1; // 4: Else,
} else { // 4.a. Assert: start is a BigInt. assert(typeof start === 'bigint', "The 'start' argument must be a bigint");
// 4.b. If end is not +∞ or -∞ and end is not a BigInt, throw a TypeError exception. if (typeof end !== 'bigint' && !(Number_isFinite(end))) {
ThrowTypeError(JSMSG_ITERATOR_RANGE_INVALID_END);
}
// 4.c. Let zero be 0. var zero = 0n;
// 4.d. Let one be 1. var one = 1n;
} // Step 5: If start is +∞ or -∞, throw a RangeError exception. if (typeof start === 'number' && !Number_isFinite(start)) {
ThrowRangeError(JSMSG_ITERATOR_RANGE_START_INFINITY);
} // Step 6: Let inclusiveEnd be false. var inclusiveEnd = false;
// Step 7: If optionOrStep is undefined or null, then // Step 7.a. Let step be undefined. var step;
// Step 8: Else if optionOrStep is an Object, then if (optionOrStep !== null && typeof optionOrStep === 'object') { // Step 8.a. Let step be ? Get(optionOrStep, "step").
step = optionOrStep.step;
// Step 8.b. Set inclusiveEnd to ToBoolean(? Get(optionOrStep, "inclusive")).
inclusiveEnd = TO_BOOLEAN(optionOrStep.inclusiveEnd);
} // Step 9: Else if type is NUMBER-RANGE and optionOrStep is a Number, then elseif (isNumberRange && typeof optionOrStep === 'number') { // Step 9.a. Let step be optionOrStep.
step = optionOrStep;
}
// Step 10: Else if type is BIGINT-RANGE and optionOrStep is a BigInt, then // Step 10.a. Let step be optionOrStep. elseif (!isNumberRange && typeof optionOrStep === 'bigint') {
step = optionOrStep;
} // Step 11: Else, throw a TypeError exception. elseif (optionOrStep !== undefined && optionOrStep !== null) {
ThrowTypeError(JSMSG_ITERATOR_RANGE_INVALID_STEP);
}
// Step 12: If step is undefined or null, then if (step === undefined || step === null) { // Step 12.a. If end > start, let step be one. // Step 12.b. Else let step be -one.
step = end > start ? one : -one;
}
// Step 13: If step is NaN, throw a RangeError exception. if (typeof step === "number" && Number_isNaN(step)) {
ThrowRangeError(JSMSG_ITERATOR_RANGE_STEP_NAN);
}
// Step 14: If type is NUMBER-RANGE and step is not a Number, throw a TypeError exception. if (isNumberRange && typeof step !== 'number') {
ThrowTypeError(JSMSG_ITERATOR_RANGE_STEP_NOT_NUMBER);
}
// Step 15: Else if type is BIGINT-RANGE and step is not a BigInt, throw a TypeError exception elseif (!isNumberRange && typeof step !== 'bigint') {
ThrowTypeError(JSMSG_ITERATOR_RANGE_STEP_NOT_BIGINT);
}
// Step 16: If step is +∞ or -∞, throw a RangeError exception. if (typeof step === 'number' && !Number_isFinite(step)) {
ThrowRangeError(JSMSG_ITERATOR_RANGE_STEP_NOT_FINITE);
}
// Step 17: If step is zero and start is not end, throw a RangeError exception. if (step === zero && start !== end) {
ThrowRangeError(JSMSG_ITERATOR_RANGE_STEP_ZERO);
} // Step 19: Return CreateIteratorFromClosure(closure, "%NumericRangeIteratorPrototype%", %NumericRangeIteratorPrototype%).
/** *Iterator.range(start,end,optionOrStep) * *https://tc39.es/proposal-iterator.range/#sec-iterator.range
*/ function IteratorRange(start, end, optionOrStep) {
// Step 1. If start is a Number, return ? CreateNumericRangeIterator(start, end, optionOrStep, NUMBER-RANGE) if (typeof start === 'number') { return CreateNumericRangeIterator(start, end, optionOrStep, true);
}
// Step 2. If start is a BigInt, return ? CreateNumericRangeIterator(start, end, optionOrStep, BIGINT-RANGE) if (typeof start === 'bigint') { return CreateNumericRangeIterator(start, end, optionOrStep, false);
}
// Step 3. Throw a TypeError exception.
ThrowTypeError(JSMSG_ITERATOR_RANGE_INVALID_START);
}
/** *Iterator.prototype.chunks(chunkSize) * *https://tc39.es/proposal-iterator-chunking/#sec-iterator.prototype.chunks
*/ function IteratorChunks(chunkSize) { // Step 1. Let O be the this value. var iterator = this;
// Step 2. If O is not an Object, throw a TypeError exception. if (!IsObject(iterator)) {
ThrowTypeError(JSMSG_OBJECT_REQUIRED, iterator === null ? "null" : typeof iterator);
}
// Step 3. Let iterated be the Iterator Record // { [[Iterator]]: O, [[NextMethod]]: undefined, [[Done]]: false }.
// Step 4. If chunkSize is not an integral Number in the inclusive interval // from 1 to (2**32 - 1), then if (!Number_isInteger(chunkSize) || (chunkSize < 1 || chunkSize > (2 ** 32) - 1)) { // Step 4.a. Let error be ThrowCompletion(a newly created RangeError object). // Step 4.b. Return ? IteratorClose(iterated, error). try {
IteratorClose(iterator);
} catch {}
ThrowRangeError(JSMSG_INVALID_CHUNKSIZE);
}
// Step 5. Set iterated to ? GetIteratorDirect(O). var nextMethod = iterator.next;
// Step 6. Let closure be a new Abstract Closure with ... // (Handled in IteratorChunksGenerator.)
// Step 7. Let result be CreateIteratorFromClosure( // closure, "Iterator Helper", %IteratorHelperPrototype%, // « [[UnderlyingIterators]] » // ). var result = NewIteratorHelper(); var generator = IteratorChunksGenerator(iterator, nextMethod, chunkSize);
// Step 8. Set result.[[UnderlyingIterators]] to « iterated ».
UnsafeSetReservedSlot(
result,
ITERATOR_HELPER_GENERATOR_SLOT,
generator
);
UnsafeSetReservedSlot(
result,
ITERATOR_HELPER_UNDERLYING_ITERATOR_SLOT,
iterator
);
// Step 9. Return result. return result;
}
/** *Iterator.prototype.chunks(chunkSize) * *Abstractclosuredefinition. * *https://tc39.es/proposal-iterator-chunking/#sec-iterator.prototype.chunks
*/ function* IteratorChunksGenerator(iterator, nextMethod, chunkSize) { // Step 6. Let closure be a new Abstract Closure // with no parameters that captures iterated and // chunkSize and performs the following steps when called: // Step 6.a. Let buffer be a new empty List. // This is an optimization that performs the equivalent of CreateArrayFromList // at the same time as constructing the buffer. // All the operations done on buffer are not affected by prototype pollution, // and thus directly using an array here is safe. // All the operations done on the buffer are not observable, // and thus reordering the operation here is safe. var buffer = [];
// Step 6.b. Repeat, // Step 6.b.i. Let value be ? IteratorStepValue(iterated). for (var value of allowContentIterWithNext(iterator, nextMethod)) { // Step 6.b.iii. Append value to buffer. // (Reordered) // NOTE: The OOM case is automatically handled by the for-of loop.
DefineDataProperty(buffer, buffer.length, value);
// Step 6.b.iv. If the number of elements in buffer is ℝ(chunkSize), then if (buffer.length === chunkSize) { // Step 6.b.iv.1. Let completion be // Completion(Yield(CreateArrayFromList(buffer))).
yield buffer;
// Step 6.b.iv.3. Set buffer to a new empty List. // This is an optimization that performs the equivalent of // CreateArrayFromList at the same time as constructing the buffer.
buffer = [];
}
}
// Step 6.b.ii. If value is done, then // Step 6.b.ii.1. If buffer is not empty, then if (buffer.length) { // Step 6.b.ii.1.a. Perform Completion(Yield(CreateArrayFromList(buffer))). // Iterator helper doesn't have throw methods, and only "normal" or "return" // completion can appear here. // Given that this is the last step inside the function, there's no // difference between handling and ignoring the completion.
yield buffer;
}
/** *Iterator.prototype.windows(windowSize,undersized) * *https://tc39.es/proposal-iterator-chunking/#sec-iterator.prototype.windows
*/ function IteratorWindows(windowSize, undersized) { // Step 1. Let O be the this value. var iterator = this;
// Step 2. If O is not an Object, throw a TypeError exception. if (!IsObject(iterator)) {
ThrowTypeError(JSMSG_OBJECT_REQUIRED, iterator === null ? "null" : typeof iterator);
}
// Step 3. Let iterated be the Iterator Record // { [[Iterator]]: O, [[NextMethod]]: undefined, [[Done]]: false }.
// Step 4. If windowSize is not an integral Number // in the inclusive interval from 1 to (2**32 - 1), then if (!Number_isInteger(windowSize) || (windowSize < 1 || windowSize > (2 ** 32) - 1)) { // Step 4.a. Let error be ThrowCompletion(a newly created RangeError object). // Step 4.b. Return ? IteratorClose(iterated, error). try {
IteratorClose(iterator);
} catch {}
ThrowRangeError(JSMSG_INVALID_WINDOWSIZE);
}
// Step 5. If undersized is undefined, set undersized to "only-full". if (undersized === undefined) {
undersized = "only-full";
}
// Step 6. If undersized is not "only-full" or "allow-partial", then if (undersized !== "only-full" && undersized !== "allow-partial") { // Step 6.a. Let error be ThrowCompletion(a newly created TypeError object). // Step 6.b. Return ? IteratorClose(iterated, error). try {
IteratorClose(iterator);
} catch {}
ThrowTypeError(
JSMSG_INVALID_UNDERSIZED_OPTION_VALUE, "undersized", ToSource(undersized)
);
}
// Step 7. Set iterated to ? GetIteratorDirect(O). var nextMethod = iterator.next;
// Step 8. Let closure be a new Abstract Closure with ... // (Handled in IteratorWindowsGenerator.)
// Step 9. Let result be CreateIteratorFromClosure( // closure, "Iterator Helper", %IteratorHelperPrototype%, // « [[UnderlyingIterators]] »). var result = NewIteratorHelper(); var generator = IteratorWindowsGenerator(iterator, nextMethod, windowSize, undersized);
// Step 10. Set result.[[UnderlyingIterators]] to « iterated ».
UnsafeSetReservedSlot(
result,
ITERATOR_HELPER_GENERATOR_SLOT,
generator
);
UnsafeSetReservedSlot(
result,
ITERATOR_HELPER_UNDERLYING_ITERATOR_SLOT,
iterator
);
// Step 11. Return result. return result;
}
/** *Iterator.prototype.windows(windowSize,undersized) * *Abstractclosuredefinition. * *https://tc39.es/proposal-iterator-chunking/#sec-iterator.prototype.windows
*/ function* IteratorWindowsGenerator(iterator, nextMethod, windowSize, undersized) { // Step 8. Let closure be a new Abstract Closure with no parameters that captures // iterated, windowSize, and undersized // and performs the following steps when called:
// Step 8.a. Let buffer be a new empty List. var buffer = new_List();
// Step 8.b. Repeat, // Step 8.b.i. Let value be ? IteratorStepValue(iterated). for (var value of allowContentIterWithNext(iterator, nextMethod)) { // Step 8.b.iii. If the number of elements in buffer is ℝ(windowSize), then if (buffer.length === windowSize) { // Step 8.b.iii.1. Remove the first element from buffer.
callFunction(std_Array_shift, buffer);
}
// Step 8.b.iv. Append value to buffer.
DefineDataProperty(buffer, buffer.length, value);
// Step 8.b.v. If the number of elements in buffer is ℝ(windowSize), then if (buffer.length === windowSize) { // Step 8.b.v.1. Let completion be Completion(Yield(CreateArrayFromList(buffer))). // Step 8.b.v.2. IfAbruptCloseIterator(completion, iterated). // NOTE: The abrupt return completion case is automatically handled by the for-of loop.
yield callFunction(std_Array_slice, buffer);
}
}
// Step 8.b.ii. If value is done, then // Step 8.b.ii.1. If undersized is "allow-partial", buffer is not empty, // and the number of elements in buffer < ℝ(windowSize), then if (undersized === "allow-partial" && buffer.length && buffer.length < windowSize) { // Step 8.b.ii.1.a. Perform Completion(Yield(CreateArrayFromList(buffer))). // Iterator helper doesn't have throw methods, and only "normal" or "return" // completion can appear here. // Given that this is the last step inside the function, there's no // difference between handling and ignoring the completion.
yield callFunction(std_Array_slice, buffer);
} // Step 8.b.ii.2. Return ReturnCompletion(undefined). // (implicit)
}
/** *Iterator.prototype.join(separator) * *https://tc39.es/proposal-iterator-join/#sec-iterator.prototype.join
*/ function IteratorJoin(separator) { // Step 1. Let O be the this value. var O = this;
// Step 2. If O is not an Object, throw a TypeError exception. if (!IsObject(O)) {
ThrowTypeError(JSMSG_OBJECT_REQUIRED, O === null ? "null" : typeof O);
}
// Step 3. Let iterated be the Iterator Record // { [[Iterator]]: O, [[NextMethod]]: undefined, [[Done]]: false }.
// Step 4. If separator is undefined, then var sep; if (separator === undefined) { // Step 4.a. Let sep be ",".
sep = ",";
} else { // Step 5. Else, // Step 5.a. Let sep be Completion(ToString(separator)). // Step 5.b. IfAbruptCloseIterator(sep, iterated). try {
sep = ToString(separator);
} catch (e) { try {
IteratorClose(O);
} catch {} throw e;
}
}
// Step 6. Set iterated to ? GetIteratorDirect(O). // (Inlined call to GetIteratorDirect.) var nextMethod = O.next;
// Step 7. Let R be the empty String. var R = "";
// Step 8. Let first be true. var first = true;
// Step 9. Repeat, // Step 9.a. Let value be ? IteratorStepValue(iterated). for (var value of allowContentIterWithNext(O, nextMethod)) { // Step 9.c. If first is true, then if (first) { // Step 9.c.i. Set first to false.
first = false;
} else { // Step 9.d. Else, // Step 9.d.i. Set R to the string-concatenation of R and sep.
R += sep;
}
// Step 9.e. If value is neither undefined nor null, then if (value !== undefined && value !== null) { // Step 9.e.i. Let S be Completion(ToString(value)). // Step 9.e.ii. IfAbruptCloseIterator(S, iterated). // Step 9.e.iii. Set R to the string-concatenation of R and S.
R += ToString(value);
}
}
// Step 9.b. If value is done, return R. return R;
}
/** *Iterator.prototype.includes(searchElement[,skippedElements]) * *https://tc39.es/proposal-iterator-includes
*/ function IteratorIncludes(searchElement, skippedElements = undefined) { // Step 1. Let O be the this value. var O = this;
// Step 2. If O is not an Object, throw a TypeError exception. if (!IsObject(O)) {
ThrowTypeError(JSMSG_OBJECT_REQUIRED, O === null ? "null" : typeof O);
}
// Step 3. Let iterated be the Iterator Record // { [[Iterator]]: O, [[NextMethod]]: undefined, [[Done]]: false }.
// Step 4. If skippedElements is undefined, then // Step 4.a. Let toSkip be 0. var toSkip = 0; // Step 5. Else, (skippedElements is not undefined) if (skippedElements !== undefined) { // Step 5.a. If skippedElements is not one of +∞, -∞, or an integral Number, then if (!(Number_isInteger(skippedElements) ||
(typeof skippedElements === "number" &&
!Number_isFinite(skippedElements) &&
!Number_isNaN(skippedElements)))) { // Step 5.a.i-ii. Let error be ThrowCompletion(...). Return ? IteratorClose(iterated, error). try {
IteratorClose(O);
} catch {}
ThrowTypeError(JSMSG_INVALID_SKIP_COUNT);
} // Step 5.b. Let toSkip be the extended mathematical value of skippedElements.
toSkip = skippedElements;
}
// Step 6. If toSkip < 0, then // Step 6.a. Let error be ThrowCompletion(a newly created RangeError object). // Step 6.b. Return ? IteratorClose(iterated, error). if (toSkip < 0) { try {
IteratorClose(O);
} catch {}
ThrowRangeError(JSMSG_NEGATIVE_LIMIT);
}
// Step 7. Let skipped be 0. var skipped = 0;
// Step 8. Set iterated to ? GetIteratorDirect(O). // (Inlined call to GetIteratorDirect.) var nextMethod = O.next;
// Step 9. Repeat, // Step 9.a. Let value be ? IteratorStepValue(iterated). for (var value of allowContentIterWithNext(O, nextMethod)) { // Step 9.c. If skipped < toSkip, then if (skipped < toSkip) { // Step 9.c.i. Set skipped to skipped + 1.
skipped++; // Step 9.d. Else if SameValueZero(value, searchElement) is true, then
} elseif (value === searchElement || (Number_isNaN(value) && Number_isNaN(searchElement))) { // Step 9.d.i. Return ? IteratorClose(iterated, NormalCompletion(true)). returntrue;
}
}
// Step 9.b. If value is done, return false. returnfalse;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.