@constructor
@globalPrivate
function createMapIterator(iteratedObject, kind)
{
"use strict";
@assert(@isMap(iteratedObject));
@putByIdDirectPrivate(this, "iteratedObject", iteratedObject);
@putByIdDirectPrivate(this, "mapIteratorKind", kind);
@putByIdDirectPrivate(this, "mapBucket", @mapBucketHead(iteratedObject));
}
function values()
{
"use strict";
if (!@isMap(this))
@throwTypeError("Map.prototype.values requires that |this| be Map");
return new @createMapIterator(this, @iterationKindValue);
}
function keys()
{
"use strict";
if (!@isMap(this))
@throwTypeError("Map.prototype.keys requires that |this| be Map");
return new @createMapIterator(this, @iterationKindKey);
}
function entries()
{
"use strict";
if (!@isMap(this))
@throwTypeError("Map.prototype.entries requires that |this| be Map");
return new @createMapIterator(this, @iterationKindKeyValue);
}
function forEach(callback )
{
"use strict";
if (!@isMap(this))
@throwTypeError("Map operation called on non-Map object");
if (typeof callback !== 'function')
@throwTypeError("Map.prototype.forEach callback must be a function");
var thisArg = @argument(1);
var bucket = @mapBucketHead(this);
do {
bucket = @mapBucketNext(bucket);
if (bucket === @sentinelMapBucket)
break;
callback.@call(thisArg, @mapBucketValue(bucket), @mapBucketKey(bucket), this);
} while (true);
}