v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
v8-console.cc
Go to the documentation of this file.
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
3// found in the LICENSE file.
4
6
12#include "include/v8-profiler.h"
14#include "src/base/macros.h"
30
31namespace v8_inspector {
32
33namespace {
34
35String16 consoleContextToString(
36 v8::Isolate* isolate, const v8::debug::ConsoleContext& consoleContext) {
37 if (consoleContext.id() == 0) return String16();
38 return toProtocolString(isolate, consoleContext.name()) + "#" +
39 String16::fromInteger(consoleContext.id());
40}
41
42class ConsoleHelper {
43 public:
44 ConsoleHelper(const v8::debug::ConsoleCallArguments& info,
45 const v8::debug::ConsoleContext& consoleContext,
46 V8InspectorImpl* inspector)
47 : m_info(info),
48 m_consoleContext(consoleContext),
49 m_inspector(inspector) {}
50
51 ConsoleHelper(const ConsoleHelper&) = delete;
52 ConsoleHelper& operator=(const ConsoleHelper&) = delete;
53
54 v8::Isolate* isolate() const { return m_inspector->isolate(); }
56 return isolate()->GetCurrentContext();
57 }
58 int contextId() const { return InspectedContext::contextId(context()); }
59 int groupId() const { return m_inspector->contextGroupId(contextId()); }
60
61 InjectedScript* injectedScript(int sessionId) {
62 InspectedContext* context = m_inspector->getContext(groupId(), contextId());
63 if (!context) return nullptr;
64 return context->getInjectedScript(sessionId);
65 }
66
67 V8InspectorSessionImpl* session(int sessionId) {
68 return m_inspector->sessionById(groupId(), sessionId);
69 }
70
71 V8ConsoleMessageStorage* consoleMessageStorage() {
72 return m_inspector->ensureConsoleMessageStorage(groupId());
73 }
74
75 void reportCall(ConsoleAPIType type) {
76 if (!m_info.Length()) return;
78 arguments.reserve(m_info.Length());
79 for (int i = 0; i < m_info.Length(); ++i) arguments.push_back(m_info[i]);
80 reportCall(type, {arguments.begin(), arguments.end()});
81 }
82
83 void reportCallWithDefaultArgument(ConsoleAPIType type,
84 const String16& message) {
86 arguments.reserve(m_info.Length());
87 for (int i = 0; i < m_info.Length(); ++i) arguments.push_back(m_info[i]);
88 if (!m_info.Length()) arguments.push_back(toV8String(isolate(), message));
89 reportCall(type, {arguments.begin(), arguments.end()});
90 }
91
92 void reportCallAndReplaceFirstArgument(ConsoleAPIType type,
93 const String16& message) {
95 arguments.push_back(toV8String(isolate(), message));
96 for (int i = 1; i < m_info.Length(); ++i) arguments.push_back(m_info[i]);
97 reportCall(type, {arguments.begin(), arguments.end()});
98 }
99
100 void reportCallWithArgument(ConsoleAPIType type, const String16& message) {
101 auto arguments =
103 reportCall(type, arguments);
104 }
105
106 void reportCall(ConsoleAPIType type,
107 v8::MemorySpan<const v8::Local<v8::Value>> arguments) {
108 if (!groupId()) return;
109 // Depending on the type of the console message, we capture only parts of
110 // the stack trace, or no stack trace at all.
111 std::unique_ptr<V8StackTraceImpl> stackTrace;
112 switch (type) {
114 // The purpose of `console.trace()` is to output a stack trace to the
115 // developer tools console, therefore we should always strive to
116 // capture a full stack trace, even before any debugger is attached.
117 stackTrace = m_inspector->debugger()->captureStackTrace(true);
118 break;
119
121 // The `console.time()` and `console.timeEnd()` APIs are meant for
122 // performance investigations, and therefore it's important to reduce
123 // the total overhead of these calls, but also make sure these APIs
124 // have consistent performance overhead. In order to guarantee that,
125 // we always capture only the top frame, otherwise the performance
126 // characteristics of `console.timeEnd()` would differ based on the
127 // current call depth, which would skew the results.
128 //
129 // See https://crbug.com/41433391 for more information.
130 stackTrace = V8StackTraceImpl::capture(m_inspector->debugger(), 1);
131 break;
132
133 default:
134 // All other APIs get a full stack trace only when the debugger is
135 // attached, otherwise record only the top frame.
136 stackTrace = m_inspector->debugger()->captureStackTrace(false);
137 break;
138 }
139 std::unique_ptr<V8ConsoleMessage> message =
141 context(), contextId(), groupId(), m_inspector,
142 m_inspector->client()->currentTimeMS(), type, arguments,
143 consoleContextToString(isolate(), m_consoleContext),
144 std::move(stackTrace));
145 consoleMessageStorage()->addMessage(std::move(message));
146 }
147
148 void reportDeprecatedCall(const char* id, const String16& message) {
149 if (!consoleMessageStorage()->shouldReportDeprecationMessage(contextId(),
150 id)) {
151 return;
152 }
153 auto arguments =
155 reportCall(ConsoleAPIType::kWarning, arguments);
156 }
157
158 bool firstArgToBoolean(bool defaultValue) {
159 if (m_info.Length() < 1) return defaultValue;
160 if (m_info[0]->IsBoolean()) return m_info[0].As<v8::Boolean>()->Value();
161 return m_info[0]->BooleanValue(m_inspector->isolate());
162 }
163
164 v8::Local<v8::String> firstArgToString() {
165 if (V8_LIKELY(m_info.Length() > 0)) {
167 if (V8_LIKELY(arg->IsString())) {
168 return arg.As<v8::String>();
169 }
171 if (!arg->IsUndefined() && arg->ToString(context()).ToLocal(&label)) {
172 return label;
173 }
174 }
175 return toV8StringInternalized(isolate(), "default");
176 }
177
178 v8::MaybeLocal<v8::Object> firstArgAsObject() {
179 if (m_info.Length() < 1 || !m_info[0]->IsObject())
181 return m_info[0].As<v8::Object>();
182 }
183
184 v8::MaybeLocal<v8::Function> firstArgAsFunction() {
185 if (m_info.Length() < 1 || !m_info[0]->IsFunction())
188 while (func->GetBoundFunction()->IsFunction())
189 func = func->GetBoundFunction().As<v8::Function>();
190 return func;
191 }
192
193 void forEachSession(std::function<void(V8InspectorSessionImpl*)> callback) {
194 m_inspector->forEachSession(groupId(), std::move(callback));
195 }
196
197 private:
200 V8InspectorImpl* m_inspector;
201};
202
203void createBoundFunctionProperty(
205 v8::Local<v8::Value> data, const char* name, v8::FunctionCallback callback,
207 v8::Local<v8::String> funcName =
208 toV8StringInternalized(context->GetIsolate(), name);
210 if (!v8::Function::New(context, callback, data, 0,
211 v8::ConstructorBehavior::kThrow, side_effect_type)
212 .ToLocal(&func))
213 return;
214 func->SetName(funcName);
215 createDataProperty(context, console, funcName, func);
216}
217
218enum InspectRequest { kRegular, kCopyToClipboard, kQueryObjects };
219
220} // namespace
221
223
225 const v8::debug::ConsoleContext& consoleContext) {
226 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.inspector"), "V8Console::Debug");
227 ConsoleHelper(info, consoleContext, m_inspector)
228 .reportCall(ConsoleAPIType::kDebug);
229}
230
232 const v8::debug::ConsoleContext& consoleContext) {
233 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.inspector"), "V8Console::Error");
234 ConsoleHelper(info, consoleContext, m_inspector)
235 .reportCall(ConsoleAPIType::kError);
236}
237
239 const v8::debug::ConsoleContext& consoleContext) {
240 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.inspector"), "V8Console::Info");
241 ConsoleHelper(info, consoleContext, m_inspector)
242 .reportCall(ConsoleAPIType::kInfo);
243}
244
246 const v8::debug::ConsoleContext& consoleContext) {
247 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.inspector"), "V8Console::Log");
248 ConsoleHelper(info, consoleContext, m_inspector)
249 .reportCall(ConsoleAPIType::kLog);
250}
251
253 const v8::debug::ConsoleContext& consoleContext) {
254 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.inspector"), "V8Console::Warn");
255 ConsoleHelper(info, consoleContext, m_inspector)
256 .reportCall(ConsoleAPIType::kWarning);
257}
258
260 const v8::debug::ConsoleContext& consoleContext) {
261 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.inspector"), "V8Console::Dir");
262 ConsoleHelper(info, consoleContext, m_inspector)
263 .reportCall(ConsoleAPIType::kDir);
264}
265
267 const v8::debug::ConsoleContext& consoleContext) {
268 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.inspector"), "V8Console::DirXml");
269 ConsoleHelper(info, consoleContext, m_inspector)
270 .reportCall(ConsoleAPIType::kDirXML);
271}
272
274 const v8::debug::ConsoleContext& consoleContext) {
275 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.inspector"), "V8Console::Table");
276 ConsoleHelper(info, consoleContext, m_inspector)
277 .reportCall(ConsoleAPIType::kTable);
278}
279
281 const v8::debug::ConsoleContext& consoleContext) {
282 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.inspector"), "V8Console::Trace");
283 ConsoleHelper(info, consoleContext, m_inspector)
284 .reportCallWithDefaultArgument(ConsoleAPIType::kTrace,
285 String16("console.trace"));
286}
287
289 const v8::debug::ConsoleContext& consoleContext) {
290 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.inspector"), "V8Console::Group");
291 ConsoleHelper(info, consoleContext, m_inspector)
292 .reportCallWithDefaultArgument(ConsoleAPIType::kStartGroup,
293 String16("console.group"));
294}
295
298 const v8::debug::ConsoleContext& consoleContext) {
300 "V8Console::GroupCollapsed");
301 ConsoleHelper(info, consoleContext, m_inspector)
302 .reportCallWithDefaultArgument(ConsoleAPIType::kStartGroupCollapsed,
303 String16("console.groupCollapsed"));
304}
305
307 const v8::debug::ConsoleContext& consoleContext) {
309 "V8Console::GroupEnd");
310 ConsoleHelper(info, consoleContext, m_inspector)
311 .reportCallWithDefaultArgument(ConsoleAPIType::kEndGroup,
312 String16("console.groupEnd"));
313}
314
316 const v8::debug::ConsoleContext& consoleContext) {
317 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.inspector"), "V8Console::Clear");
318 ConsoleHelper helper(info, consoleContext, m_inspector);
319 if (!helper.groupId()) return;
320 m_inspector->client()->consoleClear(helper.groupId());
321 helper.reportCallWithDefaultArgument(ConsoleAPIType::kClear,
322 String16("console.clear"));
323}
324
326 const v8::debug::ConsoleContext& consoleContext) {
328 "V8Console::Count");
329 ConsoleHelper helper(info, consoleContext, m_inspector);
331 toProtocolString(m_inspector->isolate(), helper.firstArgToString());
332 int count = helper.consoleMessageStorage()->count(helper.contextId(),
333 consoleContext.id(), label);
334 helper.reportCallWithArgument(ConsoleAPIType::kCount,
335 label + ": " + String16::fromInteger(count));
337 "V8Console::Count", "label",
338 TRACE_STR_COPY(label.utf8().c_str()), "count", count);
339}
340
342 const v8::debug::ConsoleContext& consoleContext) {
344 "V8Console::CountReset");
345 ConsoleHelper helper(info, consoleContext, m_inspector);
347 toProtocolString(m_inspector->isolate(), helper.firstArgToString());
348 if (!helper.consoleMessageStorage()->countReset(helper.contextId(),
349 consoleContext.id(), label)) {
350 helper.reportCallWithArgument(ConsoleAPIType::kWarning,
351 "Count for '" + label + "' does not exist");
352 }
354 "V8Console::CountReset", "label",
355 TRACE_STR_COPY(label.utf8().c_str()));
356}
357
359 const v8::debug::ConsoleContext& consoleContext) {
360 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.inspector"), "V8Console::Assert");
361 ConsoleHelper helper(info, consoleContext, m_inspector);
362 DCHECK(!helper.firstArgToBoolean(false));
363
364 v8::Isolate* isolate = m_inspector->isolate();
365 v8::LocalVector<v8::Value> arguments(isolate);
366 for (int i = 1; i < info.Length(); ++i) arguments.push_back(info[i]);
367 if (info.Length() < 2)
368 arguments.push_back(toV8String(isolate, String16("console.assert")));
369 helper.reportCall(ConsoleAPIType::kAssert,
370 {arguments.begin(), arguments.end()});
371 m_inspector->debugger()->breakProgramOnAssert(helper.groupId());
372}
373
375 const v8::debug::ConsoleContext& consoleContext) {
377 "V8Console::Profile");
378 ConsoleHelper helper(info, consoleContext, m_inspector);
379 String16 title =
380 toProtocolString(m_inspector->isolate(), helper.firstArgToString());
381 helper.forEachSession([&title](V8InspectorSessionImpl* session) {
382 session->profilerAgent()->consoleProfile(title);
383 });
385 "V8Console::Profile", "title",
386 TRACE_STR_COPY(title.utf8().c_str()));
387}
388
390 const v8::debug::ConsoleContext& consoleContext) {
392 "V8Console::ProfileEnd");
393 ConsoleHelper helper(info, consoleContext, m_inspector);
394 String16 title =
395 toProtocolString(m_inspector->isolate(), helper.firstArgToString());
396 helper.forEachSession([&title](V8InspectorSessionImpl* session) {
397 session->profilerAgent()->consoleProfileEnd(title);
398 });
400 "V8Console::ProfileEnd", "title",
401 TRACE_STR_COPY(title.utf8().c_str()));
402}
403
405 const v8::debug::ConsoleContext& consoleContext) {
406 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.inspector"), "V8Console::Time");
407 ConsoleHelper helper(info, consoleContext, m_inspector);
408 v8::Local<v8::String> label = helper.firstArgToString();
410 if (!helper.consoleMessageStorage()->time(
411 helper.contextId(), consoleContext.id(), protocolLabel)) {
412 helper.reportCallWithArgument(
414 "Timer '" + protocolLabel + "' already exists");
415 return;
416 }
418}
419
421 const v8::debug::ConsoleContext& consoleContext) {
422 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.inspector"), "V8Console::TimeLog");
423 ConsoleHelper helper(info, consoleContext, m_inspector);
424 v8::Local<v8::String> label = helper.firstArgToString();
426 std::optional<double> elapsed = helper.consoleMessageStorage()->timeLog(
427 helper.contextId(), consoleContext.id(), protocolLabel);
428 if (!elapsed.has_value()) {
429 helper.reportCallWithArgument(
431 "Timer '" + protocolLabel + "' does not exist");
432 return;
433 }
434 String16 message =
435 protocolLabel + ": " + String16::fromDouble(elapsed.value()) + " ms";
436 helper.reportCallAndReplaceFirstArgument(ConsoleAPIType::kLog, message);
437}
438
440 const v8::debug::ConsoleContext& consoleContext) {
441 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.inspector"), "V8Console::TimeEnd");
442 ConsoleHelper helper(info, consoleContext, m_inspector);
443 v8::Local<v8::String> label = helper.firstArgToString();
445 std::optional<double> elapsed = helper.consoleMessageStorage()->timeEnd(
446 helper.contextId(), consoleContext.id(), protocolLabel);
447 if (!elapsed.has_value()) {
448 helper.reportCallWithArgument(
450 "Timer '" + protocolLabel + "' does not exist");
451 return;
452 }
454 String16 message =
455 protocolLabel + ": " + String16::fromDouble(elapsed.value()) + " ms";
456 helper.reportCallWithArgument(ConsoleAPIType::kTimeEnd, message);
457}
458
460 const v8::debug::ConsoleContext& consoleContext) {
462 "V8Console::TimeStamp");
463 ConsoleHelper helper(info, consoleContext, m_inspector);
464 v8::Local<v8::String> label = helper.firstArgToString();
465
466 v8::Isolate* isolate = m_inspector->isolate();
468 args.reserve(info.Length());
469 for (int i = 0; i < info.Length(); i++) {
470 args.push_back(info[i]);
471 }
472
474}
475
478 v8::Local<v8::Value> memoryValue;
479 if (!m_inspector->client()
480 ->memoryInfo(info.GetIsolate(),
481 info.GetIsolate()->GetCurrentContext())
482 .ToLocal(&memoryValue))
483 return;
484 info.GetReturnValue().Set(memoryValue);
485}
486
489 // We can't make the attribute readonly as it breaks existing code that relies
490 // on being able to assign to console.memory in strict mode. Instead, the
491 // setter just ignores the passed value. http://crbug.com/468611
492}
493
495 v8::Isolate* isolate = info.GetIsolate();
496
498
499 if (info.Length() < 1 || !info[0]->IsString() ||
500 !info[0].As<v8::String>()->Length()) {
501 isolate->ThrowError("First argument must be a non-empty string.");
502 return;
503 }
504
506 ->NewInstance(isolate->GetCurrentContext())
507 .ToLocalChecked();
508
509 auto taskInfo = std::make_unique<TaskInfo>(isolate, this, task);
510 void* taskId = taskInfo->Id();
511 auto [iter, inserted] = m_tasks.emplace(taskId, std::move(taskInfo));
512 CHECK(inserted);
513
514 String16 nameArgument = toProtocolString(isolate, info[0].As<v8::String>());
515 StringView taskName =
516 StringView(nameArgument.characters16(), nameArgument.length());
517 m_inspector->asyncTaskScheduled(taskName, taskId, /* recurring */ true);
518
519 info.GetReturnValue().Set(task);
520}
521
523 v8::Isolate* isolate = info.GetIsolate();
524 if (info.Length() < 1 || !info[0]->IsFunction()) {
525 isolate->ThrowError("First argument must be a function.");
526 return;
527 }
528 v8::Local<v8::Function> function = info[0].As<v8::Function>();
529
530 v8::Local<v8::Object> task = info.This();
531 v8::Local<v8::Value> maybeTaskExternal;
532 if (!task->GetPrivate(isolate->GetCurrentContext(), taskInfoKey())
533 .ToLocal(&maybeTaskExternal)) {
534 // An exception is already thrown.
535 return;
536 }
537
538 if (!maybeTaskExternal->IsExternal()) {
539 isolate->ThrowError("'run' called with illegal receiver.");
540 return;
541 }
542
543 v8::Local<v8::External> taskExternal = maybeTaskExternal.As<v8::External>();
544 TaskInfo* taskInfo = reinterpret_cast<TaskInfo*>(taskExternal->Value());
545
546 m_inspector->asyncTaskStarted(taskInfo->Id());
547 {
548#ifdef V8_USE_PERFETTO
549 TRACE_EVENT(TRACE_DISABLED_BY_DEFAULT("v8.inspector"), "V8Console::runTask",
550 "data", ([&](perfetto::TracedValue context) {
551 uint64_t trace_id = v8::tracing::TraceId();
552 auto dict = std::move(context).WriteDictionary();
553 v8::CpuProfiler::CpuProfiler::CollectSample(isolate,
554 trace_id);
555 dict.Add("sampleTraceId", trace_id);
556 }));
557#endif // V8_USE_PERFETTO
558
560 if (function
561 ->Call(isolate->GetCurrentContext(), v8::Undefined(isolate), 0, {})
562 .ToLocal(&result)) {
563 info.GetReturnValue().Set(result);
564 }
565 }
566 m_inspector->asyncTaskFinished(taskInfo->Id());
567}
568
570 v8::Isolate* isolate = m_inspector->isolate();
571 if (m_taskInfoKey.IsEmpty()) {
572 m_taskInfoKey.Reset(isolate, v8::Private::New(isolate));
573 }
574 return m_taskInfoKey.Get(isolate);
575}
576
578 v8::Isolate* isolate = m_inspector->isolate();
579 if (!m_taskTemplate.IsEmpty()) {
580 return m_taskTemplate.Get(isolate);
581 }
582
583 v8::Local<v8::External> data = v8::External::New(isolate, this);
587 taskTemplate->Set(isolate, "run", funcTemplate);
588
590 return taskTemplate;
591}
592
594 m_inspector->asyncTaskCanceled(taskInfo->Id());
595 m_tasks.erase(taskInfo->Id());
596}
597
598namespace {
599
600void cleanupTaskInfo(const v8::WeakCallbackInfo<TaskInfo>& info) {
601 TaskInfo* task = info.GetParameter();
602 CHECK(task);
603 task->Cancel();
604}
605
606} // namespace
607
610 : m_task(isolate, task), m_console(console) {
611 task->SetPrivate(isolate->GetCurrentContext(), console->taskInfoKey(),
612 v8::External::New(isolate, this))
613 .Check();
614 m_task.SetWeak(this, cleanupTaskInfo, v8::WeakCallbackType::kParameter);
615}
616
618 int sessionId) {
619 v8::Isolate* isolate = info.GetIsolate();
620 info.GetReturnValue().Set(v8::Array::New(isolate));
621
623 ConsoleHelper helper(args, v8::debug::ConsoleContext(), m_inspector);
625 if (!helper.firstArgAsObject().ToLocal(&obj)) return;
627 if (!obj->GetOwnPropertyNames(isolate->GetCurrentContext()).ToLocal(&names))
628 return;
629 info.GetReturnValue().Set(names);
630}
631
633 int sessionId) {
634 v8::Isolate* isolate = info.GetIsolate();
635 info.GetReturnValue().Set(v8::Array::New(isolate));
636
638 ConsoleHelper helper(args, v8::debug::ConsoleContext(), m_inspector);
640 if (!helper.firstArgAsObject().ToLocal(&obj)) return;
642 v8::Local<v8::Context> context = isolate->GetCurrentContext();
643 if (!obj->GetOwnPropertyNames(context).ToLocal(&names)) return;
644 v8::Local<v8::Array> values = v8::Array::New(isolate, names->Length());
645 for (uint32_t i = 0; i < names->Length(); ++i) {
647 if (!names->Get(context, i).ToLocal(&key)) continue;
649 if (!obj->Get(context, key).ToLocal(&value)) continue;
650 createDataProperty(context, values, i, value);
651 }
652 info.GetReturnValue().Set(values);
653}
654
655static void setFunctionBreakpoint(ConsoleHelper& helper, int sessionId,
659 bool enable) {
660 V8InspectorSessionImpl* session = helper.session(sessionId);
661 if (session == nullptr) return;
662 if (!session->debuggerAgent()->enabled()) return;
663 if (enable) {
664 session->debuggerAgent()->setBreakpointFor(function, condition, source);
665 } else {
666 session->debuggerAgent()->removeBreakpointFor(function, source);
667 }
668}
669
671 const v8::FunctionCallbackInfo<v8::Value>& info, int sessionId) {
673 ConsoleHelper helper(args, v8::debug::ConsoleContext(), m_inspector);
676 if (!helper.firstArgAsFunction().ToLocal(&function)) return;
677 if (args.Length() > 1 && args[1]->IsString()) {
678 condition = args[1].As<v8::String>();
679 }
680 setFunctionBreakpoint(helper, sessionId, function,
682 condition, true);
683}
684
686 const v8::FunctionCallbackInfo<v8::Value>& info, int sessionId) {
688 ConsoleHelper helper(args, v8::debug::ConsoleContext(), m_inspector);
690 if (!helper.firstArgAsFunction().ToLocal(&function)) return;
691 setFunctionBreakpoint(helper, sessionId, function,
693 v8::Local<v8::String>(), false);
694}
695
697 const v8::FunctionCallbackInfo<v8::Value>& info, int sessionId) {
699 ConsoleHelper helper(args, v8::debug::ConsoleContext(), m_inspector);
701 if (!helper.firstArgAsFunction().ToLocal(&function)) return;
702 v8::Local<v8::Value> name = function->GetName();
703 if (!name->IsString() || !name.As<v8::String>()->Length())
704 name = function->GetInferredName();
705 String16 functionName =
706 toProtocolStringWithTypeCheck(info.GetIsolate(), name);
707 String16Builder builder;
708 builder.append("console.log(\"function ");
709 if (functionName.isEmpty())
710 builder.append("(anonymous function)");
711 else
712 builder.append(functionName);
713 builder.append(
714 " called\" + (typeof arguments !== \"undefined\" && arguments.length > 0 "
715 "? \" with arguments: \" + Array.prototype.join.call(arguments, \", \") "
716 ": \"\")) && false");
717 setFunctionBreakpoint(helper, sessionId, function,
719 toV8String(info.GetIsolate(), builder.toString()),
720 true);
721}
722
724 const v8::FunctionCallbackInfo<v8::Value>& info, int sessionId) {
726 ConsoleHelper helper(args, v8::debug::ConsoleContext(), m_inspector);
728 if (!helper.firstArgAsFunction().ToLocal(&function)) return;
729 setFunctionBreakpoint(helper, sessionId, function,
731 v8::Local<v8::String>(), false);
732}
733
735 const v8::FunctionCallbackInfo<v8::Value>& info, int sessionId) {
737 ConsoleHelper helper(args, v8::debug::ConsoleContext(), m_inspector);
738 InjectedScript* injectedScript = helper.injectedScript(sessionId);
739 if (!injectedScript) return;
740 info.GetReturnValue().Set(injectedScript->lastEvaluationResult());
741}
742
744 v8::Local<v8::Value> value, int sessionId,
745 InspectRequest request, V8InspectorImpl* inspector) {
746 if (request == kRegular) info.GetReturnValue().Set(value);
747
749 ConsoleHelper helper(args, v8::debug::ConsoleContext(), inspector);
750 InjectedScript* injectedScript = helper.injectedScript(sessionId);
751 if (!injectedScript) return;
752 std::unique_ptr<protocol::Runtime::RemoteObject> wrappedObject;
753 protocol::Response response = injectedScript->wrapObject(
754 value, "", WrapOptions({WrapMode::kIdOnly}), &wrappedObject);
755 if (!response.IsSuccess()) return;
756
757 std::unique_ptr<protocol::DictionaryValue> hints =
758 protocol::DictionaryValue::create();
759 if (request == kCopyToClipboard) {
760 hints->setBoolean("copyToClipboard", true);
761 } else if (request == kQueryObjects) {
762 hints->setBoolean("queryObjects", true);
763 }
764 if (V8InspectorSessionImpl* session = helper.session(sessionId)) {
765 session->runtimeAgent()->inspect(std::move(wrappedObject), std::move(hints),
766 helper.contextId());
767 }
768}
769
771 int sessionId) {
772 if (info.Length() < 1) return;
773 inspectImpl(info, info[0], sessionId, kRegular, m_inspector);
774}
775
777 int sessionId) {
778 if (info.Length() < 1) return;
779 inspectImpl(info, info[0], sessionId, kCopyToClipboard, m_inspector);
780}
781
783 const v8::FunctionCallbackInfo<v8::Value>& info, int sessionId) {
784 if (info.Length() < 1) return;
785 v8::Local<v8::Value> arg = info[0];
786 if (arg->IsFunction()) {
787 v8::Isolate* isolate = info.GetIsolate();
788 v8::TryCatch tryCatch(isolate);
789 v8::Local<v8::Value> prototype;
790 if (arg.As<v8::Function>()
791 ->Get(isolate->GetCurrentContext(),
792 toV8StringInternalized(isolate, "prototype"))
793 .ToLocal(&prototype) &&
794 prototype->IsObject()) {
795 arg = prototype;
796 }
797 if (tryCatch.HasCaught()) {
798 tryCatch.ReThrow();
799 return;
800 }
801 }
802 inspectImpl(info, arg, sessionId, kQueryObjects, m_inspector);
803}
804
806 int sessionId, unsigned num) {
809 ConsoleHelper helper(args, v8::debug::ConsoleContext(), m_inspector);
810 if (V8InspectorSessionImpl* session = helper.session(sessionId)) {
811 V8InspectorSession::Inspectable* object = session->inspectedObject(num);
812 v8::Isolate* isolate = info.GetIsolate();
813 if (object)
814 info.GetReturnValue().Set(object->get(isolate->GetCurrentContext()));
815 else
816 info.GetReturnValue().Set(v8::Undefined(isolate));
817 }
818}
819
821 v8::Local<v8::Object> console) {
822 v8::Isolate* isolate = context->GetIsolate();
823 v8::Local<v8::External> data = v8::External::New(isolate, this);
824 console->SetAccessorProperty(
825 toV8StringInternalized(isolate, "memory"),
829 .ToLocalChecked(),
830 v8::Function::New(context,
833 .ToLocalChecked(),
834 static_cast<v8::PropertyAttribute>(v8::None));
835}
836
838 v8::Local<v8::Object> console) {
839 v8::Isolate* isolate = context->GetIsolate();
840 v8::Local<v8::External> data = v8::External::New(isolate, this);
841
842 v8::MicrotasksScope microtasksScope(context,
844
845 createBoundFunctionProperty(context, console, data, "createTask",
847}
848
850 v8::Local<v8::Context> context, int sessionId) {
851 v8::Isolate* isolate = context->GetIsolate();
852 v8::MicrotasksScope microtasksScope(context,
854
855 v8::Local<v8::Object> commandLineAPI = v8::Object::New(isolate);
856 bool success = commandLineAPI->SetPrototypeV2(context, v8::Null(isolate))
857 .FromMaybe(false);
858 DCHECK(success);
859 USE(success);
860
863 *static_cast<CommandLineAPIData*>(data->GetBackingStore()->Data()) =
864 CommandLineAPIData(this, sessionId);
865 createBoundFunctionProperty(context, commandLineAPI, data, "dir",
867 createBoundFunctionProperty(context, commandLineAPI, data, "dirxml",
869 createBoundFunctionProperty(context, commandLineAPI, data, "profile",
871 createBoundFunctionProperty(context, commandLineAPI, data, "profileEnd",
873 createBoundFunctionProperty(context, commandLineAPI, data, "clear",
875 createBoundFunctionProperty(context, commandLineAPI, data, "table",
877
878 createBoundFunctionProperty(context, commandLineAPI, data, "keys",
881 createBoundFunctionProperty(context, commandLineAPI, data, "values",
884 createBoundFunctionProperty(
885 context, commandLineAPI, data, "debug",
887 createBoundFunctionProperty(
888 context, commandLineAPI, data, "undebug",
890 createBoundFunctionProperty(
891 context, commandLineAPI, data, "monitor",
893 createBoundFunctionProperty(
894 context, commandLineAPI, data, "unmonitor",
896 createBoundFunctionProperty(context, commandLineAPI, data, "inspect",
898 createBoundFunctionProperty(context, commandLineAPI, data, "copy",
900 createBoundFunctionProperty(
901 context, commandLineAPI, data, "queryObjects",
903 createBoundFunctionProperty(
904 context, commandLineAPI, data, "$_",
907 createBoundFunctionProperty(context, commandLineAPI, data, "$0",
910 createBoundFunctionProperty(context, commandLineAPI, data, "$1",
913 createBoundFunctionProperty(context, commandLineAPI, data, "$2",
916 createBoundFunctionProperty(context, commandLineAPI, data, "$3",
919 createBoundFunctionProperty(context, commandLineAPI, data, "$4",
922
924 commandLineAPI);
925 return commandLineAPI;
926}
927
928static bool isCommandLineAPIGetter(const String16& name) {
929 if (name.length() != 2) return false;
930 // $0 ... $4, $_
931 return name[0] == '$' &&
932 ((name[1] >= '0' && name[1] <= '4') || name[1] == '_');
933}
934
937 CommandLineAPIScope* scope = *static_cast<CommandLineAPIScope**>(
938 info.Data().As<v8::ArrayBuffer>()->GetBackingStore()->Data());
939 v8::Local<v8::Context> context = info.GetIsolate()->GetCurrentContext();
940 if (scope == nullptr) {
941 USE(info.HolderV2()->Delete(context, name).FromMaybe(false));
942 return;
943 }
944
946 if (!scope->commandLineAPI()->Get(context, name).ToLocal(&value)) return;
948 toProtocolStringWithTypeCheck(info.GetIsolate(), name))) {
949 DCHECK(value->IsFunction());
950 v8::MicrotasksScope microtasks(context,
952 if (value.As<v8::Function>()
953 ->Call(context, scope->commandLineAPI(), 0, nullptr)
954 .ToLocal(&value))
955 info.GetReturnValue().Set(value);
956 } else {
957 info.GetReturnValue().Set(value);
958 }
959}
960
963 const v8::PropertyCallbackInfo<void>& info) {
964 CommandLineAPIScope* scope = *static_cast<CommandLineAPIScope**>(
965 info.Data().As<v8::ArrayBuffer>()->GetBackingStore()->Data());
966 if (scope == nullptr) return;
967 v8::Local<v8::Context> context = info.GetIsolate()->GetCurrentContext();
968 if (!info.HolderV2()->Delete(context, name).FromMaybe(false)) return;
969 if (!info.HolderV2()
970 ->CreateDataProperty(context, name, value)
971 .FromMaybe(false))
972 return;
973
975 for (int i = 0; i < methods->Length(); ++i) {
976 v8::Local<v8::Value> methodName = methods->Get(scope->m_isolate, i);
977 if (methodName.IsEmpty() || !methodName->IsName()) continue;
978 if (!name->StrictEquals(methodName)) continue;
979 methods->Set(scope->m_isolate, i, v8::Undefined(scope->m_isolate));
980 break;
981 }
982}
983
984namespace {
985
986// "get"-ting these functions from the global proxy is considered a side-effect.
987// Otherwise, malicious sites could stash references to these functions through
988// previews / ValueMirror and use them across origin isolation.
989DEFINE_LAZY_LEAKY_OBJECT_GETTER(std::set<std::string_view>,
990 UnsafeCommandLineAPIFns,
991 std::initializer_list<std::string_view>{
992 "debug", "undebug", "monitor", "unmonitor",
993 "inspect", "copy", "queryObjects"})
994
995bool IsUnsafeCommandLineAPIFn(v8::Local<v8::Value> name, v8::Isolate* isolate) {
996 std::string nameStr = toProtocolStringWithTypeCheck(isolate, name).utf8();
997 return UnsafeCommandLineAPIFns()->count(nameStr) > 0;
998}
999
1000} // namespace
1001
1003 v8::Local<v8::Context> context, v8::Local<v8::Object> commandLineAPI,
1004 v8::Local<v8::Object> global)
1005 : m_isolate(context->GetIsolate()),
1006 m_context(m_isolate, context),
1007 m_commandLineAPI(m_isolate, commandLineAPI),
1008 m_global(m_isolate, global) {
1009 v8::MicrotasksScope microtasksScope(context,
1012 if (!commandLineAPI->GetOwnPropertyNames(context).ToLocal(&names)) return;
1014 v8::PrimitiveArray::New(m_isolate, names->Length()));
1015
1017 m_isolate, v8::ArrayBuffer::New(context->GetIsolate(),
1018 sizeof(CommandLineAPIScope*)));
1019 *static_cast<CommandLineAPIScope**>(
1020 thisReference()->GetBackingStore()->Data()) = this;
1022 for (uint32_t i = 0; i < names->Length(); ++i) {
1024 if (!names->Get(context, i).ToLocal(&name) || !name->IsName()) continue;
1025 if (global->Has(context, name).FromMaybe(true)) continue;
1026
1027 const v8::SideEffectType get_accessor_side_effect_type =
1028 IsUnsafeCommandLineAPIFn(name, context->GetIsolate())
1031 if (!global
1032 ->SetNativeDataProperty(
1033 context, name.As<v8::Name>(),
1036 v8::DontEnum, get_accessor_side_effect_type)
1037 .FromMaybe(false)) {
1038 continue;
1039 }
1040 methods->Set(m_isolate, i, name.As<v8::Name>());
1041 }
1042}
1043
1045 if (m_isolate->IsExecutionTerminating()) return;
1046 v8::MicrotasksScope microtasksScope(context(),
1048 *static_cast<CommandLineAPIScope**>(
1049 thisReference()->GetBackingStore()->Data()) = nullptr;
1050 v8::Local<v8::PrimitiveArray> names = installedMethods();
1051 for (int i = 0; i < names->Length(); ++i) {
1052 v8::Local<v8::Value> name = names->Get(m_isolate, i);
1053 if (name.IsEmpty() || !name->IsName()) continue;
1054 if (name->IsString()) {
1055 v8::Local<v8::Value> descriptor;
1056 bool success =
1057 global()
1058 ->GetOwnPropertyDescriptor(context(), name.As<v8::String>())
1059 .ToLocal(&descriptor);
1060 USE(success);
1061 }
1062 }
1063}
1064
1065} // namespace v8_inspector
const char * name
Definition builtins.cc:39
static Local< ArrayBuffer > New(Isolate *isolate, size_t byte_length, BackingStoreInitializationMode initialization_mode=BackingStoreInitializationMode::kZeroInitialized)
Definition api.cc:9044
static Local< Array > New(Isolate *isolate, int length=0)
Definition api.cc:8119
static Local< External > New(Isolate *isolate, void *value)
Definition api.cc:7483
static Local< FunctionTemplate > New(Isolate *isolate, FunctionCallback callback=nullptr, Local< Value > data=Local< Value >(), Local< Signature > signature=Local< Signature >(), int length=0, ConstructorBehavior behavior=ConstructorBehavior::kAllow, SideEffectType side_effect_type=SideEffectType::kHasSideEffect, const CFunction *c_function=nullptr, uint16_t instance_type=0, uint16_t allowed_receiver_instance_type_range_start=0, uint16_t allowed_receiver_instance_type_range_end=0)
Definition api.cc:1101
static MaybeLocal< Function > New(Local< Context > context, FunctionCallback callback, Local< Value > data=Local< Value >(), int length=0, ConstructorBehavior behavior=ConstructorBehavior::kAllow, SideEffectType side_effect_type=SideEffectType::kHasSideEffect)
Definition api.cc:5348
V8_WARN_UNUSED_RESULT MaybeLocal< Value > Call(v8::Isolate *isolate, Local< Context > context, Local< Value > recv, int argc, Local< Value > argv[])
Definition api.cc:5400
bool IsExecutionTerminating()
Definition api.cc:9893
V8_INLINE Local< S > As() const
V8_WARN_UNUSED_RESULT V8_INLINE bool ToLocal(Local< S > *out) const
static Local< ObjectTemplate > New(Isolate *isolate, Local< FunctionTemplate > constructor=Local< FunctionTemplate >())
Definition api.cc:1376
static Local< Object > New(Isolate *isolate)
Definition api.cc:7756
V8_WARN_UNUSED_RESULT Maybe< bool > Has(Local< Context > context, Local< Value > key)
Definition api.cc:4867
V8_WARN_UNUSED_RESULT MaybeLocal< Array > GetOwnPropertyNames(Local< Context > context)
Definition api.cc:4776
V8_WARN_UNUSED_RESULT MaybeLocal< Value > Get(Local< Context > context, Local< Value > key)
Definition api.cc:4577
V8_INLINE Local< T > Get(Isolate *isolate) const
V8_INLINE void SetWeak(P *parameter, typename WeakCallbackInfo< P >::Callback callback, WeakCallbackType type)
static Local< PrimitiveArray > New(Isolate *isolate, int length)
Definition api.cc:2035
static Local< Private > New(Isolate *isolate, Local< String > name=Local< String >())
Definition api.cc:9538
int Length() const
Definition api.cc:5616
Local< Value > ReThrow()
Definition api.cc:2792
bool HasCaught() const
Definition api.cc:2781
v8::Local< v8::String > name() const
v8::Local< v8::Value > lastEvaluationResult() const
Response wrapObject(v8::Local< v8::Value >, const String16 &groupName, const WrapOptions &wrapOptions, std::unique_ptr< protocol::Runtime::RemoteObject > *result)
void append(const String16 &)
Definition string-16.cc:156
size_t length() const
Definition string-16.h:58
static String16 fromInteger(int)
Definition string-16.cc:71
static String16 fromDouble(double)
Definition string-16.cc:98
bool isEmpty() const
Definition string-16.h:59
V8_EXPORT std::string utf8() const
Definition string-16.cc:254
const uint16_t * characters16() const
Definition string-16.h:55
TaskInfo(v8::Isolate *isolate, V8Console *console, v8::Local< v8::Object > task)
void * Id() const
Definition v8-console.h:248
v8::Global< v8::Object > m_task
Definition v8-console.h:256
static std::unique_ptr< V8ConsoleMessage > createForConsoleAPI(v8::Local< v8::Context > v8Context, int contextId, int groupId, V8InspectorImpl *inspector, double timestamp, ConsoleAPIType, v8::MemorySpan< const v8::Local< v8::Value > > arguments, const String16 &consoleContext, std::unique_ptr< V8StackTraceImpl >)
v8::Global< v8::ArrayBuffer > m_thisReference
Definition v8-console.h:76
v8::Local< v8::ArrayBuffer > thisReference() const
Definition v8-console.h:67
v8::Local< v8::Object > global() const
Definition v8-console.h:63
static void accessorGetterCallback(v8::Local< v8::Name >, const v8::PropertyCallbackInfo< v8::Value > &)
static void accessorSetterCallback(v8::Local< v8::Name >, v8::Local< v8::Value >, const v8::PropertyCallbackInfo< void > &)
v8::Global< v8::PrimitiveArray > m_installedMethods
Definition v8-console.h:75
v8::Local< v8::PrimitiveArray > installedMethods() const
Definition v8-console.h:64
CommandLineAPIScope(v8::Local< v8::Context >, v8::Local< v8::Object > commandLineAPI, v8::Local< v8::Object > global)
v8::Local< v8::Object > commandLineAPI() const
Definition v8-console.h:60
void memoryGetterCallback(const v8::FunctionCallbackInfo< v8::Value > &)
void ProfileEnd(const v8::debug::ConsoleCallArguments &, const v8::debug::ConsoleContext &consoleContext) override
v8::Global< v8::ObjectTemplate > m_taskTemplate
Definition v8-console.h:225
void keysCallback(const v8::FunctionCallbackInfo< v8::Value > &, int sessionId)
void Group(const v8::debug::ConsoleCallArguments &, const v8::debug::ConsoleContext &consoleContext) override
void debugFunctionCallback(const v8::FunctionCallbackInfo< v8::Value > &, int sessionId)
void monitorFunctionCallback(const v8::FunctionCallbackInfo< v8::Value > &, int sessionId)
void Error(const v8::debug::ConsoleCallArguments &, const v8::debug::ConsoleContext &consoleContext) override
std::pair< V8Console *, int > CommandLineAPIData
Definition v8-console.h:135
v8::Local< v8::ObjectTemplate > taskTemplate()
void Dir(const v8::debug::ConsoleCallArguments &, const v8::debug::ConsoleContext &consoleContext) override
void inspectedObject(const v8::FunctionCallbackInfo< v8::Value > &, int sessionId, unsigned num)
void Assert(const v8::debug::ConsoleCallArguments &, const v8::debug::ConsoleContext &consoleContext) override
void Log(const v8::debug::ConsoleCallArguments &, const v8::debug::ConsoleContext &consoleContext) override
v8::Local< v8::Object > createCommandLineAPI(v8::Local< v8::Context > context, int sessionId)
void GroupEnd(const v8::debug::ConsoleCallArguments &, const v8::debug::ConsoleContext &consoleContext) override
void installMemoryGetter(v8::Local< v8::Context > context, v8::Local< v8::Object > console)
void CountReset(const v8::debug::ConsoleCallArguments &, const v8::debug::ConsoleContext &consoleContext) override
V8InspectorImpl * m_inspector
Definition v8-console.h:212
void runTask(const v8::FunctionCallbackInfo< v8::Value > &)
void Clear(const v8::debug::ConsoleCallArguments &, const v8::debug::ConsoleContext &consoleContext) override
std::map< void *, std::unique_ptr< TaskInfo > > m_tasks
Definition v8-console.h:216
void undebugFunctionCallback(const v8::FunctionCallbackInfo< v8::Value > &, int sessionId)
void lastEvaluationResultCallback(const v8::FunctionCallbackInfo< v8::Value > &, int sessionId)
void queryObjectsCallback(const v8::FunctionCallbackInfo< v8::Value > &info, int sessionId)
v8::Local< v8::Private > taskInfoKey()
void Table(const v8::debug::ConsoleCallArguments &, const v8::debug::ConsoleContext &consoleContext) override
void Warn(const v8::debug::ConsoleCallArguments &, const v8::debug::ConsoleContext &consoleContext) override
void Count(const v8::debug::ConsoleCallArguments &, const v8::debug::ConsoleContext &consoleContext) override
void Profile(const v8::debug::ConsoleCallArguments &, const v8::debug::ConsoleContext &consoleContext) override
void installAsyncStackTaggingAPI(v8::Local< v8::Context > context, v8::Local< v8::Object > console)
void Time(const v8::debug::ConsoleCallArguments &, const v8::debug::ConsoleContext &consoleContext) override
void TimeStamp(const v8::debug::ConsoleCallArguments &, const v8::debug::ConsoleContext &consoleContext) override
void createTask(const v8::FunctionCallbackInfo< v8::Value > &)
void inspectCallback(const v8::FunctionCallbackInfo< v8::Value > &, int sessionId)
void TimeEnd(const v8::debug::ConsoleCallArguments &, const v8::debug::ConsoleContext &consoleContext) override
V8Console(V8InspectorImpl *inspector)
void cancelConsoleTask(TaskInfo *taskInfo)
void Info(const v8::debug::ConsoleCallArguments &, const v8::debug::ConsoleContext &consoleContext) override
void memorySetterCallback(const v8::FunctionCallbackInfo< v8::Value > &)
void valuesCallback(const v8::FunctionCallbackInfo< v8::Value > &, int sessionId)
v8::Global< v8::Private > m_taskInfoKey
Definition v8-console.h:220
void unmonitorFunctionCallback(const v8::FunctionCallbackInfo< v8::Value > &, int sessionId)
void TimeLog(const v8::debug::ConsoleCallArguments &, const v8::debug::ConsoleContext &consoleContext) override
void Trace(const v8::debug::ConsoleCallArguments &, const v8::debug::ConsoleContext &consoleContext) override
void DirXml(const v8::debug::ConsoleCallArguments &, const v8::debug::ConsoleContext &consoleContext) override
static void call(const v8::FunctionCallbackInfo< v8::Value > &info)
Definition v8-console.h:130
void copyCallback(const v8::FunctionCallbackInfo< v8::Value > &, int sessionId)
void Debug(const v8::debug::ConsoleCallArguments &, const v8::debug::ConsoleContext &consoleContext) override
void GroupCollapsed(const v8::debug::ConsoleCallArguments &, const v8::debug::ConsoleContext &consoleContext) override
void removeBreakpointFor(v8::Local< v8::Function > function, BreakpointSource source)
void setBreakpointFor(v8::Local< v8::Function > function, v8::Local< v8::String > condition, BreakpointSource source)
void breakProgramOnAssert(int targetContextGroupId)
virtual void consoleClear(int contextGroupId)
virtual void consoleTime(v8::Isolate *isolate, v8::Local< v8::String > label)
virtual void consoleTimeEnd(v8::Isolate *isolate, v8::Local< v8::String > label)
virtual v8::MaybeLocal< v8::Value > memoryInfo(v8::Isolate *, v8::Local< v8::Context >)
virtual void installAdditionalCommandLineAPI(v8::Local< v8::Context >, v8::Local< v8::Object >)
virtual void consoleTimeStampWithArgs(v8::Isolate *isolate, v8::Local< v8::String > label, const v8::LocalVector< v8::Value > &args)
void asyncTaskStarted(void *task) override
v8::Isolate * isolate() const
void asyncTaskScheduled(StringView taskName, void *task, bool recurring) override
void asyncTaskFinished(void *task) override
void asyncTaskCanceled(void *task) override
void consoleProfile(const String16 &title)
void consoleProfileEnd(const String16 &title)
static std::unique_ptr< V8StackTraceImpl > capture(V8Debugger *, int maxStackSize)
base::Vector< const DirectHandle< Object > > args
Definition execution.cc:74
Label label
Isolate * isolate
TNode< Context > context
TNode< Object > callback
ZoneVector< RpoNumber > & result
#define DEFINE_LAZY_LEAKY_OBJECT_GETTER(T, FunctionName,...)
void RecordAsyncStackTaggingCreateTaskCall(v8::Isolate *v8_isolate)
V8_INLINE uint64_t TraceId()
Definition trace-id.h:12
static bool isCommandLineAPIGetter(const String16 &name)
String16 toProtocolString(v8::Isolate *isolate, v8::Local< v8::String > value)
v8::Local< v8::String > toV8String(v8::Isolate *isolate, const String16 &string)
static void setFunctionBreakpoint(ConsoleHelper &helper, int sessionId, v8::Local< v8::Function > function, V8DebuggerAgentImpl::BreakpointSource source, v8::Local< v8::String > condition, bool enable)
v8::Maybe< bool > createDataProperty(v8::Local< v8::Context > context, v8::Local< v8::Object > object, v8::Local< v8::Name > key, v8::Local< v8::Value > value)
static void inspectImpl(const v8::FunctionCallbackInfo< v8::Value > &info, v8::Local< v8::Value > value, int sessionId, InspectRequest request, V8InspectorImpl *inspector)
String16 toProtocolStringWithTypeCheck(v8::Isolate *isolate, v8::Local< v8::Value > value)
v8::Local< v8::String > toV8StringInternalized(v8::Isolate *isolate, const String16 &string)
PropertyAttribute
Definition v8-object.h:139
@ DontEnum
Definition v8-object.h:145
@ None
Definition v8-object.h:141
V8_INLINE Local< Primitive > Null(Isolate *isolate)
SideEffectType
Definition v8-object.h:198
bool ToLocal(v8::internal::MaybeDirectHandle< v8::internal::Object > maybe, Local< T > *local)
Definition api.h:303
V8_INLINE Local< Primitive > Undefined(Isolate *isolate)
constexpr std::array< std::remove_cv_t< T >, N > to_array(T(&a)[N])
void(*)(const FunctionCallbackInfo< Value > &info) FunctionCallback
#define CHECK(condition)
Definition logging.h:124
#define DCHECK(condition)
Definition logging.h:482
#define DCHECK_GT(v1, v2)
Definition logging.h:487
#define USE(...)
Definition macros.h:293
#define TRACE_EVENT_END2(category_group, name, arg1_name, arg1_val, arg2_name, arg2_val)
#define TRACE_EVENT0(category_group, name)
#define TRACE_EVENT_END1(category_group, name, arg1_name, arg1_val)
#define TRACE_DISABLED_BY_DEFAULT(name)
#define TRACE_EVENT_BEGIN0(category_group, name)
#define TRACE_STR_COPY(str)
Definition trace-event.h:50
v8::Local< v8::Context > m_context
v8::Isolate * m_isolate
V8InspectorImpl * m_inspector
const v8::debug::ConsoleContext & m_consoleContext
const v8::debug::ConsoleCallArguments & m_info
#define V8_LIKELY(condition)
Definition v8config.h:661
std::unique_ptr< ValueMirror > value
std::unique_ptr< ValueMirror > key