#pragma once
#include "JSDOMCastedThisErrorBehavior.h"
#include "JSDOMExceptionHandling.h"
namespace WebCore {
template<typename JSClass>
class IDLAttribute {
public:
using Setter = bool(JSC::ExecState&, JSClass&, JSC::JSValue, JSC::ThrowScope&);
using StaticSetter = bool(JSC::ExecState&, JSC::JSValue, JSC::ThrowScope&);
using Getter = JSC::JSValue(JSC::ExecState&, JSClass&, JSC::ThrowScope&);
using StaticGetter = JSC::JSValue(JSC::ExecState&, JSC::ThrowScope&);
static JSClass* cast(JSC::ExecState&, JSC::EncodedJSValue);
template<Setter setter, CastedThisErrorBehavior shouldThrow = CastedThisErrorBehavior::Throw>
static bool set(JSC::ExecState& state, JSC::EncodedJSValue thisValue, JSC::EncodedJSValue encodedValue, const char* attributeName)
{
auto throwScope = DECLARE_THROW_SCOPE(state.vm());
auto* thisObject = cast(state, thisValue);
if (UNLIKELY(!thisObject))
return (shouldThrow == CastedThisErrorBehavior::Throw) ? throwSetterTypeError(state, throwScope, JSClass::info()->className, attributeName) : false;
return setter(state, *thisObject, JSC::JSValue::decode(encodedValue), throwScope);
}
template<StaticSetter setter, CastedThisErrorBehavior shouldThrow = CastedThisErrorBehavior::Throw>
static bool setStatic(JSC::ExecState& state, JSC::EncodedJSValue, JSC::EncodedJSValue encodedValue, const char*)
{
auto throwScope = DECLARE_THROW_SCOPE(state.vm());
return setter(state, JSC::JSValue::decode(encodedValue), throwScope);
}
template<Getter getter, CastedThisErrorBehavior shouldThrow = CastedThisErrorBehavior::Throw>
static JSC::EncodedJSValue get(JSC::ExecState& state, JSC::EncodedJSValue thisValue, const char* attributeName)
{
auto throwScope = DECLARE_THROW_SCOPE(state.vm());
if (shouldThrow == CastedThisErrorBehavior::Assert) {
ASSERT(cast(state, thisValue));
auto* thisObject = JSC::jsCast<JSClass*>(JSC::JSValue::decode(thisValue));
return JSC::JSValue::encode(getter(state, *thisObject, throwScope));
}
auto* thisObject = cast(state, thisValue);
if (UNLIKELY(!thisObject)) {
if (shouldThrow == CastedThisErrorBehavior::Throw)
return throwGetterTypeError(state, throwScope, JSClass::info()->className, attributeName);
if (shouldThrow == CastedThisErrorBehavior::RejectPromise)
return rejectPromiseWithGetterTypeError(state, JSClass::info()->className, attributeName);
return JSC::JSValue::encode(JSC::jsUndefined());
}
return JSC::JSValue::encode(getter(state, *thisObject, throwScope));
}
template<StaticGetter getter, CastedThisErrorBehavior shouldThrow = CastedThisErrorBehavior::Throw>
static JSC::EncodedJSValue getStatic(JSC::ExecState& state, JSC::EncodedJSValue, const char*)
{
auto throwScope = DECLARE_THROW_SCOPE(state.vm());
return JSC::JSValue::encode(getter(state, throwScope));
}
};
struct AttributeSetter {
template<typename Functor>
static auto call(JSC::ExecState&, JSC::ThrowScope&, Functor&& functor) -> std::enable_if_t<std::is_same<void, decltype(functor())>::value>
{
functor();
}
template<typename Functor>
static auto call(JSC::ExecState& state, JSC::ThrowScope& throwScope, Functor&& functor) -> std::enable_if_t<!std::is_same<void, decltype(functor())>::value>
{
auto result = functor();
if (!result.hasException())
return;
propagateException(state, throwScope, result.releaseException());
}
};
}