/*
 * Copyright (C) 2014 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 "JSJavaScriptCallFrame.h"

#if ENABLE(INSPECTOR)

#include "DebuggerScope.h"
#include "Error.h"
#include "JSCJSValue.h"
#include "JSCellInlines.h"
#include "JSJavaScriptCallFramePrototype.h"
#include "StructureInlines.h"

using namespace JSC;

namespace Inspector {

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

JSJavaScriptCallFrame::JSJavaScriptCallFrame(VM& vm, Structure* structure, PassRefPtr<JavaScriptCallFrame> impl)
    : JSDestructibleObject(vm, structure)
    , m_impl(impl.leakRef())
{
}

void JSJavaScriptCallFrame::finishCreation(VM& vm)
{
    Base::finishCreation(vm);
    ASSERT(inherits(info()));
}

JSObject* JSJavaScriptCallFrame::createPrototype(VM& vm, JSGlobalObject* globalObject)
{
    return JSJavaScriptCallFramePrototype::create(vm, globalObject, JSJavaScriptCallFramePrototype::createStructure(vm, globalObject, globalObject->objectPrototype()));
}

void JSJavaScriptCallFrame::destroy(JSC::JSCell* cell)
{
    JSJavaScriptCallFrame* thisObject = static_cast<JSJavaScriptCallFrame*>(cell);
    thisObject->JSJavaScriptCallFrame::~JSJavaScriptCallFrame();
}

void JSJavaScriptCallFrame::releaseImpl()
{
    if (m_impl) {
        m_impl->deref();
        m_impl = nullptr;
    }
}

JSJavaScriptCallFrame::~JSJavaScriptCallFrame()
{
    releaseImpl();
}

JSValue JSJavaScriptCallFrame::evaluate(ExecState* exec)
{
    JSValue exception;
    JSValue result = impl().evaluate(exec->argument(0).toString(exec)->value(exec), exception);
    if (exception)
        exec->vm().throwException(exec, exception);

    return result;
}

JSValue JSJavaScriptCallFrame::scopeType(ExecState* exec)
{
    if (!impl().scopeChain())
        return jsUndefined();

    if (!exec->argument(0).isInt32())
        return jsUndefined();
    int index = exec->argument(0).asInt32();

    DebuggerScope* scopeChain = impl().scopeChain();
    DebuggerScope::iterator end = scopeChain->end();

    bool foundLocalScope = false;
    for (DebuggerScope::iterator iter = scopeChain->begin(); iter != end; ++iter) {
        DebuggerScope* scope = iter.get();

        if (!foundLocalScope && scope->isFunctionOrEvalScope()) {
            // First function scope is the local scope, each successive one is a closure.
            if (!index)
                return jsNumber(JSJavaScriptCallFrame::LOCAL_SCOPE);
            foundLocalScope = true;
        }

        if (!index) {
            if (scope->isCatchScope())
                return jsNumber(JSJavaScriptCallFrame::CATCH_SCOPE);
            if (scope->isFunctionNameScope())
                return jsNumber(JSJavaScriptCallFrame::FUNCTION_NAME_SCOPE);
            if (scope->isWithScope())
                return jsNumber(JSJavaScriptCallFrame::WITH_SCOPE);
            if (scope->isGlobalScope()) {
                ASSERT(++iter == end);
                return jsNumber(JSJavaScriptCallFrame::GLOBAL_SCOPE);
            }
            ASSERT(scope->isFunctionOrEvalScope());
            return jsNumber(JSJavaScriptCallFrame::CLOSURE_SCOPE);
        }

        --index;
    }

    ASSERT_NOT_REACHED();
    return jsUndefined();
}

JSValue JSJavaScriptCallFrame::caller(ExecState* exec) const
{
    return toJS(exec, globalObject(), impl().caller());
}

JSValue JSJavaScriptCallFrame::sourceID(ExecState*) const
{
    return jsNumber(impl().sourceID());
}

JSValue JSJavaScriptCallFrame::line(ExecState*) const
{
    return jsNumber(impl().line());
}

JSValue JSJavaScriptCallFrame::column(ExecState*) const
{
    return jsNumber(impl().column());
}

JSValue JSJavaScriptCallFrame::functionName(ExecState* exec) const
{
    return jsString(exec, impl().functionName());
}

JSValue JSJavaScriptCallFrame::scopeChain(ExecState* exec) const
{
    if (!impl().scopeChain())
        return jsNull();

    DebuggerScope* scopeChain = impl().scopeChain();
    DebuggerScope::iterator iter = scopeChain->begin();
    DebuggerScope::iterator end = scopeChain->end();

    // We must always have something in the scope chain.
    ASSERT(iter != end);

    MarkedArgumentBuffer list;
    do {
        list.append(iter.get());
        ++iter;
    } while (iter != end);

    return constructArray(exec, nullptr, globalObject(), list);
}

JSValue JSJavaScriptCallFrame::thisObject(ExecState*) const
{
    return impl().thisValue();
}

JSValue JSJavaScriptCallFrame::type(ExecState* exec) const
{
    switch (impl().type()) {
    case DebuggerCallFrame::FunctionType:
        return jsNontrivialString(exec, ASCIILiteral("function"));
    case DebuggerCallFrame::ProgramType:
        return jsNontrivialString(exec, ASCIILiteral("program"));
    }

    ASSERT_NOT_REACHED();
    return jsNull();
}

JSValue toJS(ExecState* exec, JSGlobalObject* globalObject, JavaScriptCallFrame* impl)
{
    if (!impl)
        return jsNull();

    JSObject* prototype = JSJavaScriptCallFrame::createPrototype(exec->vm(), globalObject);
    Structure* structure = JSJavaScriptCallFrame::createStructure(exec->vm(), globalObject, prototype);
    JSJavaScriptCallFrame* javaScriptCallFrame = JSJavaScriptCallFrame::create(exec->vm(), structure, impl);

    return javaScriptCallFrame;
}

JSJavaScriptCallFrame* toJSJavaScriptCallFrame(JSValue value)
{
    return value.inherits(JSJavaScriptCallFrame::info()) ? jsCast<JSJavaScriptCallFrame*>(value) : nullptr;
}

} // namespace Inspector

#endif // ENABLE(INSPECTOR)
