2 * Copyright (C) 2010 Google Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above
11 * copyright notice, this list of conditions and the following disclaimer
12 * in the documentation and/or other materials provided with the
14 * * Neither the name of Google Inc. nor the names of its
15 * contributors may be used to endorse or promote products derived from
16 * this software without specific prior written permission.
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 #ifndef WrapperTypeInfo_h
32 #define WrapperTypeInfo_h
34 #include "gin/public/wrapper_info.h"
35 #include "platform/heap/Handle.h"
36 #include "wtf/Assertions.h"
41 class ActiveDOMObject;
44 class ScriptWrappableBase;
46 static const int v8DOMWrapperTypeIndex = static_cast<int>(gin::kWrapperInfoIndex);
47 static const int v8DOMWrapperObjectIndex = static_cast<int>(gin::kEncodedValueIndex);
48 static const int v8DefaultWrapperInternalFieldCount = static_cast<int>(gin::kNumberOfInternalFields);
49 static const int v8PrototypeTypeIndex = 0;
50 static const int v8PrototypeInternalFieldcount = 1;
52 typedef v8::Handle<v8::FunctionTemplate> (*DomTemplateFunction)(v8::Isolate*);
53 typedef void (*RefObjectFunction)(ScriptWrappableBase* internalPointer);
54 typedef void (*DerefObjectFunction)(ScriptWrappableBase* internalPointer);
55 typedef WrapperPersistentNode* (*CreatePersistentHandleFunction)(ScriptWrappableBase* internalPointer);
56 typedef ActiveDOMObject* (*ToActiveDOMObjectFunction)(v8::Handle<v8::Object>);
57 typedef EventTarget* (*ToEventTargetFunction)(v8::Handle<v8::Object>);
58 typedef void (*ResolveWrapperReachabilityFunction)(ScriptWrappableBase* internalPointer, const v8::Persistent<v8::Object>&, v8::Isolate*);
59 typedef void (*InstallConditionallyEnabledMethodsFunction)(v8::Handle<v8::Object>, v8::Isolate*);
60 typedef void (*InstallConditionallyEnabledPropertiesFunction)(v8::Handle<v8::Object>, v8::Isolate*);
62 inline void setObjectGroup(ScriptWrappableBase* internalPointer, const v8::Persistent<v8::Object>& wrapper, v8::Isolate* isolate)
64 isolate->SetObjectGroupId(wrapper, v8::UniqueId(reinterpret_cast<intptr_t>(internalPointer)));
67 // This struct provides a way to store a bunch of information that is helpful when unwrapping
68 // v8 objects. Each v8 bindings class has exactly one static WrapperTypeInfo member, so
69 // comparing pointers is a safe way to determine if types match.
70 struct WrapperTypeInfo {
71 enum WrapperTypePrototype {
72 WrapperTypeObjectPrototype,
73 WrapperTypeExceptionPrototype,
77 NodeClassId = 1, // NodeClassId must be smaller than ObjectClassId.
87 GarbageCollectedObject,
88 WillBeGarbageCollectedObject,
92 static const WrapperTypeInfo* unwrap(v8::Handle<v8::Value> typeInfoWrapper)
94 return reinterpret_cast<const WrapperTypeInfo*>(v8::External::Cast(*typeInfoWrapper)->Value());
98 bool equals(const WrapperTypeInfo* that) const
103 bool isSubclass(const WrapperTypeInfo* that) const
105 for (const WrapperTypeInfo* current = this; current; current = current->parentClass) {
113 void configureWrapper(v8::PersistentBase<v8::Object>* wrapper) const
115 wrapper->SetWrapperClassId(wrapperClassId);
116 if (lifetime == Independent)
117 wrapper->MarkIndependent();
120 v8::Handle<v8::FunctionTemplate> domTemplate(v8::Isolate* isolate) const
122 return domTemplateFunction(isolate);
125 void refObject(ScriptWrappableBase* internalPointer) const
127 ASSERT(refObjectFunction);
128 refObjectFunction(internalPointer);
131 void derefObject(ScriptWrappableBase* internalPointer) const
133 ASSERT(derefObjectFunction);
134 derefObjectFunction(internalPointer);
137 WrapperPersistentNode* createPersistentHandle(ScriptWrappableBase* internalPointer) const
139 ASSERT(createPersistentHandleFunction);
140 return createPersistentHandleFunction(internalPointer);
143 void installConditionallyEnabledMethods(v8::Handle<v8::Object> prototypeTemplate, v8::Isolate* isolate) const
145 if (installConditionallyEnabledMethodsFunction)
146 installConditionallyEnabledMethodsFunction(prototypeTemplate, isolate);
149 void installConditionallyEnabledProperties(v8::Handle<v8::Object> prototypeTemplate, v8::Isolate* isolate) const
151 if (installConditionallyEnabledPropertiesFunction)
152 installConditionallyEnabledPropertiesFunction(prototypeTemplate, isolate);
155 ActiveDOMObject* toActiveDOMObject(v8::Handle<v8::Object> object) const
157 if (!toActiveDOMObjectFunction)
159 return toActiveDOMObjectFunction(object);
162 EventTarget* toEventTarget(v8::Handle<v8::Object> object) const
164 if (!toEventTargetFunction)
166 return toEventTargetFunction(object);
169 void visitDOMWrapper(ScriptWrappableBase* internalPointer, const v8::Persistent<v8::Object>& wrapper, v8::Isolate* isolate) const
171 if (!visitDOMWrapperFunction)
172 setObjectGroup(internalPointer, wrapper, isolate);
174 visitDOMWrapperFunction(internalPointer, wrapper, isolate);
177 // This field must be the first member of the struct WrapperTypeInfo. This is also checked by a COMPILE_ASSERT() below.
178 const gin::GinEmbedder ginEmbedder;
180 const DomTemplateFunction domTemplateFunction;
181 const RefObjectFunction refObjectFunction;
182 const DerefObjectFunction derefObjectFunction;
183 const CreatePersistentHandleFunction createPersistentHandleFunction;
184 const ToActiveDOMObjectFunction toActiveDOMObjectFunction;
185 const ToEventTargetFunction toEventTargetFunction;
186 const ResolveWrapperReachabilityFunction visitDOMWrapperFunction;
187 const InstallConditionallyEnabledMethodsFunction installConditionallyEnabledMethodsFunction;
188 const InstallConditionallyEnabledPropertiesFunction installConditionallyEnabledPropertiesFunction;
189 const WrapperTypeInfo* parentClass;
190 const WrapperTypePrototype wrapperTypePrototype;
191 const WrapperClassId wrapperClassId;
192 const Lifetime lifetime;
196 COMPILE_ASSERT(offsetof(struct WrapperTypeInfo, ginEmbedder) == offsetof(struct gin::WrapperInfo, embedder), wrapper_type_info_compatible_to_gin);
198 template<typename T, int offset>
199 inline T* getInternalField(const v8::Persistent<v8::Object>& persistent)
201 // This would be unsafe, but InternalFieldCount and GetAlignedPointerFromInternalField are guaranteed not to allocate
202 const v8::Handle<v8::Object>& object = reinterpret_cast<const v8::Handle<v8::Object>&>(persistent);
203 ASSERT(offset < object->InternalFieldCount());
204 return static_cast<T*>(object->GetAlignedPointerFromInternalField(offset));
207 template<typename T, int offset>
208 inline T* getInternalField(v8::Handle<v8::Object> wrapper)
210 ASSERT(offset < wrapper->InternalFieldCount());
211 return static_cast<T*>(wrapper->GetAlignedPointerFromInternalField(offset));
214 inline ScriptWrappableBase* toScriptWrappableBase(v8::Handle<v8::Object> wrapper)
216 return getInternalField<ScriptWrappableBase, v8DOMWrapperObjectIndex>(wrapper);
219 inline const WrapperTypeInfo* toWrapperTypeInfo(const v8::Persistent<v8::Object>& wrapper)
221 return getInternalField<WrapperTypeInfo, v8DOMWrapperTypeIndex>(wrapper);
224 inline const WrapperTypeInfo* toWrapperTypeInfo(v8::Handle<v8::Object> wrapper)
226 return getInternalField<WrapperTypeInfo, v8DOMWrapperTypeIndex>(wrapper);
229 inline const WrapperPersistentNode* toPersistentHandle(const v8::Handle<v8::Object>& wrapper)
231 // Persistent handle is stored in the last internal field.
232 return static_cast<WrapperPersistentNode*>(wrapper->GetAlignedPointerFromInternalField(wrapper->InternalFieldCount() - 1));
235 inline void releaseObject(v8::Handle<v8::Object> wrapper)
237 const WrapperTypeInfo* typeInfo = toWrapperTypeInfo(wrapper);
238 if (typeInfo->gcType == WrapperTypeInfo::GarbageCollectedObject) {
239 const WrapperPersistentNode* handle = toPersistentHandle(wrapper);
240 // This will be null iff a wrapper for a hidden wrapper object,
241 // see V8DOMWrapper::setNativeInfoForHiddenWrapper().
242 WrapperPersistentNode::destroy(handle);
243 } else if (typeInfo->gcType == WrapperTypeInfo::WillBeGarbageCollectedObject) {
245 const WrapperPersistentNode* handle = toPersistentHandle(wrapper);
246 // This will be null iff a wrapper for a hidden wrapper object,
247 // see V8DOMWrapper::setNativeInfoForHiddenWrapper().
248 WrapperPersistentNode::destroy(handle);
250 typeInfo->derefObject(toScriptWrappableBase(wrapper));
253 typeInfo->derefObject(toScriptWrappableBase(wrapper));
259 #endif // WrapperTypeInfo_h