Refactor static getter function prototype to include thisValue in addition to the...
[WebKit-https.git] / Source / JavaScriptCore / API / JSCallbackObject.h
1 /*
2  * Copyright (C) 2006, 2007, 2008, 2010 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 COMPUTER, 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 COMPUTER, 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 #include <wtf/PassOwnPtr.h>
34
35 namespace JSC {
36
37 struct JSCallbackObjectData : WeakHandleOwner {
38     JSCallbackObjectData(void* privateData, JSClassRef jsClass)
39         : privateData(privateData)
40         , jsClass(jsClass)
41     {
42         JSClassRetain(jsClass);
43     }
44     
45     virtual ~JSCallbackObjectData()
46     {
47         JSClassRelease(jsClass);
48     }
49     
50     JSValue getPrivateProperty(const Identifier& propertyName) const
51     {
52         if (!m_privateProperties)
53             return JSValue();
54         return m_privateProperties->getPrivateProperty(propertyName);
55     }
56     
57     void setPrivateProperty(VM& vm, JSCell* owner, const Identifier& propertyName, JSValue value)
58     {
59         if (!m_privateProperties)
60             m_privateProperties = adoptPtr(new JSPrivatePropertyMap);
61         m_privateProperties->setPrivateProperty(vm, owner, propertyName, value);
62     }
63     
64     void deletePrivateProperty(const Identifier& propertyName)
65     {
66         if (!m_privateProperties)
67             return;
68         m_privateProperties->deletePrivateProperty(propertyName);
69     }
70
71     void visitChildren(SlotVisitor& visitor)
72     {
73         if (!m_privateProperties)
74             return;
75         m_privateProperties->visitChildren(visitor);
76     }
77
78     void* privateData;
79     JSClassRef jsClass;
80     struct JSPrivatePropertyMap {
81         JSValue getPrivateProperty(const Identifier& propertyName) const
82         {
83             PrivatePropertyMap::const_iterator location = m_propertyMap.find(propertyName.impl());
84             if (location == m_propertyMap.end())
85                 return JSValue();
86             return location->value.get();
87         }
88         
89         void setPrivateProperty(VM& vm, JSCell* owner, const Identifier& propertyName, JSValue value)
90         {
91             WriteBarrier<Unknown> empty;
92             m_propertyMap.add(propertyName.impl(), empty).iterator->value.set(vm, owner, value);
93         }
94         
95         void deletePrivateProperty(const Identifier& propertyName)
96         {
97             m_propertyMap.remove(propertyName.impl());
98         }
99
100         void visitChildren(SlotVisitor& visitor)
101         {
102             for (PrivatePropertyMap::iterator ptr = m_propertyMap.begin(); ptr != m_propertyMap.end(); ++ptr) {
103                 if (ptr->value)
104                     visitor.append(&ptr->value);
105             }
106         }
107
108     private:
109         typedef HashMap<RefPtr<StringImpl>, WriteBarrier<Unknown>, IdentifierRepHash> PrivatePropertyMap;
110         PrivatePropertyMap m_propertyMap;
111     };
112     OwnPtr<JSPrivatePropertyMap> m_privateProperties;
113     virtual void finalize(Handle<Unknown>, void*) OVERRIDE;
114 };
115
116     
117 template <class Parent>
118 class JSCallbackObject : public Parent {
119 protected:
120     JSCallbackObject(ExecState*, Structure*, JSClassRef, void* data);
121     JSCallbackObject(VM&, JSClassRef, Structure*);
122
123     void finishCreation(ExecState*);
124     void finishCreation(VM&);
125
126 public:
127     typedef Parent Base;
128
129     static JSCallbackObject* create(ExecState* exec, JSGlobalObject* globalObject, Structure* structure, JSClassRef classRef, void* data)
130     {
131         ASSERT_UNUSED(globalObject, !structure->globalObject() || structure->globalObject() == globalObject);
132         JSCallbackObject* callbackObject = new (NotNull, allocateCell<JSCallbackObject>(*exec->heap())) JSCallbackObject(exec, structure, classRef, data);
133         callbackObject->finishCreation(exec);
134         return callbackObject;
135     }
136     static JSCallbackObject<Parent>* create(VM&, JSClassRef, Structure*);
137
138     static const bool needsDestruction;
139     static void destroy(JSCell* cell)
140     {
141         static_cast<JSCallbackObject*>(cell)->JSCallbackObject::~JSCallbackObject();
142     }
143
144     void setPrivate(void* data);
145     void* getPrivate();
146
147     DECLARE_INFO;
148
149     JSClassRef classRef() const { return m_callbackObjectData->jsClass; }
150     bool inherits(JSClassRef) const;
151
152     static Structure* createStructure(VM&, JSGlobalObject*, JSValue);
153     
154     JSValue getPrivateProperty(const Identifier& propertyName) const
155     {
156         return m_callbackObjectData->getPrivateProperty(propertyName);
157     }
158     
159     void setPrivateProperty(VM& vm, const Identifier& propertyName, JSValue value)
160     {
161         m_callbackObjectData->setPrivateProperty(vm, this, propertyName, value);
162     }
163     
164     void deletePrivateProperty(const Identifier& propertyName)
165     {
166         m_callbackObjectData->deletePrivateProperty(propertyName);
167     }
168
169     using Parent::methodTable;
170
171 protected:
172     static const unsigned StructureFlags = ProhibitsPropertyCaching | OverridesGetOwnPropertySlot | InterceptsGetOwnPropertySlotByIndexEvenWhenLengthIsNotZero | ImplementsHasInstance | OverridesHasInstance | OverridesVisitChildren | OverridesGetPropertyNames | Parent::StructureFlags;
173
174 private:
175     static String className(const JSObject*);
176
177     static JSValue defaultValue(const JSObject*, ExecState*, PreferredPrimitiveType);
178
179     static bool getOwnPropertySlot(JSObject*, ExecState*, PropertyName, PropertySlot&);
180     static bool getOwnPropertySlotByIndex(JSObject*, ExecState*, unsigned propertyName, PropertySlot&);
181     
182     static void put(JSCell*, ExecState*, PropertyName, JSValue, PutPropertySlot&);
183     static void putByIndex(JSCell*, ExecState*, unsigned, JSValue, bool shouldThrow);
184
185     static bool deleteProperty(JSCell*, ExecState*, PropertyName);
186     static bool deletePropertyByIndex(JSCell*, ExecState*, unsigned);
187
188     static bool customHasInstance(JSObject*, ExecState*, JSValue);
189
190     static void getOwnNonIndexPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode);
191
192     static ConstructType getConstructData(JSCell*, ConstructData&);
193     static CallType getCallData(JSCell*, CallData&);
194
195     static void visitChildren(JSCell* cell, SlotVisitor& visitor)
196     {
197         JSCallbackObject* thisObject = jsCast<JSCallbackObject*>(cell);
198         ASSERT_GC_OBJECT_INHERITS((static_cast<Parent*>(thisObject)), JSCallbackObject<Parent>::info());
199         COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
200         ASSERT(thisObject->Parent::structure()->typeInfo().overridesVisitChildren());
201         Parent::visitChildren(thisObject, visitor);
202         thisObject->m_callbackObjectData->visitChildren(visitor);
203     }
204
205     void init(ExecState*);
206  
207     static JSCallbackObject* asCallbackObject(JSValue);
208     static JSCallbackObject* asCallbackObject(EncodedJSValue);
209  
210     static EncodedJSValue JSC_HOST_CALL call(ExecState*);
211     static EncodedJSValue JSC_HOST_CALL construct(ExecState*);
212    
213     JSValue getStaticValue(ExecState*, PropertyName);
214     static EncodedJSValue staticFunctionGetter(ExecState*, EncodedJSValue, EncodedJSValue, PropertyName);
215     static EncodedJSValue callbackGetter(ExecState*, EncodedJSValue, EncodedJSValue, PropertyName);
216
217     OwnPtr<JSCallbackObjectData> m_callbackObjectData;
218 };
219
220 } // namespace JSC
221
222 // include the actual template class implementation
223 #include "JSCallbackObjectFunctions.h"
224
225 #endif // JSCallbackObject_h