/*
 *  Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
 *  Copyright (C) 2001 Peter Kelly (pmk@post.com)
 *  Copyright (C) 2003-2019 Apple Inc. All rights reserved.
 *  Copyright (C) 2007 Eric Seidel (eric@webkit.org)
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Library General Public
 *  License as published by the Free Software Foundation; either
 *  version 2 of the License, or (at your option) any later version.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Library General Public License for more details.
 *
 *  You should have received a copy of the GNU Library General Public License
 *  along with this library; see the file COPYING.LIB.  If not, write to
 *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 *  Boston, MA 02110-1301, USA.
 *
 */

#include "config.h"
#include "Error.h"

#include "Interpreter.h"
#include "JSCJSValueInlines.h"
#include "JSGlobalObject.h"
#include "SourceCode.h"
#include "StackFrame.h"

namespace JSC {

JSObject* createError(JSGlobalObject* globalObject, const String& message, ErrorInstance::SourceAppender appender)
{
    ASSERT(!message.isEmpty());
    return ErrorInstance::create(globalObject, globalObject->vm(), globalObject->errorStructure(), message, appender, TypeNothing, true);
}

JSObject* createEvalError(JSGlobalObject* globalObject, const String& message, ErrorInstance::SourceAppender appender)
{
    ASSERT(!message.isEmpty());
    return ErrorInstance::create(globalObject, globalObject->vm(), globalObject->errorStructure(ErrorType::EvalError), message, appender, TypeNothing, true);
}

JSObject* createRangeError(JSGlobalObject* globalObject, const String& message, ErrorInstance::SourceAppender appender)
{
    ASSERT(!message.isEmpty());
    return ErrorInstance::create(globalObject, globalObject->vm(), globalObject->errorStructure(ErrorType::RangeError), message, appender, TypeNothing, true);
}

JSObject* createReferenceError(JSGlobalObject* globalObject, const String& message, ErrorInstance::SourceAppender appender)
{
    ASSERT(!message.isEmpty());
    return ErrorInstance::create(globalObject, globalObject->vm(), globalObject->errorStructure(ErrorType::ReferenceError), message, appender, TypeNothing, true);
}

JSObject* createSyntaxError(JSGlobalObject* globalObject, const String& message, ErrorInstance::SourceAppender appender)
{
    ASSERT(!message.isEmpty());
    return ErrorInstance::create(globalObject, globalObject->vm(), globalObject->errorStructure(ErrorType::SyntaxError), message, appender, TypeNothing, true);
}

JSObject* createTypeError(JSGlobalObject* globalObject, const String& message, ErrorInstance::SourceAppender appender, RuntimeType type)
{
    ASSERT(!message.isEmpty());
    return ErrorInstance::create(globalObject, globalObject->vm(), globalObject->errorStructure(ErrorType::TypeError), message, appender, type, true);
}

JSObject* createNotEnoughArgumentsError(JSGlobalObject* globalObject, ErrorInstance::SourceAppender appender)
{
    return createTypeError(globalObject, "Not enough arguments"_s, appender, TypeNothing);
}

JSObject* createURIError(JSGlobalObject* globalObject, const String& message, ErrorInstance::SourceAppender appender)
{
    ASSERT(!message.isEmpty());
    return ErrorInstance::create(globalObject, globalObject->vm(), globalObject->errorStructure(ErrorType::URIError), message, appender, TypeNothing, true);
}

JSObject* createError(JSGlobalObject* globalObject, ErrorType errorType, const String& message)
{
    return createError(globalObject, static_cast<ErrorTypeWithExtension>(errorType), message);
}

JSObject* createError(JSGlobalObject* globalObject, ErrorTypeWithExtension errorType, const String& message)
{
    switch (errorType) {
    case ErrorTypeWithExtension::Error:
        return createError(globalObject, message);
    case ErrorTypeWithExtension::EvalError:
        return createEvalError(globalObject, message);
    case ErrorTypeWithExtension::RangeError:
        return createRangeError(globalObject, message);
    case ErrorTypeWithExtension::ReferenceError:
        return createReferenceError(globalObject, message);
    case ErrorTypeWithExtension::SyntaxError:
        return createSyntaxError(globalObject, message);
    case ErrorTypeWithExtension::TypeError:
        return createTypeError(globalObject, message);
    case ErrorTypeWithExtension::URIError:
        return createURIError(globalObject, message);
    case ErrorTypeWithExtension::AggregateError:
        break;
    case ErrorTypeWithExtension::OutOfMemoryError:
        return createOutOfMemoryError(globalObject, message);
    }
    ASSERT_NOT_REACHED();
    return nullptr;
}

JSObject* createGetterTypeError(JSGlobalObject* globalObject, const String& message)
{
    ASSERT(!message.isEmpty());
    auto* error = ErrorInstance::create(globalObject, globalObject->vm(), globalObject->errorStructure(ErrorType::TypeError), message);
    error->setNativeGetterTypeError();
    return error;
}

class FindFirstCallerFrameWithCodeblockFunctor {
public:
    FindFirstCallerFrameWithCodeblockFunctor(CallFrame* startCallFrame)
        : m_startCallFrame(startCallFrame)
        , m_foundCallFrame(nullptr)
        , m_foundStartCallFrame(false)
        , m_index(0)
    { }

    StackVisitor::Status operator()(StackVisitor& visitor) const
    {
        if (!m_foundStartCallFrame && (visitor->callFrame() == m_startCallFrame))
            m_foundStartCallFrame = true;

        if (m_foundStartCallFrame) {
            if (!visitor->isWasmFrame() && visitor->callFrame()->codeBlock()) {
                m_foundCallFrame = visitor->callFrame();
                return StackVisitor::Done;
            }
            m_index++;
        }

        return StackVisitor::Continue;
    }

    CallFrame* foundCallFrame() const { return m_foundCallFrame; }
    unsigned index() const { return m_index; }

private:
    CallFrame* m_startCallFrame;
    mutable CallFrame* m_foundCallFrame;
    mutable bool m_foundStartCallFrame;
    mutable unsigned m_index;
};

std::unique_ptr<Vector<StackFrame>> getStackTrace(JSGlobalObject*, VM& vm, JSObject* obj, bool useCurrentFrame)
{
    JSGlobalObject* globalObject = obj->globalObject(vm);
    if (!globalObject->stackTraceLimit())
        return nullptr;

    size_t framesToSkip = useCurrentFrame ? 0 : 1;
    std::unique_ptr<Vector<StackFrame>> stackTrace = makeUnique<Vector<StackFrame>>();
    vm.interpreter->getStackTrace(obj, *stackTrace, framesToSkip, globalObject->stackTraceLimit().value());
    return stackTrace;
}

void getBytecodeIndex(VM& vm, CallFrame* startCallFrame, Vector<StackFrame>* stackTrace, CallFrame*& callFrame, BytecodeIndex& bytecodeIndex)
{
    FindFirstCallerFrameWithCodeblockFunctor functor(startCallFrame);
    StackVisitor::visit(vm.topCallFrame, vm, functor);
    callFrame = functor.foundCallFrame();
    unsigned stackIndex = functor.index();
    bytecodeIndex = BytecodeIndex(0);
    if (stackTrace && stackIndex < stackTrace->size() && stackTrace->at(stackIndex).hasBytecodeIndex())
        bytecodeIndex = stackTrace->at(stackIndex).bytecodeIndex();
}

bool getLineColumnAndSource(Vector<StackFrame>* stackTrace, unsigned& line, unsigned& column, String& sourceURL)
{
    line = 0;
    column = 0;
    sourceURL = String();
    
    if (!stackTrace)
        return false;
    
    for (unsigned i = 0 ; i < stackTrace->size(); ++i) {
        StackFrame& frame = stackTrace->at(i);
        if (frame.hasLineAndColumnInfo()) {
            frame.computeLineAndColumn(line, column);
            sourceURL = frame.sourceURL();
            return true;
        }
    }
    
    return false;
}

bool addErrorInfo(VM& vm, Vector<StackFrame>* stackTrace, JSObject* obj)
{
    if (!stackTrace)
        return false;

    if (!stackTrace->isEmpty()) {
        unsigned line;
        unsigned column;
        String sourceURL;
        getLineColumnAndSource(stackTrace, line, column, sourceURL);
        obj->putDirect(vm, vm.propertyNames->line, jsNumber(line));
        obj->putDirect(vm, vm.propertyNames->column, jsNumber(column));
        if (!sourceURL.isEmpty())
            obj->putDirect(vm, vm.propertyNames->sourceURL, jsString(vm, sourceURL));

        obj->putDirect(vm, vm.propertyNames->stack, jsString(vm, Interpreter::stackTraceAsString(vm, *stackTrace)), static_cast<unsigned>(PropertyAttribute::DontEnum));

        return true;
    }

    obj->putDirect(vm, vm.propertyNames->stack, vm.smallStrings.emptyString(), static_cast<unsigned>(PropertyAttribute::DontEnum));
    return false;
}

void addErrorInfo(JSGlobalObject* globalObject, JSObject* obj, bool useCurrentFrame)
{
    VM& vm = globalObject->vm();
    std::unique_ptr<Vector<StackFrame>> stackTrace = getStackTrace(globalObject, vm, obj, useCurrentFrame);
    addErrorInfo(vm, stackTrace.get(), obj);
}

JSObject* addErrorInfo(VM& vm, JSObject* error, int line, const SourceCode& source)
{
    const String& sourceURL = source.provider()->url().string();
    
    // The putDirect() calls below should really be put() so that they trigger materialization of
    // the line/sourceURL properties. Otherwise, what we set here will just be overwritten later.
    // But calling put() would be bad because we'd rather not do effectful things here. Luckily, we
    // know that this will get called on some kind of error - so we can just directly ask the
    // ErrorInstance to materialize whatever it needs to. There's a chance that we get passed some
    // other kind of object, which also has materializable properties. But this code is heuristic-ey
    // enough that if we're wrong in such corner cases, it's not the end of the world.
    if (ErrorInstance* errorInstance = jsDynamicCast<ErrorInstance*>(vm, error))
        errorInstance->materializeErrorInfoIfNeeded(vm);
    
    // FIXME: This does not modify the column property, which confusingly continues to reflect
    // the column at which the exception was thrown.
    // https://bugs.webkit.org/show_bug.cgi?id=176673
    if (line != -1)
        error->putDirect(vm, vm.propertyNames->line, jsNumber(line));
    if (!sourceURL.isNull())
        error->putDirect(vm, vm.propertyNames->sourceURL, jsString(vm, sourceURL));
    return error;
}

Exception* throwConstructorCannotBeCalledAsFunctionTypeError(JSGlobalObject* globalObject, ThrowScope& scope, const char* constructorName)
{
    return throwTypeError(globalObject, scope, makeString("calling ", constructorName, " constructor without new is invalid"));
}

Exception* throwTypeError(JSGlobalObject* globalObject, ThrowScope& scope)
{
    return throwException(globalObject, scope, createTypeError(globalObject));
}

Exception* throwTypeError(JSGlobalObject* globalObject, ThrowScope& scope, ASCIILiteral errorMessage)
{
    return throwTypeError(globalObject, scope, String(errorMessage));
}

Exception* throwTypeError(JSGlobalObject* globalObject, ThrowScope& scope, const String& message)
{
    return throwException(globalObject, scope, createTypeError(globalObject, message));
}

Exception* throwSyntaxError(JSGlobalObject* globalObject, ThrowScope& scope)
{
    return throwException(globalObject, scope, createSyntaxError(globalObject, "Syntax error"_s));
}

Exception* throwSyntaxError(JSGlobalObject* globalObject, ThrowScope& scope, const String& message)
{
    return throwException(globalObject, scope, createSyntaxError(globalObject, message));
}

Exception* throwGetterTypeError(JSGlobalObject* globalObject, ThrowScope& scope, const String& message)
{
    return throwException(globalObject, scope, createGetterTypeError(globalObject, message));
}

JSValue throwDOMAttributeGetterTypeError(JSGlobalObject* globalObject, ThrowScope& scope, const ClassInfo* classInfo, PropertyName propertyName)
{
    return throwGetterTypeError(globalObject, scope, makeString("The ", classInfo->className, '.', String(propertyName.uid()), " getter can only be used on instances of ", classInfo->className));
}

JSObject* createError(JSGlobalObject* globalObject, const String& message)
{
    return createError(globalObject, message, nullptr);
}

JSObject* createEvalError(JSGlobalObject* globalObject, const String& message)
{
    return createEvalError(globalObject, message, nullptr);
}

JSObject* createRangeError(JSGlobalObject* globalObject, const String& message)
{
    return createRangeError(globalObject, message, nullptr);
}

JSObject* createReferenceError(JSGlobalObject* globalObject, const String& message)
{
    return createReferenceError(globalObject, message, nullptr);
}

JSObject* createSyntaxError(JSGlobalObject* globalObject, const String& message)
{
    return createSyntaxError(globalObject, message, nullptr);
}

JSObject* createTypeError(JSGlobalObject* globalObject)
{
    return createTypeError(globalObject, "Type error"_s);
}

JSObject* createTypeError(JSGlobalObject* globalObject, const String& message)
{
    return createTypeError(globalObject, message, nullptr, TypeNothing);
}

JSObject* createNotEnoughArgumentsError(JSGlobalObject* globalObject)
{
    return createNotEnoughArgumentsError(globalObject, nullptr);
}

JSObject* createURIError(JSGlobalObject* globalObject, const String& message)
{
    return createURIError(globalObject, message, nullptr);
}

JSObject* createOutOfMemoryError(JSGlobalObject* globalObject)
{
    auto* error = createRangeError(globalObject, "Out of memory"_s, nullptr);
    jsCast<ErrorInstance*>(error)->setOutOfMemoryError();
    return error;
}

JSObject* createOutOfMemoryError(JSGlobalObject* globalObject, const String& message)
{
    if (message.isEmpty())
        return createOutOfMemoryError(globalObject);
    auto* error = createRangeError(globalObject, makeString("Out of memory: ", message), nullptr);
    jsCast<ErrorInstance*>(error)->setOutOfMemoryError();
    return error;
}

} // namespace JSC
