LCOV - code coverage report
Current view: top level - src/inspector - injected-script.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 417 442 94.3 %
Date: 2019-04-19 Functions: 49 54 90.7 %

          Line data    Source code
       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             : 
      31             : #include "src/inspector/injected-script.h"
      32             : 
      33             : #include <cmath>
      34             : #include <unordered_set>
      35             : 
      36             : #include "src/inspector/custom-preview.h"
      37             : #include "src/inspector/inspected-context.h"
      38             : #include "src/inspector/protocol/Protocol.h"
      39             : #include "src/inspector/remote-object-id.h"
      40             : #include "src/inspector/string-util.h"
      41             : #include "src/inspector/v8-console.h"
      42             : #include "src/inspector/v8-inspector-impl.h"
      43             : #include "src/inspector/v8-inspector-session-impl.h"
      44             : #include "src/inspector/v8-stack-trace-impl.h"
      45             : #include "src/inspector/v8-value-utils.h"
      46             : #include "src/inspector/value-mirror.h"
      47             : 
      48             : #include "include/v8-inspector.h"
      49             : 
      50             : namespace v8_inspector {
      51             : 
      52             : namespace {
      53             : static const char kGlobalHandleLabel[] = "DevTools console";
      54          50 : static bool isResolvableNumberLike(String16 query) {
      55         320 :   return query == "Infinity" || query == "-Infinity" || query == "NaN";
      56             : }
      57             : }  // namespace
      58             : 
      59             : using protocol::Array;
      60             : using protocol::Maybe;
      61             : using protocol::Runtime::InternalPropertyDescriptor;
      62             : using protocol::Runtime::PrivatePropertyDescriptor;
      63             : using protocol::Runtime::PropertyDescriptor;
      64             : using protocol::Runtime::RemoteObject;
      65             : 
      66        1300 : class InjectedScript::ProtocolPromiseHandler {
      67             :  public:
      68         650 :   static bool add(V8InspectorSessionImpl* session,
      69             :                   v8::Local<v8::Context> context, v8::Local<v8::Value> value,
      70             :                   int executionContextId, const String16& objectGroup,
      71             :                   WrapMode wrapMode, EvaluateCallback* callback) {
      72             :     v8::Local<v8::Promise::Resolver> resolver;
      73        1300 :     if (!v8::Promise::Resolver::New(context).ToLocal(&resolver)) {
      74           0 :       callback->sendFailure(Response::InternalError());
      75           0 :       return false;
      76             :     }
      77        1300 :     if (!resolver->Resolve(context, value).FromMaybe(false)) {
      78           0 :       callback->sendFailure(Response::InternalError());
      79           0 :       return false;
      80             :     }
      81             : 
      82         650 :     v8::Local<v8::Promise> promise = resolver->GetPromise();
      83             :     V8InspectorImpl* inspector = session->inspector();
      84             :     ProtocolPromiseHandler* handler = new ProtocolPromiseHandler(
      85         650 :         session, executionContextId, objectGroup, wrapMode, callback);
      86             :     v8::Local<v8::Value> wrapper = handler->m_wrapper.Get(inspector->isolate());
      87             :     v8::Local<v8::Function> thenCallbackFunction =
      88         650 :         v8::Function::New(context, thenCallback, wrapper, 0,
      89             :                           v8::ConstructorBehavior::kThrow)
      90         650 :             .ToLocalChecked();
      91        1300 :     if (promise->Then(context, thenCallbackFunction).IsEmpty()) {
      92           0 :       callback->sendFailure(Response::InternalError());
      93           0 :       return false;
      94             :     }
      95             :     v8::Local<v8::Function> catchCallbackFunction =
      96         650 :         v8::Function::New(context, catchCallback, wrapper, 0,
      97             :                           v8::ConstructorBehavior::kThrow)
      98         650 :             .ToLocalChecked();
      99        1300 :     if (promise->Catch(context, catchCallbackFunction).IsEmpty()) {
     100           0 :       callback->sendFailure(Response::InternalError());
     101           0 :       return false;
     102             :     }
     103             :     return true;
     104             :   }
     105             : 
     106             :  private:
     107         595 :   static void thenCallback(const v8::FunctionCallbackInfo<v8::Value>& info) {
     108             :     ProtocolPromiseHandler* handler = static_cast<ProtocolPromiseHandler*>(
     109         595 :         info.Data().As<v8::External>()->Value());
     110             :     DCHECK(handler);
     111             :     v8::Local<v8::Value> value =
     112             :         info.Length() > 0
     113             :             ? info[0]
     114        1190 :             : v8::Local<v8::Value>::Cast(v8::Undefined(info.GetIsolate()));
     115         595 :     handler->thenCallback(value);
     116         595 :     delete handler;
     117         595 :   }
     118             : 
     119          45 :   static void catchCallback(const v8::FunctionCallbackInfo<v8::Value>& info) {
     120             :     ProtocolPromiseHandler* handler = static_cast<ProtocolPromiseHandler*>(
     121          45 :         info.Data().As<v8::External>()->Value());
     122             :     DCHECK(handler);
     123             :     v8::Local<v8::Value> value =
     124             :         info.Length() > 0
     125             :             ? info[0]
     126          90 :             : v8::Local<v8::Value>::Cast(v8::Undefined(info.GetIsolate()));
     127          45 :     handler->catchCallback(value);
     128          45 :     delete handler;
     129          45 :   }
     130             : 
     131         650 :   ProtocolPromiseHandler(V8InspectorSessionImpl* session,
     132             :                          int executionContextId, const String16& objectGroup,
     133             :                          WrapMode wrapMode, EvaluateCallback* callback)
     134             :       : m_inspector(session->inspector()),
     135             :         m_sessionId(session->sessionId()),
     136             :         m_contextGroupId(session->contextGroupId()),
     137             :         m_executionContextId(executionContextId),
     138             :         m_objectGroup(objectGroup),
     139             :         m_wrapMode(wrapMode),
     140             :         m_callback(std::move(callback)),
     141         650 :         m_wrapper(m_inspector->isolate(),
     142        1300 :                   v8::External::New(m_inspector->isolate(), this)) {
     143             :     m_wrapper.SetWeak(this, cleanup, v8::WeakCallbackType::kParameter);
     144         650 :   }
     145             : 
     146          20 :   static void cleanup(
     147             :       const v8::WeakCallbackInfo<ProtocolPromiseHandler>& data) {
     148          20 :     if (!data.GetParameter()->m_wrapper.IsEmpty()) {
     149             :       data.GetParameter()->m_wrapper.Reset();
     150             :       data.SetSecondPassCallback(cleanup);
     151             :     } else {
     152          10 :       data.GetParameter()->sendPromiseCollected();
     153          10 :       delete data.GetParameter();
     154             :     }
     155          20 :   }
     156             : 
     157         595 :   void thenCallback(v8::Local<v8::Value> result) {
     158             :     V8InspectorSessionImpl* session =
     159         595 :         m_inspector->sessionById(m_contextGroupId, m_sessionId);
     160         600 :     if (!session) return;
     161         595 :     InjectedScript::ContextScope scope(session, m_executionContextId);
     162         595 :     Response response = scope.initialize();
     163         595 :     if (!response.isSuccess()) return;
     164        1190 :     if (m_objectGroup == "console") {
     165           5 :       scope.injectedScript()->setLastEvaluationResult(result);
     166             :     }
     167             :     std::unique_ptr<EvaluateCallback> callback =
     168         595 :         scope.injectedScript()->takeEvaluateCallback(m_callback);
     169         595 :     if (!callback) return;
     170         595 :     std::unique_ptr<protocol::Runtime::RemoteObject> wrappedValue;
     171        1190 :     response = scope.injectedScript()->wrapObject(result, m_objectGroup,
     172             :                                                   m_wrapMode, &wrappedValue);
     173         595 :     if (!response.isSuccess()) {
     174           5 :       callback->sendFailure(response);
     175             :       return;
     176             :     }
     177        1180 :     callback->sendSuccess(std::move(wrappedValue),
     178        1180 :                           Maybe<protocol::Runtime::ExceptionDetails>());
     179             :   }
     180             : 
     181          45 :   void catchCallback(v8::Local<v8::Value> result) {
     182             :     V8InspectorSessionImpl* session =
     183          45 :         m_inspector->sessionById(m_contextGroupId, m_sessionId);
     184          45 :     if (!session) return;
     185          45 :     InjectedScript::ContextScope scope(session, m_executionContextId);
     186          45 :     Response response = scope.initialize();
     187          45 :     if (!response.isSuccess()) return;
     188             :     std::unique_ptr<EvaluateCallback> callback =
     189          45 :         scope.injectedScript()->takeEvaluateCallback(m_callback);
     190          45 :     if (!callback) return;
     191          45 :     std::unique_ptr<protocol::Runtime::RemoteObject> wrappedValue;
     192          90 :     response = scope.injectedScript()->wrapObject(result, m_objectGroup,
     193             :                                                   m_wrapMode, &wrappedValue);
     194          45 :     if (!response.isSuccess()) {
     195           0 :       callback->sendFailure(response);
     196             :       return;
     197             :     }
     198             :     String16 message;
     199             :     std::unique_ptr<V8StackTraceImpl> stack;
     200             :     v8::Isolate* isolate = session->inspector()->isolate();
     201          45 :     if (result->IsNativeError()) {
     202          45 :       message = " " + toProtocolString(
     203             :                           isolate,
     204          15 :                           result->ToDetailString(isolate->GetCurrentContext())
     205             :                               .ToLocalChecked());
     206             :       v8::Local<v8::StackTrace> stackTrace = v8::debug::GetDetailedStackTrace(
     207          15 :           isolate, v8::Local<v8::Object>::Cast(result));
     208          15 :       if (!stackTrace.IsEmpty()) {
     209          30 :         stack = m_inspector->debugger()->createStackTrace(stackTrace);
     210             :       }
     211             :     }
     212          45 :     if (!stack) {
     213         105 :       stack = m_inspector->debugger()->captureStackTrace(true);
     214             :     }
     215             :     std::unique_ptr<protocol::Runtime::ExceptionDetails> exceptionDetails =
     216          45 :         protocol::Runtime::ExceptionDetails::create()
     217          90 :             .setExceptionId(m_inspector->nextExceptionId())
     218          90 :             .setText("Uncaught (in promise)" + message)
     219          10 :             .setLineNumber(stack && !stack->isEmpty() ? stack->topLineNumber()
     220          55 :                                                       : 0)
     221             :             .setColumnNumber(
     222          45 :                 stack && !stack->isEmpty() ? stack->topColumnNumber() : 0)
     223          90 :             .setException(wrappedValue->clone())
     224             :             .build();
     225          45 :     if (stack)
     226             :       exceptionDetails->setStackTrace(
     227          30 :           stack->buildInspectorObjectImpl(m_inspector->debugger()));
     228          45 :     if (stack && !stack->isEmpty())
     229          20 :       exceptionDetails->setScriptId(toString16(stack->topScriptId()));
     230         180 :     callback->sendSuccess(std::move(wrappedValue), std::move(exceptionDetails));
     231             :   }
     232             : 
     233          10 :   void sendPromiseCollected() {
     234             :     V8InspectorSessionImpl* session =
     235          10 :         m_inspector->sessionById(m_contextGroupId, m_sessionId);
     236          15 :     if (!session) return;
     237          10 :     InjectedScript::ContextScope scope(session, m_executionContextId);
     238          10 :     Response response = scope.initialize();
     239          10 :     if (!response.isSuccess()) return;
     240             :     std::unique_ptr<EvaluateCallback> callback =
     241           5 :         scope.injectedScript()->takeEvaluateCallback(m_callback);
     242           5 :     if (!callback) return;
     243          15 :     callback->sendFailure(Response::Error("Promise was collected"));
     244             :   }
     245             : 
     246             :   V8InspectorImpl* m_inspector;
     247             :   int m_sessionId;
     248             :   int m_contextGroupId;
     249             :   int m_executionContextId;
     250             :   String16 m_objectGroup;
     251             :   WrapMode m_wrapMode;
     252             :   EvaluateCallback* m_callback;
     253             :   v8::Global<v8::External> m_wrapper;
     254             : };
     255             : 
     256        3358 : InjectedScript::InjectedScript(InspectedContext* context, int sessionId)
     257       10074 :     : m_context(context), m_sessionId(sessionId) {}
     258             : 
     259        6716 : InjectedScript::~InjectedScript() { discardEvaluateCallbacks(); }
     260             : 
     261             : namespace {
     262      136786 : class PropertyAccumulator : public ValueMirror::PropertyAccumulator {
     263             :  public:
     264             :   explicit PropertyAccumulator(std::vector<PropertyMirror>* mirrors)
     265       68393 :       : m_mirrors(mirrors) {}
     266     2507084 :   bool Add(PropertyMirror mirror) override {
     267     2507084 :     m_mirrors->push_back(std::move(mirror));
     268     2507084 :     return true;
     269             :   }
     270             : 
     271             :  private:
     272             :   std::vector<PropertyMirror>* m_mirrors;
     273             : };
     274             : }  // anonymous namespace
     275             : 
     276       68393 : Response InjectedScript::getProperties(
     277             :     v8::Local<v8::Object> object, const String16& groupName, bool ownProperties,
     278             :     bool accessorPropertiesOnly, WrapMode wrapMode,
     279             :     std::unique_ptr<Array<PropertyDescriptor>>* properties,
     280             :     Maybe<protocol::Runtime::ExceptionDetails>* exceptionDetails) {
     281      136786 :   v8::HandleScope handles(m_context->isolate());
     282       68393 :   v8::Local<v8::Context> context = m_context->context();
     283       68393 :   v8::Isolate* isolate = m_context->isolate();
     284       68393 :   int sessionId = m_sessionId;
     285      136786 :   v8::TryCatch tryCatch(isolate);
     286             : 
     287       68393 :   *properties = Array<PropertyDescriptor>::create();
     288       68393 :   std::vector<PropertyMirror> mirrors;
     289             :   PropertyAccumulator accumulator(&mirrors);
     290       68393 :   if (!ValueMirror::getProperties(context, object, ownProperties,
     291             :                                   accessorPropertiesOnly, &accumulator)) {
     292             :     return createExceptionDetails(tryCatch, groupName, wrapMode,
     293           0 :                                   exceptionDetails);
     294             :   }
     295     2575477 :   for (const PropertyMirror& mirror : mirrors) {
     296             :     std::unique_ptr<PropertyDescriptor> descriptor =
     297     2507084 :         PropertyDescriptor::create()
     298             :             .setName(mirror.name)
     299     2507084 :             .setConfigurable(mirror.configurable)
     300     2507084 :             .setEnumerable(mirror.enumerable)
     301     2507084 :             .setIsOwn(mirror.isOwn)
     302             :             .build();
     303             :     Response response;
     304     2507084 :     std::unique_ptr<RemoteObject> remoteObject;
     305             :     if (mirror.value) {
     306     5013438 :       response = wrapObjectMirror(*mirror.value, groupName, wrapMode,
     307             :                                   v8::MaybeLocal<v8::Value>(),
     308             :                                   kMaxCustomPreviewDepth, &remoteObject);
     309     2506719 :       if (!response.isSuccess()) return response;
     310             :       descriptor->setValue(std::move(remoteObject));
     311     2506719 :       descriptor->setWritable(mirror.writable);
     312             :     }
     313     2507084 :     if (mirror.getter) {
     314             :       response =
     315         730 :           mirror.getter->buildRemoteObject(context, wrapMode, &remoteObject);
     316         365 :       if (!response.isSuccess()) return response;
     317             :       response =
     318         730 :           bindRemoteObjectIfNeeded(sessionId, context, mirror.getter->v8Value(),
     319             :                                    groupName, remoteObject.get());
     320         365 :       if (!response.isSuccess()) return response;
     321             :       descriptor->setGet(std::move(remoteObject));
     322             :     }
     323     2507084 :     if (mirror.setter) {
     324             :       response =
     325         720 :           mirror.setter->buildRemoteObject(context, wrapMode, &remoteObject);
     326         360 :       if (!response.isSuccess()) return response;
     327             :       response =
     328         720 :           bindRemoteObjectIfNeeded(sessionId, context, mirror.setter->v8Value(),
     329             :                                    groupName, remoteObject.get());
     330         360 :       if (!response.isSuccess()) return response;
     331             :       descriptor->setSet(std::move(remoteObject));
     332             :     }
     333     2507084 :     if (mirror.symbol) {
     334             :       response =
     335       36770 :           mirror.symbol->buildRemoteObject(context, wrapMode, &remoteObject);
     336       18385 :       if (!response.isSuccess()) return response;
     337             :       response =
     338       36770 :           bindRemoteObjectIfNeeded(sessionId, context, mirror.symbol->v8Value(),
     339             :                                    groupName, remoteObject.get());
     340       18385 :       if (!response.isSuccess()) return response;
     341             :       descriptor->setSymbol(std::move(remoteObject));
     342             :     }
     343     2507084 :     if (mirror.exception) {
     344             :       response =
     345           0 :           mirror.exception->buildRemoteObject(context, wrapMode, &remoteObject);
     346           0 :       if (!response.isSuccess()) return response;
     347           0 :       response = bindRemoteObjectIfNeeded(sessionId, context,
     348           0 :                                           mirror.exception->v8Value(),
     349             :                                           groupName, remoteObject.get());
     350           0 :       if (!response.isSuccess()) return response;
     351             :       descriptor->setValue(std::move(remoteObject));
     352             :       descriptor->setWasThrown(true);
     353             :     }
     354     2507084 :     (*properties)->addItem(std::move(descriptor));
     355             :   }
     356       68393 :   return Response::OK();
     357             : }
     358             : 
     359       68383 : Response InjectedScript::getInternalAndPrivateProperties(
     360             :     v8::Local<v8::Value> value, const String16& groupName,
     361             :     std::unique_ptr<protocol::Array<InternalPropertyDescriptor>>*
     362             :         internalProperties,
     363             :     std::unique_ptr<protocol::Array<PrivatePropertyDescriptor>>*
     364             :         privateProperties) {
     365       68383 :   *internalProperties = protocol::Array<InternalPropertyDescriptor>::create();
     366       68383 :   *privateProperties = protocol::Array<PrivatePropertyDescriptor>::create();
     367             : 
     368       68383 :   if (!value->IsObject()) return Response::OK();
     369             : 
     370       68383 :   v8::Local<v8::Object> value_obj = value.As<v8::Object>();
     371             : 
     372       68383 :   v8::Local<v8::Context> context = m_context->context();
     373       68383 :   int sessionId = m_sessionId;
     374       68383 :   std::vector<InternalPropertyMirror> internalPropertiesWrappers;
     375       68383 :   ValueMirror::getInternalProperties(m_context->context(), value_obj,
     376       68383 :                                      &internalPropertiesWrappers);
     377       69477 :   for (const auto& internalProperty : internalPropertiesWrappers) {
     378        1094 :     std::unique_ptr<RemoteObject> remoteObject;
     379             :     Response response = internalProperty.value->buildRemoteObject(
     380        1094 :         m_context->context(), WrapMode::kNoPreview, &remoteObject);
     381        1094 :     if (!response.isSuccess()) return response;
     382        2188 :     response = bindRemoteObjectIfNeeded(sessionId, context,
     383        1094 :                                         internalProperty.value->v8Value(),
     384             :                                         groupName, remoteObject.get());
     385        1094 :     if (!response.isSuccess()) return response;
     386             :     (*internalProperties)
     387        1094 :         ->addItem(InternalPropertyDescriptor::create()
     388             :                       .setName(internalProperty.name)
     389             :                       .setValue(std::move(remoteObject))
     390        1094 :                       .build());
     391             :   }
     392             :   std::vector<PrivatePropertyMirror> privatePropertyWrappers =
     393      136766 :       ValueMirror::getPrivateProperties(m_context->context(), value_obj);
     394       68418 :   for (const auto& privateProperty : privatePropertyWrappers) {
     395          35 :     std::unique_ptr<RemoteObject> remoteObject;
     396             :     Response response = privateProperty.value->buildRemoteObject(
     397          35 :         m_context->context(), WrapMode::kNoPreview, &remoteObject);
     398          35 :     if (!response.isSuccess()) return response;
     399          70 :     response = bindRemoteObjectIfNeeded(sessionId, context,
     400          35 :                                         privateProperty.value->v8Value(),
     401             :                                         groupName, remoteObject.get());
     402          35 :     if (!response.isSuccess()) return response;
     403             :     (*privateProperties)
     404          35 :         ->addItem(PrivatePropertyDescriptor::create()
     405             :                       .setName(privateProperty.name)
     406             :                       .setValue(std::move(remoteObject))
     407          35 :                       .build());
     408             :   }
     409       68383 :   return Response::OK();
     410             : }
     411             : 
     412          25 : void InjectedScript::releaseObject(const String16& objectId) {
     413             :   std::unique_ptr<protocol::Value> parsedObjectId =
     414          25 :       protocol::StringUtil::parseJSON(objectId);
     415          25 :   if (!parsedObjectId) return;
     416             :   protocol::DictionaryValue* object =
     417             :       protocol::DictionaryValue::cast(parsedObjectId.get());
     418          25 :   if (!object) return;
     419          25 :   int boundId = 0;
     420          50 :   if (!object->getInteger("id", &boundId)) return;
     421          25 :   unbindObject(boundId);
     422             : }
     423             : 
     424      532166 : Response InjectedScript::wrapObject(
     425             :     v8::Local<v8::Value> value, const String16& groupName, WrapMode wrapMode,
     426             :     std::unique_ptr<protocol::Runtime::RemoteObject>* result) {
     427             :   return wrapObject(value, groupName, wrapMode, v8::MaybeLocal<v8::Value>(),
     428      554981 :                     kMaxCustomPreviewDepth, result);
     429             : }
     430             : 
     431      555011 : Response InjectedScript::wrapObject(
     432             :     v8::Local<v8::Value> value, const String16& groupName, WrapMode wrapMode,
     433             :     v8::MaybeLocal<v8::Value> customPreviewConfig, int maxCustomPreviewDepth,
     434             :     std::unique_ptr<protocol::Runtime::RemoteObject>* result) {
     435      555011 :   v8::Local<v8::Context> context = m_context->context();
     436             :   v8::Context::Scope contextScope(context);
     437      555011 :   std::unique_ptr<ValueMirror> mirror = ValueMirror::create(context, value);
     438      555011 :   if (!mirror) return Response::InternalError();
     439             :   return wrapObjectMirror(*mirror, groupName, wrapMode, customPreviewConfig,
     440      555011 :                           maxCustomPreviewDepth, result);
     441             : }
     442             : 
     443     3061730 : Response InjectedScript::wrapObjectMirror(
     444             :     const ValueMirror& mirror, const String16& groupName, WrapMode wrapMode,
     445             :     v8::MaybeLocal<v8::Value> customPreviewConfig, int maxCustomPreviewDepth,
     446             :     std::unique_ptr<protocol::Runtime::RemoteObject>* result) {
     447     3061730 :   int customPreviewEnabled = m_customPreviewEnabled;
     448     3061730 :   int sessionId = m_sessionId;
     449     3061730 :   v8::Local<v8::Context> context = m_context->context();
     450             :   v8::Context::Scope contextScope(context);
     451     3061730 :   Response response = mirror.buildRemoteObject(context, wrapMode, result);
     452     3061730 :   if (!response.isSuccess()) return response;
     453     3061700 :   v8::Local<v8::Value> value = mirror.v8Value();
     454     6123400 :   response = bindRemoteObjectIfNeeded(sessionId, context, value, groupName,
     455             :                                       result->get());
     456     3061700 :   if (!response.isSuccess()) return response;
     457     3061700 :   if (customPreviewEnabled && value->IsObject()) {
     458         170 :     std::unique_ptr<protocol::Runtime::CustomPreview> customPreview;
     459             :     generateCustomPreview(sessionId, groupName, context, value.As<v8::Object>(),
     460             :                           customPreviewConfig, maxCustomPreviewDepth,
     461         170 :                           &customPreview);
     462         170 :     if (customPreview) (*result)->setCustomPreview(std::move(customPreview));
     463             :   }
     464     3061700 :   return Response::OK();
     465             : }
     466             : 
     467         165 : std::unique_ptr<protocol::Runtime::RemoteObject> InjectedScript::wrapTable(
     468             :     v8::Local<v8::Object> table, v8::MaybeLocal<v8::Array> maybeColumns) {
     469             :   using protocol::Runtime::RemoteObject;
     470             :   using protocol::Runtime::ObjectPreview;
     471             :   using protocol::Runtime::PropertyPreview;
     472             :   using protocol::Array;
     473             : 
     474         165 :   v8::Isolate* isolate = m_context->isolate();
     475         330 :   v8::HandleScope handles(isolate);
     476         165 :   v8::Local<v8::Context> context = m_context->context();
     477             : 
     478         165 :   std::unique_ptr<RemoteObject> remoteObject;
     479             :   Response response =
     480         330 :       wrapObject(table, "console", WrapMode::kNoPreview, &remoteObject);
     481         165 :   if (!remoteObject || !response.isSuccess()) return nullptr;
     482             : 
     483         165 :   auto mirror = ValueMirror::create(context, table);
     484         165 :   std::unique_ptr<ObjectPreview> preview;
     485         165 :   int limit = 1000;
     486             :   mirror->buildObjectPreview(context, true /* generatePreviewForTable */,
     487         165 :                              &limit, &limit, &preview);
     488         165 :   if (!preview) return nullptr;
     489             : 
     490             :   Array<PropertyPreview>* columns = preview->getProperties();
     491             :   std::unordered_set<String16> selectedColumns;
     492             :   v8::Local<v8::Array> v8Columns;
     493         160 :   if (maybeColumns.ToLocal(&v8Columns)) {
     494          40 :     for (uint32_t i = 0; i < v8Columns->Length(); ++i) {
     495             :       v8::Local<v8::Value> column;
     496          45 :       if (v8Columns->Get(context, i).ToLocal(&column) && column->IsString()) {
     497             :         selectedColumns.insert(
     498          30 :             toProtocolString(isolate, column.As<v8::String>()));
     499             :       }
     500             :     }
     501             :   }
     502         160 :   if (!selectedColumns.empty()) {
     503          60 :     for (size_t i = 0; i < columns->length(); ++i) {
     504             :       ObjectPreview* columnPreview = columns->get(i)->getValuePreview(nullptr);
     505          25 :       if (!columnPreview) continue;
     506             : 
     507             :       std::unique_ptr<Array<PropertyPreview>> filtered =
     508          25 :           Array<PropertyPreview>::create();
     509             :       Array<PropertyPreview>* columns = columnPreview->getProperties();
     510         125 :       for (size_t j = 0; j < columns->length(); ++j) {
     511             :         PropertyPreview* property = columns->get(j);
     512          50 :         if (selectedColumns.find(property->getName()) !=
     513             :             selectedColumns.end()) {
     514          50 :           filtered->addItem(property->clone());
     515             :         }
     516             :       }
     517          25 :       columnPreview->setProperties(std::move(filtered));
     518             :     }
     519             :   }
     520             :   remoteObject->setPreview(std::move(preview));
     521             :   return remoteObject;
     522             : }
     523             : 
     524         650 : void InjectedScript::addPromiseCallback(
     525             :     V8InspectorSessionImpl* session, v8::MaybeLocal<v8::Value> value,
     526             :     const String16& objectGroup, WrapMode wrapMode,
     527             :     std::unique_ptr<EvaluateCallback> callback) {
     528         650 :   if (value.IsEmpty()) {
     529           0 :     callback->sendFailure(Response::InternalError());
     530           0 :     return;
     531             :   }
     532         650 :   v8::MicrotasksScope microtasksScope(m_context->isolate(),
     533        1300 :                                       v8::MicrotasksScope::kRunMicrotasks);
     534         650 :   if (ProtocolPromiseHandler::add(
     535         650 :           session, m_context->context(), value.ToLocalChecked(),
     536         650 :           m_context->contextId(), objectGroup, wrapMode, callback.get())) {
     537        1300 :     m_evaluateCallbacks.insert(callback.release());
     538             :   }
     539             : }
     540             : 
     541        3358 : void InjectedScript::discardEvaluateCallbacks() {
     542        3363 :   for (auto& callback : m_evaluateCallbacks) {
     543          15 :     callback->sendFailure(Response::Error("Execution context was destroyed."));
     544           5 :     delete callback;
     545             :   }
     546             :   m_evaluateCallbacks.clear();
     547        3358 : }
     548             : 
     549         645 : std::unique_ptr<EvaluateCallback> InjectedScript::takeEvaluateCallback(
     550             :     EvaluateCallback* callback) {
     551             :   auto it = m_evaluateCallbacks.find(callback);
     552         645 :   if (it == m_evaluateCallbacks.end()) return nullptr;
     553         645 :   std::unique_ptr<EvaluateCallback> value(*it);
     554             :   m_evaluateCallbacks.erase(it);
     555             :   return value;
     556             : }
     557             : 
     558       70836 : Response InjectedScript::findObject(const RemoteObjectId& objectId,
     559             :                                     v8::Local<v8::Value>* outObject) const {
     560      141672 :   auto it = m_idToWrappedObject.find(objectId.id());
     561       70836 :   if (it == m_idToWrappedObject.end())
     562         120 :     return Response::Error("Could not find object with given id");
     563      141552 :   *outObject = it->second.Get(m_context->isolate());
     564       70776 :   return Response::OK();
     565             : }
     566             : 
     567       70736 : String16 InjectedScript::objectGroupName(const RemoteObjectId& objectId) const {
     568       70736 :   if (objectId.id() <= 0) return String16();
     569      141472 :   auto it = m_idToObjectGroupName.find(objectId.id());
     570       73303 :   return it != m_idToObjectGroupName.end() ? it->second : String16();
     571             : }
     572             : 
     573       46726 : void InjectedScript::releaseObjectGroup(const String16& objectGroup) {
     574       93452 :   if (objectGroup == "console") m_lastEvaluationResult.Reset();
     575       46726 :   if (objectGroup.isEmpty()) return;
     576             :   auto it = m_nameToObjectGroup.find(objectGroup);
     577       46726 :   if (it == m_nameToObjectGroup.end()) return;
     578     2125215 :   for (int id : it->second) unbindObject(id);
     579             :   m_nameToObjectGroup.erase(it);
     580             : }
     581             : 
     582         332 : void InjectedScript::setCustomObjectFormatterEnabled(bool enabled) {
     583         332 :   m_customPreviewEnabled = enabled;
     584         332 : }
     585             : 
     586          85 : v8::Local<v8::Value> InjectedScript::lastEvaluationResult() const {
     587          85 :   if (m_lastEvaluationResult.IsEmpty())
     588          20 :     return v8::Undefined(m_context->isolate());
     589          75 :   return m_lastEvaluationResult.Get(m_context->isolate());
     590             : }
     591             : 
     592           5 : void InjectedScript::setLastEvaluationResult(v8::Local<v8::Value> result) {
     593           5 :   m_lastEvaluationResult.Reset(m_context->isolate(), result);
     594             :   m_lastEvaluationResult.AnnotateStrongRetainer(kGlobalHandleLabel);
     595           5 : }
     596             : 
     597         411 : Response InjectedScript::resolveCallArgument(
     598             :     protocol::Runtime::CallArgument* callArgument,
     599             :     v8::Local<v8::Value>* result) {
     600         411 :   if (callArgument->hasObjectId()) {
     601         100 :     std::unique_ptr<RemoteObjectId> remoteObjectId;
     602             :     Response response =
     603         300 :         RemoteObjectId::parse(callArgument->getObjectId(""), &remoteObjectId);
     604         100 :     if (!response.isSuccess()) return response;
     605         100 :     if (remoteObjectId->contextId() != m_context->contextId())
     606             :       return Response::Error(
     607             :           "Argument should belong to the same JavaScript world as target "
     608           0 :           "object");
     609         100 :     return findObject(*remoteObjectId, result);
     610             :   }
     611         311 :   if (callArgument->hasValue() || callArgument->hasUnserializableValue()) {
     612             :     String16 value;
     613         306 :     if (callArgument->hasValue()) {
     614        1536 :       value = "(" + callArgument->getValue(nullptr)->toJSONString() + ")";
     615             :     } else {
     616         100 :       String16 unserializableValue = callArgument->getUnserializableValue("");
     617             :       // Protect against potential identifier resolution for NaN and Infinity.
     618         100 :       if (isResolvableNumberLike(unserializableValue))
     619         140 :         value = "Number(\"" + unserializableValue + "\")";
     620             :       else
     621             :         value = unserializableValue;
     622             :     }
     623         612 :     if (!m_context->inspector()
     624         306 :              ->compileAndRunInternalScript(
     625         306 :                  m_context->context(), toV8String(m_context->isolate(), value))
     626             :              .ToLocal(result)) {
     627          10 :       return Response::Error("Couldn't parse value object in call argument");
     628             :     }
     629         301 :     return Response::OK();
     630             :   }
     631          10 :   *result = v8::Undefined(m_context->isolate());
     632           5 :   return Response::OK();
     633             : }
     634             : 
     635        1516 : Response InjectedScript::createExceptionDetails(
     636             :     const v8::TryCatch& tryCatch, const String16& objectGroup,
     637             :     WrapMode wrapMode, Maybe<protocol::Runtime::ExceptionDetails>* result) {
     638        1516 :   if (!tryCatch.HasCaught()) return Response::InternalError();
     639        1516 :   v8::Local<v8::Message> message = tryCatch.Message();
     640        1516 :   v8::Local<v8::Value> exception = tryCatch.Exception();
     641             :   String16 messageText =
     642             :       message.IsEmpty()
     643             :           ? String16()
     644        3032 :           : toProtocolString(m_context->isolate(), message->Get());
     645             :   std::unique_ptr<protocol::Runtime::ExceptionDetails> exceptionDetails =
     646        1516 :       protocol::Runtime::ExceptionDetails::create()
     647        3032 :           .setExceptionId(m_context->inspector()->nextExceptionId())
     648        4548 :           .setText(exception.IsEmpty() ? messageText : String16("Uncaught"))
     649             :           .setLineNumber(
     650             :               message.IsEmpty()
     651             :                   ? 0
     652        1516 :                   : message->GetLineNumber(m_context->context()).FromMaybe(1) -
     653        3032 :                         1)
     654             :           .setColumnNumber(
     655             :               message.IsEmpty()
     656             :                   ? 0
     657        1516 :                   : message->GetStartColumn(m_context->context()).FromMaybe(0))
     658             :           .build();
     659        1516 :   if (!message.IsEmpty()) {
     660        3032 :     exceptionDetails->setScriptId(String16::fromInteger(
     661        6064 :         static_cast<int>(message->GetScriptOrigin().ScriptID()->Value())));
     662        1516 :     v8::Local<v8::StackTrace> stackTrace = message->GetStackTrace();
     663        1516 :     if (!stackTrace.IsEmpty() && stackTrace->GetFrameCount() > 0)
     664             :       exceptionDetails->setStackTrace(
     665             :           m_context->inspector()
     666             :               ->debugger()
     667          80 :               ->createStackTrace(stackTrace)
     668         120 :               ->buildInspectorObjectImpl(m_context->inspector()->debugger()));
     669             :   }
     670        1516 :   if (!exception.IsEmpty()) {
     671        1516 :     std::unique_ptr<protocol::Runtime::RemoteObject> wrapped;
     672             :     Response response =
     673             :         wrapObject(exception, objectGroup,
     674        1516 :                    exception->IsNativeError() ? WrapMode::kNoPreview
     675             :                                               : WrapMode::kWithPreview,
     676        1516 :                    &wrapped);
     677        1516 :     if (!response.isSuccess()) return response;
     678             :     exceptionDetails->setException(std::move(wrapped));
     679             :   }
     680             :   *result = std::move(exceptionDetails);
     681        1516 :   return Response::OK();
     682             : }
     683             : 
     684       20551 : Response InjectedScript::wrapEvaluateResult(
     685             :     v8::MaybeLocal<v8::Value> maybeResultValue, const v8::TryCatch& tryCatch,
     686             :     const String16& objectGroup, WrapMode wrapMode,
     687             :     std::unique_ptr<protocol::Runtime::RemoteObject>* result,
     688             :     Maybe<protocol::Runtime::ExceptionDetails>* exceptionDetails) {
     689             :   v8::Local<v8::Value> resultValue;
     690       20551 :   if (!tryCatch.HasCaught()) {
     691       19003 :     if (!maybeResultValue.ToLocal(&resultValue))
     692          25 :       return Response::InternalError();
     693             :     Response response = wrapObject(resultValue, objectGroup, wrapMode, result);
     694       19003 :     if (!response.isSuccess()) return response;
     695       37956 :     if (objectGroup == "console") {
     696         175 :       m_lastEvaluationResult.Reset(m_context->isolate(), resultValue);
     697             :       m_lastEvaluationResult.AnnotateStrongRetainer(kGlobalHandleLabel);
     698             :     }
     699             :   } else {
     700        1548 :     if (tryCatch.HasTerminated() || !tryCatch.CanContinue()) {
     701         114 :       return Response::Error("Execution was terminated");
     702             :     }
     703        1491 :     v8::Local<v8::Value> exception = tryCatch.Exception();
     704             :     Response response =
     705             :         wrapObject(exception, objectGroup,
     706        1491 :                    exception->IsNativeError() ? WrapMode::kNoPreview
     707             :                                               : WrapMode::kWithPreview,
     708        1491 :                    result);
     709        1491 :     if (!response.isSuccess()) return response;
     710             :     // We send exception in result for compatibility reasons, even though it's
     711             :     // accessible through exceptionDetails.exception.
     712        2982 :     response = createExceptionDetails(tryCatch, objectGroup, wrapMode,
     713             :                                       exceptionDetails);
     714        1491 :     if (!response.isSuccess()) return response;
     715             :   }
     716       20469 :   return Response::OK();
     717             : }
     718             : 
     719         425 : v8::Local<v8::Object> InjectedScript::commandLineAPI() {
     720         425 :   if (m_commandLineAPI.IsEmpty()) {
     721          30 :     m_commandLineAPI.Reset(
     722          30 :         m_context->isolate(),
     723          90 :         m_context->inspector()->console()->createCommandLineAPI(
     724          60 :             m_context->context(), m_sessionId));
     725             :     m_commandLineAPI.AnnotateStrongRetainer(kGlobalHandleLabel);
     726             :   }
     727         850 :   return m_commandLineAPI.Get(m_context->isolate());
     728             : }
     729             : 
     730       91105 : InjectedScript::Scope::Scope(V8InspectorSessionImpl* session)
     731             :     : m_inspector(session->inspector()),
     732             :       m_injectedScript(nullptr),
     733             :       m_handleScope(m_inspector->isolate()),
     734       91105 :       m_tryCatch(m_inspector->isolate()),
     735             :       m_ignoreExceptionsAndMuteConsole(false),
     736             :       m_previousPauseOnExceptionsState(v8::debug::NoBreakOnException),
     737             :       m_userGesture(false),
     738             :       m_allowEval(false),
     739             :       m_contextGroupId(session->contextGroupId()),
     740      273315 :       m_sessionId(session->sessionId()) {}
     741             : 
     742      112992 : Response InjectedScript::Scope::initialize() {
     743      112992 :   cleanup();
     744             :   V8InspectorSessionImpl* session =
     745      112992 :       m_inspector->sessionById(m_contextGroupId, m_sessionId);
     746      112992 :   if (!session) return Response::InternalError();
     747      112987 :   Response response = findInjectedScript(session);
     748      112987 :   if (!response.isSuccess()) return response;
     749      112888 :   m_context = m_injectedScript->context()->context();
     750      112888 :   m_context->Enter();
     751      112918 :   if (m_allowEval) m_context->AllowCodeGenerationFromStrings(true);
     752      112888 :   return Response::OK();
     753             : }
     754             : 
     755         425 : void InjectedScript::Scope::installCommandLineAPI() {
     756             :   DCHECK(m_injectedScript && !m_context.IsEmpty() &&
     757             :          !m_commandLineAPIScope.get());
     758        1700 :   m_commandLineAPIScope.reset(new V8Console::CommandLineAPIScope(
     759        1700 :       m_context, m_injectedScript->commandLineAPI(), m_context->Global()));
     760         425 : }
     761             : 
     762       68408 : void InjectedScript::Scope::ignoreExceptionsAndMuteConsole() {
     763             :   DCHECK(!m_ignoreExceptionsAndMuteConsole);
     764       68408 :   m_ignoreExceptionsAndMuteConsole = true;
     765       68408 :   m_inspector->client()->muteMetrics(m_contextGroupId);
     766       68408 :   m_inspector->muteExceptions(m_contextGroupId);
     767             :   m_previousPauseOnExceptionsState =
     768       68408 :       setPauseOnExceptionsState(v8::debug::NoBreakOnException);
     769       68408 : }
     770             : 
     771      136816 : v8::debug::ExceptionBreakState InjectedScript::Scope::setPauseOnExceptionsState(
     772             :     v8::debug::ExceptionBreakState newState) {
     773      273632 :   if (!m_inspector->debugger()->enabled()) return newState;
     774             :   v8::debug::ExceptionBreakState presentState =
     775      271972 :       m_inspector->debugger()->getPauseOnExceptionsState();
     776      135986 :   if (presentState != newState)
     777         708 :     m_inspector->debugger()->setPauseOnExceptionsState(newState);
     778             :   return presentState;
     779             : }
     780             : 
     781           0 : void InjectedScript::Scope::pretendUserGesture() {
     782             :   DCHECK(!m_userGesture);
     783           0 :   m_userGesture = true;
     784           0 :   m_inspector->client()->beginUserGesture();
     785           0 : }
     786             : 
     787        9679 : void InjectedScript::Scope::allowCodeGenerationFromStrings() {
     788             :   DCHECK(!m_allowEval);
     789        9679 :   if (m_context->IsCodeGenerationFromStringsAllowed()) return;
     790          25 :   m_allowEval = true;
     791          25 :   m_context->AllowCodeGenerationFromStrings(true);
     792             : }
     793             : 
     794      204097 : void InjectedScript::Scope::cleanup() {
     795      204097 :   m_commandLineAPIScope.reset();
     796      204097 :   if (!m_context.IsEmpty()) {
     797      112888 :     if (m_allowEval) m_context->AllowCodeGenerationFromStrings(false);
     798      112888 :     m_context->Exit();
     799             :     m_context.Clear();
     800             :   }
     801      204097 : }
     802             : 
     803      182210 : InjectedScript::Scope::~Scope() {
     804       91105 :   if (m_ignoreExceptionsAndMuteConsole) {
     805       68408 :     setPauseOnExceptionsState(m_previousPauseOnExceptionsState);
     806       68408 :     m_inspector->client()->unmuteMetrics(m_contextGroupId);
     807       68408 :     m_inspector->unmuteExceptions(m_contextGroupId);
     808             :   }
     809       91105 :   if (m_userGesture) m_inspector->client()->endUserGesture();
     810       91105 :   cleanup();
     811       91105 : }
     812             : 
     813        9411 : InjectedScript::ContextScope::ContextScope(V8InspectorSessionImpl* session,
     814             :                                            int executionContextId)
     815             :     : InjectedScript::Scope(session),
     816       10061 :       m_executionContextId(executionContextId) {}
     817             : 
     818             : InjectedScript::ContextScope::~ContextScope() = default;
     819             : 
     820       19191 : Response InjectedScript::ContextScope::findInjectedScript(
     821             :     V8InspectorSessionImpl* session) {
     822       19191 :   return session->findInjectedScript(m_executionContextId, m_injectedScript);
     823             : }
     824             : 
     825       69329 : InjectedScript::ObjectScope::ObjectScope(V8InspectorSessionImpl* session,
     826             :                                          const String16& remoteObjectId)
     827      138658 :     : InjectedScript::Scope(session), m_remoteObjectId(remoteObjectId) {}
     828             : 
     829             : InjectedScript::ObjectScope::~ObjectScope() = default;
     830             : 
     831       70736 : Response InjectedScript::ObjectScope::findInjectedScript(
     832             :     V8InspectorSessionImpl* session) {
     833       70736 :   std::unique_ptr<RemoteObjectId> remoteId;
     834       70736 :   Response response = RemoteObjectId::parse(m_remoteObjectId, &remoteId);
     835       70736 :   if (!response.isSuccess()) return response;
     836       70736 :   InjectedScript* injectedScript = nullptr;
     837      141472 :   response = session->findInjectedScript(remoteId.get(), injectedScript);
     838       70736 :   if (!response.isSuccess()) return response;
     839      141472 :   m_objectGroupName = injectedScript->objectGroupName(*remoteId);
     840      212208 :   response = injectedScript->findObject(*remoteId, &m_object);
     841       70736 :   if (!response.isSuccess()) return response;
     842       70676 :   m_injectedScript = injectedScript;
     843       70676 :   return Response::OK();
     844             : }
     845             : 
     846       11715 : InjectedScript::CallFrameScope::CallFrameScope(V8InspectorSessionImpl* session,
     847             :                                                const String16& remoteObjectId)
     848       23430 :     : InjectedScript::Scope(session), m_remoteCallFrameId(remoteObjectId) {}
     849             : 
     850             : InjectedScript::CallFrameScope::~CallFrameScope() = default;
     851             : 
     852       23060 : Response InjectedScript::CallFrameScope::findInjectedScript(
     853             :     V8InspectorSessionImpl* session) {
     854       23060 :   std::unique_ptr<RemoteCallFrameId> remoteId;
     855       23060 :   Response response = RemoteCallFrameId::parse(m_remoteCallFrameId, &remoteId);
     856       23060 :   if (!response.isSuccess()) return response;
     857       23050 :   m_frameOrdinal = static_cast<size_t>(remoteId->frameOrdinal());
     858       23050 :   return session->findInjectedScript(remoteId.get(), m_injectedScript);
     859             : }
     860             : 
     861     2750244 : String16 InjectedScript::bindObject(v8::Local<v8::Value> value,
     862             :                                     const String16& groupName) {
     863     2750244 :   if (m_lastBoundObjectId <= 0) m_lastBoundObjectId = 1;
     864     2750244 :   int id = m_lastBoundObjectId++;
     865     2750244 :   m_idToWrappedObject[id].Reset(m_context->isolate(), value);
     866             :   m_idToWrappedObject[id].AnnotateStrongRetainer(kGlobalHandleLabel);
     867     2750244 :   if (!groupName.isEmpty() && id > 0) {
     868             :     m_idToObjectGroupName[id] = groupName;
     869     2736985 :     m_nameToObjectGroup[groupName].push_back(id);
     870             :   }
     871             :   // TODO(dgozman): get rid of "injectedScript" notion.
     872             :   return String16::concat(
     873     5500488 :       "{\"injectedScriptId\":", String16::fromInteger(m_context->contextId()),
     874     8250732 :       ",\"id\":", String16::fromInteger(id), "}");
     875             : }
     876             : 
     877             : // static
     878     3081939 : Response InjectedScript::bindRemoteObjectIfNeeded(
     879             :     int sessionId, v8::Local<v8::Context> context, v8::Local<v8::Value> value,
     880             :     const String16& groupName, protocol::Runtime::RemoteObject* remoteObject) {
     881     3081939 :   if (!remoteObject) return Response::OK();
     882     3081939 :   if (remoteObject->hasValue()) return Response::OK();
     883     2853580 :   if (remoteObject->hasUnserializableValue()) return Response::OK();
     884     8452734 :   if (remoteObject->getType() != RemoteObject::TypeEnum::Undefined) {
     885     2750194 :     v8::Isolate* isolate = context->GetIsolate();
     886             :     V8InspectorImpl* inspector =
     887     2750194 :         static_cast<V8InspectorImpl*>(v8::debug::GetInspector(isolate));
     888             :     InspectedContext* inspectedContext =
     889     2750194 :         inspector->getContext(InspectedContext::contextId(context));
     890             :     InjectedScript* injectedScript =
     891             :         inspectedContext ? inspectedContext->getInjectedScript(sessionId)
     892     2750194 :                          : nullptr;
     893     2750194 :     if (!injectedScript) {
     894           0 :       return Response::Error("Cannot find context with specified id");
     895             :     }
     896     5500388 :     remoteObject->setObjectId(injectedScript->bindObject(value, groupName));
     897             :   }
     898     2817578 :   return Response::OK();
     899             : }
     900             : 
     901           0 : void InjectedScript::unbindObject(int id) {
     902             :   m_idToWrappedObject.erase(id);
     903             :   m_idToObjectGroupName.erase(id);
     904           0 : }
     905             : 
     906             : }  // namespace v8_inspector

Generated by: LCOV version 1.10