v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
v8-runtime-agent-impl.cc
Go to the documentation of this file.
1/*
2 * Copyright (C) 2011 Google Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met:
7 *
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above
11 * copyright notice, this list of conditions and the following disclaimer
12 * in the documentation and/or other materials provided with the
13 * distribution.
14 * * Neither the name of Google Inc. nor the names of its
15 * contributors may be used to endorse or promote products derived from
16 * this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
32
33#include <inttypes.h>
34
35#include <memory>
36
37#include "../../third_party/inspector_protocol/crdtp/json.h"
39#include "include/v8-context.h"
40#include "include/v8-cppgc.h"
41#include "include/v8-function.h"
47#include "src/inspector/protocol/Protocol.h"
48#include "src/inspector/protocol/Runtime.h"
58
59namespace v8_inspector {
60
61namespace V8RuntimeAgentImplState {
62static const char customObjectFormatterEnabled[] =
63 "customObjectFormatterEnabled";
64static const char maxCallStackSizeToCapture[] = "maxCallStackSizeToCapture";
65static const char runtimeEnabled[] = "runtimeEnabled";
66static const char bindings[] = "bindings";
67static const char globalBindingsKey[] = "";
68} // namespace V8RuntimeAgentImplState
69
70using protocol::Runtime::RemoteObject;
71
72namespace {
73
74template <typename ProtocolCallback>
75class EvaluateCallbackWrapper : public EvaluateCallback {
76 public:
77 static std::shared_ptr<EvaluateCallback> wrap(
78 std::unique_ptr<ProtocolCallback> callback) {
79 return std::shared_ptr<EvaluateCallback>(
80 new EvaluateCallbackWrapper(std::move(callback)));
81 }
82 void sendSuccess(std::unique_ptr<protocol::Runtime::RemoteObject> result,
83 std::unique_ptr<protocol::Runtime::ExceptionDetails>
84 exceptionDetails) override {
85 return m_callback->sendSuccess(std::move(result),
86 std::move(exceptionDetails));
87 }
88 void sendFailure(const protocol::DispatchResponse& response) override {
89 return m_callback->sendFailure(response);
90 }
91
92 private:
93 explicit EvaluateCallbackWrapper(std::unique_ptr<ProtocolCallback> callback)
94 : m_callback(std::move(callback)) {}
95
96 std::unique_ptr<ProtocolCallback> m_callback;
97};
98
99template <typename ProtocolCallback>
100bool wrapEvaluateResultAsync(InjectedScript* injectedScript,
101 v8::MaybeLocal<v8::Value> maybeResultValue,
102 const v8::TryCatch& tryCatch,
103 const String16& objectGroup,
104 const WrapOptions& wrapOptions,
105 bool throwOnSideEffect,
106 ProtocolCallback* callback) {
107 std::unique_ptr<RemoteObject> result;
108 std::unique_ptr<protocol::Runtime::ExceptionDetails> exceptionDetails;
109
110 Response response = injectedScript->wrapEvaluateResult(
111 maybeResultValue, tryCatch, objectGroup, wrapOptions, throwOnSideEffect,
112 &result, &exceptionDetails);
113 if (response.IsSuccess()) {
114 callback->sendSuccess(std::move(result), std::move(exceptionDetails));
115 return true;
116 }
117 callback->sendFailure(response);
118 return false;
119}
120
121void innerCallFunctionOn(
122 V8InspectorSessionImpl* session, InjectedScript::Scope& scope,
123 v8::Local<v8::Value> recv, const String16& expression,
124 std::unique_ptr<protocol::Array<protocol::Runtime::CallArgument>>
125 optionalArguments,
126 bool silent, std::unique_ptr<WrapOptions> wrapOptions, bool userGesture,
127 bool awaitPromise, const String16& objectGroup, bool throwOnSideEffect,
128 std::unique_ptr<V8RuntimeAgentImpl::CallFunctionOnCallback> callback) {
129 V8InspectorImpl* inspector = session->inspector();
130
131 v8::LocalVector<v8::Value> args(inspector->isolate());
132 if (optionalArguments) {
133 protocol::Array<protocol::Runtime::CallArgument>& arguments =
134 *optionalArguments;
135 int argc = static_cast<int>(arguments.size());
136 args.resize(argc);
137 for (int i = 0; i < argc; ++i) {
138 Response response = scope.injectedScript()->resolveCallArgument(
139 arguments[i].get(), &args[i]);
140 if (!response.IsSuccess()) {
141 callback->sendFailure(response);
142 return;
143 }
144 }
145 }
146
147 if (silent) scope.ignoreExceptionsAndMuteConsole();
148 if (userGesture) scope.pretendUserGesture();
149
150 // Temporarily enable allow evals for inspector.
151 scope.allowCodeGenerationFromStrings();
152
153 v8::MaybeLocal<v8::Value> maybeFunctionValue;
154 v8::Local<v8::Script> functionScript;
155 if (inspector
156 ->compileScript(scope.context(), "(" + expression + ")", String16())
157 .ToLocal(&functionScript)) {
158 v8::MicrotasksScope microtasksScope(scope.context(),
160 maybeFunctionValue = functionScript->Run(scope.context());
161 }
162 // Re-initialize after running client's code, as it could have destroyed
163 // context or session.
164 Response response = scope.initialize();
165 if (!response.IsSuccess()) {
166 callback->sendFailure(response);
167 return;
168 }
169
170 if (scope.tryCatch().HasCaught()) {
171 wrapEvaluateResultAsync(scope.injectedScript(), maybeFunctionValue,
172 scope.tryCatch(), objectGroup,
173 WrapOptions({WrapMode::kIdOnly}), throwOnSideEffect,
174 callback.get());
175 return;
176 }
177
178 v8::Local<v8::Value> functionValue;
179 if (!maybeFunctionValue.ToLocal(&functionValue) ||
180 !functionValue->IsFunction()) {
181 callback->sendFailure(Response::ServerError(
182 "Given expression does not evaluate to a function"));
183 return;
184 }
185
186 v8::MaybeLocal<v8::Value> maybeResultValue;
187 {
188 v8::MicrotasksScope microtasksScope(scope.context(),
190 maybeResultValue = v8::debug::CallFunctionOn(
191 scope.context(), functionValue.As<v8::Function>(), recv,
192 v8::base::VectorOf(args), throwOnSideEffect);
193 }
194 // Re-initialize after running client's code, as it could have destroyed
195 // context or session.
196 response = scope.initialize();
197 if (!response.IsSuccess()) {
198 callback->sendFailure(response);
199 return;
200 }
201
202 if (!awaitPromise || scope.tryCatch().HasCaught()) {
203 wrapEvaluateResultAsync(scope.injectedScript(), maybeResultValue,
204 scope.tryCatch(), objectGroup, *wrapOptions,
205 throwOnSideEffect, callback.get());
206 return;
207 }
208
209 scope.injectedScript()->addPromiseCallback(
210 session, maybeResultValue, objectGroup, std::move(wrapOptions),
211 false /* replMode */, throwOnSideEffect,
212 EvaluateCallbackWrapper<V8RuntimeAgentImpl::CallFunctionOnCallback>::wrap(
213 std::move(callback)));
214}
215
216Response ensureContext(V8InspectorImpl* inspector, int contextGroupId,
217 std::optional<int> executionContextId,
218 std::optional<String16> uniqueContextId,
219 int* contextId) {
220 if (executionContextId.has_value()) {
221 if (uniqueContextId.has_value()) {
222 return Response::InvalidParams(
223 "contextId and uniqueContextId are mutually exclusive");
224 }
225 *contextId = executionContextId.value();
226 } else if (uniqueContextId.has_value()) {
227 internal::V8DebuggerId uniqueId(uniqueContextId.value());
228 if (!uniqueId.isValid())
229 return Response::InvalidParams("invalid uniqueContextId");
230 int id = inspector->resolveUniqueContextId(uniqueId);
231 if (!id) return Response::InvalidParams("uniqueContextId not found");
232 *contextId = id;
233 } else {
234 v8::HandleScope handles(inspector->isolate());
235 v8::Local<v8::Context> defaultContext =
236 inspector->client()->ensureDefaultContextInGroup(contextGroupId);
237 if (defaultContext.IsEmpty())
238 return Response::ServerError("Cannot find default execution context");
239 *contextId = InspectedContext::contextId(defaultContext);
240 }
241
242 return Response::Success();
243}
244
245Response parseAdditionalSerializationParameters(
246 protocol::DictionaryValue* additionalParameters, v8::Isolate* isolate,
248 v8::LocalVector<v8::Name> keys(isolate);
249 v8::LocalVector<v8::Value> values(isolate);
250
251 if (additionalParameters != nullptr) {
252 for (size_t i = 0; i < additionalParameters->size(); ++i) {
253 String16 key = (*additionalParameters).at(i).first;
254 keys.push_back(toV8String(isolate, key));
255
256 protocol::Value* value = (*additionalParameters).at(i).second;
257 String16 stringValue;
258 if (value->asString(&stringValue)) {
259 values.push_back(toV8String(isolate, stringValue));
260 continue;
261 }
262 int intValue;
263 if (value->asInteger(&intValue)) {
264 values.push_back(v8::Int32::New(isolate, intValue));
265 continue;
266 }
267 return Response::InvalidParams(
268 "Values of serializationOptions.additionalParameters can be only of "
269 "type string or integer.");
270 }
271 }
272 CHECK(keys.size() == values.size());
273 *result = v8::Object::New(isolate, v8::Null(isolate), keys.data(),
274 values.data(), keys.size());
275
276 return Response::Success();
277}
278
279Response getWrapOptions(std::optional<bool> returnByValue,
280 std::optional<bool> generatePreview,
281 std::unique_ptr<protocol::Runtime::SerializationOptions>
282 maybeSerializationOptions,
283 v8::Isolate* isolate,
284 std::unique_ptr<WrapOptions>* result) {
285 if (maybeSerializationOptions) {
286 String16 serializationModeStr =
287 maybeSerializationOptions->getSerialization();
288 if (serializationModeStr ==
289 protocol::Runtime::SerializationOptions::SerializationEnum::Deep) {
290 v8::Local<v8::Object> additionalParameters;
291 Response response = parseAdditionalSerializationParameters(
292 maybeSerializationOptions->getAdditionalParameters(nullptr), isolate,
293 &additionalParameters);
294 if (!response.IsSuccess()) {
295 return response;
296 }
297 *result = std::make_unique<WrapOptions>(WrapOptions{
299 {maybeSerializationOptions->getMaxDepth(v8::internal::kMaxInt),
300 v8::Global<v8::Object>(isolate, additionalParameters)}});
301 return Response::Success();
302 }
303 if (serializationModeStr ==
304 protocol::Runtime::SerializationOptions::SerializationEnum::Json) {
305 *result = std::make_unique<WrapOptions>(WrapOptions{WrapMode::kJson});
306 return Response::Success();
307 }
308 if (serializationModeStr ==
309 protocol::Runtime::SerializationOptions::SerializationEnum::IdOnly) {
310 *result = std::make_unique<WrapOptions>(WrapOptions{WrapMode::kIdOnly});
311 return Response::Success();
312 }
313 return Response::InvalidParams(
314 "Unknown serializationOptions.serialization value " +
315 serializationModeStr.utf8());
316 }
317
318 if (returnByValue.value_or(false)) {
319 *result = std::make_unique<WrapOptions>(WrapOptions{WrapMode::kJson});
320 return Response::Success();
321 }
322 if (generatePreview.value_or(false)) {
323 *result = std::make_unique<WrapOptions>(WrapOptions{WrapMode::kPreview});
324 return Response::Success();
325 }
326 *result = std::make_unique<WrapOptions>(WrapOptions{WrapMode::kIdOnly});
327 return Response::Success();
328}
329
330Response getWrapOptions(std::optional<bool> returnByValue,
331 std::optional<bool> generatePreview,
332 v8::Isolate* isolate,
333 std::unique_ptr<WrapOptions>* result) {
334 return getWrapOptions(std::move(returnByValue), std::move(generatePreview),
335 nullptr /* empty serialization options */, isolate,
336 result);
337}
338
339} // namespace
340
342 V8InspectorSessionImpl* session, protocol::FrontendChannel* FrontendChannel,
343 protocol::DictionaryValue* state,
344 std::shared_ptr<V8DebuggerBarrier> debuggerBarrier)
345 : m_session(session),
346 m_state(state),
347 m_frontend(FrontendChannel),
348 m_inspector(session->inspector()),
349 m_debuggerBarrier(debuggerBarrier),
350 m_enabled(false) {}
351
353
355 const String16& expression, std::optional<String16> objectGroup,
356 std::optional<bool> includeCommandLineAPI, std::optional<bool> silent,
357 std::optional<int> executionContextId, std::optional<bool> returnByValue,
358 std::optional<bool> generatePreview, std::optional<bool> userGesture,
359 std::optional<bool> maybeAwaitPromise,
360 std::optional<bool> throwOnSideEffect, std::optional<double> timeout,
361 std::optional<bool> disableBreaks, std::optional<bool> maybeReplMode,
362 std::optional<bool> allowUnsafeEvalBlockedByCSP,
363 std::optional<String16> uniqueContextId,
364 std::unique_ptr<protocol::Runtime::SerializationOptions>
365 serializationOptions,
366 std::unique_ptr<EvaluateCallback> callback) {
367 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"),
368 "EvaluateScript");
369 int contextId = 0;
370 Response response = ensureContext(m_inspector, m_session->contextGroupId(),
371 std::move(executionContextId),
372 std::move(uniqueContextId), &contextId);
373 if (!response.IsSuccess()) {
374 callback->sendFailure(response);
375 return;
376 }
377
378 InjectedScript::ContextScope scope(m_session, contextId);
379 response = scope.initialize();
380 if (!response.IsSuccess()) {
381 callback->sendFailure(response);
382 return;
383 }
384
385 if (silent.value_or(false)) scope.ignoreExceptionsAndMuteConsole();
386 if (userGesture.value_or(false)) scope.pretendUserGesture();
387
388 if (includeCommandLineAPI.value_or(false)) scope.installCommandLineAPI();
389
390 const bool replMode = maybeReplMode.value_or(false);
391
392 if (allowUnsafeEvalBlockedByCSP.value_or(true)) {
393 // Temporarily enable allow evals for inspector.
395 }
396 v8::MaybeLocal<v8::Value> maybeResultValue;
397 {
398 V8InspectorImpl::EvaluateScope evaluateScope(scope);
399 if (timeout.has_value()) {
400 response = evaluateScope.setTimeout(timeout.value() / 1000.0);
401 if (!response.IsSuccess()) {
402 callback->sendFailure(response);
403 return;
404 }
405 }
406 v8::MicrotasksScope microtasksScope(scope.context(),
410 if (throwOnSideEffect.value_or(false)) {
412 } else if (disableBreaks.value_or(false)) {
414 }
415 const v8::Local<v8::String> source =
416 toV8String(m_inspector->isolate(), expression);
417 maybeResultValue = v8::debug::EvaluateGlobal(m_inspector->isolate(), source,
418 mode, replMode);
419 } // Run microtasks before returning result.
420
421 // Re-initialize after running client's code, as it could have destroyed
422 // context or session.
423 response = scope.initialize();
424 if (!response.IsSuccess()) {
425 callback->sendFailure(response);
426 return;
427 }
428
429 std::unique_ptr<WrapOptions> wrapOptions;
430 response = getWrapOptions(
431 std::move(returnByValue), std::move(generatePreview),
432 std::move(serializationOptions), m_inspector->isolate(), &wrapOptions);
433 if (!response.IsSuccess()) {
434 callback->sendFailure(response);
435 return;
436 }
437
438 // REPL mode always returns a promise that must be awaited.
439 const bool await = replMode || maybeAwaitPromise.value_or(false);
440 if (!await || scope.tryCatch().HasCaught()) {
441 wrapEvaluateResultAsync(scope.injectedScript(), maybeResultValue,
442 scope.tryCatch(), objectGroup.value_or(""),
443 *wrapOptions, throwOnSideEffect.value_or(false),
444 callback.get());
445 return;
446 }
448 m_session, maybeResultValue, objectGroup.value_or(""),
449 std::move(wrapOptions), replMode, throwOnSideEffect.value_or(false),
450 EvaluateCallbackWrapper<EvaluateCallback>::wrap(std::move(callback)));
451}
452
454 const String16& promiseObjectId, std::optional<bool> returnByValue,
455 std::optional<bool> generatePreview,
456 std::unique_ptr<AwaitPromiseCallback> callback) {
457 InjectedScript::ObjectScope scope(m_session, promiseObjectId);
458 Response response = scope.initialize();
459 if (!response.IsSuccess()) {
460 callback->sendFailure(response);
461 return;
462 }
463 if (!scope.object()->IsPromise()) {
464 callback->sendFailure(
465 Response::ServerError("Could not find promise with given id"));
466 return;
467 }
468
469 std::unique_ptr<WrapOptions> wrapOptions;
470 response =
471 getWrapOptions(std::move(returnByValue), std::move(generatePreview),
472 m_inspector->isolate(), &wrapOptions);
473 if (!response.IsSuccess()) {
474 callback->sendFailure(response);
475 return;
476 }
477
479 m_session, scope.object(), scope.objectGroupName(),
480 std::move(wrapOptions), false /* replMode */,
481 false /* throwOnSideEffect */,
482 EvaluateCallbackWrapper<AwaitPromiseCallback>::wrap(std::move(callback)));
483}
484
486 const String16& expression, std::optional<String16> objectId,
487 std::unique_ptr<protocol::Array<protocol::Runtime::CallArgument>>
488 optionalArguments,
489 std::optional<bool> silent, std::optional<bool> returnByValue,
490 std::optional<bool> generatePreview, std::optional<bool> userGesture,
491 std::optional<bool> awaitPromise, std::optional<int> executionContextId,
492 std::optional<String16> objectGroup, std::optional<bool> throwOnSideEffect,
493 std::optional<String16> uniqueContextId,
494 std::unique_ptr<protocol::Runtime::SerializationOptions>
495 serializationOptions,
496 std::unique_ptr<CallFunctionOnCallback> callback) {
497 int justCount = (objectId.has_value() ? 1 : 0) +
498 (executionContextId.has_value() ? 1 : 0) +
499 (uniqueContextId.has_value() ? 1 : 0);
500 if (justCount > 1) {
501 callback->sendFailure(Response::InvalidParams(
502 "ObjectId, executionContextId and uniqueContextId must mutually "
503 "exclude each other"));
504 return;
505 }
506 if (justCount < 1) {
507 callback->sendFailure(
508 Response::InvalidParams("Either objectId or executionContextId or "
509 "uniqueContextId must be specified"));
510 return;
511 }
512
513 if (objectId.has_value()) {
514 InjectedScript::ObjectScope scope(m_session, objectId.value());
515 Response response = scope.initialize();
516 if (!response.IsSuccess()) {
517 callback->sendFailure(response);
518 return;
519 }
520
521 std::unique_ptr<WrapOptions> wrapOptions;
522 response = getWrapOptions(
523 std::move(returnByValue), std::move(generatePreview),
524 std::move(serializationOptions), m_inspector->isolate(), &wrapOptions);
525 if (!response.IsSuccess()) {
526 callback->sendFailure(response);
527 return;
528 }
529
530 innerCallFunctionOn(m_session, scope, scope.object(), expression,
531 std::move(optionalArguments), silent.value_or(false),
532 std::move(wrapOptions), userGesture.value_or(false),
533 awaitPromise.value_or(false),
534 objectGroup.value_or(scope.objectGroupName()),
535 throwOnSideEffect.value_or(false), std::move(callback));
536 } else {
537 int contextId = 0;
538 Response response = ensureContext(m_inspector, m_session->contextGroupId(),
539 std::move(executionContextId),
540 std::move(uniqueContextId), &contextId);
541 if (!response.IsSuccess()) {
542 callback->sendFailure(response);
543 return;
544 }
545 InjectedScript::ContextScope scope(m_session, contextId);
546 response = scope.initialize();
547 if (!response.IsSuccess()) {
548 callback->sendFailure(response);
549 return;
550 }
551
552 std::unique_ptr<WrapOptions> wrapOptions;
553 response = getWrapOptions(
554 std::move(returnByValue), std::move(generatePreview),
555 std::move(serializationOptions), m_inspector->isolate(), &wrapOptions);
556 if (!response.IsSuccess()) {
557 callback->sendFailure(response);
558 return;
559 }
560
561 innerCallFunctionOn(m_session, scope, scope.context()->Global(), expression,
562 std::move(optionalArguments), silent.value_or(false),
563 std::move(wrapOptions), userGesture.value_or(false),
564 awaitPromise.value_or(false), objectGroup.value_or(""),
565 throwOnSideEffect.value_or(false), std::move(callback));
566 }
567}
568
570 const String16& objectId, std::optional<bool> ownProperties,
571 std::optional<bool> accessorPropertiesOnly,
572 std::optional<bool> generatePreview,
573 std::optional<bool> nonIndexedPropertiesOnly,
574 std::unique_ptr<protocol::Array<protocol::Runtime::PropertyDescriptor>>*
575 result,
576 std::unique_ptr<
577 protocol::Array<protocol::Runtime::InternalPropertyDescriptor>>*
578 internalProperties,
579 std::unique_ptr<
580 protocol::Array<protocol::Runtime::PrivatePropertyDescriptor>>*
581 privateProperties,
582 std::unique_ptr<protocol::Runtime::ExceptionDetails>* exceptionDetails) {
583 using protocol::Runtime::InternalPropertyDescriptor;
584 using protocol::Runtime::PrivatePropertyDescriptor;
585
586 InjectedScript::ObjectScope scope(m_session, objectId);
587 Response response = scope.initialize();
588 if (!response.IsSuccess()) return response;
589
591 v8::MicrotasksScope microtasks_scope(scope.context(),
593 if (!scope.object()->IsObject())
594 return Response::ServerError("Value with given id is not an object");
595
596 v8::Local<v8::Object> object = scope.object().As<v8::Object>();
597
598 std::unique_ptr<WrapOptions> wrapOptions;
599 response =
600 getWrapOptions(false /* returnByValue */, std::move(generatePreview),
601 m_inspector->isolate(), &wrapOptions);
602 if (!response.IsSuccess()) return response;
603
604 response = scope.injectedScript()->getProperties(
605 object, scope.objectGroupName(), ownProperties.value_or(false),
606 accessorPropertiesOnly.value_or(false),
607 nonIndexedPropertiesOnly.value_or(false), *wrapOptions, result,
608 exceptionDetails);
609 if (!response.IsSuccess()) return response;
610 if (*exceptionDetails) return Response::Success();
611 std::unique_ptr<protocol::Array<InternalPropertyDescriptor>>
612 internalPropertiesProtocolArray;
613 std::unique_ptr<protocol::Array<PrivatePropertyDescriptor>>
614 privatePropertiesProtocolArray;
616 object, scope.objectGroupName(), accessorPropertiesOnly.value_or(false),
617 &internalPropertiesProtocolArray, &privatePropertiesProtocolArray);
618 if (!response.IsSuccess()) return response;
619 if (!internalPropertiesProtocolArray->empty())
620 *internalProperties = std::move(internalPropertiesProtocolArray);
621 if (!privatePropertiesProtocolArray->empty())
622 *privateProperties = std::move(privatePropertiesProtocolArray);
623 return Response::Success();
624}
625
627 InjectedScript::ObjectScope scope(m_session, objectId);
628 Response response = scope.initialize();
629 if (!response.IsSuccess()) return response;
630 scope.injectedScript()->releaseObject(objectId);
631 return Response::Success();
632}
633
635 m_session->releaseObjectGroup(objectGroup);
636 return Response::Success();
637}
638
640 if (m_debuggerBarrier) {
641 m_debuggerBarrier.reset();
642 return Response::Success();
643 }
644 // TODO(chromium:1352175): the below is provisional until client-side changes
645 // land. The call should come through the barrier only once client properly
646 // communicates whether the session is waiting for debugger.
648 return Response::Success();
649}
650
653 enabled);
654 if (!m_enabled) return Response::ServerError("Runtime agent is not enabled");
656 return Response::Success();
657}
658
660 if (size < 0) {
661 return Response::ServerError(
662 "maxCallStackSizeToCapture should be non-negative");
663 }
665 TRACE_DISABLED_BY_DEFAULT("v8.inspector"),
666 "V8RuntimeAgentImpl::setMaxCallStackSizeToCapture", this,
668 if (!m_enabled) return Response::ServerError("Runtime agent is not enabled");
671 return Response::Success();
672}
673
675 V8ConsoleMessageStorage* storage =
677 storage->clear();
678 return Response::Success();
679}
680
682 const String16& expression, const String16& sourceURL, bool persistScript,
683 std::optional<int> executionContextId, std::optional<String16>* scriptId,
684 std::unique_ptr<protocol::Runtime::ExceptionDetails>* exceptionDetails) {
685 if (!m_enabled) return Response::ServerError("Runtime agent is not enabled");
686
687 int contextId = 0;
688 Response response = ensureContext(m_inspector, m_session->contextGroupId(),
689 std::move(executionContextId),
690 /*uniqueContextId*/ {}, &contextId);
691 if (!response.IsSuccess()) return response;
692 InjectedScript::ContextScope scope(m_session, contextId);
693 response = scope.initialize();
694 if (!response.IsSuccess()) return response;
695
696 if (!persistScript) m_inspector->debugger()->muteScriptParsedEvents();
698 bool isOk = m_inspector->compileScript(scope.context(), expression, sourceURL)
699 .ToLocal(&script);
700 if (!persistScript) m_inspector->debugger()->unmuteScriptParsedEvents();
701 if (!isOk) {
702 if (scope.tryCatch().HasCaught()) {
703 response = scope.injectedScript()->createExceptionDetails(
704 scope.tryCatch(), String16(), exceptionDetails);
705 if (!response.IsSuccess()) return response;
706 return Response::Success();
707 } else {
708 return Response::ServerError("Script compilation failed");
709 }
710 }
711
712 if (!persistScript) return Response::Success();
713
714 String16 scriptValueId =
715 String16::fromInteger(script->GetUnboundScript()->GetId());
716 std::unique_ptr<v8::Global<v8::Script>> global(
718 m_compiledScripts[scriptValueId] = std::move(global);
719 *scriptId = scriptValueId;
720 return Response::Success();
721}
722
724 const String16& scriptId, std::optional<int> executionContextId,
725 std::optional<String16> objectGroup, std::optional<bool> silent,
726 std::optional<bool> includeCommandLineAPI,
727 std::optional<bool> returnByValue, std::optional<bool> generatePreview,
728 std::optional<bool> awaitPromise,
729 std::unique_ptr<RunScriptCallback> callback) {
730 if (!m_enabled) {
731 callback->sendFailure(
732 Response::ServerError("Runtime agent is not enabled"));
733 return;
734 }
735
736 auto it = m_compiledScripts.find(scriptId);
737 if (it == m_compiledScripts.end()) {
738 callback->sendFailure(Response::ServerError("No script with given id"));
739 return;
740 }
741
742 int contextId = 0;
743 Response response = ensureContext(m_inspector, m_session->contextGroupId(),
744 std::move(executionContextId),
745 /*uniqueContextId*/ {}, &contextId);
746 if (!response.IsSuccess()) {
747 callback->sendFailure(response);
748 return;
749 }
750
751 InjectedScript::ContextScope scope(m_session, contextId);
752 response = scope.initialize();
753 if (!response.IsSuccess()) {
754 callback->sendFailure(response);
755 return;
756 }
757
758 if (silent.value_or(false)) scope.ignoreExceptionsAndMuteConsole();
759
760 std::unique_ptr<v8::Global<v8::Script>> scriptWrapper = std::move(it->second);
761 m_compiledScripts.erase(it);
762 v8::Local<v8::Script> script = scriptWrapper->Get(m_inspector->isolate());
763 if (script.IsEmpty()) {
764 callback->sendFailure(Response::ServerError("Script execution failed"));
765 return;
766 }
767
768 if (includeCommandLineAPI.value_or(false)) scope.installCommandLineAPI();
769
770 v8::MaybeLocal<v8::Value> maybeResultValue;
771 {
772 v8::MicrotasksScope microtasksScope(scope.context(),
774 maybeResultValue = script->Run(scope.context());
775 }
776
777 // Re-initialize after running client's code, as it could have destroyed
778 // context or session.
779 response = scope.initialize();
780 if (!response.IsSuccess()) {
781 callback->sendFailure(response);
782 return;
783 }
784
785 std::unique_ptr<WrapOptions> wrapOptions;
786 response =
787 getWrapOptions(std::move(returnByValue), std::move(generatePreview),
788 m_inspector->isolate(), &wrapOptions);
789 if (!response.IsSuccess()) {
790 callback->sendFailure(response);
791 return;
792 }
793
794 if (!awaitPromise.value_or(false) || scope.tryCatch().HasCaught()) {
795 wrapEvaluateResultAsync(scope.injectedScript(), maybeResultValue,
796 scope.tryCatch(), objectGroup.value_or(""),
797 *wrapOptions, false /* throwOnSideEffect */,
798 callback.get());
799 return;
800 }
802 m_session, maybeResultValue.ToLocalChecked(), objectGroup.value_or(""),
803 std::move(wrapOptions), false /* replMode */,
804 false /* throwOnSideEffect */,
805 EvaluateCallbackWrapper<RunScriptCallback>::wrap(std::move(callback)));
806}
807
809 const String16& prototypeObjectId, std::optional<String16> objectGroup,
810 std::unique_ptr<protocol::Runtime::RemoteObject>* objects) {
811 InjectedScript::ObjectScope scope(m_session, prototypeObjectId);
812 Response response = scope.initialize();
813 if (!response.IsSuccess()) return response;
814 if (!scope.object()->IsObject()) {
815 return Response::ServerError("Prototype should be instance of Object");
816 }
818 scope.context(), scope.object().As<v8::Object>());
819 return scope.injectedScript()->wrapObject(
820 resultArray, objectGroup.value_or(scope.objectGroupName()),
821 WrapOptions({WrapMode::kIdOnly}), objects);
822}
823
825 std::optional<int> executionContextId,
826 std::unique_ptr<protocol::Array<String16>>* outNames) {
827 int contextId = 0;
828 Response response = ensureContext(m_inspector, m_session->contextGroupId(),
829 std::move(executionContextId),
830 /*uniqueContextId*/ {}, &contextId);
831 if (!response.IsSuccess()) return response;
832
833 InjectedScript::ContextScope scope(m_session, contextId);
834 response = scope.initialize();
835 if (!response.IsSuccess()) return response;
836
837 std::vector<v8::Global<v8::String>> names;
839 *outNames = std::make_unique<protocol::Array<String16>>();
840 for (size_t i = 0; i < names.size(); ++i) {
841 (*outNames)->emplace_back(toProtocolString(
842 m_inspector->isolate(), names[i].Get(m_inspector->isolate())));
843 }
844 return Response::Success();
845}
846
848 char buf[40];
849 std::snprintf(buf, sizeof(buf), "%" PRIx64, m_inspector->isolateId());
850 *outIsolateId = buf;
851 return Response::Success();
852}
853
854Response V8RuntimeAgentImpl::getHeapUsage(double* out_usedSize,
855 double* out_totalSize,
856 double* out_embedderHeapUsedSize,
857 double* out_backingStorageSize) {
858 v8::HeapStatistics stats;
860 *out_usedSize = stats.used_heap_size();
861 *out_totalSize = stats.total_heap_size();
862 *out_backingStorageSize = stats.external_memory();
863 if (v8::CppHeap* cppHeap = m_inspector->isolate()->GetCppHeap()) {
864 cppgc::HeapStatistics cppStats =
865 cppHeap->CollectStatistics(cppgc::HeapStatistics::DetailLevel::kBrief);
866 *out_embedderHeapUsedSize = cppStats.used_size_bytes;
867 } else {
868 *out_embedderHeapUsedSize = 0;
869 }
870 return Response::Success();
871}
872
874 std::unique_ptr<TerminateExecutionCallback> callback) {
876 v8::Local<v8::Context> defaultContext =
879
880 m_inspector->debugger()->terminateExecution(defaultContext,
881 std::move(callback));
882}
883
884namespace {
885protocol::DictionaryValue* getOrCreateDictionary(
886 protocol::DictionaryValue* dict, const String16& key) {
887 if (protocol::DictionaryValue* bindings = dict->getObject(key))
888 return bindings;
889 dict->setObject(key, protocol::DictionaryValue::create());
890 return dict->getObject(key);
891}
892} // namespace
893
895 const String16& name, std::optional<int> executionContextId,
896 std::optional<String16> executionContextName) {
897 if (executionContextId.has_value()) {
898 if (executionContextName.has_value()) {
899 return Response::InvalidParams(
900 "executionContextName is mutually exclusive with executionContextId");
901 }
902 int contextId = executionContextId.value();
903 InspectedContext* context =
905 if (!context) {
906 return Response::InvalidParams(
907 "Cannot find execution context with given executionContextId");
908 }
909 addBinding(context, name);
910 return Response::Success();
911 }
912
913 // If it's a globally exposed binding, i.e. no context name specified, use
914 // a special value for the context name.
916 if (executionContextName.has_value()) {
917 contextKey = executionContextName.value();
919 return Response::InvalidParams("Invalid executionContextName");
920 }
921 }
922 // Only persist non context-specific bindings, as contextIds don't make
923 // any sense when state is restored in a different process.
924 protocol::DictionaryValue* bindings =
925 getOrCreateDictionary(m_state, V8RuntimeAgentImplState::bindings);
926 protocol::DictionaryValue* contextBindings =
927 getOrCreateDictionary(bindings, contextKey);
928 contextBindings->setBoolean(name, true);
929
932 [&name, &executionContextName, this](InspectedContext* context) {
933 if (executionContextName.has_value() &&
934 executionContextName.value() != context->humanReadableName())
935 return;
936 addBinding(context, name);
937 });
938 return Response::Success();
939}
940
943 v8::Isolate* isolate = info.GetIsolate();
944 if (info.Length() != 1 || !info[0]->IsString()) {
945 info.GetIsolate()->ThrowError(
946 "Invalid arguments: should be exactly one string.");
947 return;
948 }
949 V8InspectorImpl* inspector =
950 static_cast<V8InspectorImpl*>(v8::debug::GetInspector(isolate));
951 int contextId = InspectedContext::contextId(isolate->GetCurrentContext());
952 int contextGroupId = inspector->contextGroupId(contextId);
953
954 String16 name = toProtocolString(isolate, info.Data().As<v8::String>());
955 String16 payload = toProtocolString(isolate, info[0].As<v8::String>());
956
957 inspector->forEachSession(
958 contextGroupId,
959 [&name, &payload, &contextId](V8InspectorSessionImpl* session) {
960 session->runtimeAgent()->bindingCalled(name, payload, contextId);
961 });
962}
963
965 const String16& name) {
966 auto it = m_activeBindings.find(name);
967 if (it != m_activeBindings.end() && it->second.count(context->contextId())) {
968 return;
969 }
971 v8::Local<v8::Context> localContext = context->context();
972 v8::Local<v8::Object> global = localContext->Global();
974 v8::Local<v8::Value> functionValue;
975 v8::MicrotasksScope microtasks(localContext,
977 if (v8::Function::New(localContext, bindingCallback, v8Name)
978 .ToLocal(&functionValue)) {
979 v8::Maybe<bool> success = global->Set(localContext, v8Name, functionValue);
980 USE(success);
981 if (it == m_activeBindings.end()) {
982 m_activeBindings.emplace(name,
983 std::unordered_set<int>(context->contextId()));
984 } else {
985 m_activeBindings.at(name).insert(context->contextId());
986 }
987 }
988}
989
991 protocol::DictionaryValue* bindings =
993 if (bindings) bindings->remove(name);
994 m_activeBindings.erase(name);
995 return Response::Success();
996}
997
999 const String16& errorObjectId,
1000 std::unique_ptr<protocol::Runtime::ExceptionDetails>*
1001 out_exceptionDetails) {
1002 InjectedScript::ObjectScope scope(m_session, errorObjectId);
1003 Response response = scope.initialize();
1004 if (!response.IsSuccess()) return response;
1005
1006 const v8::Local<v8::Value> error = scope.object();
1007 if (!error->IsNativeError())
1008 return Response::ServerError("errorObjectId is not a JS error object");
1009
1010 const v8::Local<v8::Message> message =
1012
1013 response = scope.injectedScript()->createExceptionDetails(
1014 message, error, scope.objectGroupName(), out_exceptionDetails);
1015 if (!response.IsSuccess()) return response;
1016
1017 CHECK(*out_exceptionDetails);
1018
1019 // When an exception object is present, `createExceptionDetails` assumes
1020 // the exception is uncaught and will overwrite the text field to "Uncaught".
1021 // Lets use the normal message text instead.
1022 (*out_exceptionDetails)
1023 ->setText(toProtocolString(m_inspector->isolate(), message->Get()));
1024
1025 // Check if the exception has any metadata on the inspector and also attach
1026 // it.
1027 std::unique_ptr<protocol::DictionaryValue> data =
1029 if (data) {
1030 (*out_exceptionDetails)->setExceptionMetaData(std::move(data));
1031 }
1032 return Response::Success();
1033}
1034
1036 const String16& payload,
1037 int executionContextId) {
1038 if (!m_activeBindings.count(name)) return;
1039 m_frontend.bindingCalled(name, payload, executionContextId);
1040 m_frontend.flush();
1041}
1042
1044 const String16 contextName = context->humanReadableName();
1045 if (!m_enabled) return;
1046 protocol::DictionaryValue* bindings =
1048 if (!bindings) return;
1049 protocol::DictionaryValue* globalBindings =
1050 bindings->getObject(V8RuntimeAgentImplState::globalBindingsKey);
1051 if (globalBindings) {
1052 for (size_t i = 0; i < globalBindings->size(); ++i)
1053 addBinding(context, globalBindings->at(i).first);
1054 }
1055 protocol::DictionaryValue* contextBindings =
1056 contextName.isEmpty() ? nullptr : bindings->getObject(contextName);
1057 if (contextBindings) {
1058 for (size_t i = 0; i < contextBindings->size(); ++i)
1059 addBinding(context, contextBindings->at(i).first);
1060 }
1061}
1062
1064 if (!m_state->booleanProperty(V8RuntimeAgentImplState::runtimeEnabled, false))
1065 return;
1066 m_frontend.executionContextsCleared();
1067 enable();
1068 if (m_state->booleanProperty(
1071
1072 int size;
1074 &size))
1076
1079 [this](InspectedContext* context) { addBindings(context); });
1080}
1081
1083 if (m_enabled) return Response::Success();
1085 "V8RuntimeAgentImpl::enable", this,
1089 m_enabled = true;
1094 V8ConsoleMessageStorage* storage =
1096 for (const auto& message : storage->messages()) {
1097 if (!reportMessage(message.get(), false)) break;
1098 }
1099 return Response::Success();
1100}
1101
1103 if (!m_enabled) return Response::Success();
1105 "V8RuntimeAgentImpl::disable", this,
1107 m_enabled = false;
1112 reset();
1117 }
1118 return Response::Success();
1119}
1120
1122 m_compiledScripts.clear();
1123 if (m_enabled) {
1124 int sessionId = m_session->sessionId();
1126 [&sessionId](InspectedContext* context) {
1127 context->setReported(sessionId, false);
1128 });
1129 m_frontend.executionContextsCleared();
1130 }
1131}
1132
1134 InspectedContext* context) {
1135 if (!m_enabled) return;
1136 context->setReported(m_session->sessionId(), true);
1137 std::unique_ptr<protocol::Runtime::ExecutionContextDescription> description =
1138 protocol::Runtime::ExecutionContextDescription::create()
1139 .setId(context->contextId())
1140 .setName(context->humanReadableName())
1141 .setOrigin(context->origin())
1142 .setUniqueId(context->uniqueId().toString())
1143 .build();
1144 const String16& aux = context->auxData();
1145 if (!aux.isEmpty()) {
1146 std::vector<uint8_t> cbor;
1147 v8_crdtp::json::ConvertJSONToCBOR(
1148 v8_crdtp::span<uint16_t>(aux.characters16(), aux.length()), &cbor);
1149 description->setAuxData(protocol::DictionaryValue::cast(
1150 protocol::Value::parseBinary(cbor.data(), cbor.size())));
1151 }
1152 m_frontend.executionContextCreated(std::move(description));
1153}
1154
1156 InspectedContext* context) {
1157 if (m_enabled && context->isReported(m_session->sessionId())) {
1158 context->setReported(m_session->sessionId(), false);
1159 m_frontend.executionContextDestroyed(context->contextId(),
1160 context->uniqueId().toString());
1161 }
1162}
1163
1165 std::unique_ptr<protocol::Runtime::RemoteObject> objectToInspect,
1166 std::unique_ptr<protocol::DictionaryValue> hints, int executionContextId) {
1167 if (m_enabled)
1168 m_frontend.inspectRequested(std::move(objectToInspect), std::move(hints),
1169 executionContextId);
1170}
1171
1173 if (m_enabled) reportMessage(message, true);
1174}
1175
1177 bool generatePreview) {
1178 message->reportToFrontend(&m_frontend, m_session, generatePreview);
1179 m_frontend.flush();
1181}
1182} // namespace v8_inspector
Local< Object > Global()
Definition api.cc:7208
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
CppHeap * GetCppHeap() const
Definition api.cc:9871
void GetHeapStatistics(HeapStatistics *heap_statistics)
Definition api.cc:10267
V8_INLINE Local< S > As() const
V8_WARN_UNUSED_RESULT V8_INLINE bool ToLocal(Local< S > *out) const
V8_INLINE Local< T > ToLocalChecked()
static Local< Number > New(Isolate *isolate, double value)
Definition api.cc:9557
static Local< Object > New(Isolate *isolate)
Definition api.cc:7756
bool IsPromise() const
Definition api.cc:3683
bool IsObject() const
Definition api.cc:3572
v8::Local< v8::Value > object() const
v8::Local< v8::Context > context() const
InjectedScript * injectedScript() const
const v8::TryCatch & tryCatch() const
Response wrapObject(v8::Local< v8::Value >, const String16 &groupName, const WrapOptions &wrapOptions, std::unique_ptr< protocol::Runtime::RemoteObject > *result)
Response getProperties(v8::Local< v8::Object >, const String16 &groupName, bool ownProperties, bool accessorPropertiesOnly, bool nonIndexedPropertiesOnly, const WrapOptions &wrapOptions, std::unique_ptr< protocol::Array< protocol::Runtime::PropertyDescriptor > > *result, std::unique_ptr< protocol::Runtime::ExceptionDetails > *)
void addPromiseCallback(V8InspectorSessionImpl *session, v8::MaybeLocal< v8::Value > value, const String16 &objectGroup, std::unique_ptr< WrapOptions > wrapOptions, bool replMode, bool throwOnSideEffect, std::shared_ptr< EvaluateCallback > callback)
Response getInternalAndPrivateProperties(v8::Local< v8::Value >, const String16 &groupName, bool accessorPropertiesOnly, std::unique_ptr< protocol::Array< protocol::Runtime::InternalPropertyDescriptor > > *internalProperties, std::unique_ptr< protocol::Array< protocol::Runtime::PrivatePropertyDescriptor > > *privateProperties)
void releaseObject(const String16 &objectId)
Response createExceptionDetails(const v8::TryCatch &, const String16 &groupName, std::unique_ptr< protocol::Runtime::ExceptionDetails > *result)
size_t length() const
Definition string-16.h:58
static String16 fromInteger(int)
Definition string-16.cc:71
bool isEmpty() const
Definition string-16.h:59
const uint16_t * characters16() const
Definition string-16.h:55
const std::deque< std::unique_ptr< V8ConsoleMessage > > & messages() const
Response setAsyncCallStackDepth(int depth) override
void terminateExecution(v8::Local< v8::Context > context, std::unique_ptr< TerminateExecutionCallback > callback)
v8::Local< v8::Array > queryObjects(v8::Local< v8::Context > context, v8::Local< v8::Object > prototype)
void setMaxCallStackSizeToCapture(V8RuntimeAgentImpl *, int)
virtual void beginEnsureAllContextsInGroup(int contextGroupId)
virtual v8::Local< v8::Context > ensureDefaultContextInGroup(int contextGroupId)
virtual void runIfWaitingForDebugger(int contextGroupId)
virtual void endEnsureAllContextsInGroup(int contextGroupId)
protocol::Response setTimeout(double timeout)
V8ConsoleMessageStorage * ensureConsoleMessageStorage(int contextGroupId)
std::unique_ptr< protocol::DictionaryValue > getAssociatedExceptionDataForProtocol(v8::Local< v8::Value > exception)
v8::MaybeLocal< v8::Script > compileScript(v8::Local< v8::Context >, const String16 &code, const String16 &fileName)
v8::Isolate * isolate() const
InspectedContext * getContext(int groupId, int contextId) const
bool hasConsoleMessageStorage(int contextGroupId)
void forEachSession(int contextGroupId, const std::function< void(V8InspectorSessionImpl *)> &callback)
int contextGroupId(v8::Local< v8::Context >) const
void forEachContext(int contextGroupId, const std::function< void(InspectedContext *)> &callback)
void releaseObjectGroup(const String16 &objectGroup)
std::unordered_map< String16, std::unique_ptr< v8::Global< v8::Script > > > m_compiledScripts
protocol::Runtime::Frontend m_frontend
void bindingCalled(const String16 &name, const String16 &payload, int executionContextId)
std::unordered_map< String16, std::unordered_set< int > > m_activeBindings
void reportExecutionContextDestroyed(InspectedContext *)
Response getProperties(const String16 &objectId, std::optional< bool > ownProperties, std::optional< bool > accessorPropertiesOnly, std::optional< bool > generatePreview, std::optional< bool > nonIndexedPropertiesOnly, std::unique_ptr< protocol::Array< protocol::Runtime::PropertyDescriptor > > *result, std::unique_ptr< protocol::Array< protocol::Runtime::InternalPropertyDescriptor > > *internalProperties, std::unique_ptr< protocol::Array< protocol::Runtime::PrivatePropertyDescriptor > > *privateProperties, std::unique_ptr< protocol::Runtime::ExceptionDetails > *) override
bool reportMessage(V8ConsoleMessage *, bool generatePreview)
static void bindingCallback(const v8::FunctionCallbackInfo< v8::Value > &info)
void addBindings(InspectedContext *context)
Response setMaxCallStackSizeToCapture(int) override
Response addBinding(const String16 &name, std::optional< int > executionContextId, std::optional< String16 > executionContextName) override
void runScript(const String16 &, std::optional< int > executionContextId, std::optional< String16 > objectGroup, std::optional< bool > silent, std::optional< bool > includeCommandLineAPI, std::optional< bool > returnByValue, std::optional< bool > generatePreview, std::optional< bool > awaitPromise, std::unique_ptr< RunScriptCallback >) override
Response globalLexicalScopeNames(std::optional< int > executionContextId, std::unique_ptr< protocol::Array< String16 > > *outNames) override
Response getHeapUsage(double *out_usedSize, double *out_totalSize, double *out_embedderHeapUsedSize, double *out_backingStorageSize) override
Response queryObjects(const String16 &prototypeObjectId, std::optional< String16 > objectGroup, std::unique_ptr< protocol::Runtime::RemoteObject > *objects) override
Response compileScript(const String16 &expression, const String16 &sourceURL, bool persistScript, std::optional< int > executionContextId, std::optional< String16 > *, std::unique_ptr< protocol::Runtime::ExceptionDetails > *) override
std::shared_ptr< V8DebuggerBarrier > m_debuggerBarrier
void awaitPromise(const String16 &promiseObjectId, std::optional< bool > returnByValue, std::optional< bool > generatePreview, std::unique_ptr< AwaitPromiseCallback >) override
void reportExecutionContextCreated(InspectedContext *)
Response releaseObjectGroup(const String16 &objectGroup) override
Response setCustomObjectFormatterEnabled(bool) override
V8RuntimeAgentImpl(V8InspectorSessionImpl *, protocol::FrontendChannel *, protocol::DictionaryValue *state, std::shared_ptr< V8DebuggerBarrier >)
void terminateExecution(std::unique_ptr< TerminateExecutionCallback > callback) override
protocol::DictionaryValue * m_state
void evaluate(const String16 &expression, std::optional< String16 > objectGroup, std::optional< bool > includeCommandLineAPI, std::optional< bool > silent, std::optional< int > executionContextId, std::optional< bool > returnByValue, std::optional< bool > generatePreview, std::optional< bool > userGesture, std::optional< bool > awaitPromise, std::optional< bool > throwOnSideEffect, std::optional< double > timeout, std::optional< bool > disableBreaks, std::optional< bool > replMode, std::optional< bool > allowUnsafeEvalBlockedByCSP, std::optional< String16 > uniqueContextId, std::unique_ptr< protocol::Runtime::SerializationOptions > serializationOptions, std::unique_ptr< EvaluateCallback >) override
void callFunctionOn(const String16 &expression, std::optional< String16 > objectId, std::unique_ptr< protocol::Array< protocol::Runtime::CallArgument > > optionalArguments, std::optional< bool > silent, std::optional< bool > returnByValue, std::optional< bool > generatePreview, std::optional< bool > userGesture, std::optional< bool > awaitPromise, std::optional< int > executionContextId, std::optional< String16 > objectGroup, std::optional< bool > throwOnSideEffect, std::optional< String16 > uniqueContextId, std::unique_ptr< protocol::Runtime::SerializationOptions > serializationOptions, std::unique_ptr< CallFunctionOnCallback >) override
Response getExceptionDetails(const String16 &errorObjectId, std::unique_ptr< protocol::Runtime::ExceptionDetails > *out_exceptionDetails) override
Response getIsolateId(String16 *outIsolateId) override
void inspect(std::unique_ptr< protocol::Runtime::RemoteObject > objectToInspect, std::unique_ptr< protocol::DictionaryValue > hints, int executionContextId)
Response releaseObject(const String16 &objectId) override
Response removeBinding(const String16 &name) override
static constexpr int kDefaultMaxCallStackSizeToCapture
base::Vector< const DirectHandle< Object > > args
Definition execution.cc:74
refactor address components for immediate indexing make OptimizeMaglevOnNextCall optimize to turbofan instead of maglev filter for tracing turbofan compilation nullptr
TNode< Object > callback
ZoneVector< RpoNumber > & result
constexpr Vector< T > VectorOf(T *start, size_t size)
Definition vector.h:360
MaybeLocal< Value > CallFunctionOn(Local< Context > context, Local< Function > function, Local< Value > recv, base::Vector< Local< Value > > args, bool throw_on_side_effect)
void GlobalLexicalScopeNames(v8::Local< v8::Context > v8_context, std::vector< v8::Global< v8::String > > *names)
MaybeLocal< v8::Value > EvaluateGlobal(v8::Isolate *isolate, v8::Local< v8::String > source, EvaluateGlobalMode mode, bool repl)
v8_inspector::V8Inspector * GetInspector(Isolate *isolate)
v8::Local< v8::Message > CreateMessageFromException(Isolate *v8_isolate, v8::Local< v8::Value > v8_error)
constexpr int kMaxInt
Definition globals.h:374
String16 toProtocolString(v8::Isolate *isolate, v8::Local< v8::String > value)
v8::Local< v8::String > toV8String(v8::Isolate *isolate, const String16 &string)
V8_INLINE Local< Primitive > Null(Isolate *isolate)
bool ToLocal(v8::internal::MaybeDirectHandle< v8::internal::Object > maybe, Local< T > *local)
Definition api.h:303
#define CHECK(condition)
Definition logging.h:124
#define USE(...)
Definition macros.h:293
#define TRACE_EVENT0(category_group, name)
#define TRACE_DISABLED_BY_DEFAULT(name)
#define TRACE_EVENT_WITH_FLOW0(category_group, name, bind_id, flow_flags)
#define TRACE_EVENT_WITH_FLOW1(category_group, name, bind_id, flow_flags, arg1_name, arg1_val)
#define TRACE_EVENT_FLAG_FLOW_OUT
#define TRACE_EVENT_FLAG_FLOW_IN
V8InspectorImpl * m_inspector
V8InspectorSessionImpl * m_session
protocol::HeapProfiler::Frontend * m_frontend
std::unique_ptr< ProtocolCallback > m_callback
std::unique_ptr< ValueMirror > key