Move ImageBuffer utilities function to separate files
[WebKit-https.git] / Source / JavaScriptCore / API / JSCallbackObject.h
1 /*
2  * Copyright (C) 2006-2019 Apple Inc. All rights reserved.
3  * Copyright (C) 2007 Eric Seidel <eric@webkit.org>
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
15  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
18  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
25  */
26
27 #ifndef JSCallbackObject_h
28 #define JSCallbackObject_h
29
30 #include "JSObjectRef.h"
31 #include "JSValueRef.h"
32 #include "JSObject.h"
33
34 namespace JSC {
35
36 struct JSCallbackObjectData {
37     WTF_MAKE_FAST_ALLOCATED;
38 public:
39     JSCallbackObjectData(void* privateData, JSClassRef jsClass)
40         : privateData(privateData)
41         , jsClass(jsClass)
42     {
43         JSClassRetain(jsClass);
44     }
45     
46     ~JSCallbackObjectData()
47     {
48         JSClassRelease(jsClass);
49     }
50     
51     JSValue getPrivateProperty(const Identifier& propertyName) const
52     {
53         if (!m_privateProperties)
54             return JSValue();
55         return m_privateProperties->getPrivateProperty(propertyName);
56     }
57     
58     void setPrivateProperty(VM& vm, JSCell* owner, const Identifier& propertyName, JSValue value)
59     {
60         if (!m_privateProperties)
61             m_privateProperties = makeUnique<JSPrivatePropertyMap>();
62         m_privateProperties->setPrivateProperty(vm, owner, propertyName, value);
63     }
64     
65     void deletePrivateProperty(const Identifier& propertyName)
66     {
67         if (!m_privateProperties)
68             return;
69         m_privateProperties->deletePrivateProperty(propertyName);
70     }
71
72     void visitChildren(SlotVisitor& visitor)
73     {
74         JSPrivatePropertyMap* properties = m_privateProperties.get();
75         if (!properties)
76             return;
77         properties->visitChildren(visitor);
78     }
79
80     void* privateData;
81     JSClassRef jsClass;
82     struct JSPrivatePropertyMap {
83         WTF_MAKE_FAST_ALLOCATED;
84     public:
85         JSValue getPrivateProperty(const Identifier& propertyName) const
86         {
87             PrivatePropertyMap::const_iterator location = m_propertyMap.find(propertyName.impl());
88             if (location == m_propertyMap.end())
89                 return JSValue();
90             return location->value.get();
91         }
92         
93         void setPrivateProperty(VM& vm, JSCell* owner, const Identifier& propertyName, JSValue value)
94         {
95             LockHolder locker(m_lock);
96             WriteBarrier<Unknown> empty;
97             m_propertyMap.add(propertyName.impl(), empty).iterator->value.set(vm, owner, value);
98         }
99         
100         void deletePrivateProperty(const Identifier& propertyName)
101         {
102             LockHolder locker(m_lock);
103             m_propertyMap.remove(propertyName.impl());
104         }
105
106         void visitChildren(SlotVisitor& visitor)
107         {
108             LockHolder locker(m_lock);
109             for (auto& pair : m_propertyMap) {
110                 if (pair.value)
111                     visitor.append(pair.value);
112             }
113         }
114
115     private:
116         typedef HashMap<RefPtr<UniquedStringImpl>, WriteBarrier<Unknown>, IdentifierRepHash> PrivatePropertyMap;
117         PrivatePropertyMap m_propertyMap;
118         Lock m_lock;
119     };
120     std::unique_ptr<JSPrivatePropertyMap> m_privateProperties;
121 };
122
123     
124 template <class Parent>
125 class JSCallbackObject final : public Parent {
126 protected:
127     JSCallbackObject(JSGlobalObject*, Structure*, JSClassRef, void* data);
128     JSCallbackObject(VM&, JSClassRef, Structure*);
129
130     void finishCreation(JSGlobalObject*);
131     void finishCreation(VM&);
132
133 public:
134     using Base = Parent;
135     static constexpr unsigned StructureFlags = Base::StructureFlags | ProhibitsPropertyCaching | OverridesGetOwnPropertySlot | InterceptsGetOwnPropertySlotByIndexEvenWhenLengthIsNotZero | ImplementsHasInstance | OverridesGetPropertyNames | OverridesGetCallData;
136     static_assert(!(StructureFlags & ImplementsDefaultHasInstance), "using customHasInstance");
137
138     ~JSCallbackObject();
139
140     static JSCallbackObject* create(JSGlobalObject* globalObject, Structure* structure, JSClassRef classRef, void* data)
141     {
142         VM& vm = getVM(globalObject);
143         ASSERT_UNUSED(globalObject, !structure->globalObject() || structure->globalObject() == globalObject);
144         JSCallbackObject* callbackObject = new (NotNull, allocateCell<JSCallbackObject>(vm.heap)) JSCallbackObject(globalObject, structure, classRef, data);
145         callbackObject->finishCreation(globalObject);
146         return callbackObject;
147     }
148     static JSCallbackObject<Parent>* create(VM&, JSClassRef, Structure*);
149
150     static const bool needsDestruction;
151     static void destroy(JSCell* cell)
152     {
153         static_cast<JSCallbackObject*>(cell)->JSCallbackObject::~JSCallbackObject();
154     }
155
156     template<typename CellType, SubspaceAccess mode>
157     static IsoSubspace* subspaceFor(VM& vm)
158     {
159         return subspaceForImpl(vm, mode);
160     }
161
162     void setPrivate(void* data);
163     void* getPrivate();
164
165     // FIXME: We should fix the warnings for extern-template in JSObject template classes: https://bugs.webkit.org/show_bug.cgi?id=161979
166     IGNORE_CLANG_WARNINGS_BEGIN("undefined-var-template")
167     DECLARE_INFO;
168     IGNORE_CLANG_WARNINGS_END
169
170     JSClassRef classRef() const { return m_callbackObjectData->jsClass; }
171     bool inherits(JSClassRef) const;
172
173     static Structure* createStructure(VM&, JSGlobalObject*, JSValue);
174     
175     JSValue getPrivateProperty(const Identifier& propertyName) const
176     {
177         return m_callbackObjectData->getPrivateProperty(propertyName);
178     }
179     
180     void setPrivateProperty(VM& vm, const Identifier& propertyName, JSValue value)
181     {
182         m_callbackObjectData->setPrivateProperty(vm, this, propertyName, value);
183     }
184     
185     void deletePrivateProperty(const Identifier& propertyName)
186     {
187         m_callbackObjectData->deletePrivateProperty(propertyName);
188     }
189
190     using Parent::methodTable;
191
192 private:
193     static IsoSubspace* subspaceForImpl(VM&, SubspaceAccess);
194     static String className(const JSObject*, VM&);
195     static String toStringName(const JSObject*, JSGlobalObject*);
196
197     static JSValue defaultValue(const JSObject*, JSGlobalObject*, PreferredPrimitiveType);
198
199     static bool getOwnPropertySlot(JSObject*, JSGlobalObject*, PropertyName, PropertySlot&);
200     static bool getOwnPropertySlotByIndex(JSObject*, JSGlobalObject*, unsigned propertyName, PropertySlot&);
201     
202     static bool put(JSCell*, JSGlobalObject*, PropertyName, JSValue, PutPropertySlot&);
203     static bool putByIndex(JSCell*, JSGlobalObject*, unsigned, JSValue, bool shouldThrow);
204
205     static bool deleteProperty(JSCell*, JSGlobalObject*, PropertyName);
206     static bool deletePropertyByIndex(JSCell*, JSGlobalObject*, unsigned);
207
208     static bool customHasInstance(JSObject*, JSGlobalObject*, JSValue);
209
210     static void getOwnNonIndexPropertyNames(JSObject*, JSGlobalObject*, PropertyNameArray&, EnumerationMode);
211
212     static ConstructType getConstructData(JSCell*, ConstructData&);
213     static CallType getCallData(JSCell*, CallData&);
214
215     static void visitChildren(JSCell* cell, SlotVisitor& visitor)
216     {
217         JSCallbackObject* thisObject = jsCast<JSCallbackObject*>(cell);
218         ASSERT_GC_OBJECT_INHERITS((static_cast<Parent*>(thisObject)), JSCallbackObject<Parent>::info());
219         Parent::visitChildren(thisObject, visitor);
220         thisObject->m_callbackObjectData->visitChildren(visitor);
221     }
222
223     void init(JSGlobalObject*);
224  
225     static JSCallbackObject* asCallbackObject(JSValue);
226     static JSCallbackObject* asCallbackObject(EncodedJSValue);
227  
228     static EncodedJSValue JSC_HOST_CALL call(JSGlobalObject*, CallFrame*);
229     static EncodedJSValue JSC_HOST_CALL construct(JSGlobalObject*, CallFrame*);
230    
231     JSValue getStaticValue(JSGlobalObject*, PropertyName);
232     static EncodedJSValue staticFunctionGetter(JSGlobalObject*, EncodedJSValue, PropertyName);
233     static EncodedJSValue callbackGetter(JSGlobalObject*, EncodedJSValue, PropertyName);
234
235     std::unique_ptr<JSCallbackObjectData> m_callbackObjectData;
236     const ClassInfo* m_classInfo { nullptr };
237 };
238
239 } // namespace JSC
240
241 // include the actual template class implementation
242 #include "JSCallbackObjectFunctions.h"
243
244 #endif // JSCallbackObject_h