Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code

Delta Between Two Patch Sets: src/JsEngine.cpp

Issue 29442722: Issue 3593 - stop sharing v8::Isolate among tests (Closed) Base URL: https://github.com/adblockplus/libadblockplus.git
Left Patch Set: Created May 19, 2017, 5:27 p.m.
Right Patch Set: address comments Created May 26, 2017, 10:54 a.m.
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
Left: Side by side diff | Download
Right: Side by side diff | Download
« no previous file with change/comment | « include/AdblockPlus/JsEngine.h ('k') | test/BaseJsTest.cpp » ('j') | no next file with change/comment »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
LEFTRIGHT
1 /*
2 * This file is part of Adblock Plus <https://adblockplus.org/>,
3 * Copyright (C) 2006-2017 eyeo GmbH
4 *
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
7 * published by the Free Software Foundation.
8 *
9 * Adblock Plus is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with Adblock Plus. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18 #include <AdblockPlus.h>
19 #include "GlobalJsObject.h"
20 #include "JsContext.h"
21 #include "JsError.h"
22 #include "Utils.h"
23 #include "DefaultTimer.h"
24
25 namespace
26 {
27 v8::Handle<v8::Script> CompileScript(v8::Isolate* isolate,
28 const std::string& source, const std::string& filename)
29 {
30 using AdblockPlus::Utils::ToV8String;
31 const v8::Handle<v8::String> v8Source = ToV8String(isolate, source);
32 if (filename.length())
33 {
34 const v8::Handle<v8::String> v8Filename = ToV8String(isolate, filename);
35 return v8::Script::Compile(v8Source, v8Filename);
36 }
37 else
38 return v8::Script::Compile(v8Source);
39 }
40
41 void CheckTryCatch(const v8::TryCatch& tryCatch)
42 {
43 if (tryCatch.HasCaught())
44 throw AdblockPlus::JsError(tryCatch.Exception(), tryCatch.Message());
45 }
46
47 class V8Initializer
48 {
49 V8Initializer()
50 {
51 v8::V8::Initialize();
52 }
53
54 ~V8Initializer()
55 {
56 v8::V8::Dispose();
57 }
58 public:
59 static void Init()
60 {
61 // it's threadsafe since C++11 and it will be instantiated only once and
62 // destroyed at the application exit
63 static V8Initializer initializer;
64 }
65 };
66 }
67
68 using namespace AdblockPlus;
69
70 TimerPtr AdblockPlus::CreateDefaultTimer()
71 {
72 return TimerPtr(new DefaultTimer());
73 }
74
75 WebRequestPtr AdblockPlus::CreateDefaultWebRequest()
76 {
77 return WebRequestPtr(new DefaultWebRequest(std::make_shared<DefaultWebRequestS ync>()));
78 }
79
80 AdblockPlus::ScopedV8Isolate::ScopedV8Isolate()
81 {
82 V8Initializer::Init();
83 isolate = v8::Isolate::New();
84 }
85
86 AdblockPlus::ScopedV8Isolate::~ScopedV8Isolate()
87 {
88 isolate->Dispose();
89 isolate = nullptr;
90 }
91
92 JsEngine::JsWeakValuesList::~JsWeakValuesList()
93 {
94 for (auto& value : values)
95 value->Dispose();
96 }
97
98 void JsEngine::NotifyLowMemory()
99 {
100 const JsContext context(*this);
101 v8::V8::LowMemoryNotification();
102 }
103
104 void JsEngine::ScheduleTimer(const v8::Arguments& arguments)
105 {
106 auto jsEngine = FromArguments(arguments);
107 if (arguments.Length() < 2)
108 throw std::runtime_error("setTimeout requires at least 2 parameters");
109
110 if (!arguments[0]->IsFunction())
111 throw std::runtime_error("First argument to setTimeout must be a function");
112
113 auto jsValueArguments = jsEngine->ConvertArguments(arguments);
114 auto timerParamsID = jsEngine->StoreJsValues(jsValueArguments);
115
116 std::weak_ptr<JsEngine> weakJsEngine = jsEngine;
117 jsEngine->timer->SetTimer(std::chrono::milliseconds(arguments[1]->IntegerValue ()), [weakJsEngine, timerParamsID]
118 {
119 if (auto jsEngine = weakJsEngine.lock())
120 jsEngine->CallTimerTask(timerParamsID);
121 });
122 }
123
124 void JsEngine::CallTimerTask(const JsWeakValuesID& timerParamsID)
125 {
126 auto timerParams = TakeJsValues(timerParamsID);
127 JsValue callback = std::move(timerParams[0]);
128
129 timerParams.erase(timerParams.begin()); // remove callback placeholder
130 timerParams.erase(timerParams.begin()); // remove timeout param
1 callback.Call(timerParams); 131 callback.Call(timerParams);
2 } 132 }
3 133
4 AdblockPlus::JsEngine::JsEngine(const ScopedV8IsolatePtr& isolate, 134 AdblockPlus::JsEngine::JsEngine(TimerPtr timer, WebRequestPtr webRequest)
5 TimerPtr timer, WebRequestPtr webRequest) 135 : fileSystem(new DefaultFileSystem())
6 : isolate(isolate)
7 , fileSystem(new DefaultFileSystem())
8 , logSystem(new DefaultLogSystem()) 136 , logSystem(new DefaultLogSystem())
9 , timer(std::move(timer)) 137 , timer(std::move(timer))
10 , webRequest(std::move(webRequest)) 138 , webRequest(std::move(webRequest))
139 {
140 }
141
142 AdblockPlus::JsEnginePtr AdblockPlus::JsEngine::New(const AppInfo& appInfo,
143 TimerPtr timer, WebRequestPtr webRequest)
144 {
145 JsEnginePtr result(new JsEngine(std::move(timer), std::move(webRequest)));
146
147 const v8::Locker locker(result->GetIsolate());
148 const v8::Isolate::Scope isolateScope(result->GetIsolate());
149 const v8::HandleScope handleScope(result->GetIsolate());
150
151 result->context.reset(new v8::Persistent<v8::Context>(result->GetIsolate(),
152 v8::Context::New(result->GetIsolate())));
153 auto global = result->GetGlobalObject();
154 AdblockPlus::GlobalJsObject::Setup(*result, appInfo, global);
155 return result;
156 }
157
158 AdblockPlus::JsValue AdblockPlus::JsEngine::GetGlobalObject()
159 {
160 JsContext context(*this);
161 return JsValue(shared_from_this(), context.GetV8Context()->Global());
162 }
163
164 AdblockPlus::JsValue AdblockPlus::JsEngine::Evaluate(const std::string& source,
165 const std::string& filename)
166 {
167 const JsContext context(*this);
168 const v8::TryCatch tryCatch;
169 const v8::Handle<v8::Script> script = CompileScript(GetIsolate(), source,
170 filename);
171 CheckTryCatch(tryCatch);
172 v8::Local<v8::Value> result = script->Run();
173 CheckTryCatch(tryCatch);
174 return JsValue(shared_from_this(), result);
175 }
176
177 void AdblockPlus::JsEngine::SetEventCallback(const std::string& eventName,
178 const AdblockPlus::JsEngine::EventCallback& callback)
179 {
180 if (!callback)
181 {
182 RemoveEventCallback(eventName);
183 return;
184 }
185 std::lock_guard<std::mutex> lock(eventCallbacksMutex);
186 eventCallbacks[eventName] = callback;
187 }
188
189 void AdblockPlus::JsEngine::RemoveEventCallback(const std::string& eventName)
190 {
191 std::lock_guard<std::mutex> lock(eventCallbacksMutex);
192 eventCallbacks.erase(eventName);
193 }
194
195 void AdblockPlus::JsEngine::TriggerEvent(const std::string& eventName, AdblockPl us::JsValueList&& params)
196 {
197 EventCallback callback;
198 {
199 std::lock_guard<std::mutex> lock(eventCallbacksMutex);
200 auto it = eventCallbacks.find(eventName);
201 if (it == eventCallbacks.end())
202 return;
203 callback = it->second;
204 }
205 callback(move(params));
206 }
207
208 void AdblockPlus::JsEngine::Gc()
209 {
210 while (!v8::V8::IdleNotification());
211 }
212
213 AdblockPlus::JsValue AdblockPlus::JsEngine::NewValue(const std::string& val)
214 {
215 const JsContext context(*this);
216 return JsValue(shared_from_this(), Utils::ToV8String(GetIsolate(), val));
217 }
218
219 AdblockPlus::JsValue AdblockPlus::JsEngine::NewValue(int64_t val)
220 {
221 const JsContext context(*this);
222 return JsValue(shared_from_this(), v8::Number::New(GetIsolate(), val));
223 }
224
225 AdblockPlus::JsValue AdblockPlus::JsEngine::NewValue(bool val)
226 {
227 const JsContext context(*this);
228 return JsValue(shared_from_this(), v8::Boolean::New(val));
229 }
230
231 AdblockPlus::JsValue AdblockPlus::JsEngine::NewObject()
232 {
233 const JsContext context(*this);
234 return JsValue(shared_from_this(), v8::Object::New());
235 }
236
237 AdblockPlus::JsValue AdblockPlus::JsEngine::NewCallback(
238 const v8::InvocationCallback& callback)
239 {
240 const JsContext context(*this);
241
242 // Note: we are leaking this weak pointer, no obvious way to destroy it when
243 // it's no longer used
244 std::weak_ptr<JsEngine>* data =
245 new std::weak_ptr<JsEngine>(shared_from_this());
246 v8::Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(callback,
247 v8::External::New(data));
248 return JsValue(shared_from_this(), templ->GetFunction());
249 }
250
251 AdblockPlus::JsEnginePtr AdblockPlus::JsEngine::FromArguments(const v8::Argument s& arguments)
252 {
253 const v8::Local<const v8::External> external =
254 v8::Local<const v8::External>::Cast(arguments.Data());
255 std::weak_ptr<JsEngine>* data =
256 static_cast<std::weak_ptr<JsEngine>*>(external->Value());
257 JsEnginePtr result = data->lock();
258 if (!result)
259 throw std::runtime_error("Oops, our JsEngine is gone, how did that happen?") ;
260 return result;
261 }
262
263 JsEngine::JsWeakValuesID JsEngine::StoreJsValues(const JsValueList& values)
264 {
265 JsWeakValuesLists::iterator it;
266 {
267 std::lock_guard<std::mutex> lock(jsWeakValuesListsMutex);
268 it = jsWeakValuesLists.emplace(jsWeakValuesLists.end());
269 }
270 {
271 JsContext context(*this);
272 for (const auto& value : values)
273 {
274 it->values.emplace_back(new v8::Persistent<v8::Value>(GetIsolate(), value. UnwrapValue()));
275 }
276 }
277 JsWeakValuesID retValue;
278 retValue.iterator = it;
279 return retValue;
280 }
281
282 JsValueList JsEngine::TakeJsValues(const JsWeakValuesID& id)
283 {
284 JsValueList retValue;
285 {
286 JsContext context(*this);
287 for (const auto& v8Value : id.iterator->values)
288 {
289 retValue.emplace_back(JsValue(shared_from_this(), v8::Local<v8::Value>::Ne w(GetIsolate(), *v8Value)));
290 }
291 }
292 {
293 std::lock_guard<std::mutex> lock(jsWeakValuesListsMutex);
294 jsWeakValuesLists.erase(id.iterator);
295 }
296 return retValue;
297 }
298
299 AdblockPlus::JsValueList AdblockPlus::JsEngine::ConvertArguments(const v8::Argum ents& arguments)
300 {
301 const JsContext context(*this);
302 JsValueList list;
303 for (int i = 0; i < arguments.Length(); i++)
304 list.push_back(JsValue(shared_from_this(), arguments[i]));
305 return list;
306 }
307
308 AdblockPlus::FileSystemPtr AdblockPlus::JsEngine::GetFileSystem() const
309 {
310 return fileSystem;
311 }
312
313 void AdblockPlus::JsEngine::SetFileSystem(const AdblockPlus::FileSystemPtr& val)
314 {
315 if (!val)
316 throw std::runtime_error("FileSystem cannot be null");
317
318 fileSystem = val;
319 }
320
321 void AdblockPlus::JsEngine::SetWebRequest(const AdblockPlus::WebRequestSharedPtr & val)
322 {
323 if (!val)
324 throw std::runtime_error("WebRequest cannot be null");
325
326 webRequestLegacy = val;
327 }
328
329 AdblockPlus::LogSystemPtr AdblockPlus::JsEngine::GetLogSystem() const
330 {
331 return logSystem;
332 }
333
334 void AdblockPlus::JsEngine::SetLogSystem(const AdblockPlus::LogSystemPtr& val)
335 {
336 if (!val)
337 throw std::runtime_error("LogSystem cannot be null");
338
339 logSystem = val;
340 }
341
342
343 void AdblockPlus::JsEngine::SetGlobalProperty(const std::string& name,
344 const AdblockPlus::JsValue& value)
345 {
346 auto global = GetGlobalObject();
347 global.SetProperty(name, value);
348 }
LEFTRIGHT

Powered by Google App Engine
This is Rietveld