| Index: src/JsEngineInternal.h |
| =================================================================== |
| new file mode 100644 |
| --- /dev/null |
| +++ b/src/JsEngineInternal.h |
| @@ -0,0 +1,171 @@ |
| + |
| +#if !defined(ADBLOCK_PLUS_JS_ENGINE_INTERNAL_H) |
| +#define ADBLOCK_PLUS_JS_ENGINE_INTERNAL_H |
| + |
| +#include <AdblockPlus/JsEngine.h> |
| +#include <v8.h> |
| +#include <array> |
| +#include "AllocatedArray.h" |
| +#include "V8Upgrade.h" |
| + |
| +class PersistentValueArray |
| + : public AllocatedArray<V8PersistentNG<v8::Value>> |
| +{ |
| + typedef AllocatedArray<V8PersistentNG<v8::Value>> Base; |
| + /** |
| + * Copy constructor deleted. Allocation is unique to single object. |
| + */ |
| + PersistentValueArray(const PersistentValueArray&); // = delete; |
| + /** |
| + * Copy assignment deleted. Allocation is unique to single object. |
| + */ |
| + PersistentValueArray operator=(const PersistentValueArray&); // = delete; |
| + |
| +public: |
| + PersistentValueArray() |
| + : Base() |
| + {} |
| + |
| + PersistentValueArray(size_t n) |
| + : Base(n) |
| + {} |
| + |
| + /** |
| + * As-if-default move constructor |
| + */ |
| + PersistentValueArray(PersistentValueArray&& x) // = default; |
| + : Base(std::move(x)) |
| + {} |
| + /** |
| + * As-if-default move assignment |
| + */ |
| + PersistentValueArray& operator=(PersistentValueArray&& x) // = default; |
| + { |
| + Base::operator=(std::move(x)); |
| + return *this; |
| + } |
| + |
| + /** |
| + * Convert our array from `Persistent` to `Local`. |
| + */ |
| + AllocatedArray<v8::Local<v8::Value>> GetAsLocal(v8::Isolate* isolate) |
| + { |
| + const auto length = Base::Size(); |
| + AllocatedArray<v8::Local<v8::Value>> locals(length); |
| + for (size_t i = 0; i < length; ++i) |
| + { |
| + locals[i] = (*this)[i].Get(isolate); |
| + } |
| + return std::move(locals); |
| + } |
| +}; |
| + |
| +/** |
| + * \par Implementation Notes |
| + */ |
| +class JsEngineInternal |
| + : public AdblockPlus::JsEngine |
| +{ |
| + /** |
| + * Unique context associated with this isolate. |
| + */ |
| + v8::Persistent<v8::Context> context; |
| + |
| +public: |
| + JsEngineInternal(const AdblockPlus::ScopedV8IsolatePtr& isolate); |
| + |
| + /** |
| + * Retrieve our persistent v8 context as a local handle. |
| + */ |
| + v8::Local<v8::Context> GetContextAsLocal() const; |
| + |
| + /** |
| + * Retrieve the global object of our context. |
| + */ |
| + v8::Local<v8::Object> GetGlobalObject(); |
| + |
| + /** |
| + * Create a JavaScript function that binds to a C++ callback. |
| + * |
| + * We save a copy of a pointer to the present instance when we |
| + * create the JS function inside the v8 isolate. |
| + * This pointer is accessible through the `v8::Arguments` class, |
| + * which is the argument of the callback function. |
| + * The isolate pointer is already available; |
| + * the engine pointer is available if its services are needed. |
| + * |
| + * @param callback C++ callback to invoke. |
| + * @return handle function instance within our isolate |
| + * |
| + * \par Precondition |
| + * - Single-threading has been ensured |
| + * - A v8::Context has been entered. |
| + * - A handle context already exists |
| + */ |
| + v8::Local<v8::Function> MakeCallback(v8::InvocationCallback callback); |
| + |
| + /** |
| + * Extract the engine from the arguments to a function created by `MakeCallback` |
| + * |
| + * @param [v8::Arguments] |
| + * Arguments object pass as the argument to a callback function |
| + * @return |
| + * Pointer to engine instance within the arguments. |
| + * |
| + * \par Precondition |
| + */ |
| + static JsEngineInternal* ExtractEngine(const v8::Arguments& arguments); |
| + |
| + /** |
| + * Call a function with the global object as "this" |
| + */ |
| + v8::Local<v8::Value> ApplyFunction( |
| + v8::Local<v8::Function> func, |
| + AllocatedArray<v8::Local<v8::Value>> args); |
| + |
| + /** |
| + * Call a function with an arbitrary object as "this" |
| + * |
| + * Defined as a member of the engine class as part of v8 upgrade path. |
| + * Newer versions of v8 require a context argument for `v8::Function::Call()`. |
| + */ |
| + v8::Local<v8::Value> ApplyFunction( |
| + v8::Local<v8::Object> thisObject, |
| + v8::Local<v8::Function> func, |
| + AllocatedArray<v8::Local<v8::Value>> args); |
| +}; |
| + |
| +/** |
| + * Sentry class setting up a multi-threaded v8 usage environment. |
| + * |
| + * The engine has the responsibility for maintaining an isolate and a context. |
| + * This class maintains the following: |
| + * - v8 lock to ensure single-threaded JS evaluation. |
| + * - v8 scopes for isolate, handle, and scope. |
| + * - shared_ptr to engine |
| + */ |
| +class V8ExecutionScope |
| +{ |
| + /** |
| + * Multithread lock for v8. |
| + * Declared first to ensure acquiring a lock before anything else happens. |
| + */ |
| + const v8::Locker lock; |
| + /** |
| + * Isolate scope required for Isolate::GetCurrent() to work. |
| + * Probably not needed as we upgrade our v8 version. |
| + */ |
| + const v8::Isolate::Scope isolateScope; |
| + /** |
| + * Handle scope must be declared before any member that uses handles. |
| + * Required to obtain the local context handle to initialize context scope. |
| + */ |
| + const v8::HandleScope handleScope; |
| + const v8::Context::Scope contextScope; |
| +public: |
| + V8ExecutionScope(JsEngineInternal* engine); |
| +}; |
| + |
| + |
| + |
| +#endif |