| Left: | ||
| Right: |
| 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-2017 eyeo GmbH | 3 * Copyright (C) 2006-2017 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 |
| 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 12 * GNU General Public License for more details. | 12 * GNU General Public License for more details. |
| 13 * | 13 * |
| 14 * You should have received a copy of the GNU General Public License | 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/>. | 15 * along with Adblock Plus. If not, see <http://www.gnu.org/licenses/>. |
| 16 */ | 16 */ |
| 17 | 17 |
| 18 #include <AdblockPlus.h> | 18 #include <AdblockPlus.h> |
| 19 #include "GlobalJsObject.h" | 19 #include "GlobalJsObject.h" |
| 20 #include "JsContext.h" | 20 #include "JsContext.h" |
| 21 #include "JsError.h" | 21 #include "JsError.h" |
| 22 #include "Utils.h" | 22 #include "Utils.h" |
| 23 #include "DefaultTimer.h" | 23 #include "DefaultTimer.h" |
| 24 #include <libplatform/libplatform.h> | |
| 24 | 25 |
| 25 namespace | 26 namespace |
| 26 { | 27 { |
| 27 v8::Handle<v8::Script> CompileScript(v8::Isolate* isolate, | 28 v8::Handle<v8::Script> CompileScript(v8::Isolate* isolate, |
| 28 const std::string& source, const std::string& filename) | 29 const std::string& source, const std::string& filename) |
| 29 { | 30 { |
| 30 using AdblockPlus::Utils::ToV8String; | 31 using AdblockPlus::Utils::ToV8String; |
| 31 const v8::Handle<v8::String> v8Source = ToV8String(isolate, source); | 32 const v8::Handle<v8::String> v8Source = ToV8String(isolate, source); |
| 32 if (filename.length()) | 33 if (filename.length()) |
| 33 { | 34 { |
| 34 const v8::Handle<v8::String> v8Filename = ToV8String(isolate, filename); | 35 const v8::Handle<v8::String> v8Filename = ToV8String(isolate, filename); |
| 35 return v8::Script::Compile(v8Source, v8Filename); | 36 return v8::Script::Compile(v8Source, v8Filename); |
| 36 } | 37 } |
| 37 else | 38 else |
| 38 return v8::Script::Compile(v8Source); | 39 return v8::Script::Compile(v8Source); |
| 39 } | 40 } |
| 40 | 41 |
| 41 void CheckTryCatch(const v8::TryCatch& tryCatch) | 42 void CheckTryCatch(const v8::TryCatch& tryCatch) |
| 42 { | 43 { |
| 43 if (tryCatch.HasCaught()) | 44 if (tryCatch.HasCaught()) |
| 44 throw AdblockPlus::JsError(tryCatch.Exception(), tryCatch.Message()); | 45 throw AdblockPlus::JsError(tryCatch.Exception(), tryCatch.Message()); |
| 45 } | 46 } |
| 46 | 47 |
| 47 class V8Initializer | 48 class V8Initializer |
| 48 { | 49 { |
| 49 V8Initializer() | 50 V8Initializer() |
| 51 : platform(v8::platform::CreateDefaultPlatform()) | |
| 50 { | 52 { |
| 53 v8::V8::InitializePlatform(platform); | |
| 51 v8::V8::Initialize(); | 54 v8::V8::Initialize(); |
| 52 } | 55 } |
| 53 | 56 |
| 54 ~V8Initializer() | 57 ~V8Initializer() |
| 55 { | 58 { |
| 56 v8::V8::Dispose(); | 59 v8::V8::Dispose(); |
| 60 v8::V8::ShutdownPlatform(); | |
| 61 delete platform; | |
| 57 } | 62 } |
| 63 v8::Platform* platform; | |
| 58 public: | 64 public: |
| 59 static void Init() | 65 static void Init() |
| 60 { | 66 { |
| 61 // it's threadsafe since C++11 and it will be instantiated only once and | 67 // it's threadsafe since C++11 and it will be instantiated only once and |
| 62 // destroyed at the application exit | 68 // destroyed at the application exit |
| 63 static V8Initializer initializer; | 69 static V8Initializer initializer; |
| 64 } | 70 } |
| 65 }; | 71 }; |
| 66 } | 72 } |
| 67 | 73 |
| 68 using namespace AdblockPlus; | 74 using namespace AdblockPlus; |
| 69 | 75 |
| 70 TimerPtr AdblockPlus::CreateDefaultTimer() | 76 TimerPtr AdblockPlus::CreateDefaultTimer() |
| 71 { | 77 { |
| 72 return TimerPtr(new DefaultTimer()); | 78 return TimerPtr(new DefaultTimer()); |
| 73 } | 79 } |
| 74 | 80 |
| 75 WebRequestPtr AdblockPlus::CreateDefaultWebRequest() | 81 WebRequestPtr AdblockPlus::CreateDefaultWebRequest() |
| 76 { | 82 { |
| 77 return WebRequestPtr(new DefaultWebRequest(std::make_shared<DefaultWebRequestS ync>())); | 83 return WebRequestPtr(new DefaultWebRequest(std::make_shared<DefaultWebRequestS ync>())); |
| 78 } | 84 } |
| 79 | 85 |
| 80 AdblockPlus::ScopedV8Isolate::ScopedV8Isolate() | 86 AdblockPlus::ScopedV8Isolate::ScopedV8Isolate() |
| 81 { | 87 { |
| 82 V8Initializer::Init(); | 88 V8Initializer::Init(); |
| 83 isolate = v8::Isolate::New(); | 89 v8::Isolate::CreateParams isolateParams; |
| 90 isolateParams.array_buffer_allocator = v8::ArrayBuffer::Allocator::NewDefaultA llocator(); | |
| 91 isolate = v8::Isolate::New(isolateParams); | |
| 84 } | 92 } |
| 85 | 93 |
| 86 AdblockPlus::ScopedV8Isolate::~ScopedV8Isolate() | 94 AdblockPlus::ScopedV8Isolate::~ScopedV8Isolate() |
| 87 { | 95 { |
| 88 isolate->Dispose(); | 96 isolate->Dispose(); |
| 89 isolate = nullptr; | 97 isolate = nullptr; |
| 90 } | 98 } |
| 91 | 99 |
| 92 JsEngine::JsWeakValuesList::~JsWeakValuesList() | 100 JsEngine::JsWeakValuesList::~JsWeakValuesList() |
| 93 { | 101 { |
| 94 for (auto& value : values) | |
| 95 value->Dispose(); | |
| 96 } | 102 } |
| 97 | 103 |
| 98 void JsEngine::NotifyLowMemory() | 104 void JsEngine::NotifyLowMemory() |
| 99 { | 105 { |
| 100 const JsContext context(*this); | 106 const JsContext context(*this); |
| 101 v8::V8::LowMemoryNotification(); | 107 GetIsolate()->MemoryPressureNotification(v8::MemoryPressureLevel::kCritical); |
| 102 } | 108 } |
| 103 | 109 |
| 104 void JsEngine::ScheduleTimer(const v8::Arguments& arguments) | 110 void JsEngine::ScheduleTimer(const v8::FunctionCallbackInfo<v8::Value>& argument s) |
| 105 { | 111 { |
| 106 auto jsEngine = FromArguments(arguments); | 112 auto jsEngine = FromArguments(arguments); |
| 107 if (arguments.Length() < 2) | 113 if (arguments.Length() < 2) |
| 108 throw std::runtime_error("setTimeout requires at least 2 parameters"); | 114 throw std::runtime_error("setTimeout requires at least 2 parameters"); |
| 109 | 115 |
| 110 if (!arguments[0]->IsFunction()) | 116 if (!arguments[0]->IsFunction()) |
| 111 throw std::runtime_error("First argument to setTimeout must be a function"); | 117 throw std::runtime_error("First argument to setTimeout must be a function"); |
| 112 | 118 |
| 113 auto jsValueArguments = jsEngine->ConvertArguments(arguments); | 119 auto jsValueArguments = jsEngine->ConvertArguments(arguments); |
| 114 auto timerParamsID = jsEngine->StoreJsValues(jsValueArguments); | 120 auto timerParamsID = jsEngine->StoreJsValues(jsValueArguments); |
| (...skipping 26 matching lines...) Expand all Loading... | |
| 141 | 147 |
| 142 AdblockPlus::JsEnginePtr AdblockPlus::JsEngine::New(const AppInfo& appInfo, | 148 AdblockPlus::JsEnginePtr AdblockPlus::JsEngine::New(const AppInfo& appInfo, |
| 143 TimerPtr timer, WebRequestPtr webRequest) | 149 TimerPtr timer, WebRequestPtr webRequest) |
| 144 { | 150 { |
| 145 JsEnginePtr result(new JsEngine(std::move(timer), std::move(webRequest))); | 151 JsEnginePtr result(new JsEngine(std::move(timer), std::move(webRequest))); |
| 146 | 152 |
| 147 const v8::Locker locker(result->GetIsolate()); | 153 const v8::Locker locker(result->GetIsolate()); |
| 148 const v8::Isolate::Scope isolateScope(result->GetIsolate()); | 154 const v8::Isolate::Scope isolateScope(result->GetIsolate()); |
| 149 const v8::HandleScope handleScope(result->GetIsolate()); | 155 const v8::HandleScope handleScope(result->GetIsolate()); |
| 150 | 156 |
| 151 result->context.reset(new v8::Persistent<v8::Context>(result->GetIsolate(), | 157 result->context.reset(new v8::Global<v8::Context>(result->GetIsolate(), |
| 152 v8::Context::New(result->GetIsolate()))); | 158 v8::Context::New(result->GetIsolate()))); |
| 153 auto global = result->GetGlobalObject(); | 159 auto global = result->GetGlobalObject(); |
| 154 AdblockPlus::GlobalJsObject::Setup(*result, appInfo, global); | 160 AdblockPlus::GlobalJsObject::Setup(*result, appInfo, global); |
| 155 return result; | 161 return result; |
| 156 } | 162 } |
| 157 | 163 |
| 158 AdblockPlus::JsValue AdblockPlus::JsEngine::GetGlobalObject() | 164 AdblockPlus::JsValue AdblockPlus::JsEngine::GetGlobalObject() |
| 159 { | 165 { |
| 160 JsContext context(*this); | 166 JsContext context(*this); |
| 161 return JsValue(shared_from_this(), context.GetV8Context()->Global()); | 167 return JsValue(shared_from_this(), context.GetV8Context()->Global()); |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 200 auto it = eventCallbacks.find(eventName); | 206 auto it = eventCallbacks.find(eventName); |
| 201 if (it == eventCallbacks.end()) | 207 if (it == eventCallbacks.end()) |
| 202 return; | 208 return; |
| 203 callback = it->second; | 209 callback = it->second; |
| 204 } | 210 } |
| 205 callback(move(params)); | 211 callback(move(params)); |
| 206 } | 212 } |
| 207 | 213 |
| 208 void AdblockPlus::JsEngine::Gc() | 214 void AdblockPlus::JsEngine::Gc() |
| 209 { | 215 { |
| 210 while (!v8::V8::IdleNotification()); | 216 while (!GetIsolate()->IdleNotification(1000)); |
|
Oleksandr
2017/06/03 00:40:15
Maybe an explanation about the magic number would
sergei
2017/06/14 16:13:10
One cannot remove 1000 because there is no default
Oleksandr
2017/07/03 21:50:38
Acknowledged.
| |
| 211 } | 217 } |
| 212 | 218 |
| 213 AdblockPlus::JsValue AdblockPlus::JsEngine::NewValue(const std::string& val) | 219 AdblockPlus::JsValue AdblockPlus::JsEngine::NewValue(const std::string& val) |
| 214 { | 220 { |
| 215 const JsContext context(*this); | 221 const JsContext context(*this); |
| 216 return JsValue(shared_from_this(), Utils::ToV8String(GetIsolate(), val)); | 222 return JsValue(shared_from_this(), Utils::ToV8String(GetIsolate(), val)); |
| 217 } | 223 } |
| 218 | 224 |
| 219 AdblockPlus::JsValue AdblockPlus::JsEngine::NewValue(int64_t val) | 225 AdblockPlus::JsValue AdblockPlus::JsEngine::NewValue(int64_t val) |
| 220 { | 226 { |
| 221 const JsContext context(*this); | 227 const JsContext context(*this); |
| 222 return JsValue(shared_from_this(), v8::Number::New(GetIsolate(), val)); | 228 return JsValue(shared_from_this(), v8::Number::New(GetIsolate(), val)); |
| 223 } | 229 } |
| 224 | 230 |
| 225 AdblockPlus::JsValue AdblockPlus::JsEngine::NewValue(bool val) | 231 AdblockPlus::JsValue AdblockPlus::JsEngine::NewValue(bool val) |
| 226 { | 232 { |
| 227 const JsContext context(*this); | 233 const JsContext context(*this); |
| 228 return JsValue(shared_from_this(), v8::Boolean::New(val)); | 234 return JsValue(shared_from_this(), v8::Boolean::New(GetIsolate(), val)); |
| 229 } | 235 } |
| 230 | 236 |
| 231 AdblockPlus::JsValue AdblockPlus::JsEngine::NewObject() | 237 AdblockPlus::JsValue AdblockPlus::JsEngine::NewObject() |
| 232 { | 238 { |
| 233 const JsContext context(*this); | 239 const JsContext context(*this); |
| 234 return JsValue(shared_from_this(), v8::Object::New()); | 240 return JsValue(shared_from_this(), v8::Object::New(GetIsolate())); |
| 235 } | 241 } |
| 236 | 242 |
| 237 AdblockPlus::JsValue AdblockPlus::JsEngine::NewCallback( | 243 AdblockPlus::JsValue AdblockPlus::JsEngine::NewCallback( |
| 238 const v8::InvocationCallback& callback) | 244 const v8::FunctionCallback& callback) |
| 239 { | 245 { |
| 240 const JsContext context(*this); | 246 const JsContext context(*this); |
| 241 | 247 |
| 242 // Note: we are leaking this weak pointer, no obvious way to destroy it when | 248 // Note: we are leaking this weak pointer, no obvious way to destroy it when |
| 243 // it's no longer used | 249 // it's no longer used |
| 244 std::weak_ptr<JsEngine>* data = | 250 std::weak_ptr<JsEngine>* data = |
| 245 new std::weak_ptr<JsEngine>(shared_from_this()); | 251 new std::weak_ptr<JsEngine>(shared_from_this()); |
| 246 v8::Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(callback, | 252 v8::Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(GetIsolate() , callback, |
| 247 v8::External::New(data)); | 253 v8::External::New(GetIsolate(), data)); |
| 248 return JsValue(shared_from_this(), templ->GetFunction()); | 254 return JsValue(shared_from_this(), templ->GetFunction()); |
| 249 } | 255 } |
| 250 | 256 |
| 251 AdblockPlus::JsEnginePtr AdblockPlus::JsEngine::FromArguments(const v8::Argument s& arguments) | 257 AdblockPlus::JsEnginePtr AdblockPlus::JsEngine::FromArguments(const v8::Function CallbackInfo<v8::Value>& arguments) |
| 252 { | 258 { |
| 253 const v8::Local<const v8::External> external = | 259 const v8::Local<const v8::External> external = |
| 254 v8::Local<const v8::External>::Cast(arguments.Data()); | 260 v8::Local<const v8::External>::Cast(arguments.Data()); |
| 255 std::weak_ptr<JsEngine>* data = | 261 std::weak_ptr<JsEngine>* data = |
| 256 static_cast<std::weak_ptr<JsEngine>*>(external->Value()); | 262 static_cast<std::weak_ptr<JsEngine>*>(external->Value()); |
| 257 JsEnginePtr result = data->lock(); | 263 JsEnginePtr result = data->lock(); |
| 258 if (!result) | 264 if (!result) |
| 259 throw std::runtime_error("Oops, our JsEngine is gone, how did that happen?") ; | 265 throw std::runtime_error("Oops, our JsEngine is gone, how did that happen?") ; |
| 260 return result; | 266 return result; |
| 261 } | 267 } |
| 262 | 268 |
| 263 JsEngine::JsWeakValuesID JsEngine::StoreJsValues(const JsValueList& values) | 269 JsEngine::JsWeakValuesID JsEngine::StoreJsValues(const JsValueList& values) |
| 264 { | 270 { |
| 265 JsWeakValuesLists::iterator it; | 271 JsWeakValuesLists::iterator it; |
| 266 { | 272 { |
| 267 std::lock_guard<std::mutex> lock(jsWeakValuesListsMutex); | 273 std::lock_guard<std::mutex> lock(jsWeakValuesListsMutex); |
| 268 it = jsWeakValuesLists.emplace(jsWeakValuesLists.end()); | 274 it = jsWeakValuesLists.emplace(jsWeakValuesLists.end()); |
| 269 } | 275 } |
| 270 { | 276 { |
| 271 JsContext context(*this); | 277 JsContext context(*this); |
| 272 for (const auto& value : values) | 278 for (const auto& value : values) |
| 273 { | 279 { |
| 274 it->values.emplace_back(new v8::Persistent<v8::Value>(GetIsolate(), value. UnwrapValue())); | 280 it->values.emplace_back(GetIsolate(), value.UnwrapValue()); |
| 275 } | 281 } |
| 276 } | 282 } |
| 277 JsWeakValuesID retValue; | 283 JsWeakValuesID retValue; |
| 278 retValue.iterator = it; | 284 retValue.iterator = it; |
| 279 return retValue; | 285 return retValue; |
| 280 } | 286 } |
| 281 | 287 |
| 282 JsValueList JsEngine::TakeJsValues(const JsWeakValuesID& id) | 288 JsValueList JsEngine::TakeJsValues(const JsWeakValuesID& id) |
| 283 { | 289 { |
| 284 JsValueList retValue; | 290 JsValueList retValue; |
| 285 { | 291 { |
| 286 JsContext context(*this); | 292 JsContext context(*this); |
| 287 for (const auto& v8Value : id.iterator->values) | 293 for (const auto& v8Value : id.iterator->values) |
| 288 { | 294 { |
| 289 retValue.emplace_back(JsValue(shared_from_this(), v8::Local<v8::Value>::Ne w(GetIsolate(), *v8Value))); | 295 retValue.emplace_back(JsValue(shared_from_this(), v8::Local<v8::Value>::Ne w(GetIsolate(), v8Value))); |
| 290 } | 296 } |
| 291 } | 297 } |
| 292 { | 298 { |
| 293 std::lock_guard<std::mutex> lock(jsWeakValuesListsMutex); | 299 std::lock_guard<std::mutex> lock(jsWeakValuesListsMutex); |
| 294 jsWeakValuesLists.erase(id.iterator); | 300 jsWeakValuesLists.erase(id.iterator); |
| 295 } | 301 } |
| 296 return retValue; | 302 return retValue; |
| 297 } | 303 } |
| 298 | 304 |
| 299 AdblockPlus::JsValueList AdblockPlus::JsEngine::ConvertArguments(const v8::Argum ents& arguments) | 305 AdblockPlus::JsValueList AdblockPlus::JsEngine::ConvertArguments(const v8::Funct ionCallbackInfo<v8::Value>& arguments) |
| 300 { | 306 { |
| 301 const JsContext context(*this); | 307 const JsContext context(*this); |
| 302 JsValueList list; | 308 JsValueList list; |
| 303 for (int i = 0; i < arguments.Length(); i++) | 309 for (int i = 0; i < arguments.Length(); i++) |
| 304 list.push_back(JsValue(shared_from_this(), arguments[i])); | 310 list.push_back(JsValue(shared_from_this(), arguments[i])); |
| 305 return list; | 311 return list; |
| 306 } | 312 } |
| 307 | 313 |
| 308 AdblockPlus::FileSystemPtr AdblockPlus::JsEngine::GetFileSystem() const | 314 AdblockPlus::FileSystemPtr AdblockPlus::JsEngine::GetFileSystem() const |
| 309 { | 315 { |
| (...skipping 29 matching lines...) Expand all Loading... | |
| 339 logSystem = val; | 345 logSystem = val; |
| 340 } | 346 } |
| 341 | 347 |
| 342 | 348 |
| 343 void AdblockPlus::JsEngine::SetGlobalProperty(const std::string& name, | 349 void AdblockPlus::JsEngine::SetGlobalProperty(const std::string& name, |
| 344 const AdblockPlus::JsValue& value) | 350 const AdblockPlus::JsValue& value) |
| 345 { | 351 { |
| 346 auto global = GetGlobalObject(); | 352 auto global = GetGlobalObject(); |
| 347 global.SetProperty(name, value); | 353 global.SetProperty(name, value); |
| 348 } | 354 } |
| OLD | NEW |