/*
 * Copyright (C) 2012, 2016 Apple Inc. All rights reserved.
 * Copyright (C) 2015-2016 Yusuke Suzuki <utatane.tea@gmail.com>.
 *
 * 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. AND ITS CONTRIBUTORS ``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 ITS 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 "Symbol.h"

#include "Error.h"
#include "JSCInlines.h"
#include "SymbolObject.h"

namespace JSC {

const ClassInfo Symbol::s_info = { "symbol", nullptr, nullptr, nullptr, CREATE_METHOD_TABLE(Symbol) };

Symbol::Symbol(VM& vm)
    : Base(vm, vm.symbolStructure.get())
    , m_privateName()
{
}

Symbol::Symbol(VM& vm, const String& string)
    : Base(vm, vm.symbolStructure.get())
    , m_privateName(PrivateName::Description, string)
{
}

Symbol::Symbol(VM& vm, SymbolImpl& uid)
    : Base(vm, vm.symbolStructure.get())
    , m_privateName(uid)
{
}

void Symbol::finishCreation(VM& vm)
{
    Base::finishCreation(vm);
    ASSERT(inherits(vm, info()));

    vm.symbolImplToSymbolMap.set(&m_privateName.uid(), this);
}

inline SymbolObject* SymbolObject::create(VM& vm, JSGlobalObject* globalObject, Symbol* symbol)
{
    SymbolObject* object = new (NotNull, allocateCell<SymbolObject>(vm.heap)) SymbolObject(vm, globalObject->symbolObjectStructure());
    object->finishCreation(vm, symbol);
    return object;
}

JSValue Symbol::toPrimitive(JSGlobalObject*, PreferredPrimitiveType) const
{
    return const_cast<Symbol*>(this);
}

bool Symbol::getPrimitiveNumber(JSGlobalObject* globalObject, double& number, JSValue& result) const
{
    result = this;
    number = toNumber(globalObject);
    return true;
}

JSObject* Symbol::toObject(JSGlobalObject* globalObject) const
{
    return SymbolObject::create(globalObject->vm(), globalObject, const_cast<Symbol*>(this));
}

double Symbol::toNumber(JSGlobalObject* globalObject) const
{
    VM& vm = globalObject->vm();
    auto scope = DECLARE_THROW_SCOPE(vm);
    throwTypeError(globalObject, scope, "Cannot convert a symbol to a number"_s);
    return 0.0;
}

void Symbol::destroy(JSCell* cell)
{
    static_cast<Symbol*>(cell)->Symbol::~Symbol();
}

String Symbol::descriptiveString() const
{
    return makeString("Symbol(", String(m_privateName.uid()), ')');
}

String Symbol::description() const
{
    auto& uid = m_privateName.uid();
    return uid.isNullSymbol() ? String() : uid;
}

Symbol* Symbol::create(VM& vm)
{
    Symbol* symbol = new (NotNull, allocateCell<Symbol>(vm.heap)) Symbol(vm);
    symbol->finishCreation(vm);
    return symbol;
}

Symbol* Symbol::createWithDescription(VM& vm, const String& description)
{
    Symbol* symbol = new (NotNull, allocateCell<Symbol>(vm.heap)) Symbol(vm, description);
    symbol->finishCreation(vm);
    return symbol;
}

Symbol* Symbol::create(VM& vm, SymbolImpl& uid)
{
    if (Symbol* symbol = vm.symbolImplToSymbolMap.get(&uid))
        return symbol;

    Symbol* symbol = new (NotNull, allocateCell<Symbol>(vm.heap)) Symbol(vm, uid);
    symbol->finishCreation(vm);
    return symbol;
}

} // namespace JSC
