function iteratorMixin (name, object, kInternalIterator, keyIndex = 0, valueIndex = 1) {
  const makeIterator = createIterator(name, kInternalIterator, keyIndex, valueIndex)

  const properties = {
    keys: {
      writable: true,
      enumerable: true,
      configurable: true,
      value: function keys () {
        webidl.brandCheck(this, object)
        return makeIterator(this, 'key')
      }
    },
    values: {
      writable: true,
      enumerable: true,
      configurable: true,
      value: function values () {
        webidl.brandCheck(this, object)
        return makeIterator(this, 'value')
      }
    },
    entries: {
      writable: true,
      enumerable: true,
      configurable: true,
      value: function entries () {
        webidl.brandCheck(this, object)
        return makeIterator(this, 'key+value')
      }
    },
    forEach: {
      writable: true,
      enumerable: true,
      configurable: true,
      value: function forEach (callbackfn, thisArg = globalThis) {
        webidl.brandCheck(this, object)
        webidl.argumentLengthCheck(arguments, 1, `${name}.forEach`)
        if (typeof callbackfn !== 'function') {
          throw new TypeError(
            `Failed to execute 'forEach' on '${name}': parameter 1 is not of type 'Function'.`
          )
        }
        for (const { 0: key, 1: value } of makeIterator(this, 'key+value')) {
          callbackfn.call(thisArg, value, key, this)
        }
      }
    }
  }

  return Object.defineProperties(object.prototype, {
    ...properties,
    [Symbol.iterator]: {
      writable: true,
      enumerable: false,
      configurable: true,
      value: properties.entries.value
    }
  })
}
@see https://webidl.spec.whatwg.org/#dfn-iterator-prototype-object
@param {string} name name of the instance
@param {any} object class
@param {(target: any) => any} kInternalIterator
@param {string | number} [keyIndex]
@param {string | number} [valueIndex]