153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)/* 253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * Copyright (C) 2010 Google Inc. All rights reserved. 353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * 453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * Redistribution and use in source and binary forms, with or without 553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * modification, are permitted provided that the following conditions are 653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * met: 753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * 853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * * Redistributions of source code must retain the above copyright 953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * notice, this list of conditions and the following disclaimer. 1053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * * Redistributions in binary form must reproduce the above 1153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * copyright notice, this list of conditions and the following disclaimer 1253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * in the documentation and/or other materials provided with the 1353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * distribution. 1453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * * Neither the name of Google Inc. nor the names of its 1553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * contributors may be used to endorse or promote products derived from 1653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * this software without specific prior written permission. 1702772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch * 1853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 2053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 2153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 2253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 2353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 2453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 2853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) */ 3053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) 3153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#ifndef ScriptWrappable_h 3253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#define ScriptWrappable_h 3353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) 34197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch#include "bindings/core/v8/WrapperTypeInfo.h" 35197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch#include "platform/ScriptForbiddenScope.h" 36f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu#include "platform/heap/Handle.h" 3753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include <v8.h> 3853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) 39c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)namespace blink { 40c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) 41c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)/** 42c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) * The base class of all wrappable objects. 43c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) * 44c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) * This class provides the internal pointer to be stored in the wrapper objects, 45c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) * and its conversions from / to the DOM instances. 46c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) * 47c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) * Note that this class must not have vtbl (any virtual function) or any member 489e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles) * variable which increase the size of instances. Some of the classes sensitive 499e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles) * to the size inherit from this class. So this class must be zero size. 50c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) */ 519e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)#if COMPILER(MSVC) 529e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)// VC++ 2013 doesn't support EBCO (Empty Base Class Optimization). It causes 539e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)// that not always pointers to an empty base class are aligned to 4 byte 549e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)// alignment. For example, 559e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)// 569e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)// class EmptyBase1 {}; 579e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)// class EmptyBase2 {}; 589e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)// class Derived : public EmptyBase1, public EmptyBase2 {}; 599e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)// Derived d; 609e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)// // &d == 0x1000 619e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)// // static_cast<EmptyBase1*>(&d) == 0x1000 629e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)// // static_cast<EmptyBase2*>(&d) == 0x1001 // Not 4 byte alignment! 639e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)// 649e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)// This doesn't happen with other compilers which support EBCO. All the 659e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)// addresses in the above example will be 0x1000 with EBCO supported. 669e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)// 679e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)// Since v8::Object::SetAlignedPointerInInternalField requires the pointers to 689e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)// be aligned, we need a hack to specify at least 4 byte alignment to MSVC. 699e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)__declspec(align(4)) 709e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)#endif 71c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)class ScriptWrappableBase { 72c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)public: 739e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles) template<typename T> 747242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci T* toImpl() 75c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) { 76c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) // Check if T* is castable to ScriptWrappableBase*, which means T 77c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) // doesn't have two or more ScriptWrappableBase as superclasses. 78c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) // If T has two ScriptWrappableBase as superclasses, conversions 79c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) // from T* to ScriptWrappableBase* are ambiguous. 807242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci ASSERT(static_cast<ScriptWrappableBase*>(static_cast<T*>(this))); 819e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles) // The internal pointers must be aligned to at least 4 byte alignment. 827242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci ASSERT((reinterpret_cast<intptr_t>(this) & 0x3) == 0); 837242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci return static_cast<T*>(this); 84c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) } 857242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci ScriptWrappableBase* toScriptWrappableBase() 869e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles) { 879e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles) // The internal pointers must be aligned to at least 4 byte alignment. 889e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles) ASSERT((reinterpret_cast<intptr_t>(this) & 0x3) == 0); 899e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles) return this; 909e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles) } 917242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci 927242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci void assertWrapperSanity(v8::Local<v8::Object> object) 937242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci { 947242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci RELEASE_ASSERT_WITH_SECURITY_IMPLICATION(object.IsEmpty() 957242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci || object->GetAlignedPointerFromInternalField(v8DOMWrapperObjectIndex) == toScriptWrappableBase()); 967242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci } 97c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)}; 9853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) 9910f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch/** 10010f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch * ScriptWrappable wraps a V8 object and its WrapperTypeInfo. 10110f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch * 10210f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch * ScriptWrappable acts much like a v8::Persistent<> in that it keeps a 1037242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci * V8 object alive. 10410f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch * 10510f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch * The state transitions are: 1067242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci * - new: an empty ScriptWrappable. 10710f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch * - setWrapper: install a v8::Persistent (or empty) 10810f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch * - disposeWrapper (via setWeakCallback, triggered by V8 garbage collecter): 1097242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci * remove v8::Persistent and become empty. 11010f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch */ 111c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)class ScriptWrappable : public ScriptWrappableBase { 11253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)public: 1137242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci ScriptWrappable() : m_wrapper(0) { } 1147242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci 1157242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci // Returns the WrapperTypeInfo of the instance. 1167242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci // 1177242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci // This method must be overridden by DEFINE_WRAPPERTYPEINFO macro. 1187242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci virtual const WrapperTypeInfo* wrapperTypeInfo() const = 0; 1197242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci 1207242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci // Creates and returns a new wrapper object. 1217242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci virtual v8::Handle<v8::Object> wrap(v8::Handle<v8::Object> creationContext, v8::Isolate*); 12253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) 1237242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci // Associates the instance with the existing wrapper. Returns |wrapper|. 1247242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci virtual v8::Handle<v8::Object> associateWithWrapper(const WrapperTypeInfo*, v8::Handle<v8::Object> wrapper, v8::Isolate*); 1257242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci 1267242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci void setWrapper(v8::Handle<v8::Object> wrapper, v8::Isolate* isolate, const WrapperTypeInfo* wrapperTypeInfo) 12753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) { 12853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) ASSERT(!containsWrapper()); 12953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) if (!*wrapper) { 1307242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci m_wrapper = 0; 13153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) return; 13253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) } 13353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) v8::Persistent<v8::Object> persistent(isolate, wrapper); 1347242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci wrapperTypeInfo->configureWrapper(&persistent); 135a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) persistent.SetWeak(this, &setWeakCallback); 1367242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci m_wrapper = persistent.ClearAndLeak(); 13753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) ASSERT(containsWrapper()); 13853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) } 13953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) 1407757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch v8::Local<v8::Object> newLocalWrapper(v8::Isolate* isolate) const 1417757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch { 14210f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch v8::Persistent<v8::Object> persistent; 14310f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch getPersistent(&persistent); 14410f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch return v8::Local<v8::Object>::New(isolate, persistent); 1457757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch } 1467757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 147f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu bool isEqualTo(const v8::Local<v8::Object>& other) const 148f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu { 149f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu v8::Persistent<v8::Object> persistent; 150f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu getPersistent(&persistent); 151f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu return persistent == other; 152f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu } 153f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu 15453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) static bool wrapperCanBeStoredInObject(const void*) { return false; } 15553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) static bool wrapperCanBeStoredInObject(const ScriptWrappable*) { return true; } 15653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) 15710f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch static ScriptWrappable* fromObject(const void*) 15853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) { 15953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) ASSERT_NOT_REACHED(); 16010f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch return 0; 16153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) } 16253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) 16310f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch static ScriptWrappable* fromObject(ScriptWrappable* object) 16453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) { 16510f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch return object; 16653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) } 16753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) 16810f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch bool setReturnValue(v8::ReturnValue<v8::Value> returnValue) 16953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) { 17010f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch v8::Persistent<v8::Object> persistent; 17110f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch getPersistent(&persistent); 17210f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch returnValue.Set(persistent); 17310f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch return containsWrapper(); 17453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) } 17553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) 17610f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch void markAsDependentGroup(ScriptWrappable* groupRoot, v8::Isolate* isolate) 17753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) { 17810f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch ASSERT(containsWrapper()); 17910f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch ASSERT(groupRoot && groupRoot->containsWrapper()); 18010f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch 1817242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci v8::UniqueId groupId(reinterpret_cast<intptr_t>(groupRoot->m_wrapper)); 18210f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch v8::Persistent<v8::Object> wrapper; 18310f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch getPersistent(&wrapper); 18410f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch wrapper.MarkPartiallyDependent(); 18510f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch isolate->SetObjectGroupId(v8::Persistent<v8::Value>::Cast(wrapper), groupId); 18653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) } 18753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) 18810f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch void setReference(const v8::Persistent<v8::Object>& parent, v8::Isolate* isolate) 18953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) { 19010f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch v8::Persistent<v8::Object> persistent; 19110f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch getPersistent(&persistent); 19210f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch isolate->SetReference(parent, persistent); 19353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) } 19453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) 19510f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch template<typename V8T, typename T> 19610f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch static void assertWrapperSanity(v8::Local<v8::Object> object, T* objectAsT) 19753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) { 19810f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch ASSERT(objectAsT); 19910f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch RELEASE_ASSERT_WITH_SECURITY_IMPLICATION(object.IsEmpty() 2007242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci || object->GetAlignedPointerFromInternalField(v8DOMWrapperObjectIndex) == V8T::toScriptWrappableBase(objectAsT)); 20153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) } 20253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) 203e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles) template<typename V8T, typename T> 204323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) static void assertWrapperSanity(void* object, T* objectAsT) 205e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles) { 20610f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch ASSERT_NOT_REACHED(); 207e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles) } 208e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles) 20910f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch template<typename V8T, typename T> 210323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) static void assertWrapperSanity(ScriptWrappable* object, T* objectAsT) 211e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles) { 21210f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch ASSERT(object); 213323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) ASSERT(objectAsT); 2147242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci v8::Object* value = object->m_wrapper; 215323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) RELEASE_ASSERT_WITH_SECURITY_IMPLICATION(value == 0 2167242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci || value->GetAlignedPointerFromInternalField(v8DOMWrapperObjectIndex) == V8T::toScriptWrappableBase(objectAsT)); 217e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles) } 218e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles) 2197242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci using ScriptWrappableBase::assertWrapperSanity; 2207242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci 2217242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci bool containsWrapper() const { return m_wrapper; } 22210f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch 223197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch#if !ENABLE(OILPAN) 22453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)protected: 225197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch virtual ~ScriptWrappable() 22653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) { 227aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch // We must not get deleted as long as we contain a wrapper. If this happens, we screwed up ref 228aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch // counting somewhere. Crash here instead of crashing during a later gc cycle. 229aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch RELEASE_ASSERT_WITH_SECURITY_IMPLICATION(!containsWrapper()); 2307242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci m_wrapper = 0; // Break UAF attempts to wrap. 23153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) } 232197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch#endif 233197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch // With Oilpan we don't need a ScriptWrappable destructor. 234197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch // 235197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch // - 'RELEASE_ASSERT_WITH_SECURITY_IMPLICATION(!containsWrapper())' is not needed 236197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch // because Oilpan is not using reference counting at all. If containsWrapper() is true, 237197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch // it means that ScriptWrappable still has a wrapper. In this case, the destructor 238197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch // must not be called since the wrapper has a persistent handle back to this ScriptWrappable object. 239197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch // Assuming that Oilpan's GC is correct (If we cannot assume this, a lot of more things are 240197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch // already broken), we must not hit the RELEASE_ASSERT. 241197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch // 2427242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci // - 'm_wrapper = 0' is not needed because Oilpan's GC zeroes out memory when 243197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch // the memory is collected and added to a free list. 24453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) 24553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)private: 24610f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch void getPersistent(v8::Persistent<v8::Object>* persistent) const 24753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) { 24810f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch ASSERT(persistent); 24953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) 25010f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch // Horrible and super unsafe: Cast the Persistent to an Object*, so 25110f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch // that we can inject the wrapped value. This only works because 25210f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch // we previously 'stole' the object pointer from a Persistent in 25310f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch // the setWrapper() method. 2547242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci *reinterpret_cast<v8::Object**>(persistent) = m_wrapper; 25553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) } 25653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) 2577242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci void disposeWrapper(v8::Local<v8::Object> wrapper) 25853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) { 25953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) ASSERT(containsWrapper()); 26010f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch 26110f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch v8::Persistent<v8::Object> persistent; 26210f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch getPersistent(&persistent); 26310f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch 26410f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch ASSERT(wrapper == persistent); 26510f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch persistent.Reset(); 2667242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci m_wrapper = 0; 26753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) } 26853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) 269a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) static void setWeakCallback(const v8::WeakCallbackData<v8::Object, ScriptWrappable>& data) 27093ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) { 27110f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch v8::Persistent<v8::Object> persistent; 27210f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch data.GetParameter()->getPersistent(&persistent); 27310f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch ASSERT(persistent == data.GetValue()); 27409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) data.GetParameter()->disposeWrapper(data.GetValue()); 27593ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) 27693ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) // FIXME: I noticed that 50%~ of minor GC cycle times can be consumed 277a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) // inside data.GetParameter()->deref(), which causes Node destructions. We should 27893ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) // make Node destructions incremental. 27909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) releaseObject(data.GetValue()); 28093ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) } 2817242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci 2827242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci v8::Object* m_wrapper; 28393ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)}; 28453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) 2857242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci// Defines 'wrapperTypeInfo' virtual method which returns the WrapperTypeInfo of 2867242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci// the instance. Also declares a static member of type WrapperTypeInfo, of which 2877242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci// the definition is given by the IDL code generator. 2887242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci// 2897242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci// Every DOM Class T must meet either of the following conditions: 2907242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci// - T.idl inherits from [NotScriptWrappable]. 2917242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci// - T inherits from ScriptWrappable and has DEFINE_WRAPPERTYPEINFO(). 2927242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci// 2937242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci// If a DOM class T does not inherit from ScriptWrappable, you have to write 2947242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci// [NotScriptWrappable] in the IDL file as an extended attribute in order to let 2957242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci// IDL code generator know that T does not inherit from ScriptWrappable. Note 2967242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci// that [NotScriptWrappable] is inheritable. 2977242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci// 2987242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci// All the derived classes of ScriptWrappable, regardless of directly or 2997242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci// indirectly, must write this macro in the class definition. 3007242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci#define DEFINE_WRAPPERTYPEINFO() \ 3017242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tuccipublic: \ 3027242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci virtual const WrapperTypeInfo* wrapperTypeInfo() const OVERRIDE \ 3037242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci { \ 3047242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci return &s_wrapperTypeInfo; \ 3057242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci } \ 3067242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucciprivate: \ 3077242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci static const WrapperTypeInfo& s_wrapperTypeInfo 3087242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci 309c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)} // namespace blink 31053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) 31153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#endif // ScriptWrappable_h 312