@@ -132,6 +132,17 @@ struct IteratorData : public gc {
132
132
{
133
133
}
134
134
};
135
+ struct FlatMapIteratorData : public IteratorData {
136
+ IteratorRecord* innerIterator;
137
+ bool innerAlive;
138
+
139
+ FlatMapIteratorData (Value mapper)
140
+ : IteratorData(mapper)
141
+ , innerIterator(nullptr )
142
+ , innerAlive(false )
143
+ {
144
+ }
145
+ };
135
146
136
147
static std::pair<Value, bool > iteratorMapClosure (ExecutionState& state, IteratorHelperObject* obj, void * data)
137
148
{
@@ -739,6 +750,117 @@ static Value builtinIteratorToArray(ExecutionState& state, Value thisValue, size
739
750
}
740
751
}
741
752
753
+ static std::pair<Value, bool > iteratorFlatMapClosure (ExecutionState& state, IteratorHelperObject* obj, void * data)
754
+ {
755
+ // Let closure be a new Abstract Closure with no parameters that captures iterated and mapper and performs the following steps when called:
756
+ // a. Let counter be 0.
757
+ // b. Repeat,
758
+ // i. Let value be ? IteratorStepValue(iterated).
759
+ // ii. If value is done, return ReturnCompletion(undefined).
760
+ // iii. Let mapped be Completion(Call(mapper, undefined, « value, 𝔽(counter) »)).
761
+ // iv. IfAbruptCloseIterator(mapped, iterated).
762
+ // v. Let innerIterator be Completion(GetIteratorFlattenable(mapped, reject-primitives)).
763
+ // vi. IfAbruptCloseIterator(innerIterator, iterated).
764
+ // vii. Let innerAlive be true.
765
+ // viii. Repeat, while innerAlive is true,
766
+ // 1. Let innerValue be Completion(IteratorStepValue(innerIterator)).
767
+ // 2. IfAbruptCloseIterator(innerValue, iterated).
768
+ // 3. If innerValue is done, then
769
+ // a. Set innerAlive to false.
770
+ // 4. Else,
771
+ // a. Let completion be Completion(Yield(innerValue)).
772
+ // b. If completion is an abrupt completion, then
773
+ // i. Let backupCompletion be Completion(IteratorClose(innerIterator, completion)).
774
+ // ii. IfAbruptCloseIterator(backupCompletion, iterated).
775
+ // iii. Return ? IteratorClose(iterated, completion).
776
+ // ix. Set counter to counter + 1.
777
+ IteratorRecord* iterated = obj->underlyingIterator ();
778
+ FlatMapIteratorData* closureData = reinterpret_cast <FlatMapIteratorData*>(data);
779
+ Value mapper = closureData->callback ;
780
+
781
+ while (true ) {
782
+ // while innerAlive is true, Let innerValue be Completion(IteratorStepValue(innerIterator)).
783
+ if (closureData->innerAlive && closureData->innerIterator ) {
784
+ Optional<Value> innerValue;
785
+ try {
786
+ innerValue = IteratorObject::iteratorStepValue (state, closureData->innerIterator );
787
+ } catch (const Value& e) {
788
+ // IfAbruptCloseIterator(innerValue, iterated).
789
+ IteratorObject::iteratorClose (state, obj->underlyingIterator (), e, true );
790
+ }
791
+ if (!innerValue) {
792
+ // If innerValue is done, then Set innerAlive to false.
793
+ closureData->innerAlive = false ;
794
+ closureData->innerIterator = nullptr ;
795
+ } else {
796
+ // Else, Let completion be Completion(Yield(innerValue)).
797
+ return std::make_pair (innerValue.value (), false );
798
+ }
799
+ }
800
+
801
+ // Let value be ? IteratorStepValue(iterated).
802
+ auto value = IteratorObject::iteratorStepValue (state, iterated);
803
+ // If value is done, return ReturnCompletion(undefined).
804
+ if (!value) {
805
+ iterated->m_done = true ;
806
+ return std::make_pair (Value (), true );
807
+ }
808
+
809
+ // Let mapped be Completion(Call(mapper, undefined, « value, 𝔽(counter) »)).
810
+ Value args[2 ] = { value.value (), Value (closureData->counter ) };
811
+ Value mapped;
812
+
813
+ try {
814
+ mapped = Object::call (state, mapper, Value (), 2 , args);
815
+ } catch (const Value& e) {
816
+ // IfAbruptCloseIterator(mapped, iterated).
817
+ IteratorObject::iteratorClose (state, iterated, e, true );
818
+ }
819
+
820
+ // Let innerIterator be Completion(GetIteratorFlattenable(mapped, reject-primitives)).
821
+ IteratorRecord* innerIterator = nullptr ;
822
+ try {
823
+ innerIterator = IteratorObject::getIteratorFlattenable (state, mapped, IteratorObject::PrimitiveHandling::RejectPrimitives);
824
+ } catch (const Value& e) {
825
+ IteratorObject::iteratorClose (state, iterated, e, true );
826
+ }
827
+
828
+ // Let innerAlive be true.
829
+ // Set counter to counter + 1.
830
+ closureData->innerAlive = true ;
831
+ closureData->innerIterator = innerIterator;
832
+ closureData->counter = StorePositiveNumberAsOddNumber (closureData->counter + 1 );
833
+ }
834
+ }
835
+
836
+ static Value builtinIteratorFlatMap (ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
837
+ {
838
+ // Let O be the this value.
839
+ const Value& O = thisValue;
840
+
841
+ // If O is not an Object, throw a TypeError exception.
842
+ if (!O.isObject ()) {
843
+ ErrorObject::throwBuiltinError (state, ErrorCode::TypeError, " this value is not Object" );
844
+ }
845
+
846
+ // If IsCallable(mapper) is false, throw a TypeError exception.
847
+ const Value& mapper = argv[0 ];
848
+ if (!mapper.isCallable ()) {
849
+ ErrorObject::throwBuiltinError (state, ErrorCode::TypeError, " mapper is not callable" );
850
+ }
851
+
852
+ // Set iterated to ? GetIteratorDirect(O).
853
+ IteratorRecord* iterated = IteratorObject::getIteratorDirect (state, O.asObject ());
854
+
855
+ // Let result be CreateIteratorFromClosure(closure, "Iterator Helper", %IteratorHelperPrototype%, « [[UnderlyingIterator]] »).
856
+ // Set result.[[UnderlyingIterator]] to iterated.
857
+ IteratorHelperObject* result = new IteratorHelperObject (state, iteratorFlatMapClosure, iterated, new FlatMapIteratorData (mapper));
858
+
859
+ // Return result.
860
+ return result;
861
+ }
862
+
863
+
742
864
static Value builtinGenericIteratorNext (ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget)
743
865
{
744
866
if (!thisValue.isObject () || !thisValue.asObject ()->isGenericIteratorObject ()) {
@@ -840,6 +962,9 @@ void GlobalObject::installIterator(ExecutionState& state)
840
962
m_iteratorPrototype->directDefineOwnProperty (state, ObjectPropertyName (strings->toArray ),
841
963
ObjectPropertyDescriptor (new NativeFunctionObject (state, NativeFunctionInfo (strings->toArray , builtinIteratorToArray, 0 , NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
842
964
965
+ m_iteratorPrototype->directDefineOwnProperty (state, ObjectPropertyName (strings->flatMap ),
966
+ ObjectPropertyDescriptor (new NativeFunctionObject (state, NativeFunctionInfo (strings->flatMap , builtinIteratorFlatMap, 1 , NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
967
+
843
968
directDefineOwnProperty (state, ObjectPropertyName (strings->Iterator ),
844
969
ObjectPropertyDescriptor (m_iterator, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
845
970
}
0 commit comments