/*
 *  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 "ConstructData.h"
#include "ErrorConstructor.h"
#include "ExceptionHelpers.h"
#include "FunctionPrototype.h"
#include "Interpreter.h"
#include "JSArray.h"
#include "JSCInlines.h"
#include "JSFunction.h"
#include "JSGlobalObject.h"
#include "JSObject.h"
#include "JSString.h"
#include "NativeErrorConstructor.h"
#include "SourceCode.h"
#include "StackFrame.h"
#include "SuperSampler.h"

namespace JSC {

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

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

JSObject* createRangeError(ExecState* exec, const String& message, ErrorInstance::SourceAppender appender)
{
    JSGlobalObject* globalObject = exec->lexicalGlobalObject();
    return createRangeError(exec, globalObject, message, appender);
}

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

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

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

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

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

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

JSObject* createError(ExecState* exec, ErrorType errorType, const String& message)
{
    switch (errorType) {
    case ErrorType::Error:
        return createError(exec, message);
    case ErrorType::EvalError:
        return createEvalError(exec, message);
    case ErrorType::RangeError:
        return createRangeError(exec, message);
    case ErrorType::ReferenceError:
        return createReferenceError(exec, message);
    case ErrorType::SyntaxError:
        return createSyntaxError(exec, message);
    case ErrorType::TypeError:
        return createTypeError(exec, message);
    case ErrorType::URIError:
        return createURIError(exec, message);
    }
    ASSERT_NOT_REACHED();
    return nullptr;
}

JSObject* createGetterTypeError(ExecState* exec, const String& message)
{
    ASSERT(!message.isEmpty());
    JSGlobalObject* globalObject = exec->lexicalGlobalObject();
    auto* error = ErrorInstance::create(exec, 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->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(ExecState* exec, 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 = std::make_unique<Vector<StackFrame>>();
    vm.interpreter->getStackTrace(obj, *stackTrace, framesToSkip, globalObject->stackTraceLimit().value());
    if (!stackTrace->isEmpty())
        ASSERT_UNUSED(exec, exec == vm.topCallFrame || exec->isGlobalExec());
    return stackTrace;
}

void getBytecodeOffset(ExecState* exec, VM& vm, Vector<StackFrame>* stackTrace, CallFrame*& callFrame, unsigned& bytecodeOffset)
{
    FindFirstCallerFrameWithCodeblockFunctor functor(exec);
    StackVisitor::visit(vm.topCallFrame, &vm, functor);
    callFrame = functor.foundCallFrame();
    unsigned stackIndex = functor.index();
    bytecodeOffset = 0;
    if (stackTrace && stackIndex < stackTrace->size() && stackTrace->at(stackIndex).hasBytecodeOffset())
        bytecodeOffset = stackTrace->at(stackIndex).bytecodeOffset();
}

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(ExecState* exec, JSObject* obj, bool useCurrentFrame)
{
    VM& vm = exec->vm();
    std::unique_ptr<Vector<StackFrame>> stackTrace = getStackTrace(exec, vm, obj, useCurrentFrame);
    addErrorInfo(vm, stackTrace.get(), obj);
}

JSObject* addErrorInfo(CallFrame* callFrame, JSObject* error, int line, const SourceCode& source)
{
    VM& vm = callFrame->vm();
    const String& sourceURL = source.provider()->url();
    
    // 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(ExecState* exec, ThrowScope& scope, const char* constructorName)
{
    return throwTypeError(exec, scope, makeString("calling ", constructorName, " constructor without new is invalid"));
}

Exception* throwTypeError(ExecState* exec, ThrowScope& scope)
{
    return throwException(exec, scope, createTypeError(exec));
}

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

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

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

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

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

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

JSObject* createError(ExecState* exec, const String& message)
{
    return createError(exec, message, nullptr);
}

JSObject* createEvalError(ExecState* exec, const String& message)
{
    return createEvalError(exec, message, nullptr);
}

JSObject* createRangeError(ExecState* exec, const String& message)
{
    return createRangeError(exec, message, nullptr);
}

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

JSObject* createReferenceError(ExecState* exec, const String& message)
{
    return createReferenceError(exec, message, nullptr);
}

JSObject* createSyntaxError(ExecState* exec, const String& message)
{
    return createSyntaxError(exec, message, nullptr);
}

JSObject* createTypeError(ExecState* exec)
{
    return createTypeError(exec, "Type error"_s);
}

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

JSObject* createNotEnoughArgumentsError(ExecState* exec)
{
    return createNotEnoughArgumentsError(exec, nullptr);
}

JSObject* createURIError(ExecState* exec, const String& message)
{
    return createURIError(exec, message, nullptr);
}

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

JSObject* createOutOfMemoryError(ExecState* exec, const String& message)
{
    
    auto* error = createError(exec, makeString("Out of memory: ", message), nullptr);
    jsCast<ErrorInstance*>(error)->setOutOfMemoryError();
    return error;
}

} // namespace JSC
