f10478b06e60613b18afde1e7d902d97a1b07e3e
[WebKit-https.git] / Source / JavaScriptCore / runtime / GetterSetter.h
1 /*
2  *  Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
3  *  Copyright (C) 2001 Peter Kelly (pmk@post.com)
4  *  Copyright (C) 2003-2019 Apple Inc. All rights reserved.
5  *
6  *  This library is free software; you can redistribute it and/or
7  *  modify it under the terms of the GNU Library General Public
8  *  License as published by the Free Software Foundation; either
9  *  version 2 of the License, or (at your option) any later version.
10  *
11  *  This library is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  *  Library General Public License for more details.
15  *
16  *  You should have received a copy of the GNU Library General Public License
17  *  along with this library; see the file COPYING.LIB.  If not, write to
18  *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19  *  Boston, MA 02110-1301, USA.
20  *
21  */
22
23 #pragma once
24
25 #include "JSCast.h"
26
27 #include "CallFrame.h"
28 #include "JSGlobalObject.h"
29 #include "NullGetterFunction.h"
30 #include "NullSetterFunction.h"
31 #include "Structure.h"
32
33 namespace JSC {
34
35 class JSObject;
36
37 // This is an internal value object which stores getter and setter functions
38 // for a property. Instances of this class have the property that once a getter
39 // or setter is set to a non-null value, then they cannot be changed. This means
40 // that if a property holding a GetterSetter reference is constant-inferred and
41 // that constant is observed to have a non-null setter (or getter) then we can
42 // constant fold that setter (or getter).
43 class GetterSetter final : public JSNonFinalObject {
44     friend class JIT;
45     typedef JSNonFinalObject Base;
46 private:
47     GetterSetter(VM& vm, JSGlobalObject* globalObject, JSObject* getter, JSObject* setter)
48         : Base(vm, globalObject->getterSetterStructure())
49     {
50         WTF::storeStoreFence();
51         m_getter.set(vm, this, getter ? getter : globalObject->nullGetterFunction());
52         m_setter.set(vm, this, setter ? setter : globalObject->nullSetterFunction());
53     }
54
55 public:
56
57     static constexpr unsigned StructureFlags = Base::StructureFlags | OverridesGetOwnPropertySlot | StructureIsImmortal;
58
59     static GetterSetter* create(VM& vm, JSGlobalObject* globalObject, JSObject* getter, JSObject* setter)
60     {
61         GetterSetter* getterSetter = new (NotNull, allocateCell<GetterSetter>(vm.heap)) GetterSetter(vm, globalObject, getter, setter);
62         getterSetter->finishCreation(vm);
63         return getterSetter;
64     }
65
66     static GetterSetter* create(VM& vm, JSGlobalObject* globalObject, JSValue getter, JSValue setter)
67     {
68         ASSERT(getter.isUndefined() || getter.isObject());
69         ASSERT(setter.isUndefined() || setter.isObject());
70         JSObject* getterObject { nullptr };
71         JSObject* setterObject { nullptr };
72         if (getter.isObject())
73             getterObject = asObject(getter);
74         if (setter.isObject())
75             setterObject = asObject(setter);
76         return create(vm, globalObject, getterObject, setterObject);
77     }
78
79     static void visitChildren(JSCell*, SlotVisitor&);
80
81     JSObject* getter() const { return m_getter.get(); }
82
83     JSObject* getterConcurrently() const
84     {
85         JSObject* result = getter();
86         WTF::loadLoadFence();
87         return result;
88     }
89
90     bool isGetterNull() const { return !!jsDynamicCast<NullGetterFunction*>(m_getter.get()->vm(), m_getter.get()); }
91     bool isSetterNull() const { return !!jsDynamicCast<NullSetterFunction*>(m_setter.get()->vm(), m_setter.get()); }
92
93     JSObject* setter() const { return m_setter.get(); }
94
95     JSObject* setterConcurrently() const
96     {
97         JSObject* result = setter();
98         WTF::loadLoadFence();
99         return result;
100     }
101
102     static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
103     {
104         return Structure::create(vm, globalObject, prototype, TypeInfo(GetterSetterType), info());
105     }
106
107     static ptrdiff_t offsetOfGetter()
108     {
109         return OBJECT_OFFSETOF(GetterSetter, m_getter);
110     }
111
112     static ptrdiff_t offsetOfSetter()
113     {
114         return OBJECT_OFFSETOF(GetterSetter, m_setter);
115     }
116
117     DECLARE_EXPORT_INFO;
118
119     static bool getOwnPropertySlot(JSObject*, ExecState*, PropertyName, PropertySlot&) { RELEASE_ASSERT_NOT_REACHED(); return false; }
120     static bool put(JSCell*, ExecState*, PropertyName, JSValue, PutPropertySlot&) { RELEASE_ASSERT_NOT_REACHED(); return false; }
121     static bool putByIndex(JSCell*, ExecState*, unsigned, JSValue, bool) { RELEASE_ASSERT_NOT_REACHED(); return false; }
122     static bool setPrototype(JSObject*, ExecState*, JSValue, bool) { RELEASE_ASSERT_NOT_REACHED(); return false; }
123     static bool defineOwnProperty(JSObject*, ExecState*, PropertyName, const PropertyDescriptor&, bool) { RELEASE_ASSERT_NOT_REACHED(); return false; }
124     static bool deleteProperty(JSCell*, ExecState*, PropertyName) { RELEASE_ASSERT_NOT_REACHED(); return false; }
125
126 private:
127     WriteBarrier<JSObject> m_getter;
128     WriteBarrier<JSObject> m_setter;  
129 };
130
131 JSValue callGetter(ExecState*, JSValue base, JSValue getterSetter);
132 JS_EXPORT_PRIVATE bool callSetter(ExecState*, JSValue base, JSValue getterSetter, JSValue, ECMAMode);
133
134 } // namespace JSC