/**
* Copyright (c) 2012-2016 André Bargull
* Alle Rechte vorbehalten / All Rights Reserved. Use is subject to license terms.
*
* <https://github.com/anba/es6draft>
*/
package com.github.anba.es6draft.runtime.objects.collection;
import static com.github.anba.es6draft.runtime.AbstractOperations.IsCallable;
import static com.github.anba.es6draft.runtime.internal.Errors.newTypeError;
import static com.github.anba.es6draft.runtime.internal.Properties.createProperties;
import static com.github.anba.es6draft.runtime.objects.collection.MapIteratorPrototype.CreateMapIterator;
import static com.github.anba.es6draft.runtime.types.Undefined.UNDEFINED;
import java.util.Map.Entry;
import com.github.anba.es6draft.runtime.ExecutionContext;
import com.github.anba.es6draft.runtime.Realm;
import com.github.anba.es6draft.runtime.internal.Initializable;
import com.github.anba.es6draft.runtime.internal.LinkedMap;
import com.github.anba.es6draft.runtime.internal.Messages;
import com.github.anba.es6draft.runtime.internal.Properties.Accessor;
import com.github.anba.es6draft.runtime.internal.Properties.AliasFunction;
import com.github.anba.es6draft.runtime.internal.Properties.Attributes;
import com.github.anba.es6draft.runtime.internal.Properties.Function;
import com.github.anba.es6draft.runtime.internal.Properties.Prototype;
import com.github.anba.es6draft.runtime.internal.Properties.Value;
import com.github.anba.es6draft.runtime.objects.collection.MapIteratorObject.MapIterationKind;
import com.github.anba.es6draft.runtime.types.BuiltinSymbol;
import com.github.anba.es6draft.runtime.types.Callable;
import com.github.anba.es6draft.runtime.types.Intrinsics;
import com.github.anba.es6draft.runtime.types.builtins.NativeFunction;
import com.github.anba.es6draft.runtime.types.builtins.OrdinaryObject;
/**
* <h1>23 Keyed Collection</h1><br>
* <h2>23.1 Map Objects</h2>
* <ul>
* <li>23.1.3 Properties of the Map Prototype Object
* </ul>
*/
public final class MapPrototype extends OrdinaryObject implements Initializable {
/**
* Constructs a new Map prototype object.
*
* @param realm
* the realm object
*/
public MapPrototype(Realm realm) {
super(realm);
}
@Override
public void initialize(Realm realm) {
createProperties(realm, this, Properties.class);
}
/**
* Marker class for {@code Map.prototype.set}.
*/
private static final class MapPrototypeSet {
}
/**
* Returns {@code true} if <var>set</var> is the built-in {@code Map.prototype.set} function.
*
* @param set
* the set function
* @return {@code true} if <var>set</var> is the built-in {@code Map.prototype.set} function
*/
static boolean isBuiltinSet(Object set) {
return NativeFunction.isNative(set, MapPrototypeSet.class);
}
/**
* Marker class for {@code Map.prototype.entries}.
*/
private static final class MapPrototypeEntries {
}
/**
* Returns {@code true} if <var>entries</var> is the built-in {@code Map.prototype.entries} function for the
* requested realm.
*
* @param realm
* the function realm
* @param entries
* the entries function
* @return {@code true} if <var>entries</var> is the built-in {@code Map.prototype.entries} function
*/
public static boolean isBuiltinEntries(Realm realm, Object entries) {
return NativeFunction.isNative(realm, entries, MapPrototypeEntries.class);
}
/**
* 23.1.3 Properties of the Map Prototype Object
*/
public enum Properties {
;
private static MapObject thisMapObject(ExecutionContext cx, Object obj) {
if (obj instanceof MapObject) {
return (MapObject) obj;
}
throw newTypeError(cx, Messages.Key.IncompatibleObject);
}
@Prototype
public static final Intrinsics __proto__ = Intrinsics.ObjectPrototype;
/**
* 23.1.3.2 Map.prototype.constructor
*/
@Value(name = "constructor")
public static final Intrinsics constructor = Intrinsics.Map;
/**
* 23.1.3.1 Map.prototype.clear ()
*
* @param cx
* the execution context
* @param thisValue
* the function this-value
* @return the undefined value
*/
@Function(name = "clear", arity = 0)
public static Object clear(ExecutionContext cx, Object thisValue) {
/* steps 1-3 */
MapObject m = thisMapObject(cx, thisValue);
/* step 4 */
LinkedMap<Object, Object> entries = m.getMapData();
/* step 5 */
entries.clear();
/* step 6 */
return UNDEFINED;
}
/**
* 23.1.3.3 Map.prototype.delete ( key )
*
* @param cx
* the execution context
* @param thisValue
* the function this-value
* @param key
* the key
* @return {@code true} if the entry was deleted
*/
@Function(name = "delete", arity = 1)
public static Object delete(ExecutionContext cx, Object thisValue, Object key) {
/* steps 1-3 */
MapObject m = thisMapObject(cx, thisValue);
/* step 4 */
LinkedMap<Object, Object> entries = m.getMapData();
/* steps 5-6 */
return entries.delete(key);
}
/**
* 23.1.3.4 Map.prototype.entries ( )<br>
* 23.1.3.12 Map.prototype[ @@iterator ] ( )
*
* @param cx
* the execution context
* @param thisValue
* the function this-value
* @return the entries iterator
*/
@Function(name = "entries", arity = 0, nativeId = MapPrototypeEntries.class)
@AliasFunction(name = "[Symbol.iterator]", symbol = BuiltinSymbol.iterator)
public static Object entries(ExecutionContext cx, Object thisValue) {
/* steps 1-2 */
return CreateMapIterator(cx, thisValue, MapIterationKind.KeyValue);
}
/**
* 23.1.3.5 Map.prototype.forEach ( callbackfn [ , thisArg ] )
*
* @param cx
* the execution context
* @param thisValue
* the function this-value
* @param callbackfn
* the callback function
* @param thisArg
* the optional this-argument
* @return the undefined value
*/
@Function(name = "forEach", arity = 1)
public static Object forEach(ExecutionContext cx, Object thisValue, Object callbackfn,
Object thisArg) {
/* steps 1-3 */
MapObject m = thisMapObject(cx, thisValue);
/* step 4 */
if (!IsCallable(callbackfn)) {
throw newTypeError(cx, Messages.Key.NotCallable);
}
Callable callback = (Callable) callbackfn;
/* step 5 (omitted) */
/* step 6 */
LinkedMap<Object, Object> entries = m.getMapData();
/* step 7 */
for (Entry<Object, Object> e : entries) {
callback.call(cx, thisArg, e.getValue(), e.getKey(), m);
}
/* step 8 */
return UNDEFINED;
}
/**
* 23.1.3.6 Map.prototype.get ( key )
*
* @param cx
* the execution context
* @param thisValue
* the function this-value
* @param key
* the key
* @return the mapped value or undefined
*/
@Function(name = "get", arity = 1)
public static Object get(ExecutionContext cx, Object thisValue, Object key) {
/* steps 1-3 */
MapObject m = thisMapObject(cx, thisValue);
/* step 4 */
LinkedMap<Object, Object> entries = m.getMapData();
/* steps 5-6 */
Object value = entries.get(key);
return value != null ? value : UNDEFINED;
}
/**
* 23.1.3.7 Map.prototype.has ( key )
*
* @param cx
* the execution context
* @param thisValue
* the function this-value
* @param key
* the key
* @return {@code true} if the entry was found
*/
@Function(name = "has", arity = 1)
public static Object has(ExecutionContext cx, Object thisValue, Object key) {
/* steps 1-3 */
MapObject m = thisMapObject(cx, thisValue);
/* step 4 */
LinkedMap<Object, Object> entries = m.getMapData();
/* steps 5-6 */
return entries.has(key);
}
/**
* 23.1.3.8 Map.prototype.keys ( )
*
* @param cx
* the execution context
* @param thisValue
* the function this-value
* @return the keys iterator
*/
@Function(name = "keys", arity = 0)
public static Object keys(ExecutionContext cx, Object thisValue) {
/* steps 1-2 */
return CreateMapIterator(cx, thisValue, MapIterationKind.Key);
}
/**
* 23.1.3.9 Map.prototype.set ( key , value )
*
* @param cx
* the execution context
* @param thisValue
* the function this-value
* @param key
* the key
* @param value
* the value
* @return this map object
*/
@Function(name = "set", arity = 2, nativeId = MapPrototypeSet.class)
public static Object set(ExecutionContext cx, Object thisValue, Object key, Object value) {
/* steps 1-3 */
MapObject m = thisMapObject(cx, thisValue);
/* step 4 */
LinkedMap<Object, Object> entries = m.getMapData();
/* steps 5-8 */
entries.set(key, value);
/* step 9 */
return m;
}
/**
* 23.1.3.10 get Map.prototype.size
*
* @param cx
* the execution context
* @param thisValue
* the function this-value
* @return the number of entries
*/
@Accessor(name = "size", type = Accessor.Type.Getter)
public static Object size(ExecutionContext cx, Object thisValue) {
/* steps 1-3 */
MapObject m = thisMapObject(cx, thisValue);
/* step 4 */
LinkedMap<Object, Object> entries = m.getMapData();
/* steps 5-7 */
return entries.size();
}
/**
* 23.1.3.11 Map.prototype.values ( )
*
* @param cx
* the execution context
* @param thisValue
* the function this-value
* @return the values iterator
*/
@Function(name = "values", arity = 0)
public static Object values(ExecutionContext cx, Object thisValue) {
/* steps 1-2 */
return CreateMapIterator(cx, thisValue, MapIterationKind.Value);
}
/**
* 23.1.3.13 Map.prototype[ @@toStringTag ]
*/
@Value(name = "[Symbol.toStringTag]", symbol = BuiltinSymbol.toStringTag,
attributes = @Attributes(writable = false, enumerable = false, configurable = true))
public static final String toStringTag = "Map";
}
}