OLD | NEW |
1 // Copyright 2016 the V8 project authors. All rights reserved. | 1 // Copyright 2016 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "test/inspector/inspector-impl.h" | 5 #include "test/inspector/inspector-impl.h" |
6 | 6 |
7 #include "include/v8.h" | 7 #include "include/v8.h" |
8 | 8 |
9 #include "src/vector.h" | 9 #include "src/vector.h" |
| 10 #include "test/inspector/isolate-data.h" |
| 11 #include "test/inspector/task-runner.h" |
10 | 12 |
11 namespace { | 13 namespace { |
12 | 14 |
13 const int kInspectorClientIndex = 0; | |
14 | |
15 class ChannelImpl final : public v8_inspector::V8Inspector::Channel { | 15 class ChannelImpl final : public v8_inspector::V8Inspector::Channel { |
16 public: | 16 public: |
17 explicit ChannelImpl(InspectorClientImpl::FrontendChannel* frontend_channel) | 17 ChannelImpl(InspectorClientImpl::FrontendChannel* frontend_channel, |
18 : frontend_channel_(frontend_channel) {} | 18 int session_id) |
| 19 : frontend_channel_(frontend_channel), session_id_(session_id) {} |
19 virtual ~ChannelImpl() = default; | 20 virtual ~ChannelImpl() = default; |
20 | 21 |
21 private: | 22 private: |
22 void sendResponse( | 23 void sendResponse( |
23 int callId, | 24 int callId, |
24 std::unique_ptr<v8_inspector::StringBuffer> message) override { | 25 std::unique_ptr<v8_inspector::StringBuffer> message) override { |
25 frontend_channel_->SendMessageToFrontend(message->string()); | 26 frontend_channel_->SendMessageToFrontend(session_id_, message->string()); |
26 } | 27 } |
27 void sendNotification( | 28 void sendNotification( |
28 std::unique_ptr<v8_inspector::StringBuffer> message) override { | 29 std::unique_ptr<v8_inspector::StringBuffer> message) override { |
29 frontend_channel_->SendMessageToFrontend(message->string()); | 30 frontend_channel_->SendMessageToFrontend(session_id_, message->string()); |
30 } | 31 } |
31 void flushProtocolNotifications() override {} | 32 void flushProtocolNotifications() override {} |
32 | 33 |
33 InspectorClientImpl::FrontendChannel* frontend_channel_; | 34 InspectorClientImpl::FrontendChannel* frontend_channel_; |
| 35 int session_id_; |
34 DISALLOW_COPY_AND_ASSIGN(ChannelImpl); | 36 DISALLOW_COPY_AND_ASSIGN(ChannelImpl); |
35 }; | 37 }; |
36 | 38 |
37 InspectorClientImpl* InspectorClientFromContext( | |
38 v8::Local<v8::Context> context) { | |
39 InspectorClientImpl* inspector_client = static_cast<InspectorClientImpl*>( | |
40 context->GetAlignedPointerFromEmbedderData(kInspectorClientIndex)); | |
41 CHECK(inspector_client); | |
42 return inspector_client; | |
43 } | |
44 | |
45 v8::internal::Vector<uint16_t> ToVector(v8::Local<v8::String> str) { | 39 v8::internal::Vector<uint16_t> ToVector(v8::Local<v8::String> str) { |
46 v8::internal::Vector<uint16_t> buffer = | 40 v8::internal::Vector<uint16_t> buffer = |
47 v8::internal::Vector<uint16_t>::New(str->Length()); | 41 v8::internal::Vector<uint16_t>::New(str->Length()); |
48 str->Write(buffer.start(), 0, str->Length()); | 42 str->Write(buffer.start(), 0, str->Length()); |
49 return buffer; | 43 return buffer; |
50 } | 44 } |
51 | 45 |
52 void MessageHandler(v8::Local<v8::Message> message, | 46 void MessageHandler(v8::Local<v8::Message> message, |
53 v8::Local<v8::Value> exception) { | 47 v8::Local<v8::Value> exception) { |
54 v8::Isolate* isolate = v8::Isolate::GetCurrent(); | 48 v8::Isolate* isolate = v8::Isolate::GetCurrent(); |
55 v8::Local<v8::Context> context = isolate->GetEnteredContext(); | 49 v8::Local<v8::Context> context = isolate->GetEnteredContext(); |
56 if (context.IsEmpty()) return; | 50 if (context.IsEmpty()) return; |
57 v8_inspector::V8Inspector* inspector = | 51 v8_inspector::V8Inspector* inspector = |
58 InspectorClientImpl::InspectorFromContext(context); | 52 IsolateData::FromContext(context)->inspector()->inspector(); |
59 | 53 |
60 v8::Local<v8::StackTrace> stack = message->GetStackTrace(); | 54 v8::Local<v8::StackTrace> stack = message->GetStackTrace(); |
61 int script_id = | 55 int script_id = |
62 static_cast<int>(message->GetScriptOrigin().ScriptID()->Value()); | 56 static_cast<int>(message->GetScriptOrigin().ScriptID()->Value()); |
63 if (!stack.IsEmpty() && stack->GetFrameCount() > 0) { | 57 if (!stack.IsEmpty() && stack->GetFrameCount() > 0) { |
64 int top_script_id = stack->GetFrame(0)->GetScriptId(); | 58 int top_script_id = stack->GetFrame(0)->GetScriptId(); |
65 if (top_script_id == script_id) script_id = 0; | 59 if (top_script_id == script_id) script_id = 0; |
66 } | 60 } |
67 int line_number = message->GetLineNumber(context).FromMaybe(0); | 61 int line_number = message->GetLineNumber(context).FromMaybe(0); |
68 int column_number = 0; | 62 int column_number = 0; |
(...skipping 30 matching lines...) Expand all Loading... |
99 .ToLocalChecked(); | 93 .ToLocalChecked(); |
100 } | 94 } |
101 | 95 |
102 void Print(v8::Isolate* isolate, const v8_inspector::StringView& string) { | 96 void Print(v8::Isolate* isolate, const v8_inspector::StringView& string) { |
103 v8::Local<v8::String> v8_string = ToString(isolate, string); | 97 v8::Local<v8::String> v8_string = ToString(isolate, string); |
104 v8::String::Utf8Value utf8_string(v8_string); | 98 v8::String::Utf8Value utf8_string(v8_string); |
105 fwrite(*utf8_string, sizeof(**utf8_string), utf8_string.length(), stdout); | 99 fwrite(*utf8_string, sizeof(**utf8_string), utf8_string.length(), stdout); |
106 } | 100 } |
107 } // namespace | 101 } // namespace |
108 | 102 |
109 class ConnectTask : public TaskRunner::Task { | 103 InspectorClientImpl::InspectorClientImpl(v8::Isolate* isolate, |
110 public: | 104 TaskRunner* task_runner, |
111 ConnectTask(InspectorClientImpl* client, v8::base::Semaphore* ready_semaphore) | 105 FrontendChannel* frontend_channel) |
112 : client_(client), ready_semaphore_(ready_semaphore) {} | 106 : task_runner_(task_runner), |
113 virtual ~ConnectTask() = default; | 107 isolate_(isolate), |
114 | |
115 bool is_inspector_task() final { return true; } | |
116 | |
117 private: | |
118 void Run() override { | |
119 v8::HandleScope handle_scope(isolate()); | |
120 client_->connect(); | |
121 if (ready_semaphore_) ready_semaphore_->Signal(); | |
122 } | |
123 | |
124 InspectorClientImpl* client_; | |
125 v8::base::Semaphore* ready_semaphore_; | |
126 }; | |
127 | |
128 class DisconnectTask : public TaskRunner::Task { | |
129 public: | |
130 explicit DisconnectTask(InspectorClientImpl* client, bool reset_inspector, | |
131 v8::base::Semaphore* ready_semaphore) | |
132 : client_(client), | |
133 reset_inspector_(reset_inspector), | |
134 ready_semaphore_(ready_semaphore) {} | |
135 virtual ~DisconnectTask() = default; | |
136 | |
137 bool is_inspector_task() final { return true; } | |
138 | |
139 private: | |
140 void Run() override { | |
141 client_->disconnect(reset_inspector_); | |
142 if (ready_semaphore_) ready_semaphore_->Signal(); | |
143 } | |
144 | |
145 InspectorClientImpl* client_; | |
146 bool reset_inspector_; | |
147 v8::base::Semaphore* ready_semaphore_; | |
148 }; | |
149 | |
150 class CreateContextGroupTask : public TaskRunner::Task { | |
151 public: | |
152 CreateContextGroupTask(InspectorClientImpl* client, | |
153 IsolateData::SetupGlobalTasks setup_global_tasks, | |
154 v8::base::Semaphore* ready_semaphore, | |
155 int* context_group_id) | |
156 : client_(client), | |
157 setup_global_tasks_(std::move(setup_global_tasks)), | |
158 ready_semaphore_(ready_semaphore), | |
159 context_group_id_(context_group_id) {} | |
160 virtual ~CreateContextGroupTask() = default; | |
161 | |
162 bool is_inspector_task() final { return true; } | |
163 | |
164 private: | |
165 void Run() override { | |
166 *context_group_id_ = client_->createContextGroup(setup_global_tasks_); | |
167 if (ready_semaphore_) ready_semaphore_->Signal(); | |
168 } | |
169 | |
170 InspectorClientImpl* client_; | |
171 IsolateData::SetupGlobalTasks setup_global_tasks_; | |
172 v8::base::Semaphore* ready_semaphore_; | |
173 int* context_group_id_; | |
174 }; | |
175 | |
176 InspectorClientImpl::InspectorClientImpl(TaskRunner* task_runner, | |
177 FrontendChannel* frontend_channel, | |
178 v8::base::Semaphore* ready_semaphore) | |
179 : isolate_(nullptr), | |
180 task_runner_(task_runner), | |
181 frontend_channel_(frontend_channel) { | 108 frontend_channel_(frontend_channel) { |
182 task_runner_->Append(new ConnectTask(this, ready_semaphore)); | 109 isolate_->AddMessageListener(MessageHandler); |
| 110 inspector_ = v8_inspector::V8Inspector::create(isolate_, this); |
183 } | 111 } |
184 | 112 |
185 InspectorClientImpl::~InspectorClientImpl() {} | 113 InspectorClientImpl::~InspectorClientImpl() {} |
186 | 114 |
187 void InspectorClientImpl::connect() { | 115 int InspectorClientImpl::ConnectSession(int context_group_id, |
188 isolate_ = task_runner_->data()->isolate(); | 116 const v8_inspector::StringView& state) { |
189 isolate_->AddMessageListener(MessageHandler); | 117 int session_id = ++last_session_id_; |
190 channel_.reset(new ChannelImpl(frontend_channel_)); | 118 channels_[session_id].reset(new ChannelImpl(frontend_channel_, session_id)); |
191 inspector_ = v8_inspector::V8Inspector::create(isolate_, this); | 119 sessions_[session_id] = |
192 | 120 inspector_->connect(context_group_id, channels_[session_id].get(), state); |
193 if (states_.empty()) { | 121 context_group_by_session_[sessions_[session_id].get()] = context_group_id; |
194 ConnectToContextGroup(task_runner_->default_context_group_id(), | 122 return session_id; |
195 v8_inspector::StringView()); | |
196 } else { | |
197 for (const auto& it : states_) | |
198 ConnectToContextGroup(it.first, it.second->string()); | |
199 } | |
200 states_.clear(); | |
201 } | 123 } |
202 | 124 |
203 void InspectorClientImpl::ConnectToContextGroup( | 125 std::unique_ptr<v8_inspector::StringBuffer> |
204 int context_group_id, v8_inspector::StringView state) { | 126 InspectorClientImpl::DisconnectSession(int session_id) { |
205 v8::Local<v8::Context> context = | 127 auto it = sessions_.find(session_id); |
206 task_runner_->data()->GetContext(context_group_id); | 128 CHECK(it != sessions_.end()); |
207 sessions_[context_group_id] = | 129 context_group_by_session_.erase(it->second.get()); |
208 inspector_->connect(context_group_id, channel_.get(), state); | 130 std::unique_ptr<v8_inspector::StringBuffer> result = it->second->stateJSON(); |
209 context->SetAlignedPointerInEmbedderData(kInspectorClientIndex, this); | 131 sessions_.erase(it); |
| 132 channels_.erase(session_id); |
| 133 return result; |
| 134 } |
| 135 |
| 136 void InspectorClientImpl::SendMessage(int session_id, |
| 137 const v8_inspector::StringView& message) { |
| 138 auto it = sessions_.find(session_id); |
| 139 if (it != sessions_.end()) it->second->dispatchProtocolMessage(message); |
| 140 } |
| 141 |
| 142 void InspectorClientImpl::BreakProgram( |
| 143 int context_group_id, const v8_inspector::StringView& reason, |
| 144 const v8_inspector::StringView& details) { |
| 145 for (int session_id : GetSessionIds(context_group_id)) { |
| 146 auto it = sessions_.find(session_id); |
| 147 if (it != sessions_.end()) it->second->breakProgram(reason, details); |
| 148 } |
| 149 } |
| 150 |
| 151 void InspectorClientImpl::SchedulePauseOnNextStatement( |
| 152 int context_group_id, const v8_inspector::StringView& reason, |
| 153 const v8_inspector::StringView& details) { |
| 154 for (int session_id : GetSessionIds(context_group_id)) { |
| 155 auto it = sessions_.find(session_id); |
| 156 if (it != sessions_.end()) |
| 157 it->second->schedulePauseOnNextStatement(reason, details); |
| 158 } |
| 159 } |
| 160 |
| 161 void InspectorClientImpl::CancelPauseOnNextStatement(int context_group_id) { |
| 162 for (int session_id : GetSessionIds(context_group_id)) { |
| 163 auto it = sessions_.find(session_id); |
| 164 if (it != sessions_.end()) it->second->cancelPauseOnNextStatement(); |
| 165 } |
| 166 } |
| 167 |
| 168 void InspectorClientImpl::ContextCreated(v8::Local<v8::Context> context, |
| 169 int context_group_id) { |
210 v8_inspector::V8ContextInfo info(context, context_group_id, | 170 v8_inspector::V8ContextInfo info(context, context_group_id, |
211 v8_inspector::StringView()); | 171 v8_inspector::StringView()); |
212 info.hasMemoryOnConsole = true; | 172 info.hasMemoryOnConsole = true; |
213 inspector_->contextCreated(info); | 173 inspector_->contextCreated(info); |
214 } | 174 } |
215 | 175 |
216 void InspectorClientImpl::scheduleReconnect( | 176 void InspectorClientImpl::ContextDestroyed(v8::Local<v8::Context> context) { |
217 v8::base::Semaphore* ready_semaphore) { | 177 inspector_->contextDestroyed(context); |
218 task_runner_->Append( | |
219 new DisconnectTask(this, /* reset_inspector */ true, nullptr)); | |
220 task_runner_->Append(new ConnectTask(this, ready_semaphore)); | |
221 } | 178 } |
222 | 179 |
223 void InspectorClientImpl::scheduleDisconnect( | 180 std::vector<int> InspectorClientImpl::GetSessionIds(int context_group_id) { |
224 v8::base::Semaphore* ready_semaphore) { | 181 std::vector<int> result; |
225 task_runner_->Append( | 182 for (auto& it : sessions_) { |
226 new DisconnectTask(this, /* reset_inspector */ false, ready_semaphore)); | 183 if (context_group_by_session_[it.second.get()] == context_group_id) |
227 } | 184 result.push_back(it.first); |
228 | |
229 void InspectorClientImpl::disconnect(bool reset_inspector) { | |
230 for (const auto& it : sessions_) { | |
231 states_[it.first] = it.second->stateJSON(); | |
232 } | 185 } |
233 sessions_.clear(); | 186 return result; |
234 if (reset_inspector) inspector_.reset(); | |
235 } | |
236 | |
237 void InspectorClientImpl::scheduleCreateContextGroup( | |
238 IsolateData::SetupGlobalTasks setup_global_tasks, | |
239 v8::base::Semaphore* ready_semaphore, int* context_group_id) { | |
240 task_runner_->Append(new CreateContextGroupTask( | |
241 this, std::move(setup_global_tasks), ready_semaphore, context_group_id)); | |
242 } | |
243 | |
244 int InspectorClientImpl::createContextGroup( | |
245 const IsolateData::SetupGlobalTasks& setup_global_tasks) { | |
246 v8::HandleScope handle_scope(isolate_); | |
247 int context_group_id = task_runner_->data()->CreateContextGroup(); | |
248 v8::Local<v8::Context> context = | |
249 task_runner_->data()->GetContext(context_group_id); | |
250 context->SetAlignedPointerInEmbedderData(kInspectorClientIndex, this); | |
251 v8_inspector::StringView state; | |
252 sessions_[context_group_id] = | |
253 inspector_->connect(context_group_id, channel_.get(), state); | |
254 inspector_->contextCreated(v8_inspector::V8ContextInfo( | |
255 context, context_group_id, v8_inspector::StringView())); | |
256 return context_group_id; | |
257 } | 187 } |
258 | 188 |
259 bool InspectorClientImpl::formatAccessorsAsProperties( | 189 bool InspectorClientImpl::formatAccessorsAsProperties( |
260 v8::Local<v8::Value> object) { | 190 v8::Local<v8::Value> object) { |
261 v8::Isolate* isolate = v8::Isolate::GetCurrent(); | 191 v8::Isolate* isolate = v8::Isolate::GetCurrent(); |
262 v8::Local<v8::Context> context = isolate->GetCurrentContext(); | 192 v8::Local<v8::Context> context = isolate->GetCurrentContext(); |
263 v8::Local<v8::Private> shouldFormatAccessorsPrivate = v8::Private::ForApi( | 193 v8::Local<v8::Private> shouldFormatAccessorsPrivate = v8::Private::ForApi( |
264 isolate, v8::String::NewFromUtf8(isolate, "allowAccessorFormatting", | 194 isolate, v8::String::NewFromUtf8(isolate, "allowAccessorFormatting", |
265 v8::NewStringType::kNormal) | 195 v8::NewStringType::kNormal) |
266 .ToLocalChecked()); | 196 .ToLocalChecked()); |
267 CHECK(object->IsObject()); | 197 CHECK(object->IsObject()); |
268 return object.As<v8::Object>() | 198 return object.As<v8::Object>() |
269 ->HasPrivate(context, shouldFormatAccessorsPrivate) | 199 ->HasPrivate(context, shouldFormatAccessorsPrivate) |
270 .FromMaybe(false); | 200 .FromMaybe(false); |
271 } | 201 } |
272 | 202 |
273 v8::Local<v8::Context> InspectorClientImpl::ensureDefaultContextInGroup( | 203 v8::Local<v8::Context> InspectorClientImpl::ensureDefaultContextInGroup( |
274 int context_group_id) { | 204 int context_group_id) { |
275 CHECK(isolate_); | 205 CHECK(isolate_); |
276 return task_runner_->data()->GetContext(context_group_id); | 206 return task_runner_->data()->GetContext(context_group_id); |
277 } | 207 } |
278 | 208 |
279 void InspectorClientImpl::setCurrentTimeMSForTest(double time) { | 209 void InspectorClientImpl::SetCurrentTimeMSForTest(double time) { |
280 current_time_ = time; | 210 current_time_ = time; |
281 current_time_set_for_test_ = true; | 211 current_time_set_for_test_ = true; |
282 } | 212 } |
283 | 213 |
284 double InspectorClientImpl::currentTimeMS() { | 214 double InspectorClientImpl::currentTimeMS() { |
285 if (current_time_set_for_test_) return current_time_; | 215 if (current_time_set_for_test_) return current_time_; |
286 return v8::base::OS::TimeCurrentMillis(); | 216 return v8::base::OS::TimeCurrentMillis(); |
287 } | 217 } |
288 | 218 |
289 void InspectorClientImpl::setMemoryInfoForTest( | 219 void InspectorClientImpl::SetMemoryInfoForTest( |
290 v8::Local<v8::Value> memory_info) { | 220 v8::Local<v8::Value> memory_info) { |
291 memory_info_.Reset(isolate_, memory_info); | 221 memory_info_.Reset(isolate_, memory_info); |
292 } | 222 } |
293 | 223 |
294 void InspectorClientImpl::setLogConsoleApiMessageCalls(bool log) { | 224 void InspectorClientImpl::SetLogConsoleApiMessageCalls(bool log) { |
295 log_console_api_message_calls_ = log; | 225 log_console_api_message_calls_ = log; |
296 } | 226 } |
297 | 227 |
298 v8::MaybeLocal<v8::Value> InspectorClientImpl::memoryInfo( | 228 v8::MaybeLocal<v8::Value> InspectorClientImpl::memoryInfo( |
299 v8::Isolate* isolate, v8::Local<v8::Context>) { | 229 v8::Isolate* isolate, v8::Local<v8::Context>) { |
300 if (memory_info_.IsEmpty()) return v8::MaybeLocal<v8::Value>(); | 230 if (memory_info_.IsEmpty()) return v8::MaybeLocal<v8::Value>(); |
301 return memory_info_.Get(isolate); | 231 return memory_info_.Get(isolate); |
302 } | 232 } |
303 | 233 |
304 void InspectorClientImpl::runMessageLoopOnPause(int) { | 234 void InspectorClientImpl::runMessageLoopOnPause(int) { |
(...skipping 10 matching lines...) Expand all Loading... |
315 const v8_inspector::StringView& url, unsigned lineNumber, | 245 const v8_inspector::StringView& url, unsigned lineNumber, |
316 unsigned columnNumber, v8_inspector::V8StackTrace* stack) { | 246 unsigned columnNumber, v8_inspector::V8StackTrace* stack) { |
317 if (!log_console_api_message_calls_) return; | 247 if (!log_console_api_message_calls_) return; |
318 Print(isolate_, message); | 248 Print(isolate_, message); |
319 fprintf(stdout, " ("); | 249 fprintf(stdout, " ("); |
320 Print(isolate_, url); | 250 Print(isolate_, url); |
321 fprintf(stdout, ":%d:%d)", lineNumber, columnNumber); | 251 fprintf(stdout, ":%d:%d)", lineNumber, columnNumber); |
322 Print(isolate_, stack->toString()->string()); | 252 Print(isolate_, stack->toString()->string()); |
323 fprintf(stdout, "\n"); | 253 fprintf(stdout, "\n"); |
324 } | 254 } |
325 | |
326 v8_inspector::V8Inspector* InspectorClientImpl::InspectorFromContext( | |
327 v8::Local<v8::Context> context) { | |
328 return InspectorClientFromContext(context)->inspector_.get(); | |
329 } | |
330 | |
331 v8_inspector::V8InspectorSession* InspectorClientImpl::SessionFromContext( | |
332 v8::Local<v8::Context> context) { | |
333 InspectorClientImpl* client = InspectorClientFromContext(context); | |
334 for (auto& it : client->sessions_) { | |
335 if (client->task_runner_->data()->GetContext(it.first) == context) | |
336 return it.second.get(); | |
337 } | |
338 return nullptr; | |
339 } | |
340 | |
341 v8_inspector::V8InspectorSession* InspectorClientImpl::session( | |
342 int context_group_id) { | |
343 if (context_group_id) { | |
344 return sessions_[context_group_id].get(); | |
345 } else { | |
346 return sessions_.begin()->second.get(); | |
347 } | |
348 } | |
349 | |
350 class SendMessageToBackendTask : public TaskRunner::Task { | |
351 public: | |
352 explicit SendMessageToBackendTask( | |
353 const v8::internal::Vector<uint16_t>& message, int context_group_id) | |
354 : message_(message), context_group_id_(context_group_id) {} | |
355 | |
356 bool is_inspector_task() final { return true; } | |
357 | |
358 private: | |
359 void Run() override { | |
360 v8_inspector::V8InspectorSession* session = nullptr; | |
361 { | |
362 v8::HandleScope handle_scope(isolate()); | |
363 if (!context_group_id_) { | |
364 session = InspectorClientImpl::SessionFromContext(default_context()); | |
365 } else { | |
366 session = InspectorClientFromContext(default_context()) | |
367 ->sessions_[context_group_id_] | |
368 .get(); | |
369 } | |
370 if (!session) return; | |
371 } | |
372 v8_inspector::StringView message_view(message_.start(), message_.length()); | |
373 session->dispatchProtocolMessage(message_view); | |
374 } | |
375 | |
376 v8::internal::Vector<uint16_t> message_; | |
377 int context_group_id_; | |
378 }; | |
379 | |
380 TaskRunner* SendMessageToBackendExtension::backend_task_runner_ = nullptr; | |
381 | |
382 void SendMessageToBackendExtension::Run(v8::Isolate* isolate, | |
383 v8::Local<v8::ObjectTemplate> global) { | |
384 global->Set( | |
385 v8::String::NewFromUtf8(isolate, "sendMessageToBackend", | |
386 v8::NewStringType::kNormal) | |
387 .ToLocalChecked(), | |
388 v8::FunctionTemplate::New( | |
389 isolate, &SendMessageToBackendExtension::SendMessageToBackend)); | |
390 } | |
391 | |
392 void SendMessageToBackendExtension::SendMessageToBackend( | |
393 const v8::FunctionCallbackInfo<v8::Value>& args) { | |
394 CHECK(backend_task_runner_); | |
395 CHECK(args.Length() == 2 && args[0]->IsString() && args[1]->IsInt32()); | |
396 v8::Local<v8::String> message = args[0].As<v8::String>(); | |
397 backend_task_runner_->Append(new SendMessageToBackendTask( | |
398 ToVector(message), args[1].As<v8::Int32>()->Value())); | |
399 } | |
OLD | NEW |