/*
 * Copyright (C) 2013 Apple, Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
 */

#include "config.h"
#include "JSArrayIterator.h"

#include "JSCJSValueInlines.h"
#include "JSCellInlines.h"
#include "SlotVisitorInlines.h"

namespace JSC {

const ClassInfo JSArrayIterator::s_info = { "ArrayIterator", &Base::s_info, 0, 0, CREATE_METHOD_TABLE(JSArrayIterator) };

static EncodedJSValue JSC_HOST_CALL arrayIteratorNextKey(ExecState*);
static EncodedJSValue JSC_HOST_CALL arrayIteratorNextValue(ExecState*);
static EncodedJSValue JSC_HOST_CALL arrayIteratorNextGeneric(ExecState*);

void JSArrayIterator::finishCreation(VM& vm, JSGlobalObject* globalObject, ArrayIterationKind kind, JSObject* iteratedObject)
{
    Base::finishCreation(vm);
    ASSERT(inherits(info()));
    m_iterationKind = kind;
    m_iteratedObject.set(vm, this, iteratedObject);
    switch (kind) {
    case ArrayIterateKey:
        JSC_NATIVE_INTRINSIC_FUNCTION(vm.propertyNames->iteratorNextPrivateName, arrayIteratorNextKey, DontEnum, 0, ArrayIteratorNextKeyIntrinsic);
        break;
    case ArrayIterateValue:
        JSC_NATIVE_INTRINSIC_FUNCTION(vm.propertyNames->iteratorNextPrivateName, arrayIteratorNextValue, DontEnum, 0, ArrayIteratorNextValueIntrinsic);
        break;
    default:
        JSC_NATIVE_INTRINSIC_FUNCTION(vm.propertyNames->iteratorNextPrivateName, arrayIteratorNextGeneric, DontEnum, 0, ArrayIteratorNextGenericIntrinsic);
        break;
    }

}
    
    
void JSArrayIterator::visitChildren(JSCell* cell, SlotVisitor& visitor)
{
    JSArrayIterator* thisObject = jsCast<JSArrayIterator*>(cell);
    ASSERT_GC_OBJECT_INHERITS(thisObject, info());
    COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
    ASSERT(thisObject->structure()->typeInfo().overridesVisitChildren());
        
    Base::visitChildren(thisObject, visitor);
    visitor.append(&thisObject->m_iteratedObject);

}

static EncodedJSValue createIteratorResult(CallFrame* callFrame, ArrayIterationKind kind, size_t index, JSValue result, bool done)
{
    callFrame->setArgument(callFrame->argumentCount() - 1, jsBoolean(done));
    if (done)
        return JSValue::encode(callFrame->vm().iterationTerminator.get());
    
    switch (kind & ~ArrayIterateSparseTag) {
    case ArrayIterateKey:
        return JSValue::encode(jsNumber(index));
        
    case ArrayIterateValue:
        return JSValue::encode(result);
        
    case ArrayIterateKeyValue: {
        MarkedArgumentBuffer args;
        args.append(jsNumber(index));
        args.append(result);
        JSGlobalObject* globalObject = callFrame->callee()->globalObject();
        return JSValue::encode(constructArray(callFrame, 0, globalObject, args));
        
    }
    default:
        RELEASE_ASSERT_NOT_REACHED();
    }
    return JSValue::encode(JSValue());
}

static inline EncodedJSValue JSC_HOST_CALL arrayIteratorNext(CallFrame* callFrame)
{
    JSArrayIterator* iterator = jsDynamicCast<JSArrayIterator*>(callFrame->thisValue());
    if (!iterator)
        throwTypeError(callFrame, ASCIILiteral("Cannot call ArrayIterator.next() on a non-ArrayIterator object"));
    JSObject* iteratedObject = iterator->iteratedObject();
    size_t index = iterator->nextIndex();
    ArrayIterationKind kind = iterator->iterationKind();
    JSValue jsLength = JSValue(iteratedObject).get(callFrame, callFrame->propertyNames().length);
    if (callFrame->hadException())
        return JSValue::encode(jsNull());
    
    size_t length = jsLength.toUInt32(callFrame);
    if (callFrame->hadException())
        return JSValue::encode(jsNull());
    
    if (index >= length) {
        iterator->finish();
        return createIteratorResult(callFrame, kind, index, jsUndefined(), true);
    }
    if (JSValue result = iteratedObject->tryGetIndexQuickly(index)) {
        iterator->setNextIndex(index + 1);
        return createIteratorResult(callFrame, kind, index, result, false);
    }
    
    JSValue result = jsUndefined();
    PropertySlot slot(iteratedObject);
    if (kind > ArrayIterateSparseTag) {
        // We assume that the indexed property will be an own property so cache the getOwnProperty
        // method locally
        auto getOwnPropertySlotByIndex = iteratedObject->methodTable()->getOwnPropertySlotByIndex;
        while (index < length) {
            if (getOwnPropertySlotByIndex(iteratedObject, callFrame, index, slot)) {
                result = slot.getValue(callFrame, index);
                break;
            }
            if (iteratedObject->getPropertySlot(callFrame, index, slot)) {
                result = slot.getValue(callFrame, index);
                break;
            }
            index++;
        }
    } else if (iteratedObject->getPropertySlot(callFrame, index, slot))
        result = slot.getValue(callFrame, index);
    
    if (index == length)
        iterator->finish();
    else
        iterator->setNextIndex(index + 1);
    return createIteratorResult(callFrame, kind, index, jsUndefined(), index == length);
}
    
EncodedJSValue JSC_HOST_CALL arrayIteratorNextKey(CallFrame* callFrame)
{
    return arrayIteratorNext(callFrame);
}
    
EncodedJSValue JSC_HOST_CALL arrayIteratorNextValue(CallFrame* callFrame)
{
    return arrayIteratorNext(callFrame);
}
    
EncodedJSValue JSC_HOST_CALL arrayIteratorNextGeneric(CallFrame* callFrame)
{
    return arrayIteratorNext(callFrame);
}

}
