@@ -739,19 +739,23 @@ const esIteratorPrototype = Object.getPrototypeOf(Object.getPrototypeOf([][Symbo
739739
740740/**
741741 * @see https://webidl.spec.whatwg.org/#dfn-iterator-prototype-object
742- * @param {() => unknown[] } iterator
742+ * @param {() => unknown } iterator
743743 * @param {string } name name of the instance
744744 * @param {'key'|'value'|'key+value' } kind
745+ * @param {string | number } [keyIndex]
746+ * @param {string | number } [valueIndex]
745747 */
746- function makeIterator ( iterator , name , kind ) {
748+ function makeIterator ( iterator , name , kind , keyIndex = 0 , valueIndex = 1 ) {
747749 const object = {
748750 index : 0 ,
749751 kind,
750752 target : iterator
751753 }
754+ // The [[Prototype]] internal slot of an iterator prototype object must be %IteratorPrototype%.
755+ const iteratorObject = Object . create ( esIteratorPrototype )
752756
753- const i = {
754- next ( ) {
757+ Object . defineProperty ( iteratorObject , 'next' , {
758+ value : function next ( ) {
755759 // 1. Let interface be the interface for which the iterator prototype object exists.
756760
757761 // 2. Let thisValue be the this value.
@@ -763,7 +767,7 @@ function makeIterator (iterator, name, kind) {
763767
764768 // 5. If object is not a default iterator object for interface,
765769 // then throw a TypeError.
766- if ( Object . getPrototypeOf ( this ) !== i ) {
770+ if ( Object . getPrototypeOf ( this ) !== iteratorObject ) {
767771 throw new TypeError (
768772 `'next' called on an object that does not implement interface ${ name } Iterator.`
769773 )
@@ -783,68 +787,66 @@ function makeIterator (iterator, name, kind) {
783787 if ( index >= len ) {
784788 return { value : undefined , done : true }
785789 }
786-
787790 // 11. Let pair be the entry in values at index index.
788- const pair = values [ index ]
789-
791+ const { [ keyIndex ] : key , [ valueIndex ] : value } = values [ index ]
790792 // 12. Set object’s index to index + 1.
791793 object . index = index + 1
792-
793794 // 13. Return the iterator result for pair and kind.
794- return iteratorResult ( pair , kind )
795+ // https://webidl.spec.whatwg.org/#iterator-result
796+ // 1. Let result be a value determined by the value of kind:
797+ let result
798+ switch ( kind ) {
799+ case 'key' :
800+ // 1. Let idlKey be pair’s key.
801+ // 2. Let key be the result of converting idlKey to an
802+ // ECMAScript value.
803+ // 3. result is key.
804+ result = key
805+ break
806+ case 'value' :
807+ // 1. Let idlValue be pair’s value.
808+ // 2. Let value be the result of converting idlValue to
809+ // an ECMAScript value.
810+ // 3. result is value.
811+ result = value
812+ break
813+ case 'key+value' :
814+ // 1. Let idlKey be pair’s key.
815+ // 2. Let idlValue be pair’s value.
816+ // 3. Let key be the result of converting idlKey to an
817+ // ECMAScript value.
818+ // 4. Let value be the result of converting idlValue to
819+ // an ECMAScript value.
820+ // 5. Let array be ! ArrayCreate(2).
821+ // 6. Call ! CreateDataProperty(array, "0", key).
822+ // 7. Call ! CreateDataProperty(array, "1", value).
823+ // 8. result is array.
824+ result = [ key , value ]
825+ break
826+ }
827+ // 2. Return CreateIterResultObject(result, false).
828+ return {
829+ value : result ,
830+ done : false
831+ }
795832 } ,
796- // The class string of an iterator prototype object for a given interface is the
797- // result of concatenating the identifier of the interface and the string " Iterator".
798- [ Symbol . toStringTag ] : `${ name } Iterator`
799- }
800-
801- // The [[Prototype]] internal slot of an iterator prototype object must be %IteratorPrototype%.
802- Object . setPrototypeOf ( i , esIteratorPrototype )
803- // esIteratorPrototype needs to be the prototype of i
804- // which is the prototype of an empty object. Yes, it's confusing.
805- return Object . setPrototypeOf ( { } , i )
806- }
833+ writable : true ,
834+ enumerable : true ,
835+ configurable : true
836+ } )
807837
808- // https://webidl.spec.whatwg.org/#iterator-result
809- function iteratorResult ( pair , kind ) {
810- let result
811-
812- // 1. Let result be a value determined by the value of kind:
813- switch ( kind ) {
814- case 'key' : {
815- // 1. Let idlKey be pair’s key.
816- // 2. Let key be the result of converting idlKey to an
817- // ECMAScript value.
818- // 3. result is key.
819- result = pair [ 0 ]
820- break
821- }
822- case 'value' : {
823- // 1. Let idlValue be pair’s value.
824- // 2. Let value be the result of converting idlValue to
825- // an ECMAScript value.
826- // 3. result is value.
827- result = pair [ 1 ]
828- break
829- }
830- case 'key+value' : {
831- // 1. Let idlKey be pair’s key.
832- // 2. Let idlValue be pair’s value.
833- // 3. Let key be the result of converting idlKey to an
834- // ECMAScript value.
835- // 4. Let value be the result of converting idlValue to
836- // an ECMAScript value.
837- // 5. Let array be ! ArrayCreate(2).
838- // 6. Call ! CreateDataProperty(array, "0", key).
839- // 7. Call ! CreateDataProperty(array, "1", value).
840- // 8. result is array.
841- result = pair
842- break
843- }
844- }
838+ // The class string of an iterator prototype object for a given interface is the
839+ // result of concatenating the identifier of the interface and the string " Iterator".
840+ Object . defineProperty ( iteratorObject , Symbol . toStringTag , {
841+ value : `${ name } Iterator` ,
842+ writable : false ,
843+ enumerable : false ,
844+ configurable : true
845+ } )
845846
846- // 2. Return CreateIterResultObject(result, false).
847- return { value : result , done : false }
847+ // esIteratorPrototype needs to be the prototype of iteratorObject
848+ // which is the prototype of an empty object. Yes, it's confusing.
849+ return Object . create ( iteratorObject )
848850}
849851
850852/**
0 commit comments