1/*
2 * Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
3 * Copyright (C) 2003-2006, 2008-2009, 2013, 2016 Apple Inc. All rights reserved.
4 * Copyright (C) 2007 Samuel Weinig <sam@webkit.org>
5 * Copyright (C) 2009 Google, Inc. All rights reserved.
6 * Copyright (C) 2012 Ericsson AB. All rights reserved.
7 * Copyright (C) 2013 Michael Pruett <michael@68k.org>
8 *
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2 of the License, or (at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 */
23
24#pragma once
25
26#include "JSDOMCastedThisErrorBehavior.h"
27#include "JSDOMExceptionHandling.h"
28
29namespace WebCore {
30
31template<typename JSClass>
32class IDLAttribute {
33public:
34 using Setter = bool(JSC::ExecState&, JSClass&, JSC::JSValue, JSC::ThrowScope&);
35 using StaticSetter = bool(JSC::ExecState&, JSC::JSValue, JSC::ThrowScope&);
36 using Getter = JSC::JSValue(JSC::ExecState&, JSClass&, JSC::ThrowScope&);
37 using StaticGetter = JSC::JSValue(JSC::ExecState&, JSC::ThrowScope&);
38
39 static JSClass* cast(JSC::ExecState&, JSC::EncodedJSValue);
40
41 template<Setter setter, CastedThisErrorBehavior shouldThrow = CastedThisErrorBehavior::Throw>
42 static bool set(JSC::ExecState& state, JSC::EncodedJSValue thisValue, JSC::EncodedJSValue encodedValue, const char* attributeName)
43 {
44 auto throwScope = DECLARE_THROW_SCOPE(state.vm());
45
46 auto* thisObject = cast(state, thisValue);
47 if (UNLIKELY(!thisObject))
48 return (shouldThrow == CastedThisErrorBehavior::Throw) ? throwSetterTypeError(state, throwScope, JSClass::info()->className, attributeName) : false;
49
50 return setter(state, *thisObject, JSC::JSValue::decode(encodedValue), throwScope);
51 }
52
53 template<StaticSetter setter, CastedThisErrorBehavior shouldThrow = CastedThisErrorBehavior::Throw>
54 static bool setStatic(JSC::ExecState& state, JSC::EncodedJSValue, JSC::EncodedJSValue encodedValue, const char*)
55 {
56 auto throwScope = DECLARE_THROW_SCOPE(state.vm());
57
58 return setter(state, JSC::JSValue::decode(encodedValue), throwScope);
59 }
60
61 template<Getter getter, CastedThisErrorBehavior shouldThrow = CastedThisErrorBehavior::Throw>
62 static JSC::EncodedJSValue get(JSC::ExecState& state, JSC::EncodedJSValue thisValue, const char* attributeName)
63 {
64 auto throwScope = DECLARE_THROW_SCOPE(state.vm());
65
66 if (shouldThrow == CastedThisErrorBehavior::Assert) {
67 ASSERT(cast(state, thisValue));
68 auto* thisObject = JSC::jsCast<JSClass*>(JSC::JSValue::decode(thisValue));
69 return JSC::JSValue::encode(getter(state, *thisObject, throwScope));
70 }
71
72 auto* thisObject = cast(state, thisValue);
73 if (UNLIKELY(!thisObject)) {
74 if (shouldThrow == CastedThisErrorBehavior::Throw)
75 return throwGetterTypeError(state, throwScope, JSClass::info()->className, attributeName);
76 if (shouldThrow == CastedThisErrorBehavior::RejectPromise)
77 return rejectPromiseWithGetterTypeError(state, JSClass::info()->className, attributeName);
78 return JSC::JSValue::encode(JSC::jsUndefined());
79 }
80
81 return JSC::JSValue::encode(getter(state, *thisObject, throwScope));
82 }
83
84 template<StaticGetter getter, CastedThisErrorBehavior shouldThrow = CastedThisErrorBehavior::Throw>
85 static JSC::EncodedJSValue getStatic(JSC::ExecState& state, JSC::EncodedJSValue, const char*)
86 {
87 auto throwScope = DECLARE_THROW_SCOPE(state.vm());
88
89 return JSC::JSValue::encode(getter(state, throwScope));
90 }
91};
92
93struct AttributeSetter {
94 template<typename Functor>
95 static auto call(JSC::ExecState&, JSC::ThrowScope&, Functor&& functor) -> std::enable_if_t<std::is_same<void, decltype(functor())>::value>
96 {
97 functor();
98 }
99
100 template<typename Functor>
101 static auto call(JSC::ExecState& state, JSC::ThrowScope& throwScope, Functor&& functor) -> std::enable_if_t<!std::is_same<void, decltype(functor())>::value>
102 {
103 auto result = functor();
104 if (!result.hasException())
105 return;
106 propagateException(state, throwScope, result.releaseException());
107 }
108};
109
110} // namespace WebCore
111