%PDF- %PDF-
| Direktori : /home2/vacivi36/vittasync.vacivitta.com.br/vittasync/node/deps/v8/src/builtins/ |
| Current File : //home2/vacivi36/vittasync.vacivitta.com.br/vittasync/node/deps/v8/src/builtins/iterator-helpers.tq |
// Copyright 2023 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// --- Utilities
namespace iterator {
// Iterator helpers are specced as generators but implemented as direct
// iterators. As such generator states need to be tracked manually. To save
// space, this is done by assigning sentinel values to underlying.next.
// Tracks the ~completed~ generator state.
const kIteratorHelperExhausted: Null = Null;
// Tracks the ~executing~ generator state.
const kIteratorHelperExecuting: Undefined = Undefined;
macro IsIteratorHelperExhausted(helper: JSIteratorHelper): bool {
return helper.underlying.next == kIteratorHelperExhausted;
}
macro MarkIteratorHelperAsExhausted(helper: JSIteratorHelper): void {
helper.underlying.next = kIteratorHelperExhausted;
}
macro IsIteratorHelperExecuting(helper: JSIteratorHelper): bool {
return helper.underlying.next == kIteratorHelperExecuting;
}
// When a generator's state is ~executing~, attempts to reenter via next() or
// return() throw a TypeError. See step 6 in ES #sec-generatorvalidate.
macro ThrowIfIteratorHelperExecuting(
implicit context: Context)(helper: JSIteratorHelper): void {
if (IsIteratorHelperExecuting(helper)) {
ThrowTypeError(MessageTemplate::kGeneratorRunning);
}
}
macro MarkIteratorHelperAsExecuting(helper: JSIteratorHelper):
IteratorRecord {
dcheck(!IsIteratorHelperExecuting(helper));
const underlying = helper.underlying;
helper.underlying.next = kIteratorHelperExecuting;
return underlying;
}
macro MarkIteratorHelperAsFinishedExecuting(
helper: JSIteratorHelper, underlying: IteratorRecord): void {
dcheck(IsIteratorHelperExecuting(helper));
dcheck(underlying.next != kIteratorHelperExecuting);
dcheck(underlying.object == helper.underlying.object);
helper.underlying.next = underlying.next;
}
// https://tc39.es/proposal-iterator-helpers/#sec-getiteratordirect
transitioning macro GetIteratorDirect(
implicit context: Context)(obj: JSReceiver): IteratorRecord {
// 1. Let nextMethod be ? Get(obj, "next").
const nextMethod = GetProperty(obj, kNextString);
// 2. Let iteratorRecord be Record { [[Iterator]]: obj, [[NextMethod]]:
// nextMethod, [[Done]]: false }.
// 3. Return iteratorRecord.
return IteratorRecord{object: obj, next: nextMethod};
}
// --- Dispatch functions for all iterator helpers
// https://tc39.es/proposal-iterator-helpers/#sec-%iteratorhelperprototype%.next
transitioning javascript builtin IteratorHelperPrototypeNext(
js-implicit context: NativeContext, receiver: JSAny)(): JSAny {
// 1. Return ? GeneratorResume(this value, undefined, "Iterator Helper").
// Iterator helpers are specified as generators but we implement them as
// direct iterators.
const helper = Cast<JSIteratorHelper>(receiver) otherwise ThrowTypeError(
MessageTemplate::kIncompatibleMethodReceiver,
'Iterator Helper.prototype.next', receiver);
ThrowIfIteratorHelperExecuting(helper);
if (IsIteratorHelperExhausted(helper)) {
return AllocateJSIteratorResult(Undefined, True);
}
typeswitch (helper) {
case (mapHelper: JSIteratorMapHelper): {
return IteratorMapHelperNext(mapHelper);
}
case (filterHelper: JSIteratorFilterHelper): {
return IteratorFilterHelperNext(filterHelper);
}
case (takeHelper: JSIteratorTakeHelper): {
return IteratorTakeHelperNext(takeHelper);
}
case (dropHelper: JSIteratorDropHelper): {
return IteratorDropHelperNext(dropHelper);
}
case (flatMapHelper: JSIteratorFlatMapHelper): {
return IteratorFlatMapHelperNext(flatMapHelper);
}
case (Object): {
unreachable;
}
}
}
// https://tc39.es/proposal-iterator-helpers/#sec-%iteratorhelperprototype%.return
transitioning javascript builtin IteratorHelperPrototypeReturn(
js-implicit context: NativeContext, receiver: JSAny)(): JSObject {
// 1. Let O be this value.
// 2. Perform ? RequireInternalSlot(O, [[UnderlyingIterator]]).
// 3. Assert: O has a [[GeneratorState]] slot.
// 4. If O.[[GeneratorState]] is suspendedStart, then
// a. Set O.[[GeneratorState]] to completed.
// b. Perform ? IteratorClose(O.[[UnderlyingIterator]],
// NormalCompletion(unused)).
// c. Return CreateIterResultObject(undefined, true).
// 5. Let C be Completion { [[Type]]: return, [[Value]]: undefined,
// [[Target]]: empty }.
// 6. Return ? GeneratorResumeAbrupt(O, C, "Iterator Helper").
// Return for flatMap helper is not the same as other helpers.
typeswitch (receiver) {
case (helper: JSIteratorFlatMapHelper): {
ThrowIfIteratorHelperExecuting(helper);
if (IsIteratorHelperExhausted(helper)) {
return AllocateJSIteratorResult(Undefined, True);
}
MarkIteratorHelperAsExhausted(helper);
if (helper.innerAlive == True) {
try {
// d. If completion is an abrupt completion, then
// i. Let backupCompletion be Completion(IteratorClose(innerIterator,
// completion)).
IteratorClose(helper.innerIterator);
} catch (e, message) {
// ii. IfAbruptCloseIterator(backupCompletion, iterated).
IteratorCloseOnException(helper.underlying);
ReThrowWithMessage(context, e, message);
}
}
// iii. Return ? IteratorClose(completion, iterated).
IteratorClose(helper.underlying);
return AllocateJSIteratorResult(Undefined, True);
}
case (Object): {
// Iterator helpers are specified as generators. The net effect of this
// method is to close the underlying and return { value: undefined, done:
// true }.
const helper = Cast<JSIteratorHelper>(receiver) otherwise ThrowTypeError(
MessageTemplate::kIncompatibleMethodReceiver,
'Iterator Helper.prototype.return', receiver);
ThrowIfIteratorHelperExecuting(helper);
if (!IsIteratorHelperExhausted(helper)) {
MarkIteratorHelperAsExhausted(helper);
IteratorClose(helper.underlying);
}
return AllocateJSIteratorResult(Undefined, True);
}
}
}
// --- map helper
macro NewJSIteratorMapHelper(
implicit context: Context)(underlying: IteratorRecord,
mapper: Callable): JSIteratorMapHelper {
return new JSIteratorMapHelper{
map: *NativeContextSlot(ContextSlot::ITERATOR_MAP_HELPER_MAP_INDEX),
properties_or_hash: kEmptyFixedArray,
elements: kEmptyFixedArray,
underlying: underlying,
mapper: mapper,
counter: 0
};
}
// https://tc39.es/proposal-iterator-helpers/#sec-iteratorprototype.map
transitioning javascript builtin IteratorPrototypeMap(
js-implicit context: NativeContext, receiver: JSAny)(
mapper: JSAny): JSIteratorMapHelper {
const methodName: constexpr string = 'Iterator.prototype.map';
// 1. Let O be the this value.
// 2. If O is not an Object, throw a TypeError exception.
const o = Cast<JSReceiver>(receiver)
otherwise ThrowTypeError(MessageTemplate::kCalledOnNonObject, methodName);
// 3. If IsCallable(mapper) is false, throw a TypeError exception.
const mapper = Cast<Callable>(mapper)
otherwise ThrowCalledNonCallable(methodName);
// 4. Let iterated be ? GetIteratorDirect(O).
const iterated = GetIteratorDirect(o);
// Step 5 implemented in IteratorMapHelperNext
// 6. Let result be CreateIteratorFromClosure(closure, "Iterator Helper",
// %IteratorHelperPrototype%).
// 7. Set result.[[UnderlyingIterator]] to iterated.
// 8. Return result.
return NewJSIteratorMapHelper(iterated, mapper);
}
transitioning builtin IteratorMapHelperNext(
implicit context: Context)(helper: JSIteratorMapHelper): JSAny {
// a. Let counter be 0.
// (Done when creating JSIteratorMapHelper.)
const fastIteratorResultMap = GetIteratorResultMap();
const underlying = MarkIteratorHelperAsExecuting(helper);
const counter = helper.counter;
try {
// b. Repeat,
let next: JSReceiver;
try {
// i. Let next be ? IteratorStep(iterated).
next = IteratorStep(underlying, fastIteratorResultMap)
otherwise Done;
} label Done {
// ii. If next is false, return undefined.
MarkIteratorHelperAsExhausted(helper);
return AllocateJSIteratorResult(Undefined, True);
}
// iii. Let value be ? IteratorValue(next).
const value = IteratorValue(next, fastIteratorResultMap);
try {
// iv. Let mapped be Completion(
// Call(mapper, undefined, « value, 𝔽(counter) »)).
const mapped = Call(context, helper.mapper, Undefined, value, counter);
// viii. Set counter to counter + 1.
// (Done out of order. Iterator helpers are specified as generators with
// yields but we implement them as direct iterators.)
helper.counter = counter + 1;
// vi. Let completion be Completion(Yield(mapped)).
MarkIteratorHelperAsFinishedExecuting(helper, underlying);
return AllocateJSIteratorResult(mapped, False);
// vii. IfAbruptCloseIterator(completion, iterated).
// (Done in IteratorHelperPrototypeReturn.)
} catch (e, message) {
// v. IfAbruptCloseIterator(mapped, iterated).
IteratorCloseOnException(underlying);
ReThrowWithMessage(context, e, message);
}
} catch (e, message) {
MarkIteratorHelperAsExhausted(helper);
ReThrowWithMessage(context, e, message);
}
}
// --- filter helper
macro NewJSIteratorFilterHelper(
implicit context: Context)(underlying: IteratorRecord,
predicate: Callable): JSIteratorFilterHelper {
return new JSIteratorFilterHelper{
map: *NativeContextSlot(ContextSlot::ITERATOR_FILTER_HELPER_MAP_INDEX),
properties_or_hash: kEmptyFixedArray,
elements: kEmptyFixedArray,
underlying: underlying,
predicate: predicate,
counter: 0
};
}
// https://tc39.es/proposal-iterator-helpers/#sec-iteratorprototype.filter
transitioning javascript builtin IteratorPrototypeFilter(
js-implicit context: NativeContext, receiver: JSAny)(
predicate: JSAny): JSIteratorFilterHelper {
const methodName: constexpr string = 'Iterator.prototype.filter';
// 1. Let O be the this value.
// 2. If O is not an Object, throw a TypeError exception.
const o = Cast<JSReceiver>(receiver)
otherwise ThrowTypeError(MessageTemplate::kCalledOnNonObject, methodName);
// 3. If IsCallable(predicate) is false, throw a TypeError exception.
const predicate = Cast<Callable>(predicate)
otherwise ThrowCalledNonCallable(methodName);
// 4. Let iterated be ? GetIteratorDirect(O).
const iterated = GetIteratorDirect(o);
// Step 5 implemented in IteratorFilterHelperNext
// 6. Let result be CreateIteratorFromClosure(closure, "Iterator Helper",
// %IteratorHelperPrototype%).
// 7. Set result.[[UnderlyingIterator]] to iterated.
// 8. Return result.
return NewJSIteratorFilterHelper(iterated, predicate);
}
transitioning builtin IteratorFilterHelperNext(
implicit context: Context)(helper: JSIteratorFilterHelper): JSAny {
// a. Let counter be 0.
// (Done when creating JSIteratorFilterHelper.)
const fastIteratorResultMap = GetIteratorResultMap();
const underlying = MarkIteratorHelperAsExecuting(helper);
try {
while (true) {
const counter = helper.counter;
// b. Repeat,
let next: JSReceiver;
try {
// i. Let next be ? IteratorStep(iterated).
next = IteratorStep(underlying, fastIteratorResultMap)
otherwise Done;
} label Done {
// ii. If next is false, return undefined.
MarkIteratorHelperAsExhausted(helper);
return AllocateJSIteratorResult(Undefined, True);
}
// iii. Let value be ? IteratorValue(next).
const value = IteratorValue(next, fastIteratorResultMap);
try {
// iv. Let selected be Completion(
// Call(predicate, undefined, « value, 𝔽(counter) »)).
const selected =
Call(context, helper.predicate, Undefined, value, counter);
// vii. Set counter to counter + 1.
// (Done out of order. Iterator helpers are specified as generators with
// yields but we implement them as direct iterators.)
helper.counter = counter + 1;
// vi. If ToBoolean(selected) is true, then
if (ToBoolean(selected)) {
// 1. Let completion be Completion(Yield(value)).
MarkIteratorHelperAsFinishedExecuting(helper, underlying);
return AllocateJSIteratorResult(value, False);
// 2. IfAbruptCloseIterator(completion, iterated).
// (Done in IteratorHelperPrototypeReturn.)
}
} catch (e, message) {
// v. IfAbruptCloseIterator(selected, iterated).
IteratorCloseOnException(underlying);
ReThrowWithMessage(context, e, message);
}
}
} catch (e, message) {
MarkIteratorHelperAsExhausted(helper);
ReThrowWithMessage(context, e, message);
}
unreachable;
}
// --- take helper
macro NewJSIteratorTakeHelper(
implicit context: Context)(underlying: IteratorRecord,
limit: Number): JSIteratorTakeHelper {
return new JSIteratorTakeHelper{
map: *NativeContextSlot(ContextSlot::ITERATOR_TAKE_HELPER_MAP_INDEX),
properties_or_hash: kEmptyFixedArray,
elements: kEmptyFixedArray,
underlying: underlying,
remaining: limit
};
}
// https://tc39.es/proposal-iterator-helpers/#sec-iteratorprototype.take
transitioning javascript builtin IteratorPrototypeTake(
js-implicit context: NativeContext, receiver: JSAny)(
limit: JSAny): JSIteratorTakeHelper {
try {
const methodName: constexpr string = 'Iterator.prototype.take';
// 1. Let O be the this value.
// 2. If O is not an Object, throw a TypeError exception.
const o = Cast<JSReceiver>(receiver)
otherwise ThrowTypeError(MessageTemplate::kCalledOnNonObject, methodName);
// 3. Let numLimit be ? ToNumber(limit).
const numLimit = ToNumber_Inline(limit);
// 4. If numLimit is NaN, throw a RangeError exception.
if (NumberIsNaN(numLimit)) goto RangeError;
// 5. Let integerLimit be ! ToIntegerOrInfinity(numLimit).
const integerLimit = ToInteger_Inline(numLimit);
// 6. If integerLimit < 0, throw a RangeError exception.
if (integerLimit < 0) goto RangeError;
// 5. Let iterated be ? GetIteratorDirect(O).
const iterated = GetIteratorDirect(o);
// Step 6 implemented in IteratorTakeHelperNext
// 7. Let result be CreateIteratorFromClosure(closure, "Iterator Helper",
// %IteratorHelperPrototype%).
// 8. Set result.[[UnderlyingIterator]] to iterated.
// 9. Return result.
return NewJSIteratorTakeHelper(iterated, integerLimit);
} label RangeError deferred {
ThrowRangeError(MessageTemplate::kMustBePositive, limit);
}
}
transitioning builtin IteratorTakeHelperNext(
implicit context: Context)(helper: JSIteratorTakeHelper): JSAny {
// a. Let remaining be integerLimit.
// (Done when creating JSIteratorTakeHelper.)
const fastIteratorResultMap = GetIteratorResultMap();
const underlying = MarkIteratorHelperAsExecuting(helper);
const remaining = helper.remaining;
try {
// b. Repeat,
let next: JSReceiver;
// i. If remaining is 0, then
if (remaining == 0) {
// 1. Return ? IteratorClose(iterated, NormalCompletion(undefined)).
MarkIteratorHelperAsExhausted(helper);
IteratorClose(underlying);
return AllocateJSIteratorResult(Undefined, True);
}
// ii. If remaining is not +∞, then
if (!NumberIsSomeInfinity(remaining)) {
// 1. Set remaining to remaining - 1.
helper.remaining = remaining - 1;
}
try {
// iii. Let next be ? IteratorStep(iterated).
next = IteratorStep(underlying, fastIteratorResultMap)
otherwise Done;
} label Done {
// iv. If next is false, return undefined.
MarkIteratorHelperAsExhausted(helper);
return AllocateJSIteratorResult(Undefined, True);
}
// v. Let completion be Completion(Yield(? IteratorValue(next))).
const value = IteratorValue(next, fastIteratorResultMap);
MarkIteratorHelperAsFinishedExecuting(helper, underlying);
return AllocateJSIteratorResult(value, False);
// vi. IfAbruptCloseIterator(completion, iterated).
// (Done in IteratorHelperPrototypeReturn.)
} catch (e, message) {
MarkIteratorHelperAsExhausted(helper);
ReThrowWithMessage(context, e, message);
}
}
// --- drop helper
macro NewJSIteratorDropHelper(
implicit context: Context)(underlying: IteratorRecord,
limit: Number): JSIteratorDropHelper {
return new JSIteratorDropHelper{
map: *NativeContextSlot(ContextSlot::ITERATOR_DROP_HELPER_MAP_INDEX),
properties_or_hash: kEmptyFixedArray,
elements: kEmptyFixedArray,
underlying: underlying,
remaining: limit
};
}
// https://tc39.es/proposal-iterator-helpers/#sec-iteratorprototype.drop
transitioning javascript builtin IteratorPrototypeDrop(
js-implicit context: NativeContext, receiver: JSAny)(
limit: JSAny): JSIteratorDropHelper {
try {
const methodName: constexpr string = 'Iterator.prototype.drop';
// 1. Let O be the this value.
// 2. If O is not an Object, throw a TypeError exception.
const o = Cast<JSReceiver>(receiver)
otherwise ThrowTypeError(MessageTemplate::kCalledOnNonObject, methodName);
// 3. Let numLimit be ? ToNumber(limit).
const numLimit = ToNumber_Inline(limit);
// 4. If numLimit is NaN, throw a RangeError exception.
if (NumberIsNaN(numLimit)) goto RangeError;
// 5. Let integerLimit be ! ToIntegerOrInfinity(numLimit).
const integerLimit = ToInteger_Inline(numLimit);
// 6. If integerLimit < 0, throw a RangeError exception.
if (integerLimit < 0) goto RangeError;
// 5. Let iterated be ? GetIteratorDirect(O).
const iterated = GetIteratorDirect(o);
// Step 6 implemented in IteratorDropHelperNext
// 7. Let result be CreateIteratorFromClosure(closure, "Iterator Helper",
// %IteratorHelperPrototype%).
// 8. Set result.[[UnderlyingIterator]] to iterated.
// 9. Return result.
return NewJSIteratorDropHelper(iterated, integerLimit);
} label RangeError deferred {
ThrowRangeError(MessageTemplate::kMustBePositive, limit);
}
}
transitioning builtin IteratorDropHelperNext(
implicit context: Context)(helper: JSIteratorDropHelper): JSAny {
// a. Let remaining be integerLimit.
// (Done when creating JSIteratorDropHelper.)
const fastIteratorResultMap = GetIteratorResultMap();
const underlying = MarkIteratorHelperAsExecuting(helper);
let remaining = helper.remaining;
let next: JSReceiver;
try {
// b. Repeat, while remaining > 0,
try {
while (remaining > 0) {
// i. If remaining is not +∞, then
if (!NumberIsSomeInfinity(remaining)) {
// 1. Set remaining to remaining - 1.
remaining = remaining - 1;
helper.remaining = remaining;
}
// ii. Let next be ? IteratorStep(iterated).
IteratorStep(underlying, fastIteratorResultMap)
otherwise Done;
}
// c. Repeat,
// i. Let next be ? IteratorStep(iterated).
next = IteratorStep(underlying, fastIteratorResultMap)
otherwise Done;
} label Done {
// ii. If next is false, return undefined.
MarkIteratorHelperAsExhausted(helper);
return AllocateJSIteratorResult(Undefined, True);
}
// iii. Let completion be Completion(Yield(? IteratorValue(next))).
const value = IteratorValue(next, fastIteratorResultMap);
MarkIteratorHelperAsFinishedExecuting(helper, underlying);
return AllocateJSIteratorResult(value, False);
// iv. IfAbruptCloseIterator(completion, iterated).
// (Done in IteratorHelperPrototypeReturn.)
} catch (e, message) {
MarkIteratorHelperAsExhausted(helper);
ReThrowWithMessage(context, e, message);
}
}
// --- flatMap helper
const kFlatMapMethodName: constexpr string = 'Iterator.prototype.flatMap';
macro NewJSIteratorFlatMapHelper(
implicit context: Context)(underlying: IteratorRecord,
mapper: Callable): JSIteratorFlatMapHelper {
return new JSIteratorFlatMapHelper{
map: *NativeContextSlot(ContextSlot::ITERATOR_FLAT_MAP_HELPER_MAP_INDEX),
properties_or_hash: kEmptyFixedArray,
elements: kEmptyFixedArray,
underlying: underlying,
mapper: mapper,
counter: 0,
innerIterator: underlying,
innerAlive: False
};
}
// https://tc39.es/proposal-iterator-helpers/#sec-iteratorprototype.flatmap
transitioning javascript builtin IteratorPrototypeFlatMap(
js-implicit context: NativeContext, receiver: JSAny)(
mapper: JSAny): JSIteratorFlatMapHelper {
// 1. Let O be the this value.
// 2. If O is not an Object, throw a TypeError exception.
const o = Cast<JSReceiver>(receiver)
otherwise ThrowTypeError(
MessageTemplate::kCalledOnNonObject, kFlatMapMethodName);
// 3. If IsCallable(mapper) is false, throw a TypeError exception.
const mapper = Cast<Callable>(mapper)
otherwise ThrowTypeError(
MessageTemplate::kCalledNonCallable, kFlatMapMethodName);
// 4. Let iterated be ? GetIteratorDirect(O).
const iterated = GetIteratorDirect(o);
// Step 5 implemented in IteratorFlatMapHelperNext
// 6. Let result be CreateIteratorFromClosure(closure, "Iterator Helper",
// %IteratorHelperPrototype%).
// 7. Set result.[[UnderlyingIterator]] to iterated.
// 8. Return result.
return NewJSIteratorFlatMapHelper(iterated, mapper);
}
transitioning builtin IteratorFlatMapHelperNext(
implicit context: Context)(helper: JSIteratorFlatMapHelper): JSAny {
// a. Let counter be 0.
// (Done when creating JSIteratorFlatMapHelper.)
const fastIteratorResultMap = GetIteratorResultMap();
const underlying = MarkIteratorHelperAsExecuting(helper);
try {
while (true) {
const counter = helper.counter;
let innerIterator = helper.innerIterator;
// b. Repeat,
if (helper.innerAlive == False) {
let next: JSReceiver;
try {
// i. Let next be ? IteratorStep(iterated).
next = IteratorStep(underlying, fastIteratorResultMap)
otherwise Done;
} label Done {
// ii. If next is false, return undefined.
MarkIteratorHelperAsExhausted(helper);
return AllocateJSIteratorResult(Undefined, True);
}
// iii. Let value be ? IteratorValue(next).
const value = IteratorValue(next, fastIteratorResultMap);
try {
// iv. Let mapped be Completion(
// Call(mapper, undefined, « value, 𝔽(counter) »)).
const mapped =
Call(context, helper.mapper, Undefined, value, counter);
const mappedIter = Cast<JSReceiver>(mapped)
otherwise ThrowTypeError(
MessageTemplate::kCalledOnNonObject, kFlatMapMethodName);
// vi. Let innerIterator be Completion(GetIteratorFlattenable(mapped,
// reject-strings)).
innerIterator = GetIteratorFlattenable(mappedIter);
helper.innerIterator = innerIterator;
// viii. Let innerAlive be true.
helper.innerAlive = True;
} catch (e, message) {
// v. IfAbruptCloseIterator(mapped, iterated)
IteratorCloseOnException(underlying);
ReThrowWithMessage(context, e, message);
}
// x. Set counter to counter + 1.
helper.counter = counter + 1;
}
// ix. Repeat, while innerAlive is true,
try {
// 1. Let innerNext be Completion(IteratorStep(innerIterator)).
let innerNext: JSReceiver;
innerNext = IteratorStep(innerIterator, fastIteratorResultMap)
otherwise Done;
// 4. Else,
// a. Let innerValue be Completion(IteratorValue(innerNext)).
const innerValue = IteratorValue(innerNext, fastIteratorResultMap);
// c. Let completion be Completion(Yield(innerValue)).
MarkIteratorHelperAsFinishedExecuting(helper, underlying);
return AllocateJSIteratorResult(innerValue, False);
// d. If completion is an abrupt completion, then
// i. Let backupCompletion be Completion(IteratorClose(innerIterator,
// completion)).
// ii. IfAbruptCloseIterator(backupCompletion, iterated).
// iii. Return ? IteratorClose(completion, iterated).
// Done in IteratorHelperPrototypeReturn.
} catch (e, message) {
// 2. IfAbruptCloseIterator(innerNext, iterated)
IteratorCloseOnException(underlying);
ReThrowWithMessage(context, e, message);
} label Done {
// 3. If innerNext is false, then
// a. Set innerAlive to false.
helper.innerAlive = False;
}
}
} catch (e, message) {
MarkIteratorHelperAsExhausted(helper);
ReThrowWithMessage(context, e, message);
}
unreachable;
}
// --- reduce helper
// https://tc39.es/proposal-iterator-helpers/#sec-iteratorprototype.reduce
transitioning javascript builtin IteratorPrototypeReduce(
js-implicit context: NativeContext, receiver: JSAny)(...arguments): JSAny {
const methodName: constexpr string = 'Iterator.prototype.reduce';
// 1. Let O be the this value.
// 2. If O is not an Object, throw a TypeError exception.
const o = Cast<JSReceiver>(receiver)
otherwise ThrowTypeError(MessageTemplate::kCalledOnNonObject, methodName);
// 3. If IsCallable(reducer) is false, throw a TypeError exception.
const reducer = Cast<Callable>(arguments[0])
otherwise ThrowCalledNonCallable(methodName);
// 4. Let iterated be ? GetIteratorDirect(O).
const iterated = GetIteratorDirect(o);
const fastIteratorResultMap = GetIteratorResultMap();
let next: JSReceiver;
let accumulator: JSAny;
let counter: Number;
// 5. If initialValue is not present, then
if (arguments.length == 1) {
// a. Let next be ? IteratorStep(iterated).
// b. If next is false, throw a TypeError exception.
next = IteratorStep(iterated, fastIteratorResultMap)
otherwise ThrowTypeError(
MessageTemplate::kIteratorReduceNoInitial, methodName);
// c. Let accumulator be ? IteratorValue(next).
accumulator = IteratorValue(next, fastIteratorResultMap);
// d. Let counter be 1.
counter = 1;
} else {
// 6. Else,
// a. Let accumulator be initialValue.
accumulator = arguments[1];
// b. Let counter be 0.
counter = 0;
}
// 7. Repeat,
while (true) {
try {
// a. Let next be ? IteratorStep(iterated).
next = IteratorStep(iterated, fastIteratorResultMap)
otherwise Done;
} label Done {
// b. If next is false, return accumulator.
return accumulator;
}
// c. Let value be ? IteratorValue(next).
const value = IteratorValue(next, fastIteratorResultMap);
try {
// d. Let result be Completion(Call(reducer, undefined, « accumulator,
// value, 𝔽(counter) »)).
const result =
Call(context, reducer, Undefined, accumulator, value, counter);
// f. Set accumulator to result.[[Value]].
accumulator = result;
// g. Set counter to counter + 1.
counter = counter + 1;
} catch (e, message) {
// e. IfAbruptCloseIterator(result, iterated).
IteratorCloseOnException(iterated);
ReThrowWithMessage(context, e, message);
}
}
unreachable;
}
// --- toArray helper
// https://tc39.es/proposal-iterator-helpers/#sec-iteratorprototype.toarray
transitioning javascript builtin IteratorPrototypeToArray(
js-implicit context: NativeContext, receiver: JSAny)(): JSAny {
const methodName: constexpr string = 'Iterator.prototype.toArray';
// 1. Let O be the this value.
// 2. If O is not an Object, throw a TypeError exception.
const o = Cast<JSReceiver>(receiver)
otherwise ThrowTypeError(MessageTemplate::kCalledOnNonObject, methodName);
// 3. Let iterated be ? GetIteratorDirect(O).
const iterated = GetIteratorDirect(o);
// 4. Let items be a new empty List.
let items = growable_fixed_array::NewGrowableFixedArray();
const fastIteratorResultMap = GetIteratorResultMap();
let next: JSReceiver;
// 5. Repeat,
while (true) {
try {
// a. Let next be ? IteratorStep(iterated).
next = IteratorStep(iterated, fastIteratorResultMap)
otherwise Done;
} label Done {
// b. If next is false, return CreateArrayFromList(items).
return items.ToJSArray();
}
// c. Let value be ? IteratorValue(next).
const value = IteratorValue(next, fastIteratorResultMap);
// d. Append value to items.
items.Push(value);
}
unreachable;
}
// --- forEach helper
// https://tc39.es/proposal-iterator-helpers/#sec-iteratorprototype.foreach
transitioning javascript builtin IteratorPrototypeForEach(
js-implicit context: NativeContext, receiver: JSAny)(fn: JSAny): JSAny {
const methodName: constexpr string = 'Iterator.prototype.forEach';
// 1. Let O be the this value.
// 2. If O is not an Object, throw a TypeError exception.
const o = Cast<JSReceiver>(receiver)
otherwise ThrowTypeError(MessageTemplate::kCalledOnNonObject, methodName);
// 3. If IsCallable(fn) is false, throw a TypeError exception.
const fn = Cast<Callable>(fn)
otherwise ThrowCalledNonCallable(methodName);
// 4. Let iterated be ? GetIteratorDirect(O).
const iterated = GetIteratorDirect(o);
// 5. Let counter be 0.
let counter: Number = 0;
const fastIteratorResultMap = GetIteratorResultMap();
// 5. Repeat,
while (true) {
let next: JSReceiver;
try {
// a. Let next be ? IteratorStep(iterated).
next = IteratorStep(iterated, fastIteratorResultMap)
otherwise Done;
} label Done {
// b. If next is false, return undefined.
return Undefined;
}
// c. Let value be ? IteratorValue(next).
const value = IteratorValue(next, fastIteratorResultMap);
try {
// d. Let result be Completion(Call(fn, undefined, « value, 𝔽(counter)
// »)).
Call(context, fn, Undefined, value, counter);
// f. Set counter to counter + 1.
counter = counter + 1;
} catch (e, message) {
// e. IfAbruptCloseIterator(result, iterated).
IteratorCloseOnException(iterated);
ReThrowWithMessage(context, e, message);
}
}
unreachable;
}
// --- some helper
// https://tc39.es/proposal-iterator-helpers/#sec-iteratorprototype.some
transitioning javascript builtin IteratorPrototypeSome(
js-implicit context: NativeContext, receiver: JSAny)(
predicate: JSAny): JSAny {
const methodName: constexpr string = 'Iterator.prototype.some';
// 1. Let O be the this value.
// 2. If O is not an Object, throw a TypeError exception.
const o = Cast<JSReceiver>(receiver)
otherwise ThrowTypeError(MessageTemplate::kCalledOnNonObject, methodName);
// 3. If IsCallable(predicate) is false, throw a TypeError exception.
const predicate = Cast<Callable>(predicate)
otherwise ThrowCalledNonCallable(methodName);
// 4. Let iterated be ? GetIteratorDirect(O).
const iterated = GetIteratorDirect(o);
// 5. Let counter be 0.
let counter: Number = 0;
const fastIteratorResultMap = GetIteratorResultMap();
// 5. Repeat,
while (true) {
let next: JSReceiver;
try {
// a. Let next be ? IteratorStep(iterated).
next = IteratorStep(iterated, fastIteratorResultMap)
otherwise Done;
} label Done {
// b. If next is false, return false.
return False;
}
// c. Let value be ? IteratorValue(next).
const value = IteratorValue(next, fastIteratorResultMap);
let result: JSAny;
try {
// d. Let result be Completion(Call(predicate, undefined, « value,
// 𝔽(counter) »)).
result = Call(context, predicate, Undefined, value, counter);
} catch (e, message) {
// e. IfAbruptCloseIterator(result, iterated).
IteratorCloseOnException(iterated);
ReThrowWithMessage(context, e, message);
}
// f. If ToBoolean(result) is true, return ? IteratorClose(iterated,
// NormalCompletion(true)).
if (ToBoolean(result) == true) {
IteratorClose(iterated);
return True;
}
// g. Set counter to counter + 1.
counter = counter + 1;
}
unreachable;
}
// --- every helper
// https://tc39.es/proposal-iterator-helpers/#sec-iteratorprototype.every
transitioning javascript builtin IteratorPrototypeEvery(
js-implicit context: NativeContext, receiver: JSAny)(
predicate: JSAny): JSAny {
const methodName: constexpr string = 'Iterator.prototype.every';
// 1. Let O be the this value.
// 2. If O is not an Object, throw a TypeError exception.
const o = Cast<JSReceiver>(receiver)
otherwise ThrowTypeError(MessageTemplate::kCalledOnNonObject, methodName);
// 3. If IsCallable(predicate) is false, throw a TypeError exception.
const predicate = Cast<Callable>(predicate)
otherwise ThrowCalledNonCallable(methodName);
// 4. Let iterated be ? GetIteratorDirect(O).
const iterated = GetIteratorDirect(o);
// 5. Let counter be 0.
let counter: Number = 0;
const fastIteratorResultMap = GetIteratorResultMap();
// 5. Repeat,
while (true) {
let next: JSReceiver;
try {
// a. Let next be ? IteratorStep(iterated).
next = IteratorStep(iterated, fastIteratorResultMap)
otherwise Done;
} label Done {
// b. If next is false, return true.
return True;
}
// c. Let value be ? IteratorValue(next).
const value = IteratorValue(next, fastIteratorResultMap);
let result: JSAny;
try {
// d. Let result be Completion(Call(predicate, undefined, « value,
// 𝔽(counter) »)).
result = Call(context, predicate, Undefined, value, counter);
} catch (e, message) {
// e. IfAbruptCloseIterator(result, iterated).
IteratorCloseOnException(iterated);
ReThrowWithMessage(context, e, message);
}
// f. If ToBoolean(result) is false, return ? IteratorClose(iterated,
// NormalCompletion(false)).
if (ToBoolean(result) == false) {
IteratorClose(iterated);
return False;
}
// g. Set counter to counter + 1.
counter = counter + 1;
}
unreachable;
}
// --- find helper
// https://tc39.es/proposal-iterator-helpers/#sec-iteratorprototype.find
transitioning javascript builtin IteratorPrototypeFind(
js-implicit context: NativeContext, receiver: JSAny)(
predicate: JSAny): JSAny {
const methodName: constexpr string = 'Iterator.prototype.find';
// 1. Let O be the this value.
// 2. If O is not an Object, throw a TypeError exception.
const o = Cast<JSReceiver>(receiver)
otherwise ThrowTypeError(MessageTemplate::kCalledOnNonObject, methodName);
// 3. If IsCallable(predicate) is false, throw a TypeError exception.
const predicate = Cast<Callable>(predicate)
otherwise ThrowCalledNonCallable(methodName);
// 4. Let iterated be ? GetIteratorDirect(O).
const iterated = GetIteratorDirect(o);
// 5. Let counter be 0.
let counter: Number = 0;
const fastIteratorResultMap = GetIteratorResultMap();
// 5. Repeat,
while (true) {
let next: JSReceiver;
try {
// a. Let next be ? IteratorStep(iterated).
next = IteratorStep(iterated, fastIteratorResultMap)
otherwise Done;
} label Done {
// b. If next is false, return undefined.
return Undefined;
}
// c. Let value be ? IteratorValue(next).
const value = IteratorValue(next, fastIteratorResultMap);
let result: JSAny;
try {
// d. Let result be Completion(Call(predicate, undefined, « value,
// 𝔽(counter) »)).
result = Call(context, predicate, Undefined, value, counter);
} catch (e, message) {
// e. IfAbruptCloseIterator(result, iterated).
IteratorCloseOnException(iterated);
ReThrowWithMessage(context, e, message);
}
// f. If ToBoolean(result) is true, return ? IteratorClose(iterated,
// NormalCompletion(value)).
if (ToBoolean(result) == true) {
IteratorClose(iterated);
return value;
}
// g. Set counter to counter + 1.
counter = counter + 1;
}
unreachable;
}
} // namespace iterator