tasks.h 6.65 KB
Newer Older
1 2 3 4 5 6 7 8 9
// Copyright 2020 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_TASKS_H_
#define V8_TEST_INSPECTOR_TASKS_H_

#include <vector>

10 11
#include "include/v8-context.h"
#include "include/v8-function.h"
12
#include "include/v8-inspector.h"
13 14
#include "include/v8-microtask-queue.h"
#include "include/v8-primitive.h"
15
#include "src/base/platform/semaphore.h"
16
#include "test/inspector/isolate-data.h"
17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
#include "test/inspector/task-runner.h"
#include "test/inspector/utils.h"

namespace v8 {
namespace internal {

template <typename T>
void RunSyncTask(TaskRunner* task_runner, T callback) {
  class SyncTask : public TaskRunner::Task {
   public:
    SyncTask(v8::base::Semaphore* ready_semaphore, T callback)
        : ready_semaphore_(ready_semaphore), callback_(callback) {}
    ~SyncTask() override = default;
    bool is_priority_task() final { return true; }

   private:
33
    void Run(InspectorIsolateData* data) override {
34 35 36 37 38 39 40 41 42
      callback_(data);
      if (ready_semaphore_) ready_semaphore_->Signal();
    }

    v8::base::Semaphore* ready_semaphore_;
    T callback_;
  };

  v8::base::Semaphore ready_semaphore(0);
43
  task_runner->Append(std::make_unique<SyncTask>(&ready_semaphore, callback));
44 45 46 47 48 49 50 51 52 53
  ready_semaphore.Wait();
}

class SendMessageToBackendTask : public TaskRunner::Task {
 public:
  SendMessageToBackendTask(int session_id, const std::vector<uint16_t>& message)
      : session_id_(session_id), message_(message) {}
  bool is_priority_task() final { return true; }

 private:
54
  void Run(InspectorIsolateData* data) override {
55 56 57 58 59 60 61 62 63 64
    v8_inspector::StringView message_view(message_.data(), message_.size());
    data->SendMessage(session_id_, message_view);
  }

  int session_id_;
  std::vector<uint16_t> message_;
};

inline void RunAsyncTask(TaskRunner* task_runner,
                         const v8_inspector::StringView& task_name,
65
                         std::unique_ptr<TaskRunner::Task> task) {
66 67
  class AsyncTask : public TaskRunner::Task {
   public:
68 69
    explicit AsyncTask(std::unique_ptr<TaskRunner::Task> inner)
        : inner_(std::move(inner)) {}
70
    ~AsyncTask() override = default;
71 72
    AsyncTask(const AsyncTask&) = delete;
    AsyncTask& operator=(const AsyncTask&) = delete;
73
    bool is_priority_task() override { return inner_->is_priority_task(); }
74
    void Run(InspectorIsolateData* data) override {
75 76 77 78 79 80 81 82 83
      data->AsyncTaskStarted(inner_.get());
      inner_->Run(data);
      data->AsyncTaskFinished(inner_.get());
    }

   private:
    std::unique_ptr<TaskRunner::Task> inner_;
  };

84 85
  task_runner->data()->AsyncTaskScheduled(task_name, task.get(), false);
  task_runner->Append(std::make_unique<AsyncTask>(std::move(task)));
86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106
}

class ExecuteStringTask : public TaskRunner::Task {
 public:
  ExecuteStringTask(v8::Isolate* isolate, int context_group_id,
                    const std::vector<uint16_t>& expression,
                    v8::Local<v8::String> name,
                    v8::Local<v8::Integer> line_offset,
                    v8::Local<v8::Integer> column_offset,
                    v8::Local<v8::Boolean> is_module)
      : expression_(expression),
        name_(ToVector(isolate, name)),
        line_offset_(line_offset.As<v8::Int32>()->Value()),
        column_offset_(column_offset.As<v8::Int32>()->Value()),
        is_module_(is_module->Value()),
        context_group_id_(context_group_id) {}

  ExecuteStringTask(const std::string& expression, int context_group_id)
      : expression_utf8_(expression), context_group_id_(context_group_id) {}

  ~ExecuteStringTask() override = default;
107 108
  ExecuteStringTask(const ExecuteStringTask&) = delete;
  ExecuteStringTask& operator=(const ExecuteStringTask&) = delete;
109
  bool is_priority_task() override { return false; }
110
  void Run(InspectorIsolateData* data) override;
111 112 113 114 115 116 117 118 119 120 121

 private:
  std::vector<uint16_t> expression_;
  std::string expression_utf8_;
  std::vector<uint16_t> name_;
  int32_t line_offset_ = 0;
  int32_t column_offset_ = 0;
  bool is_module_ = false;
  int context_group_id_;
};

122 123 124 125 126 127 128 129 130
class SetTimeoutTask : public TaskRunner::Task {
 public:
  SetTimeoutTask(int context_group_id, v8::Isolate* isolate,
                 v8::Local<v8::Function> function)
      : function_(isolate, function), context_group_id_(context_group_id) {}
  ~SetTimeoutTask() override = default;
  bool is_priority_task() final { return false; }

 private:
131
  void Run(InspectorIsolateData* data) override {
132 133 134 135 136 137 138 139 140 141 142 143 144 145 146
    v8::MicrotasksScope microtasks_scope(data->isolate(),
                                         v8::MicrotasksScope::kRunMicrotasks);
    v8::HandleScope handle_scope(data->isolate());
    v8::Local<v8::Context> context = data->GetDefaultContext(context_group_id_);
    v8::Context::Scope context_scope(context);

    v8::Local<v8::Function> function = function_.Get(data->isolate());
    v8::MaybeLocal<v8::Value> result;
    result = function->Call(context, context->Global(), 0, nullptr);
  }

  v8::Global<v8::Function> function_;
  int context_group_id_;
};

147
class SetTimeoutExtension : public InspectorIsolateData::SetupGlobalTask {
148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164
 public:
  void Run(v8::Isolate* isolate,
           v8::Local<v8::ObjectTemplate> global) override {
    global->Set(
        ToV8String(isolate, "setTimeout"),
        v8::FunctionTemplate::New(isolate, &SetTimeoutExtension::SetTimeout));
  }

 private:
  static void SetTimeout(const v8::FunctionCallbackInfo<v8::Value>& args) {
    if (args.Length() != 2 || !args[1]->IsNumber() ||
        (!args[0]->IsFunction() && !args[0]->IsString()) ||
        args[1].As<v8::Number>()->Value() != 0.0) {
      return;
    }
    v8::Isolate* isolate = args.GetIsolate();
    v8::Local<v8::Context> context = isolate->GetCurrentContext();
165
    InspectorIsolateData* data = InspectorIsolateData::FromContext(context);
166 167 168 169 170 171
    int context_group_id = data->GetContextGroupId(context);
    const char* task_name = "setTimeout";
    v8_inspector::StringView task_name_view(
        reinterpret_cast<const uint8_t*>(task_name), strlen(task_name));
    if (args[0]->IsFunction()) {
      RunAsyncTask(data->task_runner(), task_name_view,
172 173 174
                   std::make_unique<SetTimeoutTask>(
                       context_group_id, isolate,
                       v8::Local<v8::Function>::Cast(args[0])));
175 176 177
    } else {
      RunAsyncTask(
          data->task_runner(), task_name_view,
178
          std::make_unique<ExecuteStringTask>(
179 180 181 182 183 184 185 186
              isolate, context_group_id,
              ToVector(isolate, args[0].As<v8::String>()),
              v8::String::Empty(isolate), v8::Integer::New(isolate, 0),
              v8::Integer::New(isolate, 0), v8::Boolean::New(isolate, false)));
    }
  }
};

187 188 189 190
}  // namespace internal
}  // namespace v8

#endif  //  V8_TEST_INSPECTOR_TASKS_H_