| 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;
|
|
|