/**
* 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.SetIteratorPrototype.CreateSetIterator;
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.SetIteratorObject.SetIterationKind;
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.2 Set Objects</h2>
* <ul>
* <li>23.2.3 Properties of the Set Prototype Object
* </ul>
*/
public final class SetPrototype extends OrdinaryObject implements Initializable {
/**
* Constructs a new Set prototype object.
*
* @param realm
* the realm object
*/
public SetPrototype(Realm realm) {
super(realm);
}
@Override
public void initialize(Realm realm) {
createProperties(realm, this, Properties.class);
}
/**
* Marker class for {@code Set.prototype.add}.
*/
private static final class SetPrototypeAdd {
}
/**
* Returns {@code true} if <var>add</var> is the built-in {@code Set.prototype.add} function.
*
* @param add
* the add function
* @return {@code true} if <var>add</var> is the built-in {@code Set.prototype.add} function
*/
static boolean isBuiltinAdd(Object add) {
return NativeFunction.isNative(add, SetPrototypeAdd.class);
}
/**
* Marker class for {@code Set.prototype.values}.
*/
private static final class SetPrototypeValues {
}
/**
* Returns {@code true} if <var>values</var> is the built-in {@code Set.prototype.values} function for the requested
* realm.
*
* @param realm
* the function realm
* @param values
* the values function
* @return {@code true} if <var>values</var> is the built-in {@code Set.prototype.values} function
*/
public static boolean isBuiltinValues(Realm realm, Object values) {
return NativeFunction.isNative(realm, values, SetPrototypeValues.class);
}
/**
* 23.2.3 Properties of the Set Prototype Object
*/
public enum Properties {
;
private static SetObject thisSetObject(ExecutionContext cx, Object obj) {
if (obj instanceof SetObject) {
return (SetObject) obj;
}
throw newTypeError(cx, Messages.Key.IncompatibleObject);
}
@Prototype
public static final Intrinsics __proto__ = Intrinsics.ObjectPrototype;
/**
* 23.2.3.3 Set.prototype.constructor
*/
@Value(name = "constructor")
public static final Intrinsics constructor = Intrinsics.Set;
/**
* 23.2.3.1 Set.prototype.add (value )
*
* @param cx
* the execution context
* @param thisValue
* the function this-value
* @param value
* the new value
* @return this set object
*/
@Function(name = "add", arity = 1, nativeId = SetPrototypeAdd.class)
public static Object add(ExecutionContext cx, Object thisValue, Object value) {
/* steps 1-3 */
SetObject s = thisSetObject(cx, thisValue);
/* step 4 */
LinkedMap<Object, Void> entries = s.getSetData();
/* steps 5-7 */
entries.set(value, null);
/* step 8 */
return s;
}
/**
* 23.2.3.2 Set.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 */
SetObject s = thisSetObject(cx, thisValue);
/* step 4 */
LinkedMap<Object, Void> entries = s.getSetData();
/* step 5 */
entries.clear();
/* step 6 */
return UNDEFINED;
}
/**
* 23.2.3.4 Set.prototype.delete ( value )
*
* @param cx
* the execution context
* @param thisValue
* the function this-value
* @param value
* the value
* @return {@code true} if the entry was deleted
*/
@Function(name = "delete", arity = 1)
public static Object delete(ExecutionContext cx, Object thisValue, Object value) {
/* steps 1-3 */
SetObject s = thisSetObject(cx, thisValue);
/* step 4 */
LinkedMap<Object, Void> entries = s.getSetData();
/* steps 5-6 */
return entries.delete(value);
}
/**
* 23.2.3.5 Set.prototype.entries ( )
*
* @param cx
* the execution context
* @param thisValue
* the function this-value
* @return the entries iterator
*/
@Function(name = "entries", arity = 0)
public static Object entries(ExecutionContext cx, Object thisValue) {
/* steps 1-2 */
return CreateSetIterator(cx, thisValue, SetIterationKind.KeyValue);
}
/**
* 23.2.3.6 Set.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 */
SetObject s = thisSetObject(cx, thisValue);
/* step 4 */
if (!IsCallable(callbackfn)) {
throw newTypeError(cx, Messages.Key.NotCallable);
}
Callable callback = (Callable) callbackfn;
/* step 5 (omitted) */
/* step 6 */
LinkedMap<Object, Void> entries = s.getSetData();
/* step 7 */
for (Entry<Object, Void> e : entries) {
callback.call(cx, thisArg, e.getKey(), e.getKey(), s);
}
/* step 8 */
return UNDEFINED;
}
/**
* 23.2.3.7 Set.prototype.has ( value )
*
* @param cx
* the execution context
* @param thisValue
* the function this-value
* @param value
* the value
* @return {@code true} if the entry was found
*/
@Function(name = "has", arity = 1)
public static Object has(ExecutionContext cx, Object thisValue, Object value) {
/* steps 1-3 */
SetObject s = thisSetObject(cx, thisValue);
/* step 4 */
LinkedMap<Object, Void> entries = s.getSetData();
/* steps 5-6 */
return entries.has(value);
}
/**
* 23.2.3.9 get Set.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 */
SetObject s = thisSetObject(cx, thisValue);
/* step 4 */
LinkedMap<Object, Void> entries = s.getSetData();
/* steps 5-7 */
return entries.size();
}
/**
* 23.2.3.8 Set.prototype.keys ( )<br>
* 23.2.3.10 Set.prototype.values ( )<br>
* 23.2.3.11 Set.prototype[ @@iterator ] ( )
*
* @param cx
* the execution context
* @param thisValue
* the function this-value
* @return the values iterator
*/
@Function(name = "values", arity = 0, nativeId = SetPrototypeValues.class)
@AliasFunction(name = "keys")
@AliasFunction(name = "[Symbol.iterator]", symbol = BuiltinSymbol.iterator)
public static Object values(ExecutionContext cx, Object thisValue) {
/* steps 1-2 */
return CreateSetIterator(cx, thisValue, SetIterationKind.Value);
}
/**
* 23.2.3.12 Set.prototype[ @@toStringTag ]
*/
@Value(name = "[Symbol.toStringTag]", symbol = BuiltinSymbol.toStringTag,
attributes = @Attributes(writable = false, enumerable = false, configurable = true))
public static final String toStringTag = "Set";
}
}