Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / bindings / v8 / V8PerContextData.h
index fb13537..2c62b73 100644 (file)
@@ -36,6 +36,8 @@
 #include "bindings/v8/UnsafePersistent.h"
 #include "bindings/v8/V8DOMActivityLogger.h"
 #include "bindings/v8/WrapperTypeInfo.h"
+#include "gin/public/context_holder.h"
+#include "gin/public/gin_embedders.h"
 #include <v8.h>
 #include "wtf/HashMap.h"
 #include "wtf/PassOwnPtr.h"
 namespace WebCore {
 
 class CustomElementDefinition;
+class DOMWrapperWorld;
+class V8PerContextData;
 struct V8NPObject;
 typedef WTF::Vector<V8NPObject*> V8NPObjectVector;
 typedef WTF::HashMap<int, V8NPObjectVector> V8NPObjectMap;
 
 enum V8ContextEmbedderDataField {
-    v8ContextDebugIdIndex,
-    v8ContextPerContextDataIndex,
-    v8ContextIsolatedWorld,
-    // Rather than adding more embedder data fields to v8::Context,
-    // consider adding the data to V8PerContextData instead.
+    v8ContextDebugIdIndex = static_cast<int>(gin::kDebugIdIndex),
+    v8ContextPerContextDataIndex = static_cast<int>(gin::kPerContextDataStartIndex + gin::kEmbedderBlink),
+};
+
+class V8PerContextDataHolder {
+    WTF_MAKE_NONCOPYABLE(V8PerContextDataHolder);
+public:
+    static void install(v8::Handle<v8::Context> context, DOMWrapperWorld* world)
+    {
+        new V8PerContextDataHolder(context, world);
+    }
+
+    static V8PerContextDataHolder* from(v8::Handle<v8::Context> context)
+    {
+        return static_cast<V8PerContextDataHolder*>(context->GetAlignedPointerFromEmbedderData(v8ContextPerContextDataIndex));
+    }
+
+    V8PerContextData* perContextData() const { return m_perContextData; }
+    void setPerContextData(V8PerContextData* data) { m_perContextData = data; }
+
+    DOMWrapperWorld* world() const { return m_world; }
+
+private:
+    V8PerContextDataHolder(v8::Handle<v8::Context> context, DOMWrapperWorld* world)
+        : m_context(v8::Isolate::GetCurrent(), context)
+        , m_perContextData(0)
+        , m_world(world)
+    {
+        m_context.setWeak(this, &V8PerContextDataHolder::weakCallback);
+        context->SetAlignedPointerInEmbedderData(v8ContextPerContextDataIndex, this);
+    }
+
+    ~V8PerContextDataHolder() {}
+
+    static void weakCallback(const v8::WeakCallbackData<v8::Context, V8PerContextDataHolder>& data)
+    {
+        data.GetValue()->SetAlignedPointerInEmbedderData(v8ContextPerContextDataIndex, 0);
+        delete data.GetParameter();
+    }
+
+    ScopedPersistent<v8::Context> m_context;
+    V8PerContextData* m_perContextData;
+    // This should not be a RefPtr. Otherwise, it creates a cycle:
+    // V8PerContextData => DOMWrapperWorld => DOMDataStore => global objects
+    // => Window or WorkerGlobalScope => V8PerContextData.
+    DOMWrapperWorld* m_world;
 };
 
 class V8PerContextData {
@@ -65,16 +110,13 @@ public:
         return adoptPtr(new V8PerContextData(context));
     }
 
-    ~V8PerContextData()
-    {
-        dispose();
-    }
+    ~V8PerContextData();
 
     bool init();
 
     static V8PerContextData* from(v8::Handle<v8::Context> context)
     {
-        return static_cast<V8PerContextData*>(context->GetAlignedPointerFromEmbedderData(v8ContextPerContextDataIndex));
+        return V8PerContextDataHolder::from(context)->perContextData();
     }
 
     // To create JS Wrapper objects, we create a cache of a 'boiler plate'
@@ -124,8 +166,6 @@ private:
     {
     }
 
-    void dispose();
-
     v8::Local<v8::Object> createWrapperFromCacheSlowCase(const WrapperTypeInfo*);
     v8::Local<v8::Function> constructorForTypeSlowCase(const WrapperTypeInfo*);
 
@@ -143,7 +183,7 @@ private:
     // by the DOMActivityLoggerMap in DOMWrapperWorld.
     V8DOMActivityLogger* m_activityLogger;
     v8::Isolate* m_isolate;
-    v8::Persistent<v8::Context> m_context;
+    ScopedPersistent<v8::Context> m_context;
     ScopedPersistent<v8::Value> m_errorPrototype;
 
     typedef WTF::HashMap<CustomElementDefinition*, OwnPtr<CustomElementBinding> > CustomElementBindingMap;