/*
 * Copyright (C) 2018-2021 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. 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.
 */

#pragma once

#include "DOMWrapperWorld.h"
#include "JSDOMWrapper.h"
#include <JavaScriptCore/JSCJSValue.h>
#include <JavaScriptCore/SlotVisitor.h>
#include <JavaScriptCore/Weak.h>
#include <wtf/Variant.h>

namespace WebCore {

class JSValueInWrappedObject {
public:
    JSValueInWrappedObject(JSC::JSValue = { });
    JSValueInWrappedObject(const JSValueInWrappedObject&);
    operator JSC::JSValue() const;
    explicit operator bool() const;
    JSValueInWrappedObject& operator=(const JSValueInWrappedObject& other);
    template<typename Visitor> void visit(Visitor&) const;
    void clear();

private:
    // Use a weak pointer here so that if this code or client code has a visiting mistake,
    // we get null rather than a dangling pointer to a deleted object.
    using Weak = JSC::Weak<JSC::JSCell>;
    // FIXME: Would storing a separate JSValue alongside a Weak be better than using a Variant?
    using Value = std::variant<JSC::JSValue, Weak>;
    static Value makeValue(JSC::JSValue);
    Value m_value;
};

JSC::JSValue cachedPropertyValue(JSC::JSGlobalObject&, const JSDOMObject& owner, JSValueInWrappedObject& cacheSlot, const WTF::Function<JSC::JSValue()>&);

inline auto JSValueInWrappedObject::makeValue(JSC::JSValue value) -> Value
{
    if (!value.isCell())
        return value;
    // FIXME: This is not quite right. It is possible that this value is being
    // stored in a wrapped object that does not yet have a wrapper. If garbage
    // collection occurs before the wrapped object gets a wrapper, it's possible
    // the value object could be collected, and this will become null. A future
    // version of this class should prevent the value from being collected in
    // that case. Unclear if this can actually happen in practice.
    return Weak { value.asCell() };
}

inline JSValueInWrappedObject::JSValueInWrappedObject(JSC::JSValue value)
    : m_value(makeValue(JSC::JSValue(value)))
{
}

inline JSValueInWrappedObject::JSValueInWrappedObject(const JSValueInWrappedObject& value)
    : m_value(makeValue(value))
{
}

inline JSValueInWrappedObject::operator JSC::JSValue() const
{
    return WTF::switchOn(m_value, [] (JSC::JSValue value) {
        return value;
    }, [] (const Weak& value) -> JSC::JSValue {
        return value.get();
    });
}

inline JSValueInWrappedObject::operator bool() const
{
    return JSC::JSValue { *this }.operator bool();
}

inline JSValueInWrappedObject& JSValueInWrappedObject::operator=(const JSValueInWrappedObject& other)
{
    m_value = makeValue(JSC::JSValue(other));
    return *this;
}

template<typename Visitor>
inline void JSValueInWrappedObject::visit(Visitor& visitor) const
{
    return WTF::switchOn(m_value, [] (JSC::JSValue) {
        // Nothing to visit.
    }, [&visitor] (const Weak& value) {
        visitor.append(value);
    });
}

template void JSValueInWrappedObject::visit(JSC::AbstractSlotVisitor&) const;
template void JSValueInWrappedObject::visit(JSC::SlotVisitor&) const;

inline void JSValueInWrappedObject::clear()
{
    WTF::switchOn(m_value, [] (Weak& value) {
        value.clear();
    }, [] (auto&) { });
}

inline JSC::JSValue cachedPropertyValue(JSC::JSGlobalObject& lexicalGlobalObject, const JSDOMObject& owner, JSValueInWrappedObject& cachedValue, const WTF::Function<JSC::JSValue()>& function)
{
    if (cachedValue && isWorldCompatible(lexicalGlobalObject, cachedValue))
        return cachedValue;
    auto value = function();
    cachedValue = cloneAcrossWorlds(lexicalGlobalObject, owner, value);
    lexicalGlobalObject.vm().heap.writeBarrier(&owner, value);
    ASSERT(isWorldCompatible(lexicalGlobalObject, cachedValue));
    return cachedValue;
}

} // namespace WebCore
