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 "ConstructData.h"
26#include "JSCast.h"
27#include <wtf/PtrTag.h>
28
29namespace WTF {
30class PrintStream;
31};
32
33namespace JSC {
34
35class HeapAnalyzer;
36class JSArrayBufferView;
37class Snippet;
38struct HashTable;
39
40#define METHOD_TABLE_ENTRY(method) \
41 WTF_VTBL_FUNCPTR_PTRAUTH_STR("MethodTable." #method) method
42
43struct MethodTable {
44 using DestroyFunctionPtr = void (*)(JSCell*);
45 DestroyFunctionPtr METHOD_TABLE_ENTRY(destroy);
46
47 using VisitChildrenFunctionPtr = void (*)(JSCell*, SlotVisitor&);
48 VisitChildrenFunctionPtr METHOD_TABLE_ENTRY(visitChildren);
49
50 using GetCallDataFunctionPtr = CallType (*)(JSCell*, CallData&);
51 GetCallDataFunctionPtr METHOD_TABLE_ENTRY(getCallData);
52
53 using GetConstructDataFunctionPtr = ConstructType (*)(JSCell*, ConstructData&);
54 GetConstructDataFunctionPtr METHOD_TABLE_ENTRY(getConstructData);
55
56 using PutFunctionPtr = bool (*)(JSCell*, JSGlobalObject*, PropertyName propertyName, JSValue, PutPropertySlot&);
57 PutFunctionPtr METHOD_TABLE_ENTRY(put);
58
59 using PutByIndexFunctionPtr = bool (*)(JSCell*, JSGlobalObject*, unsigned propertyName, JSValue, bool shouldThrow);
60 PutByIndexFunctionPtr METHOD_TABLE_ENTRY(putByIndex);
61
62 using DeletePropertyFunctionPtr = bool (*)(JSCell*, JSGlobalObject*, PropertyName);
63 DeletePropertyFunctionPtr METHOD_TABLE_ENTRY(deleteProperty);
64
65 using DeletePropertyByIndexFunctionPtr = bool (*)(JSCell*, JSGlobalObject*, unsigned);
66 DeletePropertyByIndexFunctionPtr METHOD_TABLE_ENTRY(deletePropertyByIndex);
67
68 using GetOwnPropertySlotFunctionPtr = bool (*)(JSObject*, JSGlobalObject*, PropertyName, PropertySlot&);
69 GetOwnPropertySlotFunctionPtr METHOD_TABLE_ENTRY(getOwnPropertySlot);
70
71 using GetOwnPropertySlotByIndexFunctionPtr = bool (*)(JSObject*, JSGlobalObject*, unsigned, PropertySlot&);
72 GetOwnPropertySlotByIndexFunctionPtr METHOD_TABLE_ENTRY(getOwnPropertySlotByIndex);
73
74 using DoPutPropertySecurityCheckFunctionPtr = void (*)(JSObject*, JSGlobalObject*, PropertyName, PutPropertySlot&);
75 DoPutPropertySecurityCheckFunctionPtr METHOD_TABLE_ENTRY(doPutPropertySecurityCheck);
76
77 using ToThisFunctionPtr = JSValue (*)(JSCell*, JSGlobalObject*, ECMAMode);
78 ToThisFunctionPtr METHOD_TABLE_ENTRY(toThis);
79
80 using DefaultValueFunctionPtr = JSValue (*)(const JSObject*, JSGlobalObject*, PreferredPrimitiveType);
81 DefaultValueFunctionPtr METHOD_TABLE_ENTRY(defaultValue);
82
83 using GetOwnPropertyNamesFunctionPtr = void (*)(JSObject*, JSGlobalObject*, PropertyNameArray&, EnumerationMode);
84 GetOwnPropertyNamesFunctionPtr METHOD_TABLE_ENTRY(getOwnPropertyNames);
85
86 using GetOwnNonIndexPropertyNamesFunctionPtr = void (*)(JSObject*, JSGlobalObject*, PropertyNameArray&, EnumerationMode);
87 GetOwnNonIndexPropertyNamesFunctionPtr METHOD_TABLE_ENTRY(getOwnNonIndexPropertyNames);
88
89 using GetPropertyNamesFunctionPtr = void (*)(JSObject*, JSGlobalObject*, PropertyNameArray&, EnumerationMode);
90 GetPropertyNamesFunctionPtr METHOD_TABLE_ENTRY(getPropertyNames);
91
92 using GetEnumerableLengthFunctionPtr = uint32_t (*)(JSGlobalObject*, JSObject*);
93 GetEnumerableLengthFunctionPtr METHOD_TABLE_ENTRY(getEnumerableLength);
94
95 GetPropertyNamesFunctionPtr METHOD_TABLE_ENTRY(getStructurePropertyNames);
96 GetPropertyNamesFunctionPtr METHOD_TABLE_ENTRY(getGenericPropertyNames);
97
98 using ClassNameFunctionPtr = String (*)(const JSObject*, VM&);
99 ClassNameFunctionPtr METHOD_TABLE_ENTRY(className);
100
101 using ToStringNameFunctionPtr = String (*)(const JSObject*, JSGlobalObject*);
102 ToStringNameFunctionPtr METHOD_TABLE_ENTRY(toStringName);
103
104 using CustomHasInstanceFunctionPtr = bool (*)(JSObject*, JSGlobalObject*, JSValue);
105 CustomHasInstanceFunctionPtr METHOD_TABLE_ENTRY(customHasInstance);
106
107 using DefineOwnPropertyFunctionPtr = bool (*)(JSObject*, JSGlobalObject*, PropertyName, const PropertyDescriptor&, bool);
108 DefineOwnPropertyFunctionPtr METHOD_TABLE_ENTRY(defineOwnProperty);
109
110 using PreventExtensionsFunctionPtr = bool (*)(JSObject*, JSGlobalObject*);
111 PreventExtensionsFunctionPtr METHOD_TABLE_ENTRY(preventExtensions);
112
113 using IsExtensibleFunctionPtr = bool (*)(JSObject*, JSGlobalObject*);
114 IsExtensibleFunctionPtr METHOD_TABLE_ENTRY(isExtensible);
115
116 using SetPrototypeFunctionPtr = bool (*)(JSObject*, JSGlobalObject*, JSValue, bool shouldThrowIfCantSet);
117 SetPrototypeFunctionPtr METHOD_TABLE_ENTRY(setPrototype);
118
119 using GetPrototypeFunctionPtr = JSValue (*)(JSObject*, JSGlobalObject*);
120 GetPrototypeFunctionPtr METHOD_TABLE_ENTRY(getPrototype);
121
122 using DumpToStreamFunctionPtr = void (*)(const JSCell*, PrintStream&);
123 DumpToStreamFunctionPtr METHOD_TABLE_ENTRY(dumpToStream);
124
125 using AnalyzeHeapFunctionPtr = void (*)(JSCell*, HeapAnalyzer&);
126 AnalyzeHeapFunctionPtr METHOD_TABLE_ENTRY(analyzeHeap);
127
128 using EstimatedSizeFunctionPtr = size_t (*)(JSCell*, VM&);
129 EstimatedSizeFunctionPtr METHOD_TABLE_ENTRY(estimatedSize);
130
131 using VisitOutputConstraintsPtr = void (*)(JSCell*, SlotVisitor&);
132 VisitOutputConstraintsPtr METHOD_TABLE_ENTRY(visitOutputConstraints);
133};
134
135#define CREATE_MEMBER_CHECKER(member) \
136 template <typename T> \
137 struct MemberCheck##member { \
138 struct Fallback { \
139 void member(...); \
140 }; \
141 struct Derived : T, Fallback { }; \
142 template <typename U, U> struct Check; \
143 typedef char Yes[2]; \
144 typedef char No[1]; \
145 template <typename U> \
146 static No &func(Check<void (Fallback::*)(...), &U::member>*); \
147 template <typename U> \
148 static Yes &func(...); \
149 enum { has = sizeof(func<Derived>(0)) == sizeof(Yes) }; \
150 }
151
152#define HAS_MEMBER_NAMED(klass, name) (MemberCheck##name<klass>::has)
153
154#define CREATE_METHOD_TABLE(ClassName) { \
155 &ClassName::destroy, \
156 &ClassName::visitChildren, \
157 &ClassName::getCallData, \
158 &ClassName::getConstructData, \
159 &ClassName::put, \
160 &ClassName::putByIndex, \
161 &ClassName::deleteProperty, \
162 &ClassName::deletePropertyByIndex, \
163 &ClassName::getOwnPropertySlot, \
164 &ClassName::getOwnPropertySlotByIndex, \
165 &ClassName::doPutPropertySecurityCheck, \
166 &ClassName::toThis, \
167 &ClassName::defaultValue, \
168 &ClassName::getOwnPropertyNames, \
169 &ClassName::getOwnNonIndexPropertyNames, \
170 &ClassName::getPropertyNames, \
171 &ClassName::getEnumerableLength, \
172 &ClassName::getStructurePropertyNames, \
173 &ClassName::getGenericPropertyNames, \
174 &ClassName::className, \
175 &ClassName::toStringName, \
176 &ClassName::customHasInstance, \
177 &ClassName::defineOwnProperty, \
178 &ClassName::preventExtensions, \
179 &ClassName::isExtensible, \
180 &ClassName::setPrototype, \
181 &ClassName::getPrototype, \
182 &ClassName::dumpToStream, \
183 &ClassName::analyzeHeap, \
184 &ClassName::estimatedSize, \
185 &ClassName::visitOutputConstraints, \
186 }, \
187 ClassName::TypedArrayStorageType, \
188 sizeof(ClassName)
189
190struct ClassInfo {
191 using CheckSubClassSnippetFunctionPtr = Ref<Snippet> (*)(void);
192
193 // A string denoting the class name. Example: "Window".
194 const char* className;
195 // Pointer to the class information of the base class.
196 // nullptrif there is none.
197 const ClassInfo* parentClass;
198 const HashTable* staticPropHashTable;
199 CheckSubClassSnippetFunctionPtr checkSubClassSnippet;
200 MethodTable methodTable;
201 TypedArrayType typedArrayStorageType;
202 unsigned staticClassSize;
203
204 static ptrdiff_t offsetOfParentClass()
205 {
206 return OBJECT_OFFSETOF(ClassInfo, parentClass);
207 }
208
209 bool isSubClassOf(const ClassInfo* other) const
210 {
211 for (const ClassInfo* ci = this; ci; ci = ci->parentClass) {
212 if (ci == other)
213 return true;
214 }
215 return false;
216 }
217
218 JS_EXPORT_PRIVATE void dump(PrintStream&) const;
219
220 JS_EXPORT_PRIVATE bool hasStaticSetterOrReadonlyProperties() const;
221};
222
223} // namespace JSC
224