Index: Source/bindings/v8/V8PerContextData.cpp |
diff --git a/Source/bindings/v8/V8PerContextData.cpp b/Source/bindings/v8/V8PerContextData.cpp |
index ff9ce8e73e72dc8caae4800aebd3c6cbb098dcc9..169e2a16fd6bddb53897e8983dbf667c72d59887 100644 |
--- a/Source/bindings/v8/V8PerContextData.cpp |
+++ b/Source/bindings/v8/V8PerContextData.cpp |
@@ -48,6 +48,73 @@ static void disposeMapWithUnsafePersistentValues(Map* map) |
map->clear(); |
} |
+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) |
+ { |
+ V8PerContextDataHolder* holder = static_cast<V8PerContextDataHolder*>(context->GetAlignedPointerFromEmbedderData(v8ContextPerContextDataIndex)); |
+ // |holder| must not be 0 because V8PerContextDataHolder is kept alive as long as the |context| is alive. |
+ // Here we have a handle to the |context|, which means that the V8PerContextDataHolder is alive. |
+ ASSERT(holder); |
+ return holder; |
+ } |
+ |
+ 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; |
+}; |
+ |
+V8PerContextData::V8PerContextData(v8::Handle<v8::Context> context, DOMWrapperWorld* world) |
+ : m_activityLogger(0) |
+ , m_isolate(context->GetIsolate()) |
+ , m_contextHolder(adoptPtr(new gin::ContextHolder(context->GetIsolate()))) |
+ , m_context(m_isolate, context) |
+ , m_customElementBindings(adoptPtr(new CustomElementBindingMap())) |
+{ |
+ m_contextHolder->SetContext(context); |
+ V8PerContextDataHolder::install(context, world); |
+ V8PerContextDataHolder::from(context)->setPerContextData(this); |
+ |
+ v8::Context::Scope contextScope(context); |
+ ASSERT(m_errorPrototype.isEmpty()); |
+ v8::Handle<v8::Object> object = v8::Handle<v8::Object>::Cast(context->Global()->Get(v8AtomicString(m_isolate, "Error"))); |
+ ASSERT(!object.IsEmpty()); |
+ v8::Handle<v8::Value> prototypeValue = object->Get(v8AtomicString(m_isolate, "prototype")); |
+ ASSERT(!prototypeValue.IsEmpty()); |
+ m_errorPrototype.set(m_isolate, prototypeValue); |
+} |
+ |
V8PerContextData::~V8PerContextData() |
{ |
v8::HandleScope handleScope(m_isolate); |
@@ -55,45 +122,25 @@ V8PerContextData::~V8PerContextData() |
disposeMapWithUnsafePersistentValues(&m_wrapperBoilerplates); |
disposeMapWithUnsafePersistentValues(&m_constructorMap); |
- m_customElementBindings.clear(); |
} |
-#define V8_STORE_PRIMORDIAL(name, Name) \ |
-{ \ |
- ASSERT(m_##name##Prototype.isEmpty()); \ |
- v8::Handle<v8::String> symbol = v8AtomicString(m_isolate, #Name); \ |
- if (symbol.IsEmpty()) \ |
- return false; \ |
- v8::Handle<v8::Object> object = v8::Handle<v8::Object>::Cast(m_context.newLocal(m_isolate)->Global()->Get(symbol)); \ |
- if (object.IsEmpty()) \ |
- return false; \ |
- v8::Handle<v8::Value> prototypeValue = object->Get(prototypeString); \ |
- if (prototypeValue.IsEmpty()) \ |
- return false; \ |
- m_##name##Prototype.set(m_isolate, prototypeValue); \ |
+V8PerContextData* V8PerContextData::from(v8::Handle<v8::Context> context) |
+{ |
+ return V8PerContextDataHolder::from(context)->perContextData(); |
} |
-bool V8PerContextData::init() |
+DOMWrapperWorld* V8PerContextData::world(v8::Handle<v8::Context> context) |
{ |
- v8::Handle<v8::Context> context = m_context.newLocal(m_isolate); |
- V8PerContextDataHolder::from(context)->setPerContextData(this); |
- |
- v8::Handle<v8::String> prototypeString = v8AtomicString(m_isolate, "prototype"); |
- if (prototypeString.IsEmpty()) |
- return false; |
- |
- V8_STORE_PRIMORDIAL(error, Error); |
- |
- return true; |
+ DOMWrapperWorld* world = V8PerContextDataHolder::from(context)->world(); |
+ ASSERT(world); |
+ return world; |
} |
-#undef V8_STORE_PRIMORDIAL |
- |
v8::Local<v8::Object> V8PerContextData::createWrapperFromCacheSlowCase(const WrapperTypeInfo* type) |
{ |
ASSERT(!m_errorPrototype.isEmpty()); |
- v8::Context::Scope scope(m_context.newLocal(m_isolate)); |
+ v8::Context::Scope scope(context()); |
v8::Local<v8::Function> function = constructorForType(type); |
v8::Local<v8::Object> instanceTemplate = V8ObjectConstructor::newInstance(function); |
if (!instanceTemplate.IsEmpty()) { |
@@ -107,7 +154,7 @@ v8::Local<v8::Function> V8PerContextData::constructorForTypeSlowCase(const Wrapp |
{ |
ASSERT(!m_errorPrototype.isEmpty()); |
- v8::Context::Scope scope(m_context.newLocal(m_isolate)); |
+ v8::Context::Scope scope(context()); |
v8::Handle<v8::FunctionTemplate> functionTemplate = type->domTemplate(m_isolate, worldType(m_isolate)); |
// Getting the function might fail if we're running out of stack or memory. |
v8::TryCatch tryCatch; |