/**
* 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;
import static com.github.anba.es6draft.runtime.AbstractOperations.CreateArrayFromList;
import static com.github.anba.es6draft.runtime.AbstractOperations.CreateIterResultObject;
import static com.github.anba.es6draft.runtime.AbstractOperations.Get;
import static com.github.anba.es6draft.runtime.AbstractOperations.ToLength;
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.types.Undefined.UNDEFINED;
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.Messages;
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.ArrayIteratorObject.ArrayIterationKind;
import com.github.anba.es6draft.runtime.objects.binary.TypedArrayObject;
import com.github.anba.es6draft.runtime.types.BuiltinSymbol;
import com.github.anba.es6draft.runtime.types.Intrinsics;
import com.github.anba.es6draft.runtime.types.ScriptObject;
import com.github.anba.es6draft.runtime.types.builtins.NativeFunction;
import com.github.anba.es6draft.runtime.types.builtins.OrdinaryObject;
/**
* <h1>22 Indexed Collections</h1><br>
* <h2>22.1 Array Objects</h2>
* <ul>
* <li>22.1.5 Array Iterator Objects
* </ul>
*/
public final class ArrayIteratorPrototype extends OrdinaryObject implements Initializable {
/**
* Constructs a new Array Iterator prototype object.
*
* @param realm
* the realm object
*/
public ArrayIteratorPrototype(Realm realm) {
super(realm);
}
@Override
public void initialize(Realm realm) {
createProperties(realm, this, Properties.class);
}
/**
* 22.1.5.1 CreateArrayIterator Abstract Operation
*
* @param cx
* the execution context
* @param array
* the array-like object
* @param kind
* the array iteration kind
* @return the new array iterator
*/
public static OrdinaryObject CreateArrayIterator(ExecutionContext cx, ScriptObject array, ArrayIterationKind kind) {
/* step 1 (not applicable) */
/* steps 2-6 */
return new ArrayIteratorObject(cx.getRealm(), array, kind, cx.getIntrinsic(Intrinsics.ArrayIteratorPrototype));
}
/**
* 22.1.5.1 CreateArrayIterator Abstract Operation
*
* @param cx
* the execution context
* @param array
* the array-like object
* @param index
* the start index
* @param kind
* the array iteration kind
* @return the new array iterator
*/
public static OrdinaryObject CreateArrayIterator(ExecutionContext cx, ScriptObject array, long index,
ArrayIterationKind kind) {
/* step 1 (not applicable) */
/* steps 2-6 */
return new ArrayIteratorObject(cx.getRealm(), array, index, kind,
cx.getIntrinsic(Intrinsics.ArrayIteratorPrototype));
}
/**
* Marker class for {@code %ArrayIteratorPrototype%.next}.
*/
private static final class ArrayIteratorPrototypeNext {
}
/**
* Returns {@code true} if <var>next</var> is the built-in {@code %ArrayIteratorPrototype%.next} function for the
* requested realm.
*
* @param realm
* the function realm
* @param next
* the next function
* @return {@code true} if <var>next</var> is the built-in {@code %ArrayIteratorPrototype%.next} function
*/
public static boolean isBuiltinNext(Realm realm, Object next) {
return NativeFunction.isNative(realm, next, ArrayIteratorPrototypeNext.class);
}
/**
* 22.1.5.2 The %ArrayIteratorPrototype% Object
*/
public enum Properties {
;
@Prototype
public static final Intrinsics __proto__ = Intrinsics.IteratorPrototype;
/**
* 22.1.5.2.1 %ArrayIteratorPrototype%.next( )
*
* @param cx
* the execution context
* @param thisValue
* the function this-value
* @return the next iterator result object
*/
@Function(name = "next", arity = 0, nativeId = ArrayIteratorPrototypeNext.class)
public static Object next(ExecutionContext cx, Object thisValue) {
/* steps 1-3 */
if (!(thisValue instanceof ArrayIteratorObject)) {
throw newTypeError(cx, Messages.Key.IncompatibleObject);
}
ArrayIteratorObject iter = (ArrayIteratorObject) thisValue;
/* step 4 */
ScriptObject array = iter.getIteratedObject();
/* step 5 */
if (array == null) {
return CreateIterResultObject(cx, UNDEFINED, true);
}
/* step 6 */
long index = iter.getNextIndex();
/* step 7 */
ArrayIterationKind itemKind = iter.getIterationKind();
/* steps 8-9 */
long len;
if (array instanceof TypedArrayObject) {
len = ((TypedArrayObject) array).getArrayLength();
} else {
len = ToLength(cx, Get(cx, array, "length"));
}
/* step 10 */
if (index >= len) {
iter.setIteratedObject(null);
return CreateIterResultObject(cx, UNDEFINED, true);
}
/* step 11 */
iter.setNextIndex(index + 1);
/* steps 12-17 */
Object result;
if (itemKind == ArrayIterationKind.Key) {
/* step 12 */
result = index;
} else {
/* step 13 */
long elementKey = index;
/* steps 14-15 */
Object elementValue = Get(cx, array, elementKey);
if (itemKind == ArrayIterationKind.Value) {
/* step 16 */
result = elementValue;
} else {
/* step 17 */
assert itemKind == ArrayIterationKind.KeyValue;
result = CreateArrayFromList(cx, index, elementValue);
}
}
/* steps 12, 18 */
return CreateIterResultObject(cx, result, false);
}
/**
* 22.1.5.2.2 %ArrayIteratorPrototype% [ @@toStringTag ]
*/
@Value(name = "[Symbol.toStringTag]", symbol = BuiltinSymbol.toStringTag,
attributes = @Attributes(writable = false, enumerable = false, configurable = true))
public static final String toStringTag = "Array Iterator";
}
}