Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(255)

Side by Side Diff: Source/bindings/core/v8/ScriptWrappable.h

Issue 540283003: bindings: Retires ScriptWrappable::init, etc. (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Addressed a review comment. Created 6 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | Source/bindings/core/v8/custom/V8DataViewCustom.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2010 Google Inc. All rights reserved. 2 * Copyright (C) 2010 Google Inc. All rights reserved.
3 * 3 *
4 * Redistribution and use in source and binary forms, with or without 4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are 5 * modification, are permitted provided that the following conditions are
6 * met: 6 * met:
7 * 7 *
8 * * Redistributions of source code must retain the above copyright 8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer. 9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above 10 * * Redistributions in binary form must reproduce the above
(...skipping 18 matching lines...) Expand all
29 */ 29 */
30 30
31 #ifndef ScriptWrappable_h 31 #ifndef ScriptWrappable_h
32 #define ScriptWrappable_h 32 #define ScriptWrappable_h
33 33
34 #include "bindings/core/v8/WrapperTypeInfo.h" 34 #include "bindings/core/v8/WrapperTypeInfo.h"
35 #include "platform/ScriptForbiddenScope.h" 35 #include "platform/ScriptForbiddenScope.h"
36 #include "platform/heap/Handle.h" 36 #include "platform/heap/Handle.h"
37 #include <v8.h> 37 #include <v8.h>
38 38
39 // Helper to call webCoreInitializeScriptWrappableForInterface in the global nam espace.
40 template <class C> inline void initializeScriptWrappableHelper(C* object)
41 {
42 void webCoreInitializeScriptWrappableForInterface(C*);
43 webCoreInitializeScriptWrappableForInterface(object);
44 }
45
46 namespace blink { 39 namespace blink {
47 40
48 /** 41 /**
49 * The base class of all wrappable objects. 42 * The base class of all wrappable objects.
50 * 43 *
51 * This class provides the internal pointer to be stored in the wrapper objects, 44 * This class provides the internal pointer to be stored in the wrapper objects,
52 * and its conversions from / to the DOM instances. 45 * and its conversions from / to the DOM instances.
53 * 46 *
54 * Note that this class must not have vtbl (any virtual function) or any member 47 * Note that this class must not have vtbl (any virtual function) or any member
55 * variable which increase the size of instances. Some of the classes sensitive 48 * variable which increase the size of instances. Some of the classes sensitive
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
100 { 93 {
101 RELEASE_ASSERT_WITH_SECURITY_IMPLICATION(object.IsEmpty() 94 RELEASE_ASSERT_WITH_SECURITY_IMPLICATION(object.IsEmpty()
102 || object->GetAlignedPointerFromInternalField(v8DOMWrapperObjectInde x) == toScriptWrappableBase()); 95 || object->GetAlignedPointerFromInternalField(v8DOMWrapperObjectInde x) == toScriptWrappableBase());
103 } 96 }
104 }; 97 };
105 98
106 /** 99 /**
107 * ScriptWrappable wraps a V8 object and its WrapperTypeInfo. 100 * ScriptWrappable wraps a V8 object and its WrapperTypeInfo.
108 * 101 *
109 * ScriptWrappable acts much like a v8::Persistent<> in that it keeps a 102 * ScriptWrappable acts much like a v8::Persistent<> in that it keeps a
110 * V8 object alive. Under the hood, however, it keeps either a TypeInfo 103 * V8 object alive.
111 * object or an actual v8 persistent (or is empty).
112 *
113 * The physical state space of ScriptWrappable is:
114 * - uintptr_t m_wrapperOrTypeInfo;
115 * - if 0: the ScriptWrappable is uninitialized/empty.
116 * - if even: a pointer to blink::TypeInfo
117 * - if odd: a pointer to v8::Persistent<v8::Object> + 1.
118 *
119 * In other words, one integer represents one of two object pointers,
120 * depending on its least signficiant bit, plus an uninitialized state.
121 * This class is meant to mask the logistics behind this.
122 *
123 * typeInfo() and newLocalWrapper will return appropriate values (possibly
124 * 0/empty) in all physical states.
125 * 104 *
126 * The state transitions are: 105 * The state transitions are:
127 * - new: an empty and invalid ScriptWrappable. 106 * - new: an empty ScriptWrappable.
128 * - init (to be called by all subclasses in their constructor):
129 * needs to call setTypeInfo
130 * - setTypeInfo: install a WrapperTypeInfo
131 * - setWrapper: install a v8::Persistent (or empty) 107 * - setWrapper: install a v8::Persistent (or empty)
132 * - disposeWrapper (via setWeakCallback, triggered by V8 garbage collecter): 108 * - disposeWrapper (via setWeakCallback, triggered by V8 garbage collecter):
133 * remove v8::Persistent and install a TypeInfo of the previous value. 109 * remove v8::Persistent and become empty.
134 */ 110 */
135 class ScriptWrappable : public ScriptWrappableBase { 111 class ScriptWrappable : public ScriptWrappableBase {
136 public: 112 public:
137 ScriptWrappable() : m_wrapperOrTypeInfo(0) { } 113 ScriptWrappable() : m_wrapper(0) { }
138
139 // Wrappables need to be initialized with their most derrived type for which
140 // bindings exist, in much the same way that certain other types need to be
141 // adopted and so forth. The overloaded initializeScriptWrappableForInterfac e()
142 // functions are implemented by the generated V8 bindings code. Declaring th e
143 // extern function in the template avoids making a centralized header of all
144 // the bindings in the universe. C++11's extern template feature may provide
145 // a cleaner solution someday.
146 template <class C> static void init(C* object)
147 {
148 initializeScriptWrappableHelper(object);
149 }
150 114
151 // Returns the WrapperTypeInfo of the instance. 115 // Returns the WrapperTypeInfo of the instance.
152 // 116 //
153 // This method must be overridden by DEFINE_WRAPPERTYPEINFO macro. 117 // This method must be overridden by DEFINE_WRAPPERTYPEINFO macro.
154 virtual const WrapperTypeInfo* wrapperTypeInfo() const = 0; 118 virtual const WrapperTypeInfo* wrapperTypeInfo() const = 0;
155 119
156 // Creates and returns a new wrapper object. 120 // Creates and returns a new wrapper object.
157 virtual v8::Handle<v8::Object> wrap(v8::Handle<v8::Object> creationContext, v8::Isolate*); 121 virtual v8::Handle<v8::Object> wrap(v8::Handle<v8::Object> creationContext, v8::Isolate*);
158 122
159 void setWrapper(v8::Handle<v8::Object> wrapper, v8::Isolate* isolate, const WrapperTypeInfo* wrapperTypeInfo) 123 void setWrapper(v8::Handle<v8::Object> wrapper, v8::Isolate* isolate, const WrapperTypeInfo* wrapperTypeInfo)
160 { 124 {
161 ASSERT(!containsWrapper()); 125 ASSERT(!containsWrapper());
162 if (!*wrapper) { 126 if (!*wrapper) {
163 m_wrapperOrTypeInfo = 0; 127 m_wrapper = 0;
164 return; 128 return;
165 } 129 }
166 v8::Persistent<v8::Object> persistent(isolate, wrapper); 130 v8::Persistent<v8::Object> persistent(isolate, wrapper);
167 wrapperTypeInfo->configureWrapper(&persistent); 131 wrapperTypeInfo->configureWrapper(&persistent);
168 persistent.SetWeak(this, &setWeakCallback); 132 persistent.SetWeak(this, &setWeakCallback);
169 m_wrapperOrTypeInfo = reinterpret_cast<uintptr_t>(persistent.ClearAndLea k()) | 1; 133 m_wrapper = persistent.ClearAndLeak();
170 ASSERT(containsWrapper()); 134 ASSERT(containsWrapper());
171 } 135 }
172 136
173 v8::Local<v8::Object> newLocalWrapper(v8::Isolate* isolate) const 137 v8::Local<v8::Object> newLocalWrapper(v8::Isolate* isolate) const
174 { 138 {
175 v8::Persistent<v8::Object> persistent; 139 v8::Persistent<v8::Object> persistent;
176 getPersistent(&persistent); 140 getPersistent(&persistent);
177 return v8::Local<v8::Object>::New(isolate, persistent); 141 return v8::Local<v8::Object>::New(isolate, persistent);
178 } 142 }
179 143
180 const WrapperTypeInfo* typeInfo()
181 {
182 if (containsTypeInfo())
183 return reinterpret_cast<const WrapperTypeInfo*>(m_wrapperOrTypeInfo) ;
184
185 if (containsWrapper()) {
186 v8::Persistent<v8::Object> persistent;
187 getPersistent(&persistent);
188 return toWrapperTypeInfo(persistent);
189 }
190
191 return 0;
192 }
193
194 void setTypeInfo(const WrapperTypeInfo* typeInfo)
195 {
196 m_wrapperOrTypeInfo = reinterpret_cast<uintptr_t>(typeInfo);
197 ASSERT(containsTypeInfo());
198 }
199
200 bool isEqualTo(const v8::Local<v8::Object>& other) const 144 bool isEqualTo(const v8::Local<v8::Object>& other) const
201 { 145 {
202 v8::Persistent<v8::Object> persistent; 146 v8::Persistent<v8::Object> persistent;
203 getPersistent(&persistent); 147 getPersistent(&persistent);
204 return persistent == other; 148 return persistent == other;
205 } 149 }
206 150
207 static bool wrapperCanBeStoredInObject(const void*) { return false; } 151 static bool wrapperCanBeStoredInObject(const void*) { return false; }
208 static bool wrapperCanBeStoredInObject(const ScriptWrappable*) { return true ; } 152 static bool wrapperCanBeStoredInObject(const ScriptWrappable*) { return true ; }
209 153
(...skipping 14 matching lines...) Expand all
224 getPersistent(&persistent); 168 getPersistent(&persistent);
225 returnValue.Set(persistent); 169 returnValue.Set(persistent);
226 return containsWrapper(); 170 return containsWrapper();
227 } 171 }
228 172
229 void markAsDependentGroup(ScriptWrappable* groupRoot, v8::Isolate* isolate) 173 void markAsDependentGroup(ScriptWrappable* groupRoot, v8::Isolate* isolate)
230 { 174 {
231 ASSERT(containsWrapper()); 175 ASSERT(containsWrapper());
232 ASSERT(groupRoot && groupRoot->containsWrapper()); 176 ASSERT(groupRoot && groupRoot->containsWrapper());
233 177
234 v8::UniqueId groupId(groupRoot->m_wrapperOrTypeInfo); 178 v8::UniqueId groupId(reinterpret_cast<intptr_t>(groupRoot->m_wrapper));
235 v8::Persistent<v8::Object> wrapper; 179 v8::Persistent<v8::Object> wrapper;
236 getPersistent(&wrapper); 180 getPersistent(&wrapper);
237 wrapper.MarkPartiallyDependent(); 181 wrapper.MarkPartiallyDependent();
238 isolate->SetObjectGroupId(v8::Persistent<v8::Value>::Cast(wrapper), grou pId); 182 isolate->SetObjectGroupId(v8::Persistent<v8::Value>::Cast(wrapper), grou pId);
239 } 183 }
240 184
241 void setReference(const v8::Persistent<v8::Object>& parent, v8::Isolate* iso late) 185 void setReference(const v8::Persistent<v8::Object>& parent, v8::Isolate* iso late)
242 { 186 {
243 v8::Persistent<v8::Object> persistent; 187 v8::Persistent<v8::Object> persistent;
244 getPersistent(&persistent); 188 getPersistent(&persistent);
(...skipping 12 matching lines...) Expand all
257 static void assertWrapperSanity(void* object, T* objectAsT) 201 static void assertWrapperSanity(void* object, T* objectAsT)
258 { 202 {
259 ASSERT_NOT_REACHED(); 203 ASSERT_NOT_REACHED();
260 } 204 }
261 205
262 template<typename V8T, typename T> 206 template<typename V8T, typename T>
263 static void assertWrapperSanity(ScriptWrappable* object, T* objectAsT) 207 static void assertWrapperSanity(ScriptWrappable* object, T* objectAsT)
264 { 208 {
265 ASSERT(object); 209 ASSERT(object);
266 ASSERT(objectAsT); 210 ASSERT(objectAsT);
267 v8::Object* value = object->getRawValue(); 211 v8::Object* value = object->m_wrapper;
268 RELEASE_ASSERT_WITH_SECURITY_IMPLICATION(value == 0 212 RELEASE_ASSERT_WITH_SECURITY_IMPLICATION(value == 0
269 || value->GetAlignedPointerFromInternalField(v8DOMWrapperObjectIndex ) == V8T::toScriptWrappableBase(objectAsT)); 213 || value->GetAlignedPointerFromInternalField(v8DOMWrapperObjectIndex ) == V8T::toScriptWrappableBase(objectAsT));
270 } 214 }
271 215
272 using ScriptWrappableBase::assertWrapperSanity; 216 using ScriptWrappableBase::assertWrapperSanity;
273 217
274 inline bool containsWrapper() const { return (m_wrapperOrTypeInfo & 1); } 218 bool containsWrapper() const { return m_wrapper; }
275 inline bool containsTypeInfo() const { return m_wrapperOrTypeInfo && !(m_wra pperOrTypeInfo & 1); }
276 219
277 #if !ENABLE(OILPAN) 220 #if !ENABLE(OILPAN)
278 protected: 221 protected:
279 virtual ~ScriptWrappable() 222 virtual ~ScriptWrappable()
280 { 223 {
281 // We must not get deleted as long as we contain a wrapper. If this happ ens, we screwed up ref 224 // We must not get deleted as long as we contain a wrapper. If this happ ens, we screwed up ref
282 // counting somewhere. Crash here instead of crashing during a later gc cycle. 225 // counting somewhere. Crash here instead of crashing during a later gc cycle.
283 RELEASE_ASSERT_WITH_SECURITY_IMPLICATION(!containsWrapper()); 226 RELEASE_ASSERT_WITH_SECURITY_IMPLICATION(!containsWrapper());
284 ASSERT(m_wrapperOrTypeInfo); // Assert initialization via init() even if not subsequently wrapped. 227 m_wrapper = 0; // Break UAF attempts to wrap.
285 m_wrapperOrTypeInfo = 0; // Break UAF attempts to wrap.
286 } 228 }
287 #endif 229 #endif
288 // With Oilpan we don't need a ScriptWrappable destructor. 230 // With Oilpan we don't need a ScriptWrappable destructor.
289 // 231 //
290 // - 'RELEASE_ASSERT_WITH_SECURITY_IMPLICATION(!containsWrapper())' is not n eeded 232 // - 'RELEASE_ASSERT_WITH_SECURITY_IMPLICATION(!containsWrapper())' is not n eeded
291 // because Oilpan is not using reference counting at all. If containsWrapper () is true, 233 // because Oilpan is not using reference counting at all. If containsWrapper () is true,
292 // it means that ScriptWrappable still has a wrapper. In this case, the dest ructor 234 // it means that ScriptWrappable still has a wrapper. In this case, the dest ructor
293 // must not be called since the wrapper has a persistent handle back to this ScriptWrappable object. 235 // must not be called since the wrapper has a persistent handle back to this ScriptWrappable object.
294 // Assuming that Oilpan's GC is correct (If we cannot assume this, a lot of more things are 236 // Assuming that Oilpan's GC is correct (If we cannot assume this, a lot of more things are
295 // already broken), we must not hit the RELEASE_ASSERT. 237 // already broken), we must not hit the RELEASE_ASSERT.
296 // 238 //
297 // - 'm_wrapperOrTypeInfo = 0' is not needed because Oilpan's GC zeroes out memory when 239 // - 'm_wrapper = 0' is not needed because Oilpan's GC zeroes out memory whe n
298 // the memory is collected and added to a free list. 240 // the memory is collected and added to a free list.
299 241
300 private: 242 private:
301 void getPersistent(v8::Persistent<v8::Object>* persistent) const 243 void getPersistent(v8::Persistent<v8::Object>* persistent) const
302 { 244 {
303 ASSERT(persistent); 245 ASSERT(persistent);
304 246
305 // Horrible and super unsafe: Cast the Persistent to an Object*, so 247 // Horrible and super unsafe: Cast the Persistent to an Object*, so
306 // that we can inject the wrapped value. This only works because 248 // that we can inject the wrapped value. This only works because
307 // we previously 'stole' the object pointer from a Persistent in 249 // we previously 'stole' the object pointer from a Persistent in
308 // the setWrapper() method. 250 // the setWrapper() method.
309 *reinterpret_cast<v8::Object**>(persistent) = getRawValue(); 251 *reinterpret_cast<v8::Object**>(persistent) = m_wrapper;
310 } 252 }
311 253
312 inline v8::Object* getRawValue() const 254 void disposeWrapper(v8::Local<v8::Object> wrapper)
313 {
314 v8::Object* object = containsWrapper() ? reinterpret_cast<v8::Object*>(m _wrapperOrTypeInfo & ~1) : 0;
315 return object;
316 }
317
318 inline void disposeWrapper(v8::Local<v8::Object> wrapper)
319 { 255 {
320 ASSERT(containsWrapper()); 256 ASSERT(containsWrapper());
321 257
322 v8::Persistent<v8::Object> persistent; 258 v8::Persistent<v8::Object> persistent;
323 getPersistent(&persistent); 259 getPersistent(&persistent);
324 260
325 ASSERT(wrapper == persistent); 261 ASSERT(wrapper == persistent);
326 persistent.Reset(); 262 persistent.Reset();
327 setTypeInfo(toWrapperTypeInfo(wrapper)); 263 m_wrapper = 0;
328 } 264 }
329 265
330 // If zero, then this contains nothing, otherwise:
331 // If the bottom bit it set, then this contains a pointer to a wrapper obj ect in the remainging bits.
332 // If the bottom bit is clear, then this contains a pointer to the wrapper type info in the remaining bits.
333 uintptr_t m_wrapperOrTypeInfo;
334
335 static void setWeakCallback(const v8::WeakCallbackData<v8::Object, ScriptWra ppable>& data) 266 static void setWeakCallback(const v8::WeakCallbackData<v8::Object, ScriptWra ppable>& data)
336 { 267 {
337 v8::Persistent<v8::Object> persistent; 268 v8::Persistent<v8::Object> persistent;
338 data.GetParameter()->getPersistent(&persistent); 269 data.GetParameter()->getPersistent(&persistent);
339 ASSERT(persistent == data.GetValue()); 270 ASSERT(persistent == data.GetValue());
340 data.GetParameter()->disposeWrapper(data.GetValue()); 271 data.GetParameter()->disposeWrapper(data.GetValue());
341 272
342 // FIXME: I noticed that 50%~ of minor GC cycle times can be consumed 273 // FIXME: I noticed that 50%~ of minor GC cycle times can be consumed
343 // inside data.GetParameter()->deref(), which causes Node destructions. We should 274 // inside data.GetParameter()->deref(), which causes Node destructions. We should
344 // make Node destructions incremental. 275 // make Node destructions incremental.
345 releaseObject(data.GetValue()); 276 releaseObject(data.GetValue());
346 } 277 }
278
279 v8::Object* m_wrapper;
347 }; 280 };
348 281
349 // Defines 'wrapperTypeInfo' virtual method which returns the WrapperTypeInfo of 282 // Defines 'wrapperTypeInfo' virtual method which returns the WrapperTypeInfo of
350 // the instance. Also declares a static member of type WrapperTypeInfo, of which 283 // the instance. Also declares a static member of type WrapperTypeInfo, of which
351 // the definition is given by the IDL code generator. 284 // the definition is given by the IDL code generator.
352 // 285 //
353 // Every DOM Class T must meet either of the following conditions: 286 // Every DOM Class T must meet either of the following conditions:
354 // - T.idl inherits from [NotScriptWrappable]. 287 // - T.idl inherits from [NotScriptWrappable].
355 // - T inherits from ScriptWrappable and has DEFINE_WRAPPERTYPEINFO(). 288 // - T inherits from ScriptWrappable and has DEFINE_WRAPPERTYPEINFO().
356 // 289 //
357 // If a DOM class T does not inherit from ScriptWrappable, you have to write 290 // If a DOM class T does not inherit from ScriptWrappable, you have to write
358 // [NotScriptWrappable] in the IDL file as an extended attribute in order to let 291 // [NotScriptWrappable] in the IDL file as an extended attribute in order to let
359 // IDL code generator know that T does not inherit from ScriptWrappable. Note 292 // IDL code generator know that T does not inherit from ScriptWrappable. Note
360 // that [NotScriptWrappable] is inheritable. 293 // that [NotScriptWrappable] is inheritable.
361 // 294 //
362 // All the derived classes of ScriptWrappable, regardless of directly or 295 // All the derived classes of ScriptWrappable, regardless of directly or
363 // indirectly, must write this macro in the class definition. 296 // indirectly, must write this macro in the class definition.
364 #define DEFINE_WRAPPERTYPEINFO() \ 297 #define DEFINE_WRAPPERTYPEINFO() \
365 public: \ 298 public: \
366 virtual const WrapperTypeInfo* wrapperTypeInfo() const OVERRIDE \ 299 virtual const WrapperTypeInfo* wrapperTypeInfo() const OVERRIDE \
367 { \ 300 { \
368 return &s_wrapperTypeInfo; \ 301 return &s_wrapperTypeInfo; \
369 } \ 302 } \
370 private: \ 303 private: \
371 static const WrapperTypeInfo& s_wrapperTypeInfo 304 static const WrapperTypeInfo& s_wrapperTypeInfo
372 305
373 } // namespace blink 306 } // namespace blink
374 307
375 #endif // ScriptWrappable_h 308 #endif // ScriptWrappable_h
OLDNEW
« no previous file with comments | « no previous file | Source/bindings/core/v8/custom/V8DataViewCustom.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698