/**
 * Copyright (c) 2012-2013 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.internal;

import static com.github.anba.es6draft.runtime.AbstractOperations.Invoke;
import static com.github.anba.es6draft.runtime.internal.Errors.throwTypeError;
import static com.github.anba.es6draft.runtime.objects.iteration.IterationAbstractOperations.IteratorComplete;
import static com.github.anba.es6draft.runtime.objects.iteration.IterationAbstractOperations.IteratorValue;

import java.util.Iterator;

import com.github.anba.es6draft.runtime.ExecutionContext;
import com.github.anba.es6draft.runtime.Realm;
import com.github.anba.es6draft.runtime.internal.Messages;
import com.github.anba.es6draft.runtime.internal.SimpleIterator;
import com.github.anba.es6draft.runtime.types.Intrinsics;
import com.github.anba.es6draft.runtime.types.ScriptObject;
import com.github.anba.es6draft.runtime.types.Type;
import com.github.anba.es6draft.runtime.types.builtins.OrdinaryObject;

/**
 *
 */
public class ListIterator<T> extends OrdinaryObject {
    private Iterator<T> iterator;

    public ListIterator(Realm realm, Iterator<T> iterator) {
        super(realm);
        this.iterator = iterator;
    }

    public Iterator<T> getIterator() {
        return iterator;
    }

    public static <T> ListIterator<T> MakeListIterator(ExecutionContext cx, Iterator<T> iterator) {
        ListIterator<T> itr = new ListIterator<>(cx.getRealm(), iterator);
        itr.setPrototype(cx.getIntrinsic(Intrinsics.ListIteratorPrototype));
        itr.preventExtensions(cx);
        return itr;
    }

    public static Iterator<?> FromListIterator(ExecutionContext cx, ScriptObject obj) {
        if (obj instanceof ListIterator) {
            return ((ListIterator<?>) obj).iterator;
        }
        return new IteratorWrapper(cx, obj);
    }

    private static class IteratorWrapper extends SimpleIterator<Object> {
        private ExecutionContext cx;
        private ScriptObject object;

        IteratorWrapper(ExecutionContext cx, ScriptObject object) {
            this.cx = cx;
            this.object = object;
        }

        @Override
        protected Object tryNext() {
            Object nextResult = Invoke(cx, object, "next");
            if (!Type.isObject(nextResult)) {
                throw throwTypeError(cx, Messages.Key.NotObjectType);
            }
            ScriptObject next = Type.objectValue(nextResult);
            boolean done = IteratorComplete(cx, next);
            if (done) {
                return null;
            }
            return IteratorValue(cx, next);
        }
    }
}

@@ -278,112 +278,70 @@
 ime.
-AbstractOp
+objects.it
 eration
-s
 .I
-nvoke;%0Aimport static com.github.anba.es6draft.runtime.internal.Errors.throwTypeError
+terationAbstractOperations.IteratorComplete
 ;%0Aim
@@ -435,32 +435,28 @@
 ons.Iterator
-Complete
+Next
 ;%0Aimport sta
@@ -691,67 +691,8 @@
 lm;%0A
-import com.github.anba.es6draft.runtime.internal.Messages;%0A
 impo
@@ -810,16 +810,16 @@
 insics;%0A
+
 import c
@@ -874,60 +874,8 @@
 ct;%0A
-import com.github.anba.es6draft.runtime.types.Type;%0A
 impo
@@ -2152,16 +2152,22 @@
         
+Script
 Object n
@@ -2173,233 +2173,33 @@
 next
-Result = Invoke(cx, object, %22next%22);%0A            if (!Type.isObject(nextResult)) %7B%0A                throw throwTypeError(cx, Messages.Key.NotObjectType);%0A            %7D%0A            ScriptObject next = Type.objectValue(nextResul
+ = IteratorNext(cx, objec
 t);%0A

Use new iteration abstract operations to retrieve the next value of an iterator