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