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 |