// Copyright 2016 the V8 project authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef V8_TEST_INSPECTOR_PROTOCOL_TASK_RUNNER_H_ #define V8_TEST_INSPECTOR_PROTOCOL_TASK_RUNNER_H_ #include #include "include/v8-inspector.h" #include "include/v8-platform.h" #include "include/v8.h" #include "src/base/atomic-utils.h" #include "src/base/macros.h" #include "src/base/platform/platform.h" #include "src/locked-queue-inl.h" #include "src/vector.h" struct VectorCompare { bool operator()(const v8::internal::Vector& lhs, const v8::internal::Vector& rhs) const { for (int i = 0; i < lhs.length() && i < rhs.length(); ++i) { if (lhs[i] != rhs[i]) return lhs[i] < rhs[i]; } return false; } }; class TaskRunner : public v8::base::Thread { public: class Task { public: virtual ~Task() {} virtual bool is_inspector_task() = 0; virtual void Run(v8::Isolate* isolate, const v8::Global& context) = 0; }; class SetupGlobalTask { public: virtual ~SetupGlobalTask() = default; virtual void Run(v8::Isolate* isolate, v8::Local global) = 0; }; using SetupGlobalTasks = std::vector>; TaskRunner(SetupGlobalTasks setup_global_tasks, bool catch_exceptions, v8::base::Semaphore* ready_semaphore); virtual ~TaskRunner(); // Thread implementation. void Run() override; // Should be called from the same thread and only from task. void RunMessageLoop(bool only_protocol); void QuitMessageLoop(); // TaskRunner takes ownership. void Append(Task* task); static TaskRunner* FromContext(v8::Local); v8::Local NewContextGroup( const SetupGlobalTasks& setup_global_tasks); v8::Local GetContext(int context_group_id); static int GetContextGroupId(v8::Local context); void Terminate(); void RegisterModule(v8::internal::Vector name, v8::Local module); static v8::MaybeLocal ModuleResolveCallback( v8::Local context, v8::Local specifier, v8::Local referrer); private: void InitializeIsolate(); Task* GetNext(bool only_protocol); SetupGlobalTasks setup_global_tasks_; bool catch_exceptions_; v8::base::Semaphore* ready_semaphore_; v8::Isolate* isolate_; intptr_t last_context_group_id_ = 0; std::map> contexts_; // deferred_queue_ combined with queue_ (in this order) have all tasks in the // correct order. Sometimes we skip non-protocol tasks by moving them from // queue_ to deferred_queue_. v8::internal::LockedQueue queue_; v8::internal::LockedQueue deffered_queue_; v8::base::Semaphore process_queue_semaphore_; std::map, v8::Global, VectorCompare> modules_; int nested_loop_count_; v8::base::AtomicNumber is_terminated_; DISALLOW_COPY_AND_ASSIGN(TaskRunner); }; class AsyncTask : public TaskRunner::Task { public: AsyncTask(const char* task_name, v8_inspector::V8Inspector* inspector); virtual ~AsyncTask() = default; void Run(v8::Isolate* isolate, const v8::Global& context) override; virtual void AsyncRun(v8::Isolate* isolate, const v8::Global& context) = 0; protected: v8_inspector::V8Inspector* inspector_; }; class ExecuteStringTask : public AsyncTask { public: ExecuteStringTask(const v8::internal::Vector& expression, v8::Local name, v8::Local line_offset, v8::Local column_offset, v8::Local is_module, const char* task_name, v8_inspector::V8Inspector* inspector); explicit ExecuteStringTask( const v8::internal::Vector& expression); bool is_inspector_task() override { return false; } void AsyncRun(v8::Isolate* isolate, const v8::Global& context) override; private: v8::internal::Vector expression_; v8::internal::Vector expression_utf8_; v8::internal::Vector name_; int32_t line_offset_ = 0; int32_t column_offset_ = 0; bool is_module_ = false; DISALLOW_COPY_AND_ASSIGN(ExecuteStringTask); }; #endif // V8_TEST_INSPECTOR_PROTOCOL_TASK_RUNNER_H_