/*
 * Copyright (C) 2018 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 = { });
    operator JSC::JSValue() const;
    explicit operator bool() const;
    void visit(JSC::SlotVisitor&) const;

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 = Variant<JSC::JSValue, Weak>;
    static Value makeValue(JSC::JSValue);
    Value m_value;
};

JSC::JSValue cachedPropertyValue(JSC::ExecState&, 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(value))
{
}

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

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

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

inline JSC::JSValue cachedPropertyValue(JSC::ExecState& state, const JSDOMObject& owner, JSValueInWrappedObject& cachedValue, const WTF::Function<JSC::JSValue()>& function)
{
    if (cachedValue && isWorldCompatible(state, cachedValue))
        return cachedValue;
    cachedValue = cloneAcrossWorlds(state, owner, function());
    ASSERT(isWorldCompatible(state, cachedValue));
    return cachedValue;
}

} // namespace WebCore
