1 /*
2  * Copyright (C) 2006 Apple Computer, Inc.  All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25 
26 #ifndef JSClassRef_h
27 #define JSClassRef_h
28 
29 #include "JSObjectRef.h"
30 
31 #include <runtime/JSObject.h>
32 #include <runtime/Protect.h>
33 #include <runtime/UString.h>
34 #include <runtime/WeakGCPtr.h>
35 #include <wtf/HashMap.h>
36 #include <wtf/RefCounted.h>
37 
38 struct StaticValueEntry : FastAllocBase {
StaticValueEntryStaticValueEntry39     StaticValueEntry(JSObjectGetPropertyCallback _getProperty, JSObjectSetPropertyCallback _setProperty, JSPropertyAttributes _attributes)
40         : getProperty(_getProperty), setProperty(_setProperty), attributes(_attributes)
41     {
42     }
43 
44     JSObjectGetPropertyCallback getProperty;
45     JSObjectSetPropertyCallback setProperty;
46     JSPropertyAttributes attributes;
47 };
48 
49 struct StaticFunctionEntry : FastAllocBase {
StaticFunctionEntryStaticFunctionEntry50     StaticFunctionEntry(JSObjectCallAsFunctionCallback _callAsFunction, JSPropertyAttributes _attributes)
51         : callAsFunction(_callAsFunction), attributes(_attributes)
52     {
53     }
54 
55     JSObjectCallAsFunctionCallback callAsFunction;
56     JSPropertyAttributes attributes;
57 };
58 
59 typedef HashMap<RefPtr<JSC::UString::Rep>, StaticValueEntry*> OpaqueJSClassStaticValuesTable;
60 typedef HashMap<RefPtr<JSC::UString::Rep>, StaticFunctionEntry*> OpaqueJSClassStaticFunctionsTable;
61 
62 struct OpaqueJSClass;
63 
64 // An OpaqueJSClass (JSClass) is created without a context, so it can be used with any context, even across context groups.
65 // This structure holds data members that vary across context groups.
66 struct OpaqueJSClassContextData : Noncopyable {
67     OpaqueJSClassContextData(OpaqueJSClass*);
68     ~OpaqueJSClassContextData();
69 
70     // It is necessary to keep OpaqueJSClass alive because of the following rare scenario:
71     // 1. A class is created and used, so its context data is stored in JSGlobalData hash map.
72     // 2. The class is released, and when all JS objects that use it are collected, OpaqueJSClass
73     // is deleted (that's the part prevented by this RefPtr).
74     // 3. Another class is created at the same address.
75     // 4. When it is used, the old context data is found in JSGlobalData and used.
76     RefPtr<OpaqueJSClass> m_class;
77 
78     OpaqueJSClassStaticValuesTable* staticValues;
79     OpaqueJSClassStaticFunctionsTable* staticFunctions;
80     JSC::WeakGCPtr<JSC::JSObject> cachedPrototype;
81 };
82 
83 struct OpaqueJSClass : public ThreadSafeShared<OpaqueJSClass> {
84     static PassRefPtr<OpaqueJSClass> create(const JSClassDefinition*);
85     static PassRefPtr<OpaqueJSClass> createNoAutomaticPrototype(const JSClassDefinition*);
86     ~OpaqueJSClass();
87 
88     JSC::UString className();
89     OpaqueJSClassStaticValuesTable* staticValues(JSC::ExecState*);
90     OpaqueJSClassStaticFunctionsTable* staticFunctions(JSC::ExecState*);
91     JSC::JSObject* prototype(JSC::ExecState*);
92 
93     OpaqueJSClass* parentClass;
94     OpaqueJSClass* prototypeClass;
95 
96     JSObjectInitializeCallback initialize;
97     JSObjectFinalizeCallback finalize;
98     JSObjectHasPropertyCallback hasProperty;
99     JSObjectGetPropertyCallback getProperty;
100     JSObjectSetPropertyCallback setProperty;
101     JSObjectDeletePropertyCallback deleteProperty;
102     JSObjectGetPropertyNamesCallback getPropertyNames;
103     JSObjectCallAsFunctionCallback callAsFunction;
104     JSObjectCallAsConstructorCallback callAsConstructor;
105     JSObjectHasInstanceCallback hasInstance;
106     JSObjectConvertToTypeCallback convertToType;
107 
108 private:
109     friend struct OpaqueJSClassContextData;
110 
111     OpaqueJSClass();
112     OpaqueJSClass(const OpaqueJSClass&);
113     OpaqueJSClass(const JSClassDefinition*, OpaqueJSClass* protoClass);
114 
115     OpaqueJSClassContextData& contextData(JSC::ExecState*);
116 
117     // UStrings in these data members should not be put into any IdentifierTable.
118     JSC::UString m_className;
119     OpaqueJSClassStaticValuesTable* m_staticValues;
120     OpaqueJSClassStaticFunctionsTable* m_staticFunctions;
121 };
122 
123 #endif // JSClassRef_h
124