OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2012 Google Inc. All rights reserved. | 2 * Copyright (C) 2012 Google Inc. All rights reserved. |
3 * | 3 * |
4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
5 * modification, are permitted provided that the following conditions are | 5 * modification, are permitted provided that the following conditions are |
6 * met: | 6 * met: |
7 * | 7 * |
8 * * Redistributions of source code must retain the above copyright | 8 * * Redistributions of source code must retain the above copyright |
9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
10 * * Redistributions in binary form must reproduce the above | 10 * * Redistributions in binary form must reproduce the above |
(...skipping 30 matching lines...) Expand all Loading... |
41 | 41 |
42 template<typename Map> | 42 template<typename Map> |
43 static void disposeMapWithUnsafePersistentValues(Map* map) | 43 static void disposeMapWithUnsafePersistentValues(Map* map) |
44 { | 44 { |
45 typename Map::iterator it = map->begin(); | 45 typename Map::iterator it = map->begin(); |
46 for (; it != map->end(); ++it) | 46 for (; it != map->end(); ++it) |
47 it->value.dispose(); | 47 it->value.dispose(); |
48 map->clear(); | 48 map->clear(); |
49 } | 49 } |
50 | 50 |
| 51 class V8PerContextDataHolder { |
| 52 WTF_MAKE_NONCOPYABLE(V8PerContextDataHolder); |
| 53 public: |
| 54 static void install(v8::Handle<v8::Context> context, DOMWrapperWorld* world) |
| 55 { |
| 56 new V8PerContextDataHolder(context, world); |
| 57 } |
| 58 |
| 59 static V8PerContextDataHolder* from(v8::Handle<v8::Context> context) |
| 60 { |
| 61 V8PerContextDataHolder* holder = static_cast<V8PerContextDataHolder*>(co
ntext->GetAlignedPointerFromEmbedderData(v8ContextPerContextDataIndex)); |
| 62 // |holder| must not be 0 because V8PerContextDataHolder is kept alive a
s long as the |context| is alive. |
| 63 // Here we have a handle to the |context|, which means that the V8PerCon
textDataHolder is alive. |
| 64 ASSERT(holder); |
| 65 return holder; |
| 66 } |
| 67 |
| 68 V8PerContextData* perContextData() const { return m_perContextData; } |
| 69 void setPerContextData(V8PerContextData* data) { m_perContextData = data; } |
| 70 DOMWrapperWorld* world() const { return m_world; } |
| 71 |
| 72 private: |
| 73 V8PerContextDataHolder(v8::Handle<v8::Context> context, DOMWrapperWorld* wor
ld) |
| 74 : m_context(v8::Isolate::GetCurrent(), context) |
| 75 , m_perContextData(0) |
| 76 , m_world(world) |
| 77 { |
| 78 m_context.setWeak(this, &V8PerContextDataHolder::weakCallback); |
| 79 context->SetAlignedPointerInEmbedderData(v8ContextPerContextDataIndex, t
his); |
| 80 } |
| 81 |
| 82 ~V8PerContextDataHolder() { } |
| 83 |
| 84 static void weakCallback(const v8::WeakCallbackData<v8::Context, V8PerContex
tDataHolder>& data) |
| 85 { |
| 86 data.GetValue()->SetAlignedPointerInEmbedderData(v8ContextPerContextData
Index, 0); |
| 87 delete data.GetParameter(); |
| 88 } |
| 89 |
| 90 ScopedPersistent<v8::Context> m_context; |
| 91 V8PerContextData* m_perContextData; |
| 92 // This should not be a RefPtr. Otherwise, it creates a cycle: |
| 93 // V8PerContextData => DOMWrapperWorld => DOMDataStore => global objects |
| 94 // => Window or WorkerGlobalScope => V8PerContextData. |
| 95 DOMWrapperWorld* m_world; |
| 96 }; |
| 97 |
| 98 V8PerContextData::V8PerContextData(v8::Handle<v8::Context> context, DOMWrapperWo
rld* world) |
| 99 : m_activityLogger(0) |
| 100 , m_isolate(context->GetIsolate()) |
| 101 , m_contextHolder(adoptPtr(new gin::ContextHolder(context->GetIsolate()))) |
| 102 , m_context(m_isolate, context) |
| 103 , m_customElementBindings(adoptPtr(new CustomElementBindingMap())) |
| 104 { |
| 105 m_contextHolder->SetContext(context); |
| 106 V8PerContextDataHolder::install(context, world); |
| 107 V8PerContextDataHolder::from(context)->setPerContextData(this); |
| 108 |
| 109 v8::Context::Scope contextScope(context); |
| 110 ASSERT(m_errorPrototype.isEmpty()); |
| 111 v8::Handle<v8::Object> object = v8::Handle<v8::Object>::Cast(context->Global
()->Get(v8AtomicString(m_isolate, "Error"))); |
| 112 ASSERT(!object.IsEmpty()); |
| 113 v8::Handle<v8::Value> prototypeValue = object->Get(v8AtomicString(m_isolate,
"prototype")); |
| 114 ASSERT(!prototypeValue.IsEmpty()); |
| 115 m_errorPrototype.set(m_isolate, prototypeValue); |
| 116 } |
| 117 |
51 V8PerContextData::~V8PerContextData() | 118 V8PerContextData::~V8PerContextData() |
52 { | 119 { |
53 v8::HandleScope handleScope(m_isolate); | 120 v8::HandleScope handleScope(m_isolate); |
54 V8PerContextDataHolder::from(m_context.newLocal(m_isolate))->setPerContextDa
ta(0); | 121 V8PerContextDataHolder::from(m_context.newLocal(m_isolate))->setPerContextDa
ta(0); |
55 | 122 |
56 disposeMapWithUnsafePersistentValues(&m_wrapperBoilerplates); | 123 disposeMapWithUnsafePersistentValues(&m_wrapperBoilerplates); |
57 disposeMapWithUnsafePersistentValues(&m_constructorMap); | 124 disposeMapWithUnsafePersistentValues(&m_constructorMap); |
58 m_customElementBindings.clear(); | |
59 } | 125 } |
60 | 126 |
61 #define V8_STORE_PRIMORDIAL(name, Name) \ | 127 V8PerContextData* V8PerContextData::from(v8::Handle<v8::Context> context) |
62 { \ | 128 { |
63 ASSERT(m_##name##Prototype.isEmpty()); \ | 129 return V8PerContextDataHolder::from(context)->perContextData(); |
64 v8::Handle<v8::String> symbol = v8AtomicString(m_isolate, #Name); \ | |
65 if (symbol.IsEmpty()) \ | |
66 return false; \ | |
67 v8::Handle<v8::Object> object = v8::Handle<v8::Object>::Cast(m_context.newLo
cal(m_isolate)->Global()->Get(symbol)); \ | |
68 if (object.IsEmpty()) \ | |
69 return false; \ | |
70 v8::Handle<v8::Value> prototypeValue = object->Get(prototypeString); \ | |
71 if (prototypeValue.IsEmpty()) \ | |
72 return false; \ | |
73 m_##name##Prototype.set(m_isolate, prototypeValue); \ | |
74 } | 130 } |
75 | 131 |
76 bool V8PerContextData::init() | 132 DOMWrapperWorld* V8PerContextData::world(v8::Handle<v8::Context> context) |
77 { | 133 { |
78 v8::Handle<v8::Context> context = m_context.newLocal(m_isolate); | 134 DOMWrapperWorld* world = V8PerContextDataHolder::from(context)->world(); |
79 V8PerContextDataHolder::from(context)->setPerContextData(this); | 135 ASSERT(world); |
80 | 136 return world; |
81 v8::Handle<v8::String> prototypeString = v8AtomicString(m_isolate, "prototyp
e"); | |
82 if (prototypeString.IsEmpty()) | |
83 return false; | |
84 | |
85 V8_STORE_PRIMORDIAL(error, Error); | |
86 | |
87 return true; | |
88 } | 137 } |
89 | 138 |
90 #undef V8_STORE_PRIMORDIAL | |
91 | |
92 v8::Local<v8::Object> V8PerContextData::createWrapperFromCacheSlowCase(const Wra
pperTypeInfo* type) | 139 v8::Local<v8::Object> V8PerContextData::createWrapperFromCacheSlowCase(const Wra
pperTypeInfo* type) |
93 { | 140 { |
94 ASSERT(!m_errorPrototype.isEmpty()); | 141 ASSERT(!m_errorPrototype.isEmpty()); |
95 | 142 |
96 v8::Context::Scope scope(m_context.newLocal(m_isolate)); | 143 v8::Context::Scope scope(context()); |
97 v8::Local<v8::Function> function = constructorForType(type); | 144 v8::Local<v8::Function> function = constructorForType(type); |
98 v8::Local<v8::Object> instanceTemplate = V8ObjectConstructor::newInstance(fu
nction); | 145 v8::Local<v8::Object> instanceTemplate = V8ObjectConstructor::newInstance(fu
nction); |
99 if (!instanceTemplate.IsEmpty()) { | 146 if (!instanceTemplate.IsEmpty()) { |
100 m_wrapperBoilerplates.set(type, UnsafePersistent<v8::Object>(m_isolate,
instanceTemplate)); | 147 m_wrapperBoilerplates.set(type, UnsafePersistent<v8::Object>(m_isolate,
instanceTemplate)); |
101 return instanceTemplate->Clone(); | 148 return instanceTemplate->Clone(); |
102 } | 149 } |
103 return v8::Local<v8::Object>(); | 150 return v8::Local<v8::Object>(); |
104 } | 151 } |
105 | 152 |
106 v8::Local<v8::Function> V8PerContextData::constructorForTypeSlowCase(const Wrapp
erTypeInfo* type) | 153 v8::Local<v8::Function> V8PerContextData::constructorForTypeSlowCase(const Wrapp
erTypeInfo* type) |
107 { | 154 { |
108 ASSERT(!m_errorPrototype.isEmpty()); | 155 ASSERT(!m_errorPrototype.isEmpty()); |
109 | 156 |
110 v8::Context::Scope scope(m_context.newLocal(m_isolate)); | 157 v8::Context::Scope scope(context()); |
111 v8::Handle<v8::FunctionTemplate> functionTemplate = type->domTemplate(m_isol
ate, worldType(m_isolate)); | 158 v8::Handle<v8::FunctionTemplate> functionTemplate = type->domTemplate(m_isol
ate, worldType(m_isolate)); |
112 // Getting the function might fail if we're running out of stack or memory. | 159 // Getting the function might fail if we're running out of stack or memory. |
113 v8::TryCatch tryCatch; | 160 v8::TryCatch tryCatch; |
114 v8::Local<v8::Function> function = functionTemplate->GetFunction(); | 161 v8::Local<v8::Function> function = functionTemplate->GetFunction(); |
115 if (function.IsEmpty()) | 162 if (function.IsEmpty()) |
116 return v8::Local<v8::Function>(); | 163 return v8::Local<v8::Function>(); |
117 | 164 |
118 if (type->parentClass) { | 165 if (type->parentClass) { |
119 v8::Local<v8::Object> prototypeTemplate = constructorForType(type->paren
tClass); | 166 v8::Local<v8::Object> prototypeTemplate = constructorForType(type->paren
tClass); |
120 if (prototypeTemplate.IsEmpty()) | 167 if (prototypeTemplate.IsEmpty()) |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
212 if (!data->IsString()) | 259 if (!data->IsString()) |
213 return -1; | 260 return -1; |
214 v8::String::Utf8Value utf8(data); | 261 v8::String::Utf8Value utf8(data); |
215 char* comma = strnstr(*utf8, ",", utf8.length()); | 262 char* comma = strnstr(*utf8, ",", utf8.length()); |
216 if (!comma) | 263 if (!comma) |
217 return -1; | 264 return -1; |
218 return atoi(comma + 1); | 265 return atoi(comma + 1); |
219 } | 266 } |
220 | 267 |
221 } // namespace WebCore | 268 } // namespace WebCore |
OLD | NEW |