v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
injected-script.cc
Go to the documentation of this file.
1/*
2 * Copyright (C) 2012 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 <cmath>
34#include <memory>
35#include <unordered_set>
36
37#include "../../third_party/inspector_protocol/crdtp/json.h"
39#include "include/v8-context.h"
40#include "include/v8-function.h"
46#include "src/inspector/protocol/Protocol.h"
57
58namespace v8_inspector {
59
60namespace {
61const char kGlobalHandleLabel[] = "DevTools console";
62bool isResolvableNumberLike(String16 query) {
63 return query == "Infinity" || query == "-Infinity" || query == "NaN";
64}
65} // namespace
66
67using protocol::Array;
68using protocol::Runtime::InternalPropertyDescriptor;
69using protocol::Runtime::PrivatePropertyDescriptor;
70using protocol::Runtime::PropertyDescriptor;
71using protocol::Runtime::RemoteObject;
72
73// static
75 std::weak_ptr<EvaluateCallback> callback, InjectedScript* injectedScript,
76 std::unique_ptr<protocol::Runtime::RemoteObject> result,
77 std::unique_ptr<protocol::Runtime::ExceptionDetails> exceptionDetails) {
78 std::shared_ptr<EvaluateCallback> cb = callback.lock();
79 if (!cb) return;
80 injectedScript->deleteEvaluateCallback(cb);
81 CHECK_EQ(cb.use_count(), 1);
82 cb->sendSuccess(std::move(result), std::move(exceptionDetails));
83}
84
85// static
86void EvaluateCallback::sendFailure(std::weak_ptr<EvaluateCallback> callback,
87 InjectedScript* injectedScript,
88 const protocol::DispatchResponse& response) {
89 std::shared_ptr<EvaluateCallback> cb = callback.lock();
90 if (!cb) return;
91 injectedScript->deleteEvaluateCallback(cb);
92 CHECK_EQ(cb.use_count(), 1);
93 cb->sendFailure(response);
94}
95
97 public:
98 static void add(V8InspectorSessionImpl* session,
100 int executionContextId, const String16& objectGroup,
101 std::unique_ptr<WrapOptions> wrapOptions, bool replMode,
102 bool throwOnSideEffect,
103 std::weak_ptr<EvaluateCallback> callback) {
104 InjectedScript::ContextScope scope(session, executionContextId);
105 Response response = scope.initialize();
106 if (!response.IsSuccess()) return;
107
110 if (value->IsPromise()) {
111 // If value is a promise, we can chain the handlers directly onto `value`.
112 promise = value.As<v8::Promise>();
113 } else {
114 // Otherwise we do `Promise.resolve(value)`.
115 CHECK(!replMode);
116 if (!v8::Promise::Resolver::New(context).ToLocal(&resolver)) {
118 Response::InternalError());
119 return;
120 }
121 if (!resolver->Resolve(context, value).FromMaybe(false)) {
123 Response::InternalError());
124 return;
125 }
126 promise = resolver->GetPromise();
127 }
128
129 V8InspectorImpl* inspector = session->inspector();
130 PromiseHandlerTracker::Id handlerId =
131 inspector->promiseHandlerTracker().create(
132 session, executionContextId, objectGroup, std::move(wrapOptions),
133 replMode, throwOnSideEffect, callback, promise);
135 v8::Number::New(inspector->isolate(), handlerId);
136 v8::Local<v8::Function> thenCallbackFunction =
137 v8::Function::New(context, thenCallback, data, 0,
139 .ToLocalChecked();
140 v8::Local<v8::Function> catchCallbackFunction =
141 v8::Function::New(context, catchCallback, data, 0,
143 .ToLocalChecked();
144
145 if (promise->Then(context, thenCallbackFunction, catchCallbackFunction)
146 .IsEmpty()) {
147 // Re-initialize after returning from JS.
148 Response new_response = scope.initialize();
149 if (!new_response.IsSuccess()) return;
151 Response::InternalError());
152 }
153 }
154
155 private:
157
159 // TODO(szuend): Cache the string in a v8::Persistent handle.
161 isolate, reinterpret_cast<const uint8_t*>(".repl_result"))
162 .ToLocalChecked();
163 }
164
166 PromiseHandlerTracker::Id handlerId =
167 static_cast<PromiseHandlerTracker::Id>(
168 info.Data().As<v8::Number>()->Value());
169 PromiseHandlerTracker& handlerTracker =
170 static_cast<V8InspectorImpl*>(
171 v8::debug::GetInspector(info.GetIsolate()))
172 ->promiseHandlerTracker();
173 // We currently store the handlers with the inspector. In rare cases the
174 // inspector dies (discarding the handler) with the micro task queue
175 // running after. Don't do anything in that case.
176 ProtocolPromiseHandler* handler = handlerTracker.get(handlerId);
177 if (!handler) return;
179 info.Length() > 0 ? info[0]
180 : v8::Undefined(info.GetIsolate()).As<v8::Value>();
181 handler->thenCallback(value);
182 handlerTracker.discard(handlerId,
184 }
185
187 PromiseHandlerTracker::Id handlerId =
188 static_cast<PromiseHandlerTracker::Id>(
189 info.Data().As<v8::Number>()->Value());
190 PromiseHandlerTracker& handlerTracker =
191 static_cast<V8InspectorImpl*>(
192 v8::debug::GetInspector(info.GetIsolate()))
193 ->promiseHandlerTracker();
194 // We currently store the handlers with the inspector. In rare cases the
195 // inspector dies (discarding the handler) with the micro task queue
196 // running after. Don't do anything in that case.
197 ProtocolPromiseHandler* handler = handlerTracker.get(handlerId);
198 if (!handler) return;
200 info.Length() > 0 ? info[0]
201 : v8::Undefined(info.GetIsolate()).As<v8::Value>();
202 handler->catchCallback(value);
203 handlerTracker.discard(handlerId,
205 }
206
208 V8InspectorSessionImpl* session,
209 int executionContextId, const String16& objectGroup,
210 std::unique_ptr<WrapOptions> wrapOptions,
211 bool replMode, bool throwOnSideEffect,
212 std::weak_ptr<EvaluateCallback> callback,
213 v8::Local<v8::Promise> evaluationResult)
214 : m_inspector(session->inspector()),
215 m_sessionId(session->sessionId()),
216 m_contextGroupId(session->contextGroupId()),
217 m_executionContextId(executionContextId),
218 m_objectGroup(objectGroup),
219 m_wrapOptions(std::move(wrapOptions)),
220 m_replMode(replMode),
221 m_throwOnSideEffect(throwOnSideEffect),
222 m_callback(std::move(callback)),
223 m_evaluationResult(m_inspector->isolate(), evaluationResult) {
226 }
227
228 static void cleanup(
230 auto id = reinterpret_cast<PromiseHandlerTracker::Id>(data.GetParameter());
231 PromiseHandlerTracker& handlerTracker =
232 static_cast<V8InspectorImpl*>(
233 v8::debug::GetInspector(data.GetIsolate()))
234 ->promiseHandlerTracker();
235 // {discard} deletes the {ProtocolPromiseHandler} which resets the handle.
236 handlerTracker.discard(
238 }
239
241 // We don't need the m_evaluationResult in the `thenCallback`, but we also
242 // don't want `cleanup` running in case we re-enter JS.
244 V8InspectorSessionImpl* session =
246 if (!session) return;
248 Response response = scope.initialize();
249 if (!response.IsSuccess()) return;
250
251 // In REPL mode the result is additionally wrapped in an object.
252 // The evaluation result can be found at ".repl_result".
254 if (m_replMode) {
256 if (!result->ToObject(scope.context()).ToLocal(&object)) {
258 response);
259 return;
260 }
261
264 if (!object->Get(scope.context(), name).ToLocal(&result)) {
266 response);
267 return;
268 }
269 }
270
271 if (m_objectGroup == "console") {
273 }
274
275 std::unique_ptr<protocol::Runtime::RemoteObject> wrappedValue;
276 response = scope.injectedScript()->wrapObject(
277 result, m_objectGroup, *m_wrapOptions, &wrappedValue);
278 if (!response.IsSuccess()) {
280 response);
281 return;
282 }
284 std::move(wrappedValue), nullptr);
285 }
286
288 // Hold strongly onto m_evaluationResult now to prevent `cleanup` from
289 // running in case any code below triggers GC.
291 V8InspectorSessionImpl* session =
293 if (!session) return;
295 Response response = scope.initialize();
296 if (!response.IsSuccess()) return;
297 std::unique_ptr<protocol::Runtime::RemoteObject> wrappedValue;
298 response = scope.injectedScript()->wrapObject(
299 result, m_objectGroup, *m_wrapOptions, &wrappedValue);
300 if (!response.IsSuccess()) {
302 response);
303 return;
304 }
305 v8::Isolate* isolate = session->inspector()->isolate();
306
307 v8::MaybeLocal<v8::Message> maybeMessage =
312 // In case a MessageObject was attached to the rejected promise, we
313 // construct the exception details from the message object. Otherwise
314 // we try to capture a fresh stack trace.
315 if (maybeMessage.ToLocal(&message)) {
316 v8::Local<v8::Value> exception = result;
317 if (!m_throwOnSideEffect) {
318 session->inspector()->client()->dispatchError(scope.context(), message,
319 exception);
320 }
321 std::unique_ptr<protocol::Runtime::ExceptionDetails> exceptionDetails;
322 response = scope.injectedScript()->createExceptionDetails(
323 message, exception, m_objectGroup, &exceptionDetails);
324 if (!response.IsSuccess()) {
326 response);
327 return;
328 }
329
331 std::move(wrappedValue),
332 std::move(exceptionDetails));
333 return;
334 }
335
336 String16 messageString;
337 std::unique_ptr<V8StackTraceImpl> stack;
338 if (result->IsNativeError()) {
339 messageString =
340 " " +
341 toProtocolString(isolate,
342 result->ToDetailString(isolate->GetCurrentContext())
343 .ToLocalChecked());
344 v8::Local<v8::StackTrace> stackTrace =
346 if (!stackTrace.IsEmpty()) {
347 stack = m_inspector->debugger()->createStackTrace(stackTrace);
348 }
349 }
350 if (!stack) {
351 stack = m_inspector->debugger()->captureStackTrace(true);
352 }
353
354 // REPL mode implicitly handles the script like an async function.
355 // Do not prepend the '(in promise)' prefix for these exceptions since that
356 // would be confusing for the user. The stringified error is part of the
357 // exception and does not need to be added in REPL mode, otherwise it would
358 // be printed twice.
359 String16 exceptionDetailsText =
360 m_replMode ? "Uncaught" : "Uncaught (in promise)" + messageString;
361 std::unique_ptr<protocol::Runtime::ExceptionDetails> exceptionDetails =
362 protocol::Runtime::ExceptionDetails::create()
363 .setExceptionId(m_inspector->nextExceptionId())
364 .setText(exceptionDetailsText)
365 .setLineNumber(stack && !stack->isEmpty() ? stack->topLineNumber()
366 : 0)
367 .setColumnNumber(
368 stack && !stack->isEmpty() ? stack->topColumnNumber() : 0)
369 .build();
370 response = scope.injectedScript()->addExceptionToDetails(
371 result, exceptionDetails.get(), m_objectGroup);
372 if (!response.IsSuccess()) {
374 response);
375 return;
376 }
377 if (stack)
378 exceptionDetails->setStackTrace(
379 stack->buildInspectorObjectImpl(m_inspector->debugger()));
380 if (stack && !stack->isEmpty())
381 exceptionDetails->setScriptId(
382 String16::fromInteger(stack->topScriptId()));
384 std::move(wrappedValue),
385 std::move(exceptionDetails));
386 }
387
393 std::unique_ptr<WrapOptions> m_wrapOptions;
396 std::weak_ptr<EvaluateCallback> m_callback;
398};
399
401 : m_context(context), m_sessionId(sessionId) {}
402
404
405namespace {
406class PropertyAccumulator : public ValueMirror::PropertyAccumulator {
407 public:
408 explicit PropertyAccumulator(std::vector<PropertyMirror>* mirrors)
409 : m_mirrors(mirrors) {}
410 bool Add(PropertyMirror mirror) override {
411 m_mirrors->push_back(std::move(mirror));
412 return true;
413 }
414
415 private:
416 std::vector<PropertyMirror>* m_mirrors;
417};
418} // anonymous namespace
419
421 v8::Local<v8::Object> object, const String16& groupName, bool ownProperties,
422 bool accessorPropertiesOnly, bool nonIndexedPropertiesOnly,
423 const WrapOptions& wrapOptions,
424 std::unique_ptr<Array<PropertyDescriptor>>* properties,
425 std::unique_ptr<protocol::Runtime::ExceptionDetails>* exceptionDetails) {
428 v8::Isolate* isolate = m_context->isolate();
429 int sessionId = m_sessionId;
430 v8::TryCatch tryCatch(isolate);
431
432 *properties = std::make_unique<Array<PropertyDescriptor>>();
433 std::vector<PropertyMirror> mirrors;
434 PropertyAccumulator accumulator(&mirrors);
435 if (!ValueMirror::getProperties(context, object, ownProperties,
436 accessorPropertiesOnly,
437 nonIndexedPropertiesOnly, &accumulator)) {
438 return createExceptionDetails(tryCatch, groupName, exceptionDetails);
439 }
440 for (const PropertyMirror& mirror : mirrors) {
441 std::unique_ptr<PropertyDescriptor> descriptor =
442 PropertyDescriptor::create()
443 .setName(mirror.name)
444 .setConfigurable(mirror.configurable)
445 .setEnumerable(mirror.enumerable)
446 .setIsOwn(mirror.isOwn)
447 .build();
448 std::unique_ptr<RemoteObject> remoteObject;
449 if (mirror.value) {
450 Response response = wrapObjectMirror(
451 *mirror.value, groupName, wrapOptions, v8::MaybeLocal<v8::Value>(),
452 kMaxCustomPreviewDepth, &remoteObject);
453 if (!response.IsSuccess()) return response;
454 descriptor->setValue(std::move(remoteObject));
455 descriptor->setWritable(mirror.writable);
456 }
457 if (mirror.getter) {
458 Response response =
459 mirror.getter->buildRemoteObject(context, wrapOptions, &remoteObject);
460 if (!response.IsSuccess()) return response;
461 response = bindRemoteObjectIfNeeded(sessionId, context,
462 mirror.getter->v8Value(isolate),
463 groupName, remoteObject.get());
464 if (!response.IsSuccess()) return response;
465 descriptor->setGet(std::move(remoteObject));
466 }
467 if (mirror.setter) {
468 Response response =
469 mirror.setter->buildRemoteObject(context, wrapOptions, &remoteObject);
470 if (!response.IsSuccess()) return response;
471 response = bindRemoteObjectIfNeeded(sessionId, context,
472 mirror.setter->v8Value(isolate),
473 groupName, remoteObject.get());
474 if (!response.IsSuccess()) return response;
475 descriptor->setSet(std::move(remoteObject));
476 }
477 if (mirror.symbol) {
478 Response response =
479 mirror.symbol->buildRemoteObject(context, wrapOptions, &remoteObject);
480 if (!response.IsSuccess()) return response;
481 response = bindRemoteObjectIfNeeded(sessionId, context,
482 mirror.symbol->v8Value(isolate),
483 groupName, remoteObject.get());
484 if (!response.IsSuccess()) return response;
485 descriptor->setSymbol(std::move(remoteObject));
486 }
487 if (mirror.exception) {
488 Response response = mirror.exception->buildRemoteObject(
489 context, wrapOptions, &remoteObject);
490 if (!response.IsSuccess()) return response;
491 response = bindRemoteObjectIfNeeded(sessionId, context,
492 mirror.exception->v8Value(isolate),
493 groupName, remoteObject.get());
494 if (!response.IsSuccess()) return response;
495 descriptor->setValue(std::move(remoteObject));
496 descriptor->setWasThrown(true);
497 }
498 (*properties)->emplace_back(std::move(descriptor));
499 }
500 return Response::Success();
501}
502
504 v8::Local<v8::Value> value, const String16& groupName,
505 bool accessorPropertiesOnly,
506 std::unique_ptr<protocol::Array<InternalPropertyDescriptor>>*
507 internalProperties,
508 std::unique_ptr<protocol::Array<PrivatePropertyDescriptor>>*
509 privateProperties) {
510 *internalProperties = std::make_unique<Array<InternalPropertyDescriptor>>();
511 *privateProperties = std::make_unique<Array<PrivatePropertyDescriptor>>();
512
513 if (!value->IsObject()) return Response::Success();
514
515 v8::Local<v8::Object> value_obj = value.As<v8::Object>();
516
518 int sessionId = m_sessionId;
519
520 if (!accessorPropertiesOnly) {
521 std::vector<InternalPropertyMirror> internalPropertiesWrappers;
523 &internalPropertiesWrappers);
524 for (const auto& internalProperty : internalPropertiesWrappers) {
525 std::unique_ptr<RemoteObject> remoteObject;
526 Response response = internalProperty.value->buildRemoteObject(
528 &remoteObject);
529 if (!response.IsSuccess()) return response;
530 response = bindRemoteObjectIfNeeded(
531 sessionId, context,
532 internalProperty.value->v8Value(context->GetIsolate()), groupName,
533 remoteObject.get());
534 if (!response.IsSuccess()) return response;
535 (*internalProperties)
536 ->emplace_back(InternalPropertyDescriptor::create()
537 .setName(internalProperty.name)
538 .setValue(std::move(remoteObject))
539 .build());
540 }
541 }
542
543 std::vector<PrivatePropertyMirror> privatePropertyWrappers =
544 ValueMirror::getPrivateProperties(context, value_obj,
545 accessorPropertiesOnly);
546 for (const auto& privateProperty : privatePropertyWrappers) {
547 std::unique_ptr<PrivatePropertyDescriptor> descriptor =
548 PrivatePropertyDescriptor::create()
549 .setName(privateProperty.name)
550 .build();
551
552 std::unique_ptr<RemoteObject> remoteObject;
553 DCHECK((privateProperty.getter || privateProperty.setter) ^
554 (!!privateProperty.value));
555 if (privateProperty.value) {
556 Response response = privateProperty.value->buildRemoteObject(
557 context, WrapOptions({WrapMode::kIdOnly}), &remoteObject);
558 if (!response.IsSuccess()) return response;
559 response = bindRemoteObjectIfNeeded(
560 sessionId, context,
561 privateProperty.value->v8Value(context->GetIsolate()), groupName,
562 remoteObject.get());
563 if (!response.IsSuccess()) return response;
564 descriptor->setValue(std::move(remoteObject));
565 }
566
567 if (privateProperty.getter) {
568 Response response = privateProperty.getter->buildRemoteObject(
569 context, WrapOptions({WrapMode::kIdOnly}), &remoteObject);
570 if (!response.IsSuccess()) return response;
571 response = bindRemoteObjectIfNeeded(
572 sessionId, context,
573 privateProperty.getter->v8Value(context->GetIsolate()), groupName,
574 remoteObject.get());
575 if (!response.IsSuccess()) return response;
576 descriptor->setGet(std::move(remoteObject));
577 }
578
579 if (privateProperty.setter) {
580 Response response = privateProperty.setter->buildRemoteObject(
581 context, WrapOptions({WrapMode::kIdOnly}), &remoteObject);
582 if (!response.IsSuccess()) return response;
583 response = bindRemoteObjectIfNeeded(
584 sessionId, context,
585 privateProperty.setter->v8Value(context->GetIsolate()), groupName,
586 remoteObject.get());
587 if (!response.IsSuccess()) return response;
588 descriptor->setSet(std::move(remoteObject));
589 }
590
591 (*privateProperties)->emplace_back(std::move(descriptor));
592 }
593 return Response::Success();
594}
595
597 std::unique_ptr<RemoteObjectId> remoteId;
598 Response response = RemoteObjectId::parse(objectId, &remoteId);
599 if (response.IsSuccess()) unbindObject(remoteId->id());
600}
601
603 v8::Local<v8::Value> value, const String16& groupName,
604 const WrapOptions& wrapOptions,
605 std::unique_ptr<protocol::Runtime::RemoteObject>* result) {
606 return wrapObject(value, groupName, wrapOptions, v8::MaybeLocal<v8::Value>(),
608}
609
611 v8::Local<v8::Value> value, const String16& groupName,
612 const WrapOptions& wrapOptions,
613 v8::MaybeLocal<v8::Value> customPreviewConfig, int maxCustomPreviewDepth,
614 std::unique_ptr<protocol::Runtime::RemoteObject>* result) {
616 v8::Context::Scope contextScope(context);
617 std::unique_ptr<ValueMirror> mirror = ValueMirror::create(context, value);
618 if (!mirror) return Response::InternalError();
619 return wrapObjectMirror(*mirror, groupName, wrapOptions, customPreviewConfig,
620 maxCustomPreviewDepth, result);
621}
622
624 const ValueMirror& mirror, const String16& groupName,
625 const WrapOptions& wrapOptions,
626 v8::MaybeLocal<v8::Value> customPreviewConfig, int maxCustomPreviewDepth,
627 std::unique_ptr<protocol::Runtime::RemoteObject>* result) {
628 int customPreviewEnabled = m_customPreviewEnabled;
629 int sessionId = m_sessionId;
631 v8::Context::Scope contextScope(context);
632 Response response = mirror.buildRemoteObject(context, wrapOptions, result);
633 if (!response.IsSuccess()) return response;
634 v8::Local<v8::Value> value = mirror.v8Value(context->GetIsolate());
635 response = bindRemoteObjectIfNeeded(sessionId, context, value, groupName,
636 result->get());
637 if (!response.IsSuccess()) return response;
638 if (customPreviewEnabled && value->IsObject()) {
639 std::unique_ptr<protocol::Runtime::CustomPreview> customPreview;
640 generateCustomPreview(m_context->isolate(), sessionId, groupName,
641 value.As<v8::Object>(), customPreviewConfig,
642 maxCustomPreviewDepth, &customPreview);
643 if (customPreview) (*result)->setCustomPreview(std::move(customPreview));
644 }
645 if (wrapOptions.mode == WrapMode::kDeep) {
646 V8SerializationDuplicateTracker duplicateTracker{context};
647
648 std::unique_ptr<protocol::DictionaryValue> deepSerializedValueDict;
649 response = mirror.buildDeepSerializedValue(
650 context, wrapOptions.serializationOptions.maxDepth,
652 m_context->isolate()),
653 duplicateTracker, &deepSerializedValueDict);
654 if (!response.IsSuccess()) return response;
655
657 deepSerializedValueDict->getString("type", &type);
658
659 std::unique_ptr<protocol::Runtime::DeepSerializedValue>
660 deepSerializedValue = protocol::Runtime::DeepSerializedValue::create()
661 .setType(type)
662 .build();
663
664 protocol::Value* maybeValue = deepSerializedValueDict->get("value");
665 if (maybeValue != nullptr) {
666 deepSerializedValue->setValue(maybeValue->clone());
667 }
668
669 int weakLocalObjectReference;
670 if (deepSerializedValueDict->getInteger("weakLocalObjectReference",
671 &weakLocalObjectReference)) {
672 deepSerializedValue->setWeakLocalObjectReference(
673 weakLocalObjectReference);
674 }
675
676 if (!response.IsSuccess()) return response;
677 (*result)->setDeepSerializedValue(std::move(deepSerializedValue));
678 }
679
680 return Response::Success();
681}
682
683std::unique_ptr<protocol::Runtime::RemoteObject> InjectedScript::wrapTable(
685 using protocol::Array;
686 using protocol::Runtime::ObjectPreview;
687 using protocol::Runtime::PropertyPreview;
688 using protocol::Runtime::RemoteObject;
689
690 v8::Isolate* isolate = m_context->isolate();
691 v8::HandleScope handles(isolate);
693
694 std::unique_ptr<RemoteObject> remoteObject;
695 Response response = wrapObject(
696 table, "console", WrapOptions({WrapMode::kIdOnly}), &remoteObject);
697 if (!remoteObject || !response.IsSuccess()) return nullptr;
698
699 auto mirror = ValueMirror::create(context, table);
700 std::unique_ptr<ObjectPreview> preview;
701 int limit = 1000;
702 mirror->buildObjectPreview(context, true /* generatePreviewForTable */,
703 &limit, &limit, &preview);
704 if (!preview) return nullptr;
705
706 std::vector<String16> selectedColumns;
707 std::unordered_set<String16> columnSet;
708 v8::Local<v8::Array> v8Columns;
709 if (maybeColumns.ToLocal(&v8Columns)) {
710 for (uint32_t i = 0; i < v8Columns->Length(); ++i) {
712 if (v8Columns->Get(context, i).ToLocal(&column) && column->IsString()) {
713 String16 name = toProtocolString(isolate, column.As<v8::String>());
714 if (columnSet.find(name) == columnSet.end()) {
715 columnSet.insert(name);
716 selectedColumns.push_back(name);
717 }
718 }
719 }
720 }
721 if (!selectedColumns.empty()) {
722 for (const std::unique_ptr<PropertyPreview>& prop :
723 *preview->getProperties()) {
724 ObjectPreview* columnPreview = prop->getValuePreview(nullptr);
725 if (!columnPreview) continue;
726 // Use raw pointer here since the lifetime of each PropertyPreview is
727 // ensured by columnPreview. This saves an additional clone.
728 std::unordered_map<String16, PropertyPreview*> columnMap;
729 for (const std::unique_ptr<PropertyPreview>& property :
730 *columnPreview->getProperties()) {
731 if (columnSet.find(property->getName()) == columnSet.end()) continue;
732 columnMap[property->getName()] = property.get();
733 }
734 auto filtered = std::make_unique<Array<PropertyPreview>>();
735 for (const String16& column : selectedColumns) {
736 if (columnMap.find(column) == columnMap.end()) continue;
737 filtered->push_back(columnMap[column]->Clone());
738 }
739 columnPreview->setProperties(std::move(filtered));
740 }
741 }
742 remoteObject->setPreview(std::move(preview));
743 return remoteObject;
744}
745
748 const String16& objectGroup, std::unique_ptr<WrapOptions> wrapOptions,
749 bool replMode, bool throwOnSideEffect,
750 std::shared_ptr<EvaluateCallback> callback) {
752 // After stashing the shared_ptr in `m_evaluateCallback`, we reset `callback`.
753 // `ProtocolPromiseHandler:add` can take longer than the life time of this
754 // `InjectedScript` and we don't want `callback` to survive that.
755 std::weak_ptr<EvaluateCallback> weak_callback = callback;
756 callback.reset();
757 CHECK_EQ(weak_callback.use_count(), 1);
758
759 if (value.IsEmpty()) {
760 EvaluateCallback::sendFailure(weak_callback, this,
761 Response::InternalError());
762 return;
763 }
764
765 v8::MicrotasksScope microtasksScope(m_context->context(),
768 value.ToLocalChecked(), m_context->contextId(),
769 objectGroup, std::move(wrapOptions), replMode,
770 throwOnSideEffect, weak_callback);
771 // Do not add any code here! `this` might be invalid.
772 // `ProtocolPromiseHandler::add` calls into JS which could kill this
773 // `InjectedScript`.
774}
775
777 while (!m_evaluateCallbacks.empty()) {
779 *m_evaluateCallbacks.begin(), this,
780 Response::ServerError("Execution context was destroyed."));
781 }
782 CHECK(m_evaluateCallbacks.empty());
783}
784
786 std::shared_ptr<EvaluateCallback> callback) {
787 auto it = m_evaluateCallbacks.find(callback);
788 CHECK_NE(it, m_evaluateCallbacks.end());
789 m_evaluateCallbacks.erase(it);
790}
791
793 v8::Local<v8::Value>* outObject) const {
794 auto it = m_idToWrappedObject.find(objectId.id());
795 if (it == m_idToWrappedObject.end())
796 return Response::ServerError("Could not find object with given id");
797 *outObject = it->second.Get(m_context->isolate());
798 return Response::Success();
799}
800
802 if (objectId.id() <= 0) return String16();
803 auto it = m_idToObjectGroupName.find(objectId.id());
804 return it != m_idToObjectGroupName.end() ? it->second : String16();
805}
806
808 if (objectGroup == "console") m_lastEvaluationResult.Reset();
809 if (objectGroup.isEmpty()) return;
810 auto it = m_nameToObjectGroup.find(objectGroup);
811 if (it == m_nameToObjectGroup.end()) return;
812 for (int id : it->second) unbindObject(id);
813 m_nameToObjectGroup.erase(it);
814}
815
819
825
830
832 protocol::Runtime::CallArgument* callArgument,
834 if (callArgument->hasObjectId()) {
835 std::unique_ptr<RemoteObjectId> remoteObjectId;
836 Response response =
837 RemoteObjectId::parse(callArgument->getObjectId(""), &remoteObjectId);
838 if (!response.IsSuccess()) return response;
839 if (remoteObjectId->contextId() != m_context->contextId() ||
840 remoteObjectId->isolateId() != m_context->inspector()->isolateId()) {
841 return Response::ServerError(
842 "Argument should belong to the same JavaScript world as target "
843 "object");
844 }
845 return findObject(*remoteObjectId, result);
846 }
847 if (callArgument->hasValue() || callArgument->hasUnserializableValue()) {
849 if (callArgument->hasValue()) {
850 std::vector<uint8_t> json;
851 v8_crdtp::json::ConvertCBORToJSON(
852 v8_crdtp::SpanFrom(callArgument->getValue(nullptr)->Serialize()),
853 &json);
854 value =
855 "(" +
856 String16(reinterpret_cast<const char*>(json.data()), json.size()) +
857 ")";
858 } else {
859 String16 unserializableValue = callArgument->getUnserializableValue("");
860 // Protect against potential identifier resolution for NaN and Infinity.
861 if (isResolvableNumberLike(unserializableValue))
862 value = "Number(\"" + unserializableValue + "\")";
863 else
864 value = unserializableValue;
865 }
866 if (!m_context->inspector()
869 .ToLocal(result)) {
870 return Response::ServerError(
871 "Couldn't parse value object in call argument");
872 }
873 return Response::Success();
874 }
876 return Response::Success();
877}
878
880 v8::Local<v8::Value> exception,
881 protocol::Runtime::ExceptionDetails* exceptionDetails,
882 const String16& objectGroup) {
883 if (exception.IsEmpty()) return Response::Success();
884 std::unique_ptr<protocol::Runtime::RemoteObject> wrapped;
885 Response response =
886 wrapObject(exception, objectGroup,
887 exception->IsNativeError() ? WrapOptions({WrapMode::kIdOnly})
889 &wrapped);
890 if (!response.IsSuccess()) return response;
891 exceptionDetails->setException(std::move(wrapped));
892 return Response::Success();
893}
894
896 const v8::TryCatch& tryCatch, const String16& objectGroup,
897 std::unique_ptr<protocol::Runtime::ExceptionDetails>* result) {
898 if (!tryCatch.HasCaught()) return Response::InternalError();
899 v8::Local<v8::Message> message = tryCatch.Message();
900 v8::Local<v8::Value> exception = tryCatch.Exception();
901 return createExceptionDetails(message, exception, objectGroup, result);
902}
903
906 const String16& objectGroup,
907 std::unique_ptr<protocol::Runtime::ExceptionDetails>* result) {
908 String16 messageText =
909 message.IsEmpty()
910 ? String16()
911 : toProtocolString(m_context->isolate(), message->Get());
912 std::unique_ptr<protocol::Runtime::ExceptionDetails> exceptionDetails =
913 protocol::Runtime::ExceptionDetails::create()
914 .setExceptionId(m_context->inspector()->nextExceptionId())
915 .setText(exception.IsEmpty() ? messageText : String16("Uncaught"))
916 .setLineNumber(
917 message.IsEmpty()
918 ? 0
919 : message->GetLineNumber(m_context->context()).FromMaybe(1) -
920 1)
921 .setColumnNumber(
922 message.IsEmpty()
923 ? 0
924 : message->GetStartColumn(m_context->context()).FromMaybe(0))
925 .build();
926 if (!message.IsEmpty()) {
927 exceptionDetails->setScriptId(
928 String16::fromInteger(message->GetScriptOrigin().ScriptId()));
929 v8::Local<v8::StackTrace> stackTrace = message->GetStackTrace();
930 if (!stackTrace.IsEmpty() && stackTrace->GetFrameCount() > 0) {
931 std::unique_ptr<V8StackTraceImpl> v8StackTrace =
932 m_context->inspector()->debugger()->createStackTrace(stackTrace);
933 if (v8StackTrace) {
934 exceptionDetails->setStackTrace(v8StackTrace->buildInspectorObjectImpl(
936 }
937 }
938 }
939 Response response =
940 addExceptionToDetails(exception, exceptionDetails.get(), objectGroup);
941 if (!response.IsSuccess()) return response;
942 *result = std::move(exceptionDetails);
943 return Response::Success();
944}
945
947 v8::MaybeLocal<v8::Value> maybeResultValue, const v8::TryCatch& tryCatch,
948 const String16& objectGroup, const WrapOptions& wrapOptions,
949 bool throwOnSideEffect,
950 std::unique_ptr<protocol::Runtime::RemoteObject>* result,
951 std::unique_ptr<protocol::Runtime::ExceptionDetails>* exceptionDetails) {
952 v8::Local<v8::Value> resultValue;
953 if (!tryCatch.HasCaught()) {
954 if (!maybeResultValue.ToLocal(&resultValue)) {
955 if (!tryCatch.CanContinue()) {
956 return Response::ServerError("Execution was terminated");
957 }
958 return Response::InternalError();
959 }
960 Response response =
961 wrapObject(resultValue, objectGroup, wrapOptions, result);
962 if (!response.IsSuccess()) return response;
963 if (objectGroup == "console") {
966 }
967 } else {
968 if (tryCatch.HasTerminated() || !tryCatch.CanContinue()) {
969 return Response::ServerError("Execution was terminated");
970 }
971 v8::Local<v8::Value> exception = tryCatch.Exception();
972 if (!throwOnSideEffect) {
974 m_context->context(), tryCatch.Message(), exception);
975 }
976 Response response = wrapObject(exception, objectGroup,
977 exception->IsNativeError()
980 result);
981 if (!response.IsSuccess()) return response;
982 // We send exception in result for compatibility reasons, even though it's
983 // accessible through exceptionDetails.exception.
984 response = createExceptionDetails(tryCatch, objectGroup, exceptionDetails);
985 if (!response.IsSuccess()) return response;
986 }
987 return Response::Success();
988}
989
1001
1003 : m_inspector(session->inspector()),
1004 m_injectedScript(nullptr),
1005 m_handleScope(m_inspector->isolate()),
1006 m_tryCatch(m_inspector->isolate()),
1007 m_ignoreExceptionsAndMuteConsole(false),
1008 m_previousPauseOnExceptionsState(v8::debug::NoBreakOnException),
1009 m_userGesture(false),
1010 m_allowEval(false),
1011 m_contextGroupId(session->contextGroupId()),
1012 m_sessionId(session->sessionId()) {}
1013
1015 cleanup();
1016 V8InspectorSessionImpl* session =
1017 m_inspector->sessionById(m_contextGroupId, m_sessionId);
1018 if (!session) return Response::InternalError();
1019 Response response = findInjectedScript(session);
1020 if (!response.IsSuccess()) return response;
1021 m_context = m_injectedScript->context()->context();
1022 m_context->Enter();
1023 if (m_allowEval) m_context->AllowCodeGenerationFromStrings(true);
1024 return Response::Success();
1025}
1026
1028 DCHECK(m_injectedScript && !m_context.IsEmpty() &&
1029 !m_commandLineAPIScope.get());
1030 V8InspectorSessionImpl* session =
1031 m_inspector->sessionById(m_contextGroupId, m_sessionId);
1032 if (session->clientTrustLevel() != V8Inspector::kFullyTrusted) {
1033 return;
1034 }
1035 m_commandLineAPIScope.reset(new V8Console::CommandLineAPIScope(
1036 m_context, m_injectedScript->commandLineAPI(), m_context->Global()));
1037}
1038
1040 DCHECK(!m_ignoreExceptionsAndMuteConsole);
1041 m_ignoreExceptionsAndMuteConsole = true;
1042 m_inspector->client()->muteMetrics(m_contextGroupId);
1043 m_inspector->muteExceptions(m_contextGroupId);
1044 m_previousPauseOnExceptionsState =
1045 setPauseOnExceptionsState(v8::debug::NoBreakOnException);
1046}
1047
1050 if (!m_inspector->debugger()->enabled()) return newState;
1051 v8::debug::ExceptionBreakState presentState =
1052 m_inspector->debugger()->getPauseOnExceptionsState();
1053 if (presentState != newState)
1054 m_inspector->debugger()->setPauseOnExceptionsState(newState);
1055 return presentState;
1056}
1057
1059 DCHECK(!m_userGesture);
1060 m_userGesture = true;
1061 m_inspector->client()->beginUserGesture();
1062}
1063
1065 DCHECK(!m_allowEval);
1066 if (m_context->IsCodeGenerationFromStringsAllowed()) return;
1067 m_allowEval = true;
1068 m_context->AllowCodeGenerationFromStrings(true);
1069}
1070
1074
1076 m_commandLineAPIScope.reset();
1077 if (!m_context.IsEmpty()) {
1078 if (m_allowEval) m_context->AllowCodeGenerationFromStrings(false);
1079 m_context->Exit();
1080 m_context.Clear();
1081 }
1082}
1083
1085 if (m_ignoreExceptionsAndMuteConsole) {
1086 setPauseOnExceptionsState(m_previousPauseOnExceptionsState);
1087 m_inspector->client()->unmuteMetrics(m_contextGroupId);
1088 m_inspector->unmuteExceptions(m_contextGroupId);
1089 }
1090 if (m_userGesture) m_inspector->client()->endUserGesture();
1091 cleanup();
1092}
1093
1095 int executionContextId)
1096 : InjectedScript::Scope(session),
1097 m_executionContextId(executionContextId) {}
1098
1100
1102 V8InspectorSessionImpl* session) {
1103 return session->findInjectedScript(m_executionContextId, m_injectedScript);
1104}
1105
1107 const String16& remoteObjectId)
1108 : InjectedScript::Scope(session), m_remoteObjectId(remoteObjectId) {}
1109
1111
1113 V8InspectorSessionImpl* session) {
1114 std::unique_ptr<RemoteObjectId> remoteId;
1115 Response response = RemoteObjectId::parse(m_remoteObjectId, &remoteId);
1116 if (!response.IsSuccess()) return response;
1117 InjectedScript* injectedScript = nullptr;
1118 response = session->findInjectedScript(remoteId.get(), injectedScript);
1119 if (!response.IsSuccess()) return response;
1120 m_objectGroupName = injectedScript->objectGroupName(*remoteId);
1121 response = injectedScript->findObject(*remoteId, &m_object);
1122 if (!response.IsSuccess()) return response;
1123 m_injectedScript = injectedScript;
1124 return Response::Success();
1125}
1126
1128 const String16& remoteObjectId)
1129 : InjectedScript::Scope(session), m_remoteCallFrameId(remoteObjectId) {}
1130
1132
1134 V8InspectorSessionImpl* session) {
1135 std::unique_ptr<RemoteCallFrameId> remoteId;
1136 Response response = RemoteCallFrameId::parse(m_remoteCallFrameId, &remoteId);
1137 if (!response.IsSuccess()) return response;
1138 m_frameOrdinal = static_cast<size_t>(remoteId->frameOrdinal());
1139 return session->findInjectedScript(remoteId.get(), m_injectedScript);
1140}
1141
1143 const String16& groupName) {
1145 int id = m_lastBoundObjectId++;
1146 m_idToWrappedObject[id].Reset(m_context->isolate(), value);
1147 m_idToWrappedObject[id].AnnotateStrongRetainer(kGlobalHandleLabel);
1148 if (!groupName.isEmpty() && id > 0) {
1149 m_idToObjectGroupName[id] = groupName;
1150 m_nameToObjectGroup[groupName].push_back(id);
1151 }
1153 m_context->contextId(), id);
1154}
1155
1156// static
1158 int sessionId, v8::Local<v8::Context> context, v8::Local<v8::Value> value,
1159 const String16& groupName, protocol::Runtime::RemoteObject* remoteObject) {
1160 if (!remoteObject) return Response::Success();
1161 if (remoteObject->hasValue()) return Response::Success();
1162 if (remoteObject->hasUnserializableValue()) return Response::Success();
1163 if (remoteObject->getType() != RemoteObject::TypeEnum::Undefined) {
1164 v8::Isolate* isolate = context->GetIsolate();
1165 V8InspectorImpl* inspector =
1166 static_cast<V8InspectorImpl*>(v8::debug::GetInspector(isolate));
1167 InspectedContext* inspectedContext =
1168 inspector->getContext(InspectedContext::contextId(context));
1169 InjectedScript* injectedScript =
1170 inspectedContext ? inspectedContext->getInjectedScript(sessionId)
1171 : nullptr;
1172 if (!injectedScript) {
1173 return Response::ServerError("Cannot find context with specified id");
1174 }
1175 remoteObject->setObjectId(injectedScript->bindObject(value, groupName));
1176 }
1177 return Response::Success();
1178}
1179
1181 m_idToWrappedObject.erase(id);
1182 m_idToObjectGroupName.erase(id);
1183}
1184
1186
1188
1189template <typename... Args>
1191 Id id = m_lastUsedId++;
1194 std::forward<Args>(args)...);
1195 m_promiseHandlers.emplace(id, handler);
1196 return id;
1197}
1198
1200 auto iter = m_promiseHandlers.find(id);
1201 CHECK_NE(iter, m_promiseHandlers.end());
1202 InjectedScript::ProtocolPromiseHandler* handler = iter->second.get();
1203
1204 switch (reason) {
1205 case DiscardReason::kPromiseCollected:
1206 sendFailure(handler, Response::ServerError("Promise was collected"));
1207 break;
1208 case DiscardReason::kTearDown:
1209 sendFailure(handler, Response::ServerError(
1210 "Tearing down inspector/session/context"));
1211 break;
1212 case DiscardReason::kFulfilled:
1213 // Do nothing.
1214 break;
1215 }
1216
1217 m_promiseHandlers.erase(id);
1218}
1219
1221 Id id) const {
1222 auto iter = m_promiseHandlers.find(id);
1223 if (iter == m_promiseHandlers.end()) return nullptr;
1224
1225 return iter->second.get();
1226}
1227
1230 const protocol::DispatchResponse& response) const {
1231 V8InspectorImpl* inspector = handler->m_inspector;
1232 V8InspectorSessionImpl* session =
1233 inspector->sessionById(handler->m_contextGroupId, handler->m_sessionId);
1234 if (!session) return;
1235 InjectedScript::ContextScope scope(session, handler->m_executionContextId);
1236 Response res = scope.initialize();
1237 if (!res.IsSuccess()) return;
1238 EvaluateCallback::sendFailure(handler->m_callback, scope.injectedScript(),
1239 response);
1240}
1241
1243 while (!m_promiseHandlers.empty()) {
1244 discard(m_promiseHandlers.begin()->first, DiscardReason::kTearDown);
1245 }
1246 CHECK(m_promiseHandlers.empty());
1247}
1248
1249} // namespace v8_inspector
static Local< StackTrace > GetStackTrace(Local< Value > exception)
Definition api.cc:11152
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_INLINE Local< S > As() const
V8_WARN_UNUSED_RESULT V8_INLINE bool ToLocal(Local< S > *out) const
static Local< Number > New(Isolate *isolate, double value)
Definition api.cc:9557
V8_INLINE void AnnotateStrongRetainer(const char *label)
V8_INLINE Local< T > Get(Isolate *isolate) const
V8_INLINE P * ClearWeak()
V8_INLINE void SetWeak(P *parameter, typename WeakCallbackInfo< P >::Callback callback, WeakCallbackType type)
static V8_WARN_UNUSED_RESULT MaybeLocal< Resolver > New(Local< Context > context)
Definition api.cc:8640
static V8_WARN_UNUSED_RESULT MaybeLocal< String > NewFromOneByte(Isolate *isolate, const uint8_t *data, NewStringType type=NewStringType::kNormal, int length=-1)
Definition api.cc:7599
void SetVerbose(bool value)
Definition api.cc:2856
Local< v8::Message > Message() const
Definition api.cc:2829
bool HasTerminated() const
Definition api.cc:2787
Local< Value > Exception() const
Definition api.cc:2798
bool HasCaught() const
Definition api.cc:2781
bool CanContinue() const
Definition api.cc:2785
static void sendFailure(std::weak_ptr< EvaluateCallback > callback, InjectedScript *injectedScript, const protocol::DispatchResponse &response)
static void sendSuccess(std::weak_ptr< EvaluateCallback > callback, InjectedScript *injectedScript, std::unique_ptr< protocol::Runtime::RemoteObject > result, std::unique_ptr< protocol::Runtime::ExceptionDetails > exceptionDetails)
Response findInjectedScript(V8InspectorSessionImpl *) override
CallFrameScope(V8InspectorSessionImpl *, const String16 &remoteCallFrameId)
Response findInjectedScript(V8InspectorSessionImpl *) override
ContextScope(V8InspectorSessionImpl *, int executionContextId)
ObjectScope(V8InspectorSessionImpl *, const String16 &remoteObjectId)
Response findInjectedScript(V8InspectorSessionImpl *) override
static void thenCallback(const v8::FunctionCallbackInfo< v8::Value > &info)
static v8::Local< v8::String > GetDotReplResultString(v8::Isolate *isolate)
static void cleanup(const v8::WeakCallbackInfo< PromiseHandlerTracker::Id > &data)
static void add(V8InspectorSessionImpl *session, v8::Local< v8::Context > context, v8::Local< v8::Value > value, int executionContextId, const String16 &objectGroup, std::unique_ptr< WrapOptions > wrapOptions, bool replMode, bool throwOnSideEffect, std::weak_ptr< EvaluateCallback > callback)
void catchCallback(v8::Local< v8::Value > result)
static void catchCallback(const v8::FunctionCallbackInfo< v8::Value > &info)
ProtocolPromiseHandler(PromiseHandlerTracker::Id id, V8InspectorSessionImpl *session, int executionContextId, const String16 &objectGroup, std::unique_ptr< WrapOptions > wrapOptions, bool replMode, bool throwOnSideEffect, std::weak_ptr< EvaluateCallback > callback, v8::Local< v8::Promise > evaluationResult)
v8::Local< v8::Context > context() const
InjectedScript * injectedScript() const
v8::debug::ExceptionBreakState setPauseOnExceptionsState(v8::debug::ExceptionBreakState)
v8::Local< v8::Value > lastEvaluationResult() const
std::unordered_map< String16, std::vector< int > > m_nameToObjectGroup
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 > *)
static Response bindRemoteObjectIfNeeded(int sessionId, v8::Local< v8::Context > context, v8::Local< v8::Value >, const String16 &groupName, protocol::Runtime::RemoteObject *remoteObject)
void setLastEvaluationResult(v8::Local< v8::Value > result)
v8::Global< v8::Object > m_commandLineAPI
void releaseObjectGroup(const String16 &)
Response resolveCallArgument(protocol::Runtime::CallArgument *, v8::Local< v8::Value > *result)
std::unordered_map< int, v8::Global< v8::Value > > m_idToWrappedObject
InjectedScript(InspectedContext *, int sessionId)
String16 bindObject(v8::Local< v8::Value >, const String16 &groupName)
v8::Local< v8::Object > commandLineAPI()
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 wrapEvaluateResult(v8::MaybeLocal< v8::Value > maybeResultValue, const v8::TryCatch &, const String16 &objectGroup, const WrapOptions &wrapOptions, bool throwOnSideEffect, std::unique_ptr< protocol::Runtime::RemoteObject > *result, std::unique_ptr< protocol::Runtime::ExceptionDetails > *)
Response addExceptionToDetails(v8::Local< v8::Value > exception, protocol::Runtime::ExceptionDetails *exceptionDetails, const String16 &objectGroup)
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 wrapObjectMirror(const ValueMirror &mirror, const String16 &groupName, const WrapOptions &wrapOptions, v8::MaybeLocal< v8::Value > customPreviewConfig, int maxCustomPreviewDepth, std::unique_ptr< protocol::Runtime::RemoteObject > *result)
Response findObject(const RemoteObjectId &, v8::Local< v8::Value > *) const
v8::Global< v8::Value > m_lastEvaluationResult
Response createExceptionDetails(const v8::TryCatch &, const String16 &groupName, std::unique_ptr< protocol::Runtime::ExceptionDetails > *result)
std::unique_ptr< protocol::Runtime::RemoteObject > wrapTable(v8::Local< v8::Object > table, v8::MaybeLocal< v8::Array > columns)
String16 objectGroupName(const RemoteObjectId &) const
std::unordered_set< std::shared_ptr< EvaluateCallback > > m_evaluateCallbacks
std::unordered_map< int, String16 > m_idToObjectGroupName
void deleteEvaluateCallback(std::shared_ptr< EvaluateCallback > callback)
v8::Local< v8::Context > context() const
static int contextId(v8::Local< v8::Context >)
InjectedScript * getInjectedScript(int sessionId)
V8InspectorImpl * inspector() const
InjectedScript::ProtocolPromiseHandler * get(Id id) const
void discard(Id id, DiscardReason reason)
void sendFailure(InjectedScript::ProtocolPromiseHandler *handler, const protocol::DispatchResponse &response) const
static Response parse(const String16 &, std::unique_ptr< RemoteCallFrameId > *)
static Response parse(const String16 &, std::unique_ptr< RemoteObjectId > *)
static String16 serialize(uint64_t isolateId, int injectedScriptId, int id)
static String16 fromInteger(int)
Definition string-16.cc:71
bool isEmpty() const
Definition string-16.h:59
v8::Local< v8::Object > createCommandLineAPI(v8::Local< v8::Context > context, int sessionId)
std::unique_ptr< V8StackTraceImpl > createStackTrace(v8::Local< v8::StackTrace >)
std::unique_ptr< V8StackTraceImpl > captureStackTrace(bool fullStack)
virtual void dispatchError(v8::Local< v8::Context >, v8::Local< v8::Message >, v8::Local< v8::Value >)
v8::MaybeLocal< v8::Value > compileAndRunInternalScript(v8::Local< v8::Context >, v8::Local< v8::String >)
v8::Isolate * isolate() const
InspectedContext * getContext(int groupId, int contextId) const
V8_EXPORT_PRIVATE V8Console * console()
PromiseHandlerTracker & promiseHandlerTracker()
V8InspectorSessionImpl * sessionById(int contextGroupId, int sessionId)
V8Inspector::ClientTrustLevel clientTrustLevel()
Response findInjectedScript(int contextId, InjectedScript *&)
static std::unique_ptr< ValueMirror > create(v8::Local< v8::Context > context, v8::Local< v8::Value > value)
virtual v8::Local< v8::Value > v8Value(v8::Isolate *isolate) const =0
virtual Response buildDeepSerializedValue(v8::Local< v8::Context > context, int maxDepth, v8::Local< v8::Object > additionalParameters, V8SerializationDuplicateTracker &duplicateTracker, std::unique_ptr< protocol::DictionaryValue > *result) const =0
static bool getProperties(v8::Local< v8::Context > context, v8::Local< v8::Object > object, bool ownProperties, bool accessorPropertiesOnly, bool nonIndexedPropertiesOnly, PropertyAccumulator *accumulator)
virtual protocol::Response buildRemoteObject(v8::Local< v8::Context > context, const WrapOptions &wrapOptions, std::unique_ptr< protocol::Runtime::RemoteObject > *result) const =0
static void getInternalProperties(v8::Local< v8::Context > context, v8::Local< v8::Object > object, std::vector< InternalPropertyMirror > *mirrors)
static std::vector< PrivatePropertyMirror > getPrivateProperties(v8::Local< v8::Context > context, v8::Local< v8::Object > object, bool accessorPropertiesOnly)
base::Vector< const DirectHandle< Object > > args
Definition execution.cc:74
std::vector< PropertyMirror > * m_mirrors
TNode< Object > callback
ZoneVector< RpoNumber > & result
ZoneStack< RpoNumber > & stack
STL namespace.
MaybeLocal< Message > GetMessageFromPromise(Local< Promise > p)
v8_inspector::V8Inspector * GetInspector(Isolate *isolate)
void generateCustomPreview(v8::Isolate *isolate, int sessionId, const String16 &groupName, v8::Local< v8::Object > object, v8::MaybeLocal< v8::Value > maybeConfig, int maxDepth, std::unique_ptr< CustomPreview > *preview)
String16 toProtocolString(v8::Isolate *isolate, v8::Local< v8::String > value)
const int kMaxCustomPreviewDepth
v8::Local< v8::String > toV8String(v8::Isolate *isolate, const String16 &string)
V8_INLINE Local< Primitive > Undefined(Isolate *isolate)
#define CHECK(condition)
Definition logging.h:124
#define CHECK_NE(lhs, rhs)
#define CHECK_EQ(lhs, rhs)
#define DCHECK(condition)
Definition logging.h:482
WrapSerializationOptions serializationOptions
Definition v8-debugger.h:44
v8::Global< v8::Object > additionalParameters
Definition v8-debugger.h:39
v8::TryCatch m_tryCatch
v8::Local< v8::Context > m_context
V8InspectorImpl * m_inspector
std::unique_ptr< ValueMirror > value
wasm::ValueType type