| OLD | NEW |
| (Empty) |
| 1 /* | |
| 2 * Copyright (C) 2009 Google 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 are | |
| 6 * met: | |
| 7 * | |
| 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 | |
| 13 * distribution. | |
| 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. | |
| 17 * | |
| 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. | |
| 29 */ | |
| 30 | |
| 31 #ifndef SKY_ENGINE_BINDINGS_CORE_V8_DOMDATASTORE_H_ | |
| 32 #define SKY_ENGINE_BINDINGS_CORE_V8_DOMDATASTORE_H_ | |
| 33 | |
| 34 #include "sky/engine/bindings/core/v8/DOMWrapperMap.h" | |
| 35 #include "sky/engine/bindings/core/v8/DOMWrapperWorld.h" | |
| 36 #include "sky/engine/bindings/core/v8/ScriptWrappable.h" | |
| 37 #include "sky/engine/bindings/core/v8/WrapperTypeInfo.h" | |
| 38 #include "sky/engine/wtf/Noncopyable.h" | |
| 39 #include "sky/engine/wtf/StdLibExtras.h" | |
| 40 #include "v8/include/v8.h" | |
| 41 | |
| 42 namespace blink { | |
| 43 | |
| 44 class Node; | |
| 45 | |
| 46 class DOMDataStore { | |
| 47 WTF_MAKE_NONCOPYABLE(DOMDataStore); | |
| 48 public: | |
| 49 explicit DOMDataStore(bool isMainWorld); | |
| 50 ~DOMDataStore(); | |
| 51 | |
| 52 static DOMDataStore& current(v8::Isolate*); | |
| 53 | |
| 54 // We can use a wrapper stored in a ScriptWrappable when we're in the main w
orld. | |
| 55 // This method does the fast check if we're in the main world. If this metho
d returns true, | |
| 56 // it is guaranteed that we're in the main world. On the other hand, if this
method returns | |
| 57 // false, nothing is guaranteed (we might be in the main world). | |
| 58 template<typename T> | |
| 59 static bool canUseScriptWrappable(T* object) | |
| 60 { | |
| 61 return ScriptWrappable::wrapperCanBeStoredInObject(object); | |
| 62 } | |
| 63 | |
| 64 static bool canUseScriptWrappableNonTemplate(Node* object) | |
| 65 { | |
| 66 return true; | |
| 67 } | |
| 68 | |
| 69 template<typename V8T, typename T, typename Wrappable> | |
| 70 static bool setReturnValueFromWrapperFast(v8::ReturnValue<v8::Value> returnV
alue, T* object, v8::Local<v8::Object> holder, Wrappable* wrappable) | |
| 71 { | |
| 72 if (canUseScriptWrappable(object)) { | |
| 73 ScriptWrappable::assertWrapperSanity<V8T, T>(object, object); | |
| 74 return ScriptWrappable::fromObject(object)->setReturnValue(returnVal
ue); | |
| 75 } | |
| 76 // The second fastest way to check if we're in the main world is to chec
k if | |
| 77 // the wrappable's wrapper is the same as the holder. | |
| 78 // FIXME: Investigate if it's worth having this check for performance. | |
| 79 if (holderContainsWrapper(holder, wrappable)) { | |
| 80 if (ScriptWrappable::wrapperCanBeStoredInObject(object)) { | |
| 81 ScriptWrappable::assertWrapperSanity<V8T, T>(object, object); | |
| 82 return ScriptWrappable::fromObject(object)->setReturnValue(retur
nValue); | |
| 83 } | |
| 84 return DOMWrapperWorld::mainWorld().domDataStore().m_wrapperMap.setR
eturnValueFrom(returnValue, V8T::toScriptWrappableBase(object)); | |
| 85 } | |
| 86 return current(returnValue.GetIsolate()).template setReturnValueFrom<V8T
>(returnValue, object); | |
| 87 } | |
| 88 | |
| 89 template<typename V8T, typename T> | |
| 90 static bool setReturnValueFromWrapper(v8::ReturnValue<v8::Value> returnValue
, T* object) | |
| 91 { | |
| 92 if (canUseScriptWrappable(object)) { | |
| 93 ScriptWrappable::assertWrapperSanity<V8T, T>(object, object); | |
| 94 return ScriptWrappable::fromObject(object)->setReturnValue(returnVal
ue); | |
| 95 } | |
| 96 return current(returnValue.GetIsolate()).template setReturnValueFrom<V8T
>(returnValue, object); | |
| 97 } | |
| 98 | |
| 99 template<typename V8T, typename T> | |
| 100 static bool setReturnValueFromWrapperForMainWorld(v8::ReturnValue<v8::Value>
returnValue, T* object) | |
| 101 { | |
| 102 if (ScriptWrappable::wrapperCanBeStoredInObject(object)) | |
| 103 return ScriptWrappable::fromObject(object)->setReturnValue(returnVal
ue); | |
| 104 return DOMWrapperWorld::mainWorld().domDataStore().m_wrapperMap.setRetur
nValueFrom(returnValue, V8T::toScriptWrappableBase(object)); | |
| 105 } | |
| 106 | |
| 107 template<typename V8T, typename T> | |
| 108 static v8::Handle<v8::Object> getWrapper(T* object, v8::Isolate* isolate) | |
| 109 { | |
| 110 if (canUseScriptWrappable(object)) { | |
| 111 v8::Handle<v8::Object> result = ScriptWrappable::fromObject(object)-
>newLocalWrapper(isolate); | |
| 112 // Security: always guard against malicious tampering. | |
| 113 ScriptWrappable::assertWrapperSanity<V8T, T>(result, object); | |
| 114 return result; | |
| 115 } | |
| 116 return current(isolate).template get<V8T>(object, isolate); | |
| 117 } | |
| 118 | |
| 119 static v8::Handle<v8::Object> getWrapperNonTemplate(ScriptWrappableBase* obj
ect, v8::Isolate* isolate) | |
| 120 { | |
| 121 return current(isolate).getNonTemplate(object, isolate); | |
| 122 } | |
| 123 | |
| 124 static v8::Handle<v8::Object> getWrapperNonTemplate(ScriptWrappable* object,
v8::Isolate* isolate) | |
| 125 { | |
| 126 return current(isolate).getNonTemplate(object, isolate); | |
| 127 } | |
| 128 | |
| 129 static v8::Handle<v8::Object> getWrapperNonTemplate(Node* node, v8::Isolate*
isolate) | |
| 130 { | |
| 131 if (canUseScriptWrappableNonTemplate(node)) { | |
| 132 v8::Handle<v8::Object> result = ScriptWrappable::fromObject(node)->n
ewLocalWrapper(isolate); | |
| 133 // Security: always guard against malicious tampering. | |
| 134 ScriptWrappable::fromObject(node)->assertWrapperSanity(result); | |
| 135 return result; | |
| 136 } | |
| 137 return current(isolate).getNonTemplate(ScriptWrappable::fromObject(node)
, isolate); | |
| 138 } | |
| 139 | |
| 140 template<typename V8T, typename T> | |
| 141 static void setWrapperReference(const v8::Persistent<v8::Object>& parent, T*
child, v8::Isolate* isolate) | |
| 142 { | |
| 143 if (canUseScriptWrappable(child)) { | |
| 144 ScriptWrappable::assertWrapperSanity<V8T, T>(child, child); | |
| 145 ScriptWrappable::fromObject(child)->setReference(parent, isolate); | |
| 146 return; | |
| 147 } | |
| 148 current(isolate).template setReference<V8T>(parent, child, isolate); | |
| 149 } | |
| 150 | |
| 151 template<typename V8T, typename T> | |
| 152 static void setWrapper(T* object, v8::Handle<v8::Object> wrapper, v8::Isolat
e* isolate, const WrapperTypeInfo* wrapperTypeInfo) | |
| 153 { | |
| 154 if (canUseScriptWrappable(object)) { | |
| 155 ScriptWrappable::fromObject(object)->setWrapper(wrapper, isolate, wr
apperTypeInfo); | |
| 156 return; | |
| 157 } | |
| 158 return current(isolate).template set<V8T>(object, wrapper, isolate, wrap
perTypeInfo); | |
| 159 } | |
| 160 | |
| 161 static void setWrapperNonTemplate(ScriptWrappableBase* object, v8::Handle<v8
::Object> wrapper, v8::Isolate* isolate, const WrapperTypeInfo* wrapperTypeInfo) | |
| 162 { | |
| 163 return current(isolate).setNonTemplate(object, wrapper, isolate, wrapper
TypeInfo); | |
| 164 } | |
| 165 | |
| 166 static void setWrapperNonTemplate(ScriptWrappable* object, v8::Handle<v8::Ob
ject> wrapper, v8::Isolate* isolate, const WrapperTypeInfo* wrapperTypeInfo) | |
| 167 { | |
| 168 return current(isolate).setNonTemplate(object, wrapper, isolate, wrapper
TypeInfo); | |
| 169 } | |
| 170 | |
| 171 static void setWrapperNonTemplate(Node* node, v8::Handle<v8::Object> wrapper
, v8::Isolate* isolate, const WrapperTypeInfo* wrapperTypeInfo) | |
| 172 { | |
| 173 if (canUseScriptWrappableNonTemplate(node)) { | |
| 174 ScriptWrappable::fromObject(node)->setWrapper(wrapper, isolate, wrap
perTypeInfo); | |
| 175 return; | |
| 176 } | |
| 177 return current(isolate).setNonTemplate(ScriptWrappable::fromObject(node)
, wrapper, isolate, wrapperTypeInfo); | |
| 178 } | |
| 179 | |
| 180 template<typename V8T, typename T> | |
| 181 static bool containsWrapper(T* object, v8::Isolate* isolate) | |
| 182 { | |
| 183 return current(isolate).template containsWrapper<V8T>(object); | |
| 184 } | |
| 185 | |
| 186 static bool containsWrapperNonTemplate(ScriptWrappableBase* object, v8::Isol
ate* isolate) | |
| 187 { | |
| 188 return current(isolate).containsWrapperNonTemplate(object); | |
| 189 } | |
| 190 | |
| 191 static bool containsWrapperNonTemplate(ScriptWrappable* object, v8::Isolate*
isolate) | |
| 192 { | |
| 193 return current(isolate).containsWrapperNonTemplate(object); | |
| 194 } | |
| 195 | |
| 196 template<typename V8T, typename T> | |
| 197 v8::Handle<v8::Object> get(T* object, v8::Isolate* isolate) | |
| 198 { | |
| 199 if (ScriptWrappable::wrapperCanBeStoredInObject(object) && m_isMainWorld
) | |
| 200 return ScriptWrappable::fromObject(object)->newLocalWrapper(isolate)
; | |
| 201 return m_wrapperMap.newLocal(V8T::toScriptWrappableBase(object), isolate
); | |
| 202 } | |
| 203 | |
| 204 v8::Handle<v8::Object> getNonTemplate(ScriptWrappableBase* object, v8::Isola
te* isolate) | |
| 205 { | |
| 206 return m_wrapperMap.newLocal(object->toScriptWrappableBase(), isolate); | |
| 207 } | |
| 208 | |
| 209 v8::Handle<v8::Object> getNonTemplate(ScriptWrappable* object, v8::Isolate*
isolate) | |
| 210 { | |
| 211 if (m_isMainWorld) | |
| 212 return object->newLocalWrapper(isolate); | |
| 213 return m_wrapperMap.newLocal(object->toScriptWrappableBase(), isolate); | |
| 214 } | |
| 215 | |
| 216 template<typename V8T, typename T> | |
| 217 void setReference(const v8::Persistent<v8::Object>& parent, T* child, v8::Is
olate* isolate) | |
| 218 { | |
| 219 if (ScriptWrappable::wrapperCanBeStoredInObject(child) && m_isMainWorld)
{ | |
| 220 ScriptWrappable::fromObject(child)->setReference(parent, isolate); | |
| 221 return; | |
| 222 } | |
| 223 m_wrapperMap.setReference(parent, V8T::toScriptWrappableBase(child), iso
late); | |
| 224 } | |
| 225 | |
| 226 template<typename V8T, typename T> | |
| 227 bool setReturnValueFrom(v8::ReturnValue<v8::Value> returnValue, T* object) | |
| 228 { | |
| 229 if (ScriptWrappable::wrapperCanBeStoredInObject(object) && m_isMainWorld
) | |
| 230 return ScriptWrappable::fromObject(object)->setReturnValue(returnVal
ue); | |
| 231 return m_wrapperMap.setReturnValueFrom(returnValue, V8T::toScriptWrappab
leBase(object)); | |
| 232 } | |
| 233 | |
| 234 template<typename V8T, typename T> | |
| 235 bool containsWrapper(T* object) | |
| 236 { | |
| 237 if (ScriptWrappable::wrapperCanBeStoredInObject(object) && m_isMainWorld
) | |
| 238 return ScriptWrappable::fromObject(object)->containsWrapper(); | |
| 239 return m_wrapperMap.containsKey(V8T::toScriptWrappableBase(object)); | |
| 240 } | |
| 241 | |
| 242 bool containsWrapperNonTemplate(ScriptWrappableBase* object) | |
| 243 { | |
| 244 return m_wrapperMap.containsKey(object->toScriptWrappableBase()); | |
| 245 } | |
| 246 | |
| 247 bool containsWrapperNonTemplate(ScriptWrappable* object) | |
| 248 { | |
| 249 if (m_isMainWorld) | |
| 250 return object->containsWrapper(); | |
| 251 return m_wrapperMap.containsKey(object->toScriptWrappableBase()); | |
| 252 } | |
| 253 | |
| 254 private: | |
| 255 template<typename V8T, typename T> | |
| 256 void set(T* object, v8::Handle<v8::Object> wrapper, v8::Isolate* isolate, co
nst WrapperTypeInfo* wrapperTypeInfo) | |
| 257 { | |
| 258 ASSERT(object); | |
| 259 ASSERT(!wrapper.IsEmpty()); | |
| 260 if (ScriptWrappable::wrapperCanBeStoredInObject(object) && m_isMainWorld
) { | |
| 261 ScriptWrappable::fromObject(object)->setWrapper(wrapper, isolate, wr
apperTypeInfo); | |
| 262 return; | |
| 263 } | |
| 264 m_wrapperMap.set(V8T::toScriptWrappableBase(object), wrapper, wrapperTyp
eInfo); | |
| 265 } | |
| 266 | |
| 267 void setNonTemplate(ScriptWrappableBase* object, v8::Handle<v8::Object> wrap
per, v8::Isolate* isolate, const WrapperTypeInfo* wrapperTypeInfo) | |
| 268 { | |
| 269 ASSERT(object); | |
| 270 ASSERT(!wrapper.IsEmpty()); | |
| 271 m_wrapperMap.set(object->toScriptWrappableBase(), wrapper, wrapperTypeIn
fo); | |
| 272 } | |
| 273 | |
| 274 void setNonTemplate(ScriptWrappable* object, v8::Handle<v8::Object> wrapper,
v8::Isolate* isolate, const WrapperTypeInfo* wrapperTypeInfo) | |
| 275 { | |
| 276 ASSERT(object); | |
| 277 ASSERT(!wrapper.IsEmpty()); | |
| 278 if (m_isMainWorld) { | |
| 279 ScriptWrappable::fromObject(object)->setWrapper(wrapper, isolate, wr
apperTypeInfo); | |
| 280 return; | |
| 281 } | |
| 282 m_wrapperMap.set(object->toScriptWrappableBase(), wrapper, wrapperTypeIn
fo); | |
| 283 } | |
| 284 | |
| 285 static bool holderContainsWrapper(v8::Local<v8::Object>, void*) | |
| 286 { | |
| 287 return false; | |
| 288 } | |
| 289 | |
| 290 static bool holderContainsWrapper(v8::Local<v8::Object> holder, ScriptWrappa
ble* wrappable) | |
| 291 { | |
| 292 // Verify our assumptions about the main world. | |
| 293 ASSERT(wrappable); | |
| 294 ASSERT(!wrappable->containsWrapper() || !wrappable->isEqualTo(holder) ||
current(v8::Isolate::GetCurrent()).m_isMainWorld); | |
| 295 return wrappable->isEqualTo(holder); | |
| 296 } | |
| 297 | |
| 298 bool m_isMainWorld; | |
| 299 DOMWrapperMap<ScriptWrappableBase> m_wrapperMap; | |
| 300 }; | |
| 301 | |
| 302 template <> | |
| 303 inline void DOMWrapperMap<ScriptWrappableBase>::PersistentValueMapTraits::Dispos
e( | |
| 304 v8::Isolate* isolate, | |
| 305 v8::UniquePersistent<v8::Object> value, | |
| 306 ScriptWrappableBase* key) | |
| 307 { | |
| 308 RELEASE_ASSERT(!value.IsEmpty()); // See crbug.com/368095. | |
| 309 releaseObject(v8::Local<v8::Object>::New(isolate, value)); | |
| 310 } | |
| 311 | |
| 312 } // namespace blink | |
| 313 | |
| 314 #endif // SKY_ENGINE_BINDINGS_CORE_V8_DOMDATASTORE_H_ | |
| OLD | NEW |