@@ -808,19 +808,23 @@ const esIteratorPrototype = Object.getPrototypeOf(Object.getPrototypeOf([][Symbo
808808
809809/**
810810 * @see https://webidl.spec.whatwg.org/#dfn-iterator-prototype-object
811- * @param {() => unknown[] } iterator
811+ * @param {() => unknown } iterator
812812 * @param {string } name name of the instance
813813 * @param {'key'|'value'|'key+value' } kind
814+ * @param {string | number } [keyIndex]
815+ * @param {string | number } [valueIndex]
814816 */
815- function makeIterator ( iterator , name , kind ) {
817+ function makeIterator ( iterator , name , kind , keyIndex = 0 , valueIndex = 1 ) {
816818 const object = {
817819 index : 0 ,
818820 kind,
819821 target : iterator
820822 }
823+ // The [[Prototype]] internal slot of an iterator prototype object must be %IteratorPrototype%.
824+ const iteratorObject = Object . create ( esIteratorPrototype )
821825
822- const i = {
823- next ( ) {
826+ Object . defineProperty ( iteratorObject , 'next' , {
827+ value : function next ( ) {
824828 // 1. Let interface be the interface for which the iterator prototype object exists.
825829
826830 // 2. Let thisValue be the this value.
@@ -832,7 +836,7 @@ function makeIterator (iterator, name, kind) {
832836
833837 // 5. If object is not a default iterator object for interface,
834838 // then throw a TypeError.
835- if ( Object . getPrototypeOf ( this ) !== i ) {
839+ if ( Object . getPrototypeOf ( this ) !== iteratorObject ) {
836840 throw new TypeError (
837841 `'next' called on an object that does not implement interface ${ name } Iterator.`
838842 )
@@ -852,68 +856,66 @@ function makeIterator (iterator, name, kind) {
852856 if ( index >= len ) {
853857 return { value : undefined , done : true }
854858 }
855-
856859 // 11. Let pair be the entry in values at index index.
857- const pair = values [ index ]
858-
860+ const { [ keyIndex ] : key , [ valueIndex ] : value } = values [ index ]
859861 // 12. Set object’s index to index + 1.
860862 object . index = index + 1
861-
862863 // 13. Return the iterator result for pair and kind.
863- return iteratorResult ( pair , kind )
864+ // https://webidl.spec.whatwg.org/#iterator-result
865+ // 1. Let result be a value determined by the value of kind:
866+ let result
867+ switch ( kind ) {
868+ case 'key' :
869+ // 1. Let idlKey be pair’s key.
870+ // 2. Let key be the result of converting idlKey to an
871+ // ECMAScript value.
872+ // 3. result is key.
873+ result = key
874+ break
875+ case 'value' :
876+ // 1. Let idlValue be pair’s value.
877+ // 2. Let value be the result of converting idlValue to
878+ // an ECMAScript value.
879+ // 3. result is value.
880+ result = value
881+ break
882+ case 'key+value' :
883+ // 1. Let idlKey be pair’s key.
884+ // 2. Let idlValue be pair’s value.
885+ // 3. Let key be the result of converting idlKey to an
886+ // ECMAScript value.
887+ // 4. Let value be the result of converting idlValue to
888+ // an ECMAScript value.
889+ // 5. Let array be ! ArrayCreate(2).
890+ // 6. Call ! CreateDataProperty(array, "0", key).
891+ // 7. Call ! CreateDataProperty(array, "1", value).
892+ // 8. result is array.
893+ result = [ key , value ]
894+ break
895+ }
896+ // 2. Return CreateIterResultObject(result, false).
897+ return {
898+ value : result ,
899+ done : false
900+ }
864901 } ,
865- // The class string of an iterator prototype object for a given interface is the
866- // result of concatenating the identifier of the interface and the string " Iterator".
867- [ Symbol . toStringTag ] : `${ name } Iterator`
868- }
869-
870- // The [[Prototype]] internal slot of an iterator prototype object must be %IteratorPrototype%.
871- Object . setPrototypeOf ( i , esIteratorPrototype )
872- // esIteratorPrototype needs to be the prototype of i
873- // which is the prototype of an empty object. Yes, it's confusing.
874- return Object . setPrototypeOf ( { } , i )
875- }
902+ writable : true ,
903+ enumerable : true ,
904+ configurable : true
905+ } )
876906
877- // https://webidl.spec.whatwg.org/#iterator-result
878- function iteratorResult ( pair , kind ) {
879- let result
880-
881- // 1. Let result be a value determined by the value of kind:
882- switch ( kind ) {
883- case 'key' : {
884- // 1. Let idlKey be pair’s key.
885- // 2. Let key be the result of converting idlKey to an
886- // ECMAScript value.
887- // 3. result is key.
888- result = pair [ 0 ]
889- break
890- }
891- case 'value' : {
892- // 1. Let idlValue be pair’s value.
893- // 2. Let value be the result of converting idlValue to
894- // an ECMAScript value.
895- // 3. result is value.
896- result = pair [ 1 ]
897- break
898- }
899- case 'key+value' : {
900- // 1. Let idlKey be pair’s key.
901- // 2. Let idlValue be pair’s value.
902- // 3. Let key be the result of converting idlKey to an
903- // ECMAScript value.
904- // 4. Let value be the result of converting idlValue to
905- // an ECMAScript value.
906- // 5. Let array be ! ArrayCreate(2).
907- // 6. Call ! CreateDataProperty(array, "0", key).
908- // 7. Call ! CreateDataProperty(array, "1", value).
909- // 8. result is array.
910- result = pair
911- break
912- }
913- }
907+ // The class string of an iterator prototype object for a given interface is the
908+ // result of concatenating the identifier of the interface and the string " Iterator".
909+ Object . defineProperty ( iteratorObject , Symbol . toStringTag , {
910+ value : `${ name } Iterator` ,
911+ writable : false ,
912+ enumerable : false ,
913+ configurable : true
914+ } )
914915
915- // 2. Return CreateIterResultObject(result, false).
916- return { value : result , done : false }
916+ // esIteratorPrototype needs to be the prototype of iteratorObject
917+ // which is the prototype of an empty object. Yes, it's confusing.
918+ return Object . create ( iteratorObject )
917919}
918920
919921/**
0 commit comments