OLD | NEW |
1 /* | 1 /* |
2 * This file is part of Adblock Plus <https://adblockplus.org/>, | 2 * This file is part of Adblock Plus <https://adblockplus.org/>, |
3 * Copyright (C) 2006-present eyeo GmbH | 3 * Copyright (C) 2006-present eyeo GmbH |
4 * | 4 * |
5 * Adblock Plus is free software: you can redistribute it and/or modify | 5 * Adblock Plus is free software: you can redistribute it and/or modify |
6 * it under the terms of the GNU General Public License version 3 as | 6 * it under the terms of the GNU General Public License version 3 as |
7 * published by the Free Software Foundation. | 7 * published by the Free Software Foundation. |
8 * | 8 * |
9 * Adblock Plus is distributed in the hope that it will be useful, | 9 * Adblock Plus is distributed in the hope that it will be useful, |
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of | 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
101 private: | 101 private: |
102 ScopedV8Isolate(const ScopedV8Isolate&); | 102 ScopedV8Isolate(const ScopedV8Isolate&); |
103 ScopedV8Isolate& operator=(const ScopedV8Isolate&); | 103 ScopedV8Isolate& operator=(const ScopedV8Isolate&); |
104 | 104 |
105 v8::Isolate* isolate; | 105 v8::Isolate* isolate; |
106 }; | 106 }; |
107 } | 107 } |
108 | 108 |
109 using namespace AdblockPlus; | 109 using namespace AdblockPlus; |
110 | 110 |
111 JsEngine::JsWeakValuesList::~JsWeakValuesList() | 111 template <> JsWeakValuesList<v8::Global<v8::Value>>::~JsWeakValuesList() |
112 { | 112 { |
113 } | 113 } |
114 | 114 |
115 void JsEngine::NotifyLowMemory() | 115 |
| 116 template <> void AdblockPlus::JSENGINEV8::NotifyLowMemory() |
116 { | 117 { |
117 const JsContext context(*this); | 118 const JsContext context(*this); |
118 GetIsolate()->MemoryPressureNotification(v8::MemoryPressureLevel::kCritical); | 119 GetIsolate()->MemoryPressureNotification(v8::MemoryPressureLevel::kCritical); |
119 } | 120 } |
120 | 121 |
121 void JsEngine::ScheduleTimer(const v8::FunctionCallbackInfo<v8::Value>& argument
s) | 122 template <> void AdblockPlus::JSENGINEV8::ScheduleTimer(const v8::FunctionCallba
ckInfo<v8::Value>& arguments) |
122 { | 123 { |
123 auto jsEngine = FromArguments(arguments); | 124 auto jsEngine = FromArguments(arguments); |
124 if (arguments.Length() < 2) | 125 if (arguments.Length() < 2) |
125 throw std::runtime_error("setTimeout requires at least 2 parameters"); | 126 throw std::runtime_error("setTimeout requires at least 2 parameters"); |
126 | 127 |
127 if (!arguments[0]->IsFunction()) | 128 if (!arguments[0]->IsFunction()) |
128 throw std::runtime_error("First argument to setTimeout must be a function"); | 129 throw std::runtime_error("First argument to setTimeout must be a function"); |
129 | 130 |
130 auto jsValueArguments = jsEngine->ConvertArguments(arguments); | 131 auto jsValueArguments = jsEngine->ConvertArguments(arguments); |
131 auto timerParamsID = jsEngine->StoreJsValues(jsValueArguments); | 132 auto timerParamsID = jsEngine->StoreJsValues(jsValueArguments); |
132 | 133 |
133 std::weak_ptr<JsEngine> weakJsEngine = jsEngine; | 134 std::weak_ptr<JsEngine> weakJsEngine = jsEngine; |
134 jsEngine->platform.WithTimer( | 135 jsEngine->platform.WithTimer( |
135 [arguments, weakJsEngine, timerParamsID](ITimer& timer) | 136 [arguments, weakJsEngine, timerParamsID](ITimer& timer) |
136 { | 137 { |
137 timer.SetTimer( | 138 timer.SetTimer( |
138 std::chrono::milliseconds( | 139 std::chrono::milliseconds( |
139 arguments[1]->IntegerValue()), [weakJsEngine, timerParamsID] | 140 arguments[1]->IntegerValue()), [weakJsEngine, timerParamsID] |
140 { | 141 { |
141 if (auto jsEngine = weakJsEngine.lock()) | 142 if (auto jsEngine = weakJsEngine.lock()) |
142 jsEngine->CallTimerTask(timerParamsID); | 143 jsEngine->CallTimerTask(timerParamsID); |
143 }); | 144 }); |
144 }); | 145 }); |
145 } | 146 } |
146 | 147 |
147 void JsEngine::CallTimerTask(const JsWeakValuesID& timerParamsID) | 148 template <> void AdblockPlus::JSENGINEV8::CallTimerTask(const JsWeakValuesID& ti
merParamsID) |
148 { | 149 { |
149 auto timerParams = TakeJsValues(timerParamsID); | 150 auto timerParams = TakeJsValues(timerParamsID); |
150 JsValue callback = std::move(timerParams[0]); | 151 JsValue callback = std::move(timerParams[0]); |
151 | 152 |
152 timerParams.erase(timerParams.begin()); // remove callback placeholder | 153 timerParams.erase(timerParams.begin()); // remove callback placeholder |
153 timerParams.erase(timerParams.begin()); // remove timeout param | 154 timerParams.erase(timerParams.begin()); // remove timeout param |
154 callback.Call(timerParams); | 155 callback.Call(timerParams); |
155 } | 156 } |
156 | 157 |
157 AdblockPlus::JsEngine::JsEngine(Platform& platform, std::unique_ptr<IV8IsolatePr
ovider> isolate) | 158 template <> AdblockPlus::JSENGINEV8::JsEngineTemplate(Platform& platform, std::u
nique_ptr<IV8IsolateProvider> isolate) |
158 : platform(platform) | 159 : platform(platform) |
159 , isolate(std::move(isolate)) | 160 , isolate(std::move(isolate)) |
160 { | 161 { |
161 } | 162 } |
162 | 163 |
163 AdblockPlus::JsEnginePtr AdblockPlus::JsEngine::New(const AppInfo& appInfo, | 164 |
| 165 template <> AdblockPlus::JsEnginePtr AdblockPlus::JSENGINEV8::New(const AppInfo&
appInfo, |
164 Platform& platform, std::unique_ptr<IV8IsolateProvider> isolate) | 166 Platform& platform, std::unique_ptr<IV8IsolateProvider> isolate) |
165 { | 167 { |
166 if (!isolate) | 168 if (!isolate) |
167 { | 169 { |
168 isolate.reset(new ScopedV8Isolate()); | 170 isolate.reset(new ScopedV8Isolate()); |
169 } | 171 } |
170 JsEnginePtr result(new JsEngine(platform, std::move(isolate))); | 172 JsEnginePtr result(new JsEngine(platform, std::move(isolate))); |
171 | 173 |
172 const v8::Locker locker(result->GetIsolate()); | 174 const v8::Locker locker(result->GetIsolate()); |
173 const v8::Isolate::Scope isolateScope(result->GetIsolate()); | 175 const v8::Isolate::Scope isolateScope(result->GetIsolate()); |
174 const v8::HandleScope handleScope(result->GetIsolate()); | 176 const v8::HandleScope handleScope(result->GetIsolate()); |
175 | 177 |
176 result->context.reset(new v8::Global<v8::Context>(result->GetIsolate(), | 178 result->context.reset(new v8::Global<v8::Context>(result->GetIsolate(), |
177 v8::Context::New(result->GetIsolate()))); | 179 v8::Context::New(result->GetIsolate()))); |
178 auto global = result->GetGlobalObject(); | 180 auto global = result->GetGlobalObject(); |
179 AdblockPlus::GlobalJsObject::Setup(*result, appInfo, global); | 181 AdblockPlus::GlobalJsObject::Setup(*result, appInfo, global); |
180 return result; | 182 return result; |
181 } | 183 } |
182 | 184 |
183 AdblockPlus::JsValue AdblockPlus::JsEngine::GetGlobalObject() | 185 template <> AdblockPlus::JsValue AdblockPlus::JSENGINEV8::GetGlobalObject() |
184 { | 186 { |
185 JsContext context(*this); | 187 JsContext context(*this); |
186 return JsValue(shared_from_this(), context.GetV8Context()->Global()); | 188 return JsValue(shared_from_this(), context.GetJSEngineContext()->Global()); |
187 } | 189 } |
188 | 190 |
189 AdblockPlus::JsValue AdblockPlus::JsEngine::Evaluate(const std::string& source, | 191 template <> AdblockPlus::JsValue AdblockPlus::JSENGINEV8::Evaluate(const std::st
ring& source, |
190 const std::string& filename) | 192 const std::string& filename) |
191 { | 193 { |
192 const JsContext context(*this); | 194 const JsContext context(*this); |
193 const v8::TryCatch tryCatch; | 195 const v8::TryCatch tryCatch; |
194 const v8::Handle<v8::Script> script = CompileScript(GetIsolate(), source, | 196 const v8::Handle<v8::Script> script = CompileScript(GetIsolate(), source, |
195 filename); | 197 filename); |
196 CheckTryCatch(tryCatch); | 198 CheckTryCatch(tryCatch); |
197 v8::Local<v8::Value> result = script->Run(); | 199 v8::Local<v8::Value> result = script->Run(); |
198 CheckTryCatch(tryCatch); | 200 CheckTryCatch(tryCatch); |
199 return JsValue(shared_from_this(), result); | 201 return JsValue(shared_from_this(), result); |
200 } | 202 } |
201 | 203 |
202 void AdblockPlus::JsEngine::SetEventCallback(const std::string& eventName, | 204 template <> void AdblockPlus::JSENGINEV8::SetEventCallback(const std::string& ev
entName, |
203 const AdblockPlus::JsEngine::EventCallback& callback) | 205 const AdblockPlus::JSENGINEV8::EventCallback& callback) |
204 { | 206 { |
205 if (!callback) | 207 if (!callback) |
206 { | 208 { |
207 RemoveEventCallback(eventName); | 209 RemoveEventCallback(eventName); |
208 return; | 210 return; |
209 } | 211 } |
210 std::lock_guard<std::mutex> lock(eventCallbacksMutex); | 212 std::lock_guard<std::mutex> lock(eventCallbacksMutex); |
211 eventCallbacks[eventName] = callback; | 213 eventCallbacks[eventName] = callback; |
212 } | 214 } |
213 | 215 |
214 void AdblockPlus::JsEngine::RemoveEventCallback(const std::string& eventName) | 216 template <> void AdblockPlus::JSENGINEV8::RemoveEventCallback(const std::string&
eventName) |
215 { | 217 { |
216 std::lock_guard<std::mutex> lock(eventCallbacksMutex); | 218 std::lock_guard<std::mutex> lock(eventCallbacksMutex); |
217 eventCallbacks.erase(eventName); | 219 eventCallbacks.erase(eventName); |
218 } | 220 } |
219 | 221 |
220 void AdblockPlus::JsEngine::TriggerEvent(const std::string& eventName, AdblockPl
us::JsValueList&& params) | 222 template <> void AdblockPlus::JSENGINEV8::TriggerEvent(const std::string& eventN
ame, AdblockPlus::JsValueList&& params) |
221 { | 223 { |
222 EventCallback callback; | 224 EventCallback callback; |
223 { | 225 { |
224 std::lock_guard<std::mutex> lock(eventCallbacksMutex); | 226 std::lock_guard<std::mutex> lock(eventCallbacksMutex); |
225 auto it = eventCallbacks.find(eventName); | 227 auto it = eventCallbacks.find(eventName); |
226 if (it == eventCallbacks.end()) | 228 if (it == eventCallbacks.end()) |
227 return; | 229 return; |
228 callback = it->second; | 230 callback = it->second; |
229 } | 231 } |
230 callback(move(params)); | 232 callback(move(params)); |
231 } | 233 } |
232 | 234 |
233 void AdblockPlus::JsEngine::Gc() | 235 template <> void AdblockPlus::JSENGINEV8::Gc() |
234 { | 236 { |
235 while (!GetIsolate()->IdleNotification(1000)); | 237 while (!GetIsolate()->IdleNotification(1000)); |
236 } | 238 } |
237 | 239 |
238 AdblockPlus::JsValue AdblockPlus::JsEngine::NewValue(const std::string& val) | 240 template <> AdblockPlus::JsValue AdblockPlus::JSENGINEV8::NewValue(const std::st
ring& val) |
239 { | 241 { |
240 const JsContext context(*this); | 242 const JsContext context(*this); |
241 return JsValue(shared_from_this(), Utils::ToV8String(GetIsolate(), val)); | 243 return JsValue(shared_from_this(), Utils::ToV8String(GetIsolate(), val)); |
242 } | 244 } |
243 | 245 |
244 AdblockPlus::JsValue AdblockPlus::JsEngine::NewValue(int64_t val) | 246 template <> AdblockPlus::JsValue AdblockPlus::JSENGINEV8::NewValue(int64_t val) |
245 { | 247 { |
246 const JsContext context(*this); | 248 const JsContext context(*this); |
247 return JsValue(shared_from_this(), v8::Number::New(GetIsolate(), val)); | 249 return JsValue(shared_from_this(), v8::Number::New(GetIsolate(), val)); |
248 } | 250 } |
249 | 251 |
250 AdblockPlus::JsValue AdblockPlus::JsEngine::NewValue(bool val) | 252 template <> AdblockPlus::JsValue AdblockPlus::JSENGINEV8::NewValue(bool val) |
251 { | 253 { |
252 const JsContext context(*this); | 254 const JsContext context(*this); |
253 return JsValue(shared_from_this(), v8::Boolean::New(GetIsolate(), val)); | 255 return JsValue(shared_from_this(), v8::Boolean::New(GetIsolate(), val)); |
254 } | 256 } |
255 | 257 |
256 AdblockPlus::JsValue AdblockPlus::JsEngine::NewObject() | 258 template <> AdblockPlus::JsValue AdblockPlus::JSENGINEV8::NewObject() |
257 { | 259 { |
258 const JsContext context(*this); | 260 const JsContext context(*this); |
259 return JsValue(shared_from_this(), v8::Object::New(GetIsolate())); | 261 return JsValue(shared_from_this(), v8::Object::New(GetIsolate())); |
260 } | 262 } |
261 | 263 |
262 AdblockPlus::JsValue AdblockPlus::JsEngine::NewCallback( | 264 template <> AdblockPlus::JsValue AdblockPlus::JSENGINEV8::NewCallback( |
263 const v8::FunctionCallback& callback) | 265 const v8::FunctionCallback& callback) |
264 { | 266 { |
265 const JsContext context(*this); | 267 const JsContext context(*this); |
266 | 268 |
267 // Note: we are leaking this weak pointer, no obvious way to destroy it when | 269 // Note: we are leaking this weak pointer, no obvious way to destroy it when |
268 // it's no longer used | 270 // it's no longer used |
269 std::weak_ptr<JsEngine>* data = | 271 std::weak_ptr<JsEngine>* data = |
270 new std::weak_ptr<JsEngine>(shared_from_this()); | 272 new std::weak_ptr<JsEngine>(shared_from_this()); |
271 v8::Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(GetIsolate()
, callback, | 273 v8::Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(GetIsolate()
, callback, |
272 v8::External::New(GetIsolate(), data)); | 274 v8::External::New(GetIsolate(), data)); |
273 return JsValue(shared_from_this(), templ->GetFunction()); | 275 return JsValue(shared_from_this(), templ->GetFunction()); |
274 } | 276 } |
275 | 277 |
276 AdblockPlus::JsEnginePtr AdblockPlus::JsEngine::FromArguments(const v8::Function
CallbackInfo<v8::Value>& arguments) | 278 template <> AdblockPlus::JsEnginePtr AdblockPlus::JSENGINEV8::FromArguments(cons
t v8::FunctionCallbackInfo<v8::Value>& arguments) |
277 { | 279 { |
278 const v8::Local<const v8::External> external = | 280 const v8::Local<const v8::External> external = |
279 v8::Local<const v8::External>::Cast(arguments.Data()); | 281 v8::Local<const v8::External>::Cast(arguments.Data()); |
280 std::weak_ptr<JsEngine>* data = | 282 std::weak_ptr<JsEngine>* data = |
281 static_cast<std::weak_ptr<JsEngine>*>(external->Value()); | 283 static_cast<std::weak_ptr<JsEngine>*>(external->Value()); |
282 JsEnginePtr result = data->lock(); | 284 JsEnginePtr result = data->lock(); |
283 if (!result) | 285 if (!result) |
284 throw std::runtime_error("Oops, our JsEngine is gone, how did that happen?")
; | 286 throw std::runtime_error("Oops, our JsEngine is gone, how did that happen?")
; |
285 return result; | 287 return result; |
286 } | 288 } |
287 | 289 |
288 JsEngine::JsWeakValuesID JsEngine::StoreJsValues(const JsValueList& values) | 290 template <> AdblockPlus::JsWeakValuesID AdblockPlus::JSENGINEV8::StoreJsValues(c
onst JsValueList& values) |
289 { | 291 { |
290 JsWeakValuesLists::iterator it; | 292 JsWeakValuesLists::iterator it; |
291 { | 293 { |
292 std::lock_guard<std::mutex> lock(jsWeakValuesListsMutex); | 294 std::lock_guard<std::mutex> lock(jsWeakValuesListsMutex); |
293 it = jsWeakValuesLists.emplace(jsWeakValuesLists.end()); | 295 it = jsWeakValuesLists.emplace(jsWeakValuesLists.end()); |
294 } | 296 } |
295 { | 297 { |
296 JsContext context(*this); | 298 JsContext context(*this); |
297 for (const auto& value : values) | 299 for (const auto& value : values) |
298 { | 300 { |
299 it->values.emplace_back(GetIsolate(), value.UnwrapValue()); | 301 it->values.emplace_back(GetIsolate(), value.UnwrapValue()); |
300 } | 302 } |
301 } | 303 } |
302 JsWeakValuesID retValue; | 304 JsWeakValuesID retValue; |
303 retValue.iterator = it; | 305 retValue.iterator = it; |
304 return retValue; | 306 return retValue; |
305 } | 307 } |
306 | 308 |
307 JsValueList JsEngine::TakeJsValues(const JsWeakValuesID& id) | 309 template <> JsValueList JSENGINEV8::TakeJsValues(const JsWeakValuesID& id) |
308 { | 310 { |
309 JsValueList retValue; | 311 JsValueList retValue; |
310 { | 312 { |
311 JsContext context(*this); | 313 JsContext context(*this); |
312 for (const auto& v8Value : id.iterator->values) | 314 for (const auto& v8Value : id.iterator->values) |
313 { | 315 { |
314 retValue.emplace_back(JsValue(shared_from_this(), v8::Local<v8::Value>::Ne
w(GetIsolate(), v8Value))); | 316 retValue.emplace_back(JsValue(shared_from_this(), v8::Local<v8::Value>::Ne
w(GetIsolate(), v8Value))); |
315 } | 317 } |
316 } | 318 } |
317 { | 319 { |
318 std::lock_guard<std::mutex> lock(jsWeakValuesListsMutex); | 320 std::lock_guard<std::mutex> lock(jsWeakValuesListsMutex); |
319 jsWeakValuesLists.erase(id.iterator); | 321 jsWeakValuesLists.erase(id.iterator); |
320 } | 322 } |
321 return retValue; | 323 return retValue; |
322 } | 324 } |
323 | 325 |
324 AdblockPlus::JsValueList AdblockPlus::JsEngine::ConvertArguments(const v8::Funct
ionCallbackInfo<v8::Value>& arguments) | 326 template <> AdblockPlus::JsValueList AdblockPlus::JSENGINEV8::ConvertArguments(c
onst v8::FunctionCallbackInfo<v8::Value>& arguments) |
325 { | 327 { |
326 const JsContext context(*this); | 328 const JsContext context(*this); |
327 JsValueList list; | 329 JsValueList list; |
328 for (int i = 0; i < arguments.Length(); i++) | 330 for (int i = 0; i < arguments.Length(); i++) |
329 list.push_back(JsValue(shared_from_this(), arguments[i])); | 331 list.push_back(JsValue(shared_from_this(), arguments[i])); |
330 return list; | 332 return list; |
331 } | 333 } |
332 | 334 |
333 void AdblockPlus::JsEngine::SetGlobalProperty(const std::string& name, | 335 void AdblockPlus::JSENGINEV8::SetGlobalProperty(const std::string& name, |
334 const AdblockPlus::JsValue& value) | 336 const AdblockPlus::JsValue& value) |
335 { | 337 { |
336 auto global = GetGlobalObject(); | 338 auto global = GetGlobalObject(); |
337 global.SetProperty(name, value); | 339 global.SetProperty(name, value); |
338 } | 340 } |
OLD | NEW |