| Index: src/JsEngine.cpp |
| =================================================================== |
| --- a/src/JsEngine.cpp |
| +++ b/src/JsEngine.cpp |
| @@ -1,202 +1,240 @@ |
| -/* |
| - * This file is part of Adblock Plus <http://adblockplus.org/>, |
| - * Copyright (C) 2006-2014 Eyeo GmbH |
| - * |
| - * Adblock Plus is free software: you can redistribute it and/or modify |
| - * it under the terms of the GNU General Public License version 3 as |
| - * published by the Free Software Foundation. |
| - * |
| - * Adblock Plus is distributed in the hope that it will be useful, |
| - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| - * GNU General Public License for more details. |
| - * |
| - * You should have received a copy of the GNU General Public License |
| - * along with Adblock Plus. If not, see <http://www.gnu.org/licenses/>. |
| - */ |
| - |
| -#include <AdblockPlus.h> |
| - |
| -#include "GlobalJsObject.h" |
| -#include "JsContext.h" |
| -#include "JsError.h" |
| -#include "Utils.h" |
| - |
| -namespace |
| -{ |
| - v8::Handle<v8::Script> CompileScript(const std::string& source, const std::string& filename) |
| - { |
| - const v8::Handle<v8::String> v8Source = v8::String::New(source.c_str()); |
| - if (filename.length()) |
| - { |
| - const v8::Handle<v8::String> v8Filename = v8::String::New(filename.c_str()); |
| - return v8::Script::Compile(v8Source, v8Filename); |
| - } |
| - else |
| - return v8::Script::Compile(v8Source); |
| - } |
| - |
| - void CheckTryCatch(const v8::TryCatch& tryCatch) |
| - { |
| - if (tryCatch.HasCaught()) |
| - throw AdblockPlus::JsError(tryCatch.Exception(), tryCatch.Message()); |
| - } |
| -} |
| - |
| -AdblockPlus::JsEngine::JsEngine() |
| - : isolate(v8::Isolate::GetCurrent()) |
| -{ |
| -} |
| - |
| -AdblockPlus::JsEnginePtr AdblockPlus::JsEngine::New(const AppInfo& appInfo) |
| -{ |
| - JsEnginePtr result(new JsEngine()); |
| - |
| - const v8::Locker locker(result->isolate); |
| - const v8::HandleScope handleScope; |
| - |
| - result->context.reset(result->isolate, v8::Context::New(result->isolate)); |
| - AdblockPlus::GlobalJsObject::Setup(result, appInfo, |
| - JsValuePtr(new JsValue(result, v8::Local<v8::Context>::New(result->isolate, result->context)->Global(), JsValue::Private::CtrArg()))); |
| - return result; |
| -} |
| - |
| -AdblockPlus::JsValuePtr AdblockPlus::JsEngine::Evaluate(const std::string& source, |
| - const std::string& filename) |
| -{ |
| - const JsContext context(shared_from_this()); |
| - const v8::TryCatch tryCatch; |
| - const v8::Handle<v8::Script> script = CompileScript(source, filename); |
| - CheckTryCatch(tryCatch); |
| - v8::Local<v8::Value> result = script->Run(); |
| - CheckTryCatch(tryCatch); |
| - return JsValuePtr(new JsValue(shared_from_this(), result, JsValue::Private::CtrArg())); |
| -} |
| - |
| -void AdblockPlus::JsEngine::SetEventCallback(const std::string& eventName, |
| - AdblockPlus::JsEngine::EventCallback callback) |
| -{ |
| - eventCallbacks[eventName] = callback; |
| -} |
| - |
| -void AdblockPlus::JsEngine::RemoveEventCallback(const std::string& eventName) |
| -{ |
| - eventCallbacks.erase(eventName); |
| -} |
| - |
| -void AdblockPlus::JsEngine::TriggerEvent(const std::string& eventName, AdblockPlus::JsValueList& params) |
| -{ |
| - EventMap::iterator it = eventCallbacks.find(eventName); |
| - if (it != eventCallbacks.end()) |
| - it->second(params); |
| -} |
| - |
| -void AdblockPlus::JsEngine::Gc() |
| -{ |
| - while (!v8::V8::IdleNotification()); |
| -} |
| - |
| -AdblockPlus::JsValuePtr AdblockPlus::JsEngine::NewValue(const std::string& val) |
| -{ |
| - const JsContext context(shared_from_this()); |
| - return JsValuePtr(new JsValue(shared_from_this(), |
| - v8::String::New(val.c_str(), val.length()), JsValue::Private::CtrArg())); |
| -} |
| - |
| -AdblockPlus::JsValuePtr AdblockPlus::JsEngine::NewValue(int64_t val) |
| -{ |
| - const JsContext context(shared_from_this()); |
| - return JsValuePtr(new JsValue(shared_from_this(), v8::Number::New(val), JsValue::Private::CtrArg())); |
| -} |
| - |
| -AdblockPlus::JsValuePtr AdblockPlus::JsEngine::NewValue(bool val) |
| -{ |
| - const JsContext context(shared_from_this()); |
| - return JsValuePtr(new JsValue(shared_from_this(), v8::Boolean::New(val), JsValue::Private::CtrArg())); |
| -} |
| - |
| -AdblockPlus::JsValuePtr AdblockPlus::JsEngine::NewObject() |
| -{ |
| - const JsContext context(shared_from_this()); |
| - return JsValuePtr(new JsValue(shared_from_this(), v8::Object::New(), JsValue::Private::CtrArg())); |
| -} |
| - |
| -AdblockPlus::JsValuePtr AdblockPlus::JsEngine::NewCallback( |
| - v8::InvocationCallback callback) |
| -{ |
| - const JsContext context(shared_from_this()); |
| - |
| - // Note: we are leaking this weak pointer, no obvious way to destroy it when |
| - // it's no longer used |
| - std::tr1::weak_ptr<JsEngine>* data = |
| - new std::tr1::weak_ptr<JsEngine>(shared_from_this()); |
| - v8::Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(callback, |
| - v8::External::New(data)); |
| - return JsValuePtr(new JsValue(shared_from_this(), templ->GetFunction(), JsValue::Private::CtrArg())); |
| -} |
| - |
| -AdblockPlus::JsEnginePtr AdblockPlus::JsEngine::FromArguments(const v8::Arguments& arguments) |
| -{ |
| - const v8::Local<const v8::External> external = |
| - v8::Local<const v8::External>::Cast(arguments.Data()); |
| - std::tr1::weak_ptr<JsEngine>* data = |
| - static_cast<std::tr1::weak_ptr<JsEngine>*>(external->Value()); |
| - JsEnginePtr result = data->lock(); |
| - if (!result) |
| - throw std::runtime_error("Oops, our JsEngine is gone, how did that happen?"); |
| - return result; |
| -} |
| - |
| -AdblockPlus::JsValueList AdblockPlus::JsEngine::ConvertArguments(const v8::Arguments& arguments) |
| -{ |
| - const JsContext context(shared_from_this()); |
| - JsValueList list; |
| - for (int i = 0; i < arguments.Length(); i++) |
| - list.push_back(JsValuePtr(new JsValue(shared_from_this(), arguments[i], JsValue::Private::CtrArg()))); |
| - return list; |
| -} |
| - |
| -AdblockPlus::FileSystemPtr AdblockPlus::JsEngine::GetFileSystem() |
| -{ |
| - if (!fileSystem) |
| - fileSystem.reset(new DefaultFileSystem()); |
| - return fileSystem; |
| -} |
| - |
| -void AdblockPlus::JsEngine::SetFileSystem(AdblockPlus::FileSystemPtr val) |
| -{ |
| - if (!val) |
| - throw std::runtime_error("FileSystem cannot be null"); |
| - |
| - fileSystem = val; |
| -} |
| - |
| -AdblockPlus::WebRequestPtr AdblockPlus::JsEngine::GetWebRequest() |
| -{ |
| - if (!webRequest) |
| - webRequest.reset(new DefaultWebRequest()); |
| - return webRequest; |
| -} |
| - |
| -void AdblockPlus::JsEngine::SetWebRequest(AdblockPlus::WebRequestPtr val) |
| -{ |
| - if (!val) |
| - throw std::runtime_error("WebRequest cannot be null"); |
| - |
| - webRequest = val; |
| -} |
| - |
| -AdblockPlus::LogSystemPtr AdblockPlus::JsEngine::GetLogSystem() |
| -{ |
| - if (!logSystem) |
| - logSystem.reset(new DefaultLogSystem()); |
| - return logSystem; |
| -} |
| - |
| -void AdblockPlus::JsEngine::SetLogSystem(AdblockPlus::LogSystemPtr val) |
| -{ |
| - if (!val) |
| - throw std::runtime_error("LogSystem cannot be null"); |
| - |
| - logSystem = val; |
| -} |
| +/* |
| + * This file is part of Adblock Plus <http://adblockplus.org/>, |
| + * Copyright (C) 2006-2014 Eyeo GmbH |
| + * |
| + * Adblock Plus is free software: you can redistribute it and/or modify |
| + * it under the terms of the GNU General Public License version 3 as |
| + * published by the Free Software Foundation. |
| + * |
| + * Adblock Plus is distributed in the hope that it will be useful, |
| + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| + * GNU General Public License for more details. |
| + * |
| + * You should have received a copy of the GNU General Public License |
| + * along with Adblock Plus. If not, see <http://www.gnu.org/licenses/>. |
| + */ |
| + |
| +#include <AdblockPlus.h> |
| +#include <libplatform/libplatform.h> |
| + |
| +#include "GlobalJsObject.h" |
| +#include "JsContext.h" |
| +#include "JsError.h" |
| +#include "Utils.h" |
| + |
| +namespace |
| +{ |
| + const int g_kIdleNotificationTimeuotMsec = 20; |
| + v8::Handle<v8::Script> CompileScript(v8::Isolate* isolate, const std::string& source, const std::string& filename) |
| + { |
| + const v8::Handle<v8::String> v8Source = AdblockPlus::Utils::ToV8String(isolate, source); |
| + if (filename.length()) |
| + { |
| + const v8::Handle<v8::String> v8Filename = AdblockPlus::Utils::ToV8String(isolate, filename); |
| + return v8::Script::Compile(v8Source, v8Filename); |
| + } |
| + else |
| + return v8::Script::Compile(v8Source); |
| + } |
| + |
| + void CheckTryCatch(const v8::TryCatch& tryCatch) |
| + { |
| + if (tryCatch.HasCaught()) |
| + throw AdblockPlus::JsError(tryCatch.Exception(), tryCatch.Message()); |
| + } |
| + |
| + class V8Initializer |
| + { |
| + V8Initializer() |
| + { |
| + v8::Platform* platform = v8::platform::CreateDefaultPlatform(); |
| + v8::V8::InitializePlatform(platform); |
| + v8::V8::Initialize(); |
| + } |
| + |
| + ~V8Initializer() |
| + { |
| + v8::V8::Dispose(); |
| + v8::V8::ShutdownPlatform(); |
| + } |
| + std::unique_ptr<v8::Platform> platform; |
| + public: |
| + static void Init() |
| + { |
| + // it's threadsafe since C++11 and it will be instantiated only once and destroyed at the |
| + // application exit |
| + static V8Initializer initializer; |
| + } |
| + }; |
| + |
| +} |
| + |
| +AdblockPlus::JsEngine::JsEngine(PrivateCtrArg) |
| +{ |
| +} |
| + |
| +AdblockPlus::JsEnginePtr AdblockPlus::JsEngine::New(const AppInfo& appInfo) |
| +{ |
| + V8Initializer::Init(); |
| + auto result = std::make_shared<JsEngine>(PrivateCtrArg{}); |
| + |
| + const v8::Locker locker{result->isolate}; |
| + const v8::HandleScope handleScope{result->isolate}; |
| + result->context = v8::UniquePersistent<v8::Context>{result->isolate, v8::Context::New(result->isolate)}; |
| + auto localContext = v8::Local<v8::Object>::Cast(v8::Local<v8::Context>::New(result->isolate, result->context)->Global()); |
| + |
| + v8::Context::Scope context_scope{v8::Local<v8::Context>::New(result->isolate, result->context)}; |
| + JsValue jsValueContext(result, localContext, JsValue::Private::CtrArg{}); |
| + AdblockPlus::GlobalJsObject::Setup(result, appInfo, jsValueContext); |
| + |
| + return result; |
| +} |
| + |
| +AdblockPlus::JsEngine::~JsEngine() |
| +{ |
| +} |
| + |
| +AdblockPlus::JsValuePtr AdblockPlus::JsEngine::Evaluate(const std::string& source, |
| + const std::string& filename) |
| +{ |
| + const JsContext context{*this}; |
| + const v8::TryCatch tryCatch; |
| + const v8::Handle<v8::Script> script = CompileScript(isolate, source, filename); |
| + CheckTryCatch(tryCatch); |
| + v8::Local<v8::Value> result = script->Run(); |
| + CheckTryCatch(tryCatch); |
| + return std::make_shared<JsValue>(shared_from_this(), result, JsValue::Private::CtrArg{}); |
| +} |
| + |
| +void AdblockPlus::JsEngine::SetEventCallback(const std::string& eventName, |
| + AdblockPlus::JsEngine::EventCallback callback) |
| +{ |
| + eventCallbacks[eventName] = callback; |
| +} |
| + |
| +void AdblockPlus::JsEngine::RemoveEventCallback(const std::string& eventName) |
| +{ |
| + eventCallbacks.erase(eventName); |
| +} |
| + |
| +void AdblockPlus::JsEngine::TriggerEvent(const std::string& eventName, AdblockPlus::JsValueList& params) |
| +{ |
| + EventMap::iterator it = eventCallbacks.find(eventName); |
| + if (it != eventCallbacks.end()) |
| + it->second(params); |
| +} |
| + |
| +void AdblockPlus::JsEngine::Gc() |
| +{ |
| + while (!isolate->IdleNotification(g_kIdleNotificationTimeuotMsec)); |
| +} |
| + |
| +AdblockPlus::JsValuePtr AdblockPlus::JsEngine::NewValue(const std::string& val) |
| +{ |
| + const JsContext context{*this}; |
| + return std::make_shared<JsValue>(shared_from_this(), |
| + AdblockPlus::Utils::ToV8String(isolate, val), |
| + JsValue::Private::CtrArg{}); |
| +} |
| + |
| +AdblockPlus::JsValuePtr AdblockPlus::JsEngine::NewValue(int64_t val) |
| +{ |
| + const JsContext context{*this}; |
| + return std::make_shared<JsValue>(shared_from_this(), v8::Number::New(isolate, val), |
| + JsValue::Private::CtrArg{}); |
| +} |
| + |
| +AdblockPlus::JsValuePtr AdblockPlus::JsEngine::NewValue(bool val) |
| +{ |
| + const JsContext context{*this}; |
| + return std::make_shared<JsValue>(shared_from_this(), v8::Boolean::New(isolate, val), |
| + JsValue::Private::CtrArg{}); |
| +} |
| + |
| +AdblockPlus::JsValuePtr AdblockPlus::JsEngine::NewObject() |
| +{ |
| + const JsContext context{*this}; |
| + return std::make_shared<JsValue>(shared_from_this(), v8::Object::New(isolate), |
| + JsValue::Private::CtrArg{}); |
| +} |
| + |
| +AdblockPlus::JsValuePtr AdblockPlus::JsEngine::NewCallback( |
| + v8::FunctionCallback callback) |
| +{ |
| + const JsContext context{*this}; |
| + |
| + // Note: we are leaking this weak pointer, no obvious way to destroy it when |
| + // it's no longer used |
| + std::tr1::weak_ptr<JsEngine>* data = |
| + new std::tr1::weak_ptr<JsEngine>(shared_from_this()); |
| + v8::Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate, callback, |
| + v8::External::New(isolate, data)); |
| + return std::make_shared<JsValue>(shared_from_this(), templ->GetFunction(), JsValue::Private::CtrArg{}); |
| +} |
| + |
| +AdblockPlus::JsEnginePtr AdblockPlus::JsEngine::FromArguments(const v8::FunctionCallbackInfo<v8::Value>& arguments) |
| +{ |
| + const v8::Local<const v8::External> external = |
| + v8::Local<const v8::External>::Cast(arguments.Data()); |
| + std::tr1::weak_ptr<JsEngine>* data = |
| + static_cast<std::tr1::weak_ptr<JsEngine>*>(external->Value()); |
| + JsEnginePtr result = data->lock(); |
| + if (!result) |
| + throw std::runtime_error("Oops, our JsEngine is gone, how did that happen?"); |
| + return result; |
| +} |
| + |
| +AdblockPlus::JsValueList AdblockPlus::JsEngine::ConvertArguments(const v8::FunctionCallbackInfo<v8::Value>& arguments) |
| +{ |
| + const JsContext context{*this}; |
| + JsValueList list; |
| + for (int i = 0; i < arguments.Length(); i++) |
| + list.emplace_back(std::make_shared<JsValue>(shared_from_this(), arguments[i], JsValue::Private::CtrArg{})); |
| + return list; |
| +} |
| + |
| +AdblockPlus::FileSystemPtr AdblockPlus::JsEngine::GetFileSystem() |
| +{ |
| + if (!fileSystem) |
| + fileSystem.reset(new DefaultFileSystem()); |
| + return fileSystem; |
| +} |
| + |
| +void AdblockPlus::JsEngine::SetFileSystem(AdblockPlus::FileSystemPtr val) |
| +{ |
| + if (!val) |
| + throw std::runtime_error("FileSystem cannot be null"); |
| + |
| + fileSystem = val; |
| +} |
| + |
| +AdblockPlus::WebRequestPtr AdblockPlus::JsEngine::GetWebRequest() |
| +{ |
| + if (!webRequest) |
| + webRequest.reset(new DefaultWebRequest()); |
| + return webRequest; |
| +} |
| + |
| +void AdblockPlus::JsEngine::SetWebRequest(AdblockPlus::WebRequestPtr val) |
| +{ |
| + if (!val) |
| + throw std::runtime_error("WebRequest cannot be null"); |
| + |
| + webRequest = val; |
| +} |
| + |
| +AdblockPlus::LogSystemPtr AdblockPlus::JsEngine::GetLogSystem() |
| +{ |
| + if (!logSystem) |
| + logSystem.reset(new DefaultLogSystem()); |
| + return logSystem; |
| +} |
| + |
| +void AdblockPlus::JsEngine::SetLogSystem(AdblockPlus::LogSystemPtr val) |
| +{ |
| + if (!val) |
| + throw std::runtime_error("LogSystem cannot be null"); |
| + |
| + logSystem = val; |
| +} |