LCOV - code coverage report
Current view: top level - src/inspector - v8-console.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 395 426 92.7 %
Date: 2019-04-17 Functions: 59 62 95.2 %

          Line data    Source code
       1             : // Copyright 2016 the V8 project authors. All rights reserved.
       2             : // Use of this source code is governed by a BSD-style license that can be
       3             : // found in the LICENSE file.
       4             : 
       5             : #include "src/inspector/v8-console.h"
       6             : 
       7             : #include "src/base/macros.h"
       8             : #include "src/inspector/injected-script.h"
       9             : #include "src/inspector/inspected-context.h"
      10             : #include "src/inspector/string-util.h"
      11             : #include "src/inspector/v8-console-message.h"
      12             : #include "src/inspector/v8-debugger-agent-impl.h"
      13             : #include "src/inspector/v8-inspector-impl.h"
      14             : #include "src/inspector/v8-inspector-session-impl.h"
      15             : #include "src/inspector/v8-profiler-agent-impl.h"
      16             : #include "src/inspector/v8-runtime-agent-impl.h"
      17             : #include "src/inspector/v8-stack-trace-impl.h"
      18             : #include "src/inspector/v8-value-utils.h"
      19             : 
      20             : #include "include/v8-inspector.h"
      21             : 
      22             : namespace v8_inspector {
      23             : 
      24             : namespace {
      25             : 
      26        6950 : String16 consoleContextToString(
      27             :     v8::Isolate* isolate, const v8::debug::ConsoleContext& consoleContext) {
      28        6950 :   if (consoleContext.id() == 0) return String16();
      29         340 :   return toProtocolString(isolate, consoleContext.name()) + "#" +
      30         255 :          String16::fromInteger(consoleContext.id());
      31             : }
      32             : 
      33             : class ConsoleHelper {
      34             :  public:
      35        7323 :   ConsoleHelper(const v8::debug::ConsoleCallArguments& info,
      36             :                 const v8::debug::ConsoleContext& consoleContext,
      37             :                 V8InspectorImpl* inspector)
      38             :       : m_info(info),
      39             :         m_consoleContext(consoleContext),
      40             :         m_isolate(inspector->isolate()),
      41             :         m_context(m_isolate->GetCurrentContext()),
      42             :         m_inspector(inspector),
      43        7323 :         m_contextId(InspectedContext::contextId(m_context)),
      44       14646 :         m_groupId(m_inspector->contextGroupId(m_contextId)) {}
      45             : 
      46             :   int contextId() const { return m_contextId; }
      47             :   int groupId() const { return m_groupId; }
      48             : 
      49         170 :   InjectedScript* injectedScript(int sessionId) {
      50         170 :     InspectedContext* context = m_inspector->getContext(m_groupId, m_contextId);
      51         170 :     if (!context) return nullptr;
      52         170 :     return context->getInjectedScript(sessionId);
      53             :   }
      54             : 
      55             :   V8InspectorSessionImpl* session(int sessionId) {
      56         260 :     return m_inspector->sessionById(m_groupId, sessionId);
      57             :   }
      58             : 
      59             :   V8ConsoleMessageStorage* consoleMessageStorage() {
      60        7015 :     return m_inspector->ensureConsoleMessageStorage(m_groupId);
      61             :   }
      62             : 
      63        5890 :   void reportCall(ConsoleAPIType type) {
      64       11780 :     if (!m_info.Length()) return;
      65             :     std::vector<v8::Local<v8::Value>> arguments;
      66        5890 :     arguments.reserve(m_info.Length());
      67       35380 :     for (int i = 0; i < m_info.Length(); ++i) arguments.push_back(m_info[i]);
      68        5890 :     reportCall(type, arguments);
      69             :   }
      70             : 
      71         465 :   void reportCallWithDefaultArgument(ConsoleAPIType type,
      72             :                                      const String16& message) {
      73             :     std::vector<v8::Local<v8::Value>> arguments;
      74        2410 :     for (int i = 0; i < m_info.Length(); ++i) arguments.push_back(m_info[i]);
      75         560 :     if (!m_info.Length()) arguments.push_back(toV8String(m_isolate, message));
      76         465 :     reportCall(type, arguments);
      77         465 :   }
      78             : 
      79          10 :   void reportCallAndReplaceFirstArgument(ConsoleAPIType type,
      80             :                                          const String16& message) {
      81             :     std::vector<v8::Local<v8::Value>> arguments;
      82          20 :     arguments.push_back(toV8String(m_isolate, message));
      83          80 :     for (int i = 1; i < m_info.Length(); ++i) arguments.push_back(m_info[i]);
      84          10 :     reportCall(type, arguments);
      85          10 :   }
      86             : 
      87         170 :   void reportCallWithArgument(ConsoleAPIType type, const String16& message) {
      88             :     std::vector<v8::Local<v8::Value>> arguments(1,
      89         340 :                                                 toV8String(m_isolate, message));
      90         170 :     reportCall(type, arguments);
      91         170 :   }
      92             : 
      93        6615 :   void reportCall(ConsoleAPIType type,
      94             :                   const std::vector<v8::Local<v8::Value>>& arguments) {
      95        6615 :     if (!m_groupId) return;
      96             :     std::unique_ptr<V8ConsoleMessage> message =
      97             :         V8ConsoleMessage::createForConsoleAPI(
      98             :             m_context, m_contextId, m_groupId, m_inspector,
      99        6615 :             m_inspector->client()->currentTimeMS(), type, arguments,
     100       13230 :             consoleContextToString(m_isolate, m_consoleContext),
     101       33075 :             m_inspector->debugger()->captureStackTrace(false));
     102        6615 :     consoleMessageStorage()->addMessage(std::move(message));
     103             :   }
     104             : 
     105             :   void reportDeprecatedCall(const char* id, const String16& message) {
     106             :     if (!consoleMessageStorage()->shouldReportDeprecationMessage(m_contextId,
     107             :                                                                  id)) {
     108             :       return;
     109             :     }
     110             :     std::vector<v8::Local<v8::Value>> arguments(1,
     111             :                                                 toV8String(m_isolate, message));
     112             :     reportCall(ConsoleAPIType::kWarning, arguments);
     113             :   }
     114             : 
     115             :   bool firstArgToBoolean(bool defaultValue) {
     116             :     if (m_info.Length() < 1) return defaultValue;
     117             :     if (m_info[0]->IsBoolean()) return m_info[0].As<v8::Boolean>()->Value();
     118             :     return m_info[0]->BooleanValue(m_context->GetIsolate());
     119             :   }
     120             : 
     121         528 :   String16 firstArgToString(const String16& defaultValue,
     122             :                             bool allowUndefined = true) {
     123        1266 :     if (m_info.Length() < 1 || (!allowUndefined && m_info[0]->IsUndefined())) {
     124             :       return defaultValue;
     125             :     }
     126             :     v8::Local<v8::String> titleValue;
     127         876 :     v8::TryCatch tryCatch(m_context->GetIsolate());
     128        1314 :     if (!m_info[0]->ToString(m_context).ToLocal(&titleValue))
     129             :       return defaultValue;
     130         433 :     return toProtocolString(m_context->GetIsolate(), titleValue);
     131             :   }
     132             : 
     133          10 :   v8::MaybeLocal<v8::Object> firstArgAsObject() {
     134          30 :     if (m_info.Length() < 1 || !m_info[0]->IsObject())
     135           0 :       return v8::MaybeLocal<v8::Object>();
     136          20 :     return m_info[0].As<v8::Object>();
     137             :   }
     138             : 
     139         150 :   v8::MaybeLocal<v8::Function> firstArgAsFunction() {
     140         450 :     if (m_info.Length() < 1 || !m_info[0]->IsFunction())
     141           0 :       return v8::MaybeLocal<v8::Function>();
     142         150 :     v8::Local<v8::Function> func = m_info[0].As<v8::Function>();
     143         390 :     while (func->GetBoundFunction()->IsFunction())
     144          45 :       func = func->GetBoundFunction().As<v8::Function>();
     145         150 :     return func;
     146             :   }
     147             : 
     148             :   void forEachSession(std::function<void(V8InspectorSessionImpl*)> callback) {
     149         268 :     m_inspector->forEachSession(m_groupId, std::move(callback));
     150             :   }
     151             : 
     152             :  private:
     153             :   const v8::debug::ConsoleCallArguments& m_info;
     154             :   const v8::debug::ConsoleContext& m_consoleContext;
     155             :   v8::Isolate* m_isolate;
     156             :   v8::Local<v8::Context> m_context;
     157             :   V8InspectorImpl* m_inspector = nullptr;
     158             :   int m_contextId;
     159             :   int m_groupId;
     160             : 
     161             :   DISALLOW_COPY_AND_ASSIGN(ConsoleHelper);
     162             : };
     163             : 
     164         495 : void returnDataCallback(const v8::FunctionCallbackInfo<v8::Value>& info) {
     165             :   info.GetReturnValue().Set(info.Data());
     166         495 : }
     167             : 
     168         630 : void createBoundFunctionProperty(
     169             :     v8::Local<v8::Context> context, v8::Local<v8::Object> console,
     170             :     v8::Local<v8::Value> data, const char* name, v8::FunctionCallback callback,
     171             :     const char* description = nullptr,
     172             :     v8::SideEffectType side_effect_type = v8::SideEffectType::kHasSideEffect) {
     173             :   v8::Local<v8::String> funcName =
     174         630 :       toV8StringInternalized(context->GetIsolate(), name);
     175             :   v8::Local<v8::Function> func;
     176        1260 :   if (!v8::Function::New(context, callback, data, 0,
     177             :                          v8::ConstructorBehavior::kThrow, side_effect_type)
     178             :            .ToLocal(&func))
     179           0 :     return;
     180         630 :   func->SetName(funcName);
     181         630 :   if (description) {
     182             :     v8::Local<v8::String> returnValue =
     183         900 :         toV8String(context->GetIsolate(), description);
     184             :     v8::Local<v8::Function> toStringFunction;
     185         900 :     if (v8::Function::New(context, returnDataCallback, returnValue, 0,
     186             :                           v8::ConstructorBehavior::kThrow,
     187         450 :                           v8::SideEffectType::kHasNoSideEffect)
     188             :             .ToLocal(&toStringFunction))
     189             :       createDataProperty(context, func, toV8StringInternalized(
     190             :                                             context->GetIsolate(), "toString"),
     191         900 :                          toStringFunction);
     192             :   }
     193         630 :   createDataProperty(context, console, funcName, func);
     194             : }
     195             : 
     196             : enum InspectRequest { kRegular, kCopyToClipboard, kQueryObjects };
     197             : 
     198             : }  // namespace
     199             : 
     200        7370 : V8Console::V8Console(V8InspectorImpl* inspector) : m_inspector(inspector) {}
     201             : 
     202          20 : void V8Console::Debug(const v8::debug::ConsoleCallArguments& info,
     203             :                       const v8::debug::ConsoleContext& consoleContext) {
     204             :   ConsoleHelper(info, consoleContext, m_inspector)
     205          20 :       .reportCall(ConsoleAPIType::kDebug);
     206          20 : }
     207             : 
     208          20 : void V8Console::Error(const v8::debug::ConsoleCallArguments& info,
     209             :                       const v8::debug::ConsoleContext& consoleContext) {
     210             :   ConsoleHelper(info, consoleContext, m_inspector)
     211          20 :       .reportCall(ConsoleAPIType::kError);
     212          20 : }
     213             : 
     214          20 : void V8Console::Info(const v8::debug::ConsoleCallArguments& info,
     215             :                      const v8::debug::ConsoleContext& consoleContext) {
     216             :   ConsoleHelper(info, consoleContext, m_inspector)
     217          20 :       .reportCall(ConsoleAPIType::kInfo);
     218          20 : }
     219             : 
     220        5600 : void V8Console::Log(const v8::debug::ConsoleCallArguments& info,
     221             :                     const v8::debug::ConsoleContext& consoleContext) {
     222             :   ConsoleHelper(info, consoleContext, m_inspector)
     223        5600 :       .reportCall(ConsoleAPIType::kLog);
     224        5600 : }
     225             : 
     226           5 : void V8Console::Warn(const v8::debug::ConsoleCallArguments& info,
     227             :                      const v8::debug::ConsoleContext& consoleContext) {
     228             :   ConsoleHelper(info, consoleContext, m_inspector)
     229           5 :       .reportCall(ConsoleAPIType::kWarning);
     230           5 : }
     231             : 
     232          20 : void V8Console::Dir(const v8::debug::ConsoleCallArguments& info,
     233             :                     const v8::debug::ConsoleContext& consoleContext) {
     234             :   ConsoleHelper(info, consoleContext, m_inspector)
     235          20 :       .reportCall(ConsoleAPIType::kDir);
     236          20 : }
     237             : 
     238          15 : void V8Console::DirXml(const v8::debug::ConsoleCallArguments& info,
     239             :                        const v8::debug::ConsoleContext& consoleContext) {
     240             :   ConsoleHelper(info, consoleContext, m_inspector)
     241          15 :       .reportCall(ConsoleAPIType::kDirXML);
     242          15 : }
     243             : 
     244         190 : void V8Console::Table(const v8::debug::ConsoleCallArguments& info,
     245             :                       const v8::debug::ConsoleContext& consoleContext) {
     246             :   ConsoleHelper(info, consoleContext, m_inspector)
     247         190 :       .reportCall(ConsoleAPIType::kTable);
     248         190 : }
     249             : 
     250         400 : void V8Console::Trace(const v8::debug::ConsoleCallArguments& info,
     251             :                       const v8::debug::ConsoleContext& consoleContext) {
     252             :   ConsoleHelper(info, consoleContext, m_inspector)
     253        1200 :       .reportCallWithDefaultArgument(ConsoleAPIType::kTrace,
     254         400 :                                      String16("console.trace"));
     255         400 : }
     256             : 
     257           5 : void V8Console::Group(const v8::debug::ConsoleCallArguments& info,
     258             :                       const v8::debug::ConsoleContext& consoleContext) {
     259             :   ConsoleHelper(info, consoleContext, m_inspector)
     260          15 :       .reportCallWithDefaultArgument(ConsoleAPIType::kStartGroup,
     261           5 :                                      String16("console.group"));
     262           5 : }
     263             : 
     264           5 : void V8Console::GroupCollapsed(
     265             :     const v8::debug::ConsoleCallArguments& info,
     266             :     const v8::debug::ConsoleContext& consoleContext) {
     267             :   ConsoleHelper(info, consoleContext, m_inspector)
     268          15 :       .reportCallWithDefaultArgument(ConsoleAPIType::kStartGroupCollapsed,
     269           5 :                                      String16("console.groupCollapsed"));
     270           5 : }
     271             : 
     272           5 : void V8Console::GroupEnd(const v8::debug::ConsoleCallArguments& info,
     273             :                          const v8::debug::ConsoleContext& consoleContext) {
     274             :   ConsoleHelper(info, consoleContext, m_inspector)
     275          15 :       .reportCallWithDefaultArgument(ConsoleAPIType::kEndGroup,
     276           5 :                                      String16("console.groupEnd"));
     277           5 : }
     278             : 
     279          50 : void V8Console::Clear(const v8::debug::ConsoleCallArguments& info,
     280             :                       const v8::debug::ConsoleContext& consoleContext) {
     281          50 :   ConsoleHelper helper(info, consoleContext, m_inspector);
     282          50 :   if (!helper.groupId()) return;
     283          50 :   m_inspector->client()->consoleClear(helper.groupId());
     284         100 :   helper.reportCallWithDefaultArgument(ConsoleAPIType::kClear,
     285          50 :                                        String16("console.clear"));
     286             : }
     287             : 
     288         105 : static String16 identifierFromTitleOrStackTrace(
     289             :     const String16& title, const ConsoleHelper& helper,
     290             :     const v8::debug::ConsoleContext& consoleContext,
     291             :     V8InspectorImpl* inspector) {
     292             :   String16 identifier;
     293         105 :   if (title.isEmpty()) {
     294             :     std::unique_ptr<V8StackTraceImpl> stackTrace =
     295           0 :         V8StackTraceImpl::capture(inspector->debugger(), helper.groupId(), 1);
     296           0 :     if (stackTrace && !stackTrace->isEmpty()) {
     297           0 :       identifier = toString16(stackTrace->topSourceURL()) + ":" +
     298           0 :                    String16::fromInteger(stackTrace->topLineNumber());
     299             :     }
     300             :   } else {
     301         315 :     identifier = title + "@";
     302             :   }
     303         420 :   identifier = consoleContextToString(inspector->isolate(), consoleContext) +
     304         210 :                "@" + identifier;
     305             : 
     306         105 :   return identifier;
     307             : }
     308             : 
     309          85 : void V8Console::Count(const v8::debug::ConsoleCallArguments& info,
     310             :                       const v8::debug::ConsoleContext& consoleContext) {
     311          85 :   ConsoleHelper helper(info, consoleContext, m_inspector);
     312         170 :   String16 title = helper.firstArgToString(String16("default"), false);
     313             :   String16 identifier = identifierFromTitleOrStackTrace(
     314          85 :       title, helper, consoleContext, m_inspector);
     315             : 
     316             :   int count =
     317          85 :       helper.consoleMessageStorage()->count(helper.contextId(), identifier);
     318          85 :   String16 countString = String16::fromInteger(count);
     319         255 :   helper.reportCallWithArgument(
     320             :       ConsoleAPIType::kCount,
     321         425 :       title.isEmpty() ? countString : (title + ": " + countString));
     322          85 : }
     323             : 
     324          20 : void V8Console::CountReset(const v8::debug::ConsoleCallArguments& info,
     325             :                            const v8::debug::ConsoleContext& consoleContext) {
     326          20 :   ConsoleHelper helper(info, consoleContext, m_inspector);
     327          40 :   String16 title = helper.firstArgToString(String16("default"), false);
     328             :   String16 identifier = identifierFromTitleOrStackTrace(
     329          20 :       title, helper, consoleContext, m_inspector);
     330             : 
     331          20 :   if (!helper.consoleMessageStorage()->countReset(helper.contextId(),
     332             :                                                   identifier)) {
     333             :     helper.reportCallWithArgument(ConsoleAPIType::kWarning,
     334          20 :                                   "Count for '" + title + "' does not exist");
     335             :   }
     336          20 : }
     337             : 
     338          80 : void V8Console::Assert(const v8::debug::ConsoleCallArguments& info,
     339             :                        const v8::debug::ConsoleContext& consoleContext) {
     340          80 :   ConsoleHelper helper(info, consoleContext, m_inspector);
     341             :   DCHECK(!helper.firstArgToBoolean(false));
     342             : 
     343             :   std::vector<v8::Local<v8::Value>> arguments;
     344         125 :   for (int i = 1; i < info.Length(); ++i) arguments.push_back(info[i]);
     345          80 :   if (info.Length() < 2)
     346         280 :     arguments.push_back(
     347          70 :         toV8String(m_inspector->isolate(), String16("console.assert")));
     348          80 :   helper.reportCall(ConsoleAPIType::kAssert, arguments);
     349         160 :   m_inspector->debugger()->breakProgramOnAssert(helper.groupId());
     350          80 : }
     351             : 
     352         134 : void V8Console::Profile(const v8::debug::ConsoleCallArguments& info,
     353             :                         const v8::debug::ConsoleContext& consoleContext) {
     354         134 :   ConsoleHelper helper(info, consoleContext, m_inspector);
     355         402 :   helper.forEachSession([&helper](V8InspectorSessionImpl* session) {
     356             :     session->profilerAgent()->consoleProfile(
     357         670 :         helper.firstArgToString(String16()));
     358         134 :   });
     359         134 : }
     360             : 
     361         134 : void V8Console::ProfileEnd(const v8::debug::ConsoleCallArguments& info,
     362             :                            const v8::debug::ConsoleContext& consoleContext) {
     363         134 :   ConsoleHelper helper(info, consoleContext, m_inspector);
     364         402 :   helper.forEachSession([&helper](V8InspectorSessionImpl* session) {
     365             :     session->profilerAgent()->consoleProfileEnd(
     366         670 :         helper.firstArgToString(String16()));
     367         134 :   });
     368         134 : }
     369             : 
     370          70 : static void timeFunction(const v8::debug::ConsoleCallArguments& info,
     371             :                          const v8::debug::ConsoleContext& consoleContext,
     372             :                          bool timelinePrefix, V8InspectorImpl* inspector) {
     373          70 :   ConsoleHelper helper(info, consoleContext, inspector);
     374         140 :   String16 protocolTitle = helper.firstArgToString("default", false);
     375          70 :   if (timelinePrefix) protocolTitle = "Timeline '" + protocolTitle + "'";
     376             :   const String16& timerId =
     377         210 :       protocolTitle + "@" +
     378         210 :       consoleContextToString(inspector->isolate(), consoleContext);
     379          70 :   if (helper.consoleMessageStorage()->hasTimer(helper.contextId(), timerId)) {
     380             :     helper.reportCallWithArgument(
     381             :         ConsoleAPIType::kWarning,
     382          20 :         "Timer '" + protocolTitle + "' already exists");
     383             :     return;
     384             :   }
     385          65 :   inspector->client()->consoleTime(toStringView(protocolTitle));
     386          65 :   helper.consoleMessageStorage()->time(helper.contextId(), timerId);
     387             : }
     388             : 
     389          85 : static void timeEndFunction(const v8::debug::ConsoleCallArguments& info,
     390             :                             const v8::debug::ConsoleContext& consoleContext,
     391             :                             bool timeLog, V8InspectorImpl* inspector) {
     392          85 :   ConsoleHelper helper(info, consoleContext, inspector);
     393         170 :   String16 protocolTitle = helper.firstArgToString("default", false);
     394             :   const String16& timerId =
     395         255 :       protocolTitle + "@" +
     396         255 :       consoleContextToString(inspector->isolate(), consoleContext);
     397          85 :   if (!helper.consoleMessageStorage()->hasTimer(helper.contextId(), timerId)) {
     398             :     helper.reportCallWithArgument(
     399             :         ConsoleAPIType::kWarning,
     400          40 :         "Timer '" + protocolTitle + "' does not exist");
     401             :     return;
     402             :   }
     403          75 :   inspector->client()->consoleTimeEnd(toStringView(protocolTitle));
     404         225 :   String16 title = protocolTitle + "@" +
     405         225 :                    consoleContextToString(inspector->isolate(), consoleContext);
     406             :   double elapsed;
     407          75 :   if (timeLog) {
     408             :     elapsed =
     409          10 :         helper.consoleMessageStorage()->timeLog(helper.contextId(), title);
     410             :   } else {
     411             :     elapsed =
     412          65 :         helper.consoleMessageStorage()->timeEnd(helper.contextId(), title);
     413             :   }
     414             :   String16 message =
     415         450 :       protocolTitle + ": " + String16::fromDouble(elapsed) + "ms";
     416          75 :   if (timeLog)
     417          10 :     helper.reportCallAndReplaceFirstArgument(ConsoleAPIType::kLog, message);
     418             :   else
     419          65 :     helper.reportCallWithArgument(ConsoleAPIType::kTimeEnd, message);
     420             : }
     421             : 
     422          70 : void V8Console::Time(const v8::debug::ConsoleCallArguments& info,
     423             :                      const v8::debug::ConsoleContext& consoleContext) {
     424          70 :   timeFunction(info, consoleContext, false, m_inspector);
     425          70 : }
     426             : 
     427          15 : void V8Console::TimeLog(const v8::debug::ConsoleCallArguments& info,
     428             :                         const v8::debug::ConsoleContext& consoleContext) {
     429          15 :   timeEndFunction(info, consoleContext, true, m_inspector);
     430          15 : }
     431             : 
     432          70 : void V8Console::TimeEnd(const v8::debug::ConsoleCallArguments& info,
     433             :                         const v8::debug::ConsoleContext& consoleContext) {
     434          70 :   timeEndFunction(info, consoleContext, false, m_inspector);
     435          70 : }
     436             : 
     437           0 : void V8Console::TimeStamp(const v8::debug::ConsoleCallArguments& info,
     438             :                           const v8::debug::ConsoleContext& consoleContext) {
     439           0 :   ConsoleHelper helper(info, consoleContext, m_inspector);
     440           0 :   String16 title = helper.firstArgToString(String16());
     441           0 :   m_inspector->client()->consoleTimeStamp(toStringView(title));
     442           0 : }
     443             : 
     444          20 : void V8Console::memoryGetterCallback(
     445             :     const v8::FunctionCallbackInfo<v8::Value>& info) {
     446             :   v8::Local<v8::Value> memoryValue;
     447          40 :   if (!m_inspector->client()
     448          20 :            ->memoryInfo(info.GetIsolate(),
     449          40 :                         info.GetIsolate()->GetCurrentContext())
     450             :            .ToLocal(&memoryValue))
     451             :     return;
     452             :   info.GetReturnValue().Set(memoryValue);
     453             : }
     454             : 
     455           0 : void V8Console::memorySetterCallback(
     456             :     const v8::FunctionCallbackInfo<v8::Value>& info) {
     457             :   // We can't make the attribute readonly as it breaks existing code that relies
     458             :   // on being able to assign to console.memory in strict mode. Instead, the
     459             :   // setter just ignores the passed value.  http://crbug.com/468611
     460           0 : }
     461             : 
     462          10 : void V8Console::keysCallback(const v8::FunctionCallbackInfo<v8::Value>& info,
     463             :                              int sessionId) {
     464             :   v8::Isolate* isolate = info.GetIsolate();
     465          10 :   info.GetReturnValue().Set(v8::Array::New(isolate));
     466             : 
     467          10 :   v8::debug::ConsoleCallArguments args(info);
     468          20 :   ConsoleHelper helper(args, v8::debug::ConsoleContext(), m_inspector);
     469             :   v8::Local<v8::Object> obj;
     470          20 :   if (!helper.firstArgAsObject().ToLocal(&obj)) return;
     471             :   v8::Local<v8::Array> names;
     472          20 :   if (!obj->GetOwnPropertyNames(isolate->GetCurrentContext()).ToLocal(&names))
     473             :     return;
     474             :   info.GetReturnValue().Set(names);
     475             : }
     476             : 
     477           0 : void V8Console::valuesCallback(const v8::FunctionCallbackInfo<v8::Value>& info,
     478             :                                int sessionId) {
     479             :   v8::Isolate* isolate = info.GetIsolate();
     480           0 :   info.GetReturnValue().Set(v8::Array::New(isolate));
     481             : 
     482           0 :   v8::debug::ConsoleCallArguments args(info);
     483           0 :   ConsoleHelper helper(args, v8::debug::ConsoleContext(), m_inspector);
     484             :   v8::Local<v8::Object> obj;
     485           0 :   if (!helper.firstArgAsObject().ToLocal(&obj)) return;
     486             :   v8::Local<v8::Array> names;
     487           0 :   v8::Local<v8::Context> context = isolate->GetCurrentContext();
     488           0 :   if (!obj->GetOwnPropertyNames(context).ToLocal(&names)) return;
     489           0 :   v8::Local<v8::Array> values = v8::Array::New(isolate, names->Length());
     490           0 :   for (uint32_t i = 0; i < names->Length(); ++i) {
     491             :     v8::Local<v8::Value> key;
     492           0 :     if (!names->Get(context, i).ToLocal(&key)) continue;
     493             :     v8::Local<v8::Value> value;
     494           0 :     if (!obj->Get(context, key).ToLocal(&value)) continue;
     495           0 :     createDataProperty(context, values, i, value);
     496             :   }
     497             :   info.GetReturnValue().Set(values);
     498             : }
     499             : 
     500         150 : static void setFunctionBreakpoint(ConsoleHelper& helper, int sessionId,
     501             :                                   v8::Local<v8::Function> function,
     502             :                                   V8DebuggerAgentImpl::BreakpointSource source,
     503             :                                   v8::Local<v8::String> condition,
     504             :                                   bool enable) {
     505             :   V8InspectorSessionImpl* session = helper.session(sessionId);
     506         150 :   if (session == nullptr) return;
     507         150 :   if (!session->debuggerAgent()->enabled()) return;
     508         150 :   if (enable) {
     509          80 :     session->debuggerAgent()->setBreakpointFor(function, condition, source);
     510             :   } else {
     511          70 :     session->debuggerAgent()->removeBreakpointFor(function, source);
     512             :   }
     513             : }
     514             : 
     515          50 : void V8Console::debugFunctionCallback(
     516             :     const v8::FunctionCallbackInfo<v8::Value>& info, int sessionId) {
     517          50 :   v8::debug::ConsoleCallArguments args(info);
     518         100 :   ConsoleHelper helper(args, v8::debug::ConsoleContext(), m_inspector);
     519             :   v8::Local<v8::Function> function;
     520             :   v8::Local<v8::String> condition;
     521         100 :   if (!helper.firstArgAsFunction().ToLocal(&function)) return;
     522          55 :   if (args.Length() > 1 && args[1]->IsString()) {
     523           5 :     condition = args[1].As<v8::String>();
     524             :   }
     525             :   setFunctionBreakpoint(helper, sessionId, function,
     526             :                         V8DebuggerAgentImpl::DebugCommandBreakpointSource,
     527          50 :                         condition, true);
     528             : }
     529             : 
     530          40 : void V8Console::undebugFunctionCallback(
     531             :     const v8::FunctionCallbackInfo<v8::Value>& info, int sessionId) {
     532          40 :   v8::debug::ConsoleCallArguments args(info);
     533          80 :   ConsoleHelper helper(args, v8::debug::ConsoleContext(), m_inspector);
     534             :   v8::Local<v8::Function> function;
     535          80 :   if (!helper.firstArgAsFunction().ToLocal(&function)) return;
     536          40 :   setFunctionBreakpoint(helper, sessionId, function,
     537             :                         V8DebuggerAgentImpl::DebugCommandBreakpointSource,
     538          40 :                         v8::Local<v8::String>(), false);
     539             : }
     540             : 
     541          30 : void V8Console::monitorFunctionCallback(
     542             :     const v8::FunctionCallbackInfo<v8::Value>& info, int sessionId) {
     543          30 :   v8::debug::ConsoleCallArguments args(info);
     544          60 :   ConsoleHelper helper(args, v8::debug::ConsoleContext(), m_inspector);
     545             :   v8::Local<v8::Function> function;
     546          60 :   if (!helper.firstArgAsFunction().ToLocal(&function)) return;
     547          30 :   v8::Local<v8::Value> name = function->GetName();
     548          30 :   if (!name->IsString() || !v8::Local<v8::String>::Cast(name)->Length())
     549           0 :     name = function->GetInferredName();
     550             :   String16 functionName =
     551          30 :       toProtocolStringWithTypeCheck(info.GetIsolate(), name);
     552          30 :   String16Builder builder;
     553          60 :   builder.append("console.log(\"function ");
     554          30 :   if (functionName.isEmpty())
     555           0 :     builder.append("(anonymous function)");
     556             :   else
     557          30 :     builder.append(functionName);
     558          60 :   builder.append(
     559             :       " called\" + (arguments.length > 0 ? \" with arguments: \" + "
     560          30 :       "Array.prototype.join.call(arguments, \", \") : \"\")) && false");
     561          30 :   setFunctionBreakpoint(helper, sessionId, function,
     562             :                         V8DebuggerAgentImpl::MonitorCommandBreakpointSource,
     563          60 :                         toV8String(info.GetIsolate(), builder.toString()),
     564          30 :                         true);
     565             : }
     566             : 
     567          30 : void V8Console::unmonitorFunctionCallback(
     568             :     const v8::FunctionCallbackInfo<v8::Value>& info, int sessionId) {
     569          30 :   v8::debug::ConsoleCallArguments args(info);
     570          60 :   ConsoleHelper helper(args, v8::debug::ConsoleContext(), m_inspector);
     571             :   v8::Local<v8::Function> function;
     572          60 :   if (!helper.firstArgAsFunction().ToLocal(&function)) return;
     573          30 :   setFunctionBreakpoint(helper, sessionId, function,
     574             :                         V8DebuggerAgentImpl::MonitorCommandBreakpointSource,
     575          30 :                         v8::Local<v8::String>(), false);
     576             : }
     577             : 
     578          85 : void V8Console::lastEvaluationResultCallback(
     579             :     const v8::FunctionCallbackInfo<v8::Value>& info, int sessionId) {
     580          85 :   v8::debug::ConsoleCallArguments args(info);
     581         170 :   ConsoleHelper helper(args, v8::debug::ConsoleContext(), m_inspector);
     582          85 :   InjectedScript* injectedScript = helper.injectedScript(sessionId);
     583          85 :   if (!injectedScript) return;
     584          85 :   info.GetReturnValue().Set(injectedScript->lastEvaluationResult());
     585             : }
     586             : 
     587          85 : static void inspectImpl(const v8::FunctionCallbackInfo<v8::Value>& info,
     588             :                         v8::Local<v8::Value> value, int sessionId,
     589             :                         InspectRequest request, V8InspectorImpl* inspector) {
     590          85 :   if (request == kRegular) info.GetReturnValue().Set(value);
     591             : 
     592          85 :   v8::debug::ConsoleCallArguments args(info);
     593          85 :   ConsoleHelper helper(args, v8::debug::ConsoleContext(), inspector);
     594          85 :   InjectedScript* injectedScript = helper.injectedScript(sessionId);
     595          90 :   if (!injectedScript) return;
     596          80 :   std::unique_ptr<protocol::Runtime::RemoteObject> wrappedObject;
     597             :   protocol::Response response = injectedScript->wrapObject(
     598         160 :       value, "", WrapMode::kNoPreview, &wrappedObject);
     599          80 :   if (!response.isSuccess()) return;
     600             : 
     601             :   std::unique_ptr<protocol::DictionaryValue> hints =
     602             :       protocol::DictionaryValue::create();
     603          80 :   if (request == kCopyToClipboard) {
     604          10 :     hints->setBoolean("copyToClipboard", true);
     605          75 :   } else if (request == kQueryObjects) {
     606          40 :     hints->setBoolean("queryObjects", true);
     607             :   }
     608          80 :   if (V8InspectorSessionImpl* session = helper.session(sessionId)) {
     609         160 :     session->runtimeAgent()->inspect(std::move(wrappedObject),
     610          80 :                                      std::move(hints));
     611             :   }
     612             : }
     613             : 
     614          60 : void V8Console::inspectCallback(const v8::FunctionCallbackInfo<v8::Value>& info,
     615             :                                 int sessionId) {
     616          60 :   if (info.Length() < 1) return;
     617         120 :   inspectImpl(info, info[0], sessionId, kRegular, m_inspector);
     618             : }
     619             : 
     620           5 : void V8Console::copyCallback(const v8::FunctionCallbackInfo<v8::Value>& info,
     621             :                              int sessionId) {
     622           5 :   if (info.Length() < 1) return;
     623          10 :   inspectImpl(info, info[0], sessionId, kCopyToClipboard, m_inspector);
     624             : }
     625             : 
     626          20 : void V8Console::queryObjectsCallback(
     627             :     const v8::FunctionCallbackInfo<v8::Value>& info, int sessionId) {
     628          20 :   if (info.Length() < 1) return;
     629             :   v8::Local<v8::Value> arg = info[0];
     630          20 :   if (arg->IsFunction()) {
     631             :     v8::Isolate* isolate = info.GetIsolate();
     632          10 :     v8::TryCatch tryCatch(isolate);
     633             :     v8::Local<v8::Value> prototype;
     634           5 :     if (arg.As<v8::Function>()
     635           5 :             ->Get(isolate->GetCurrentContext(),
     636          15 :                   toV8StringInternalized(isolate, "prototype"))
     637          10 :             .ToLocal(&prototype) &&
     638           5 :         prototype->IsObject()) {
     639             :       arg = prototype;
     640             :     }
     641           5 :     if (tryCatch.HasCaught()) {
     642           0 :       tryCatch.ReThrow();
     643           0 :       return;
     644             :     }
     645             :   }
     646          20 :   inspectImpl(info, arg, sessionId, kQueryObjects, m_inspector);
     647             : }
     648             : 
     649          30 : void V8Console::inspectedObject(const v8::FunctionCallbackInfo<v8::Value>& info,
     650             :                                 int sessionId, unsigned num) {
     651             :   DCHECK_GT(V8InspectorSessionImpl::kInspectedObjectBufferSize, num);
     652          30 :   v8::debug::ConsoleCallArguments args(info);
     653          60 :   ConsoleHelper helper(args, v8::debug::ConsoleContext(), m_inspector);
     654          30 :   if (V8InspectorSessionImpl* session = helper.session(sessionId)) {
     655          30 :     V8InspectorSession::Inspectable* object = session->inspectedObject(num);
     656             :     v8::Isolate* isolate = info.GetIsolate();
     657          30 :     if (object)
     658          20 :       info.GetReturnValue().Set(object->get(isolate->GetCurrentContext()));
     659             :     else
     660             :       info.GetReturnValue().Set(v8::Undefined(isolate));
     661             :   }
     662          30 : }
     663             : 
     664        1233 : void V8Console::installMemoryGetter(v8::Local<v8::Context> context,
     665             :                                     v8::Local<v8::Object> console) {
     666        1233 :   v8::Isolate* isolate = context->GetIsolate();
     667        1233 :   v8::Local<v8::External> data = v8::External::New(isolate, this);
     668        2466 :   console->SetAccessorProperty(
     669             :       toV8StringInternalized(isolate, "memory"),
     670        1233 :       v8::Function::New(
     671             :           context, &V8Console::call<&V8Console::memoryGetterCallback>, data, 0,
     672        1233 :           v8::ConstructorBehavior::kThrow, v8::SideEffectType::kHasNoSideEffect)
     673             :           .ToLocalChecked(),
     674        1233 :       v8::Function::New(context,
     675             :                         &V8Console::call<&V8Console::memorySetterCallback>,
     676        1233 :                         data, 0, v8::ConstructorBehavior::kThrow)
     677             :           .ToLocalChecked(),
     678        1233 :       static_cast<v8::PropertyAttribute>(v8::None), v8::DEFAULT);
     679        1233 : }
     680             : 
     681          30 : v8::Local<v8::Object> V8Console::createCommandLineAPI(
     682             :     v8::Local<v8::Context> context, int sessionId) {
     683          30 :   v8::Isolate* isolate = context->GetIsolate();
     684             :   v8::MicrotasksScope microtasksScope(isolate,
     685          60 :                                       v8::MicrotasksScope::kDoNotRunMicrotasks);
     686             : 
     687          30 :   v8::Local<v8::Object> commandLineAPI = v8::Object::New(isolate);
     688             :   bool success =
     689          30 :       commandLineAPI->SetPrototype(context, v8::Null(isolate)).FromMaybe(false);
     690             :   DCHECK(success);
     691             :   USE(success);
     692             : 
     693             :   v8::Local<v8::ArrayBuffer> data =
     694          30 :       v8::ArrayBuffer::New(isolate, sizeof(CommandLineAPIData));
     695          60 :   *static_cast<CommandLineAPIData*>(data->GetContents().Data()) =
     696             :       CommandLineAPIData(this, sessionId);
     697          30 :   createBoundFunctionProperty(context, commandLineAPI, data, "dir",
     698             :                               &V8Console::call<&V8Console::Dir>,
     699          30 :                               "function dir(value) { [Command Line API] }");
     700          30 :   createBoundFunctionProperty(context, commandLineAPI, data, "dirxml",
     701             :                               &V8Console::call<&V8Console::DirXml>,
     702          30 :                               "function dirxml(value) { [Command Line API] }");
     703          30 :   createBoundFunctionProperty(context, commandLineAPI, data, "profile",
     704             :                               &V8Console::call<&V8Console::Profile>,
     705          30 :                               "function profile(title) { [Command Line API] }");
     706          30 :   createBoundFunctionProperty(
     707             :       context, commandLineAPI, data, "profileEnd",
     708             :       &V8Console::call<&V8Console::ProfileEnd>,
     709          30 :       "function profileEnd(title) { [Command Line API] }");
     710          30 :   createBoundFunctionProperty(context, commandLineAPI, data, "clear",
     711             :                               &V8Console::call<&V8Console::Clear>,
     712          30 :                               "function clear() { [Command Line API] }");
     713          30 :   createBoundFunctionProperty(
     714             :       context, commandLineAPI, data, "table",
     715             :       &V8Console::call<&V8Console::Table>,
     716          30 :       "function table(data, [columns]) { [Command Line API] }");
     717             : 
     718          30 :   createBoundFunctionProperty(context, commandLineAPI, data, "keys",
     719             :                               &V8Console::call<&V8Console::keysCallback>,
     720             :                               "function keys(object) { [Command Line API] }",
     721          30 :                               v8::SideEffectType::kHasNoSideEffect);
     722          30 :   createBoundFunctionProperty(context, commandLineAPI, data, "values",
     723             :                               &V8Console::call<&V8Console::valuesCallback>,
     724             :                               "function values(object) { [Command Line API] }",
     725          30 :                               v8::SideEffectType::kHasNoSideEffect);
     726          30 :   createBoundFunctionProperty(
     727             :       context, commandLineAPI, data, "debug",
     728             :       &V8Console::call<&V8Console::debugFunctionCallback>,
     729          30 :       "function debug(function, condition) { [Command Line API] }");
     730          30 :   createBoundFunctionProperty(
     731             :       context, commandLineAPI, data, "undebug",
     732             :       &V8Console::call<&V8Console::undebugFunctionCallback>,
     733          30 :       "function undebug(function) { [Command Line API] }");
     734          30 :   createBoundFunctionProperty(
     735             :       context, commandLineAPI, data, "monitor",
     736             :       &V8Console::call<&V8Console::monitorFunctionCallback>,
     737          30 :       "function monitor(function) { [Command Line API] }");
     738          30 :   createBoundFunctionProperty(
     739             :       context, commandLineAPI, data, "unmonitor",
     740             :       &V8Console::call<&V8Console::unmonitorFunctionCallback>,
     741          30 :       "function unmonitor(function) { [Command Line API] }");
     742          30 :   createBoundFunctionProperty(
     743             :       context, commandLineAPI, data, "inspect",
     744             :       &V8Console::call<&V8Console::inspectCallback>,
     745          30 :       "function inspect(object) { [Command Line API] }");
     746          30 :   createBoundFunctionProperty(context, commandLineAPI, data, "copy",
     747             :                               &V8Console::call<&V8Console::copyCallback>,
     748          30 :                               "function copy(value) { [Command Line API] }");
     749          30 :   createBoundFunctionProperty(
     750             :       context, commandLineAPI, data, "queryObjects",
     751             :       &V8Console::call<&V8Console::queryObjectsCallback>,
     752          30 :       "function queryObjects(constructor) { [Command Line API] }");
     753          30 :   createBoundFunctionProperty(
     754             :       context, commandLineAPI, data, "$_",
     755             :       &V8Console::call<&V8Console::lastEvaluationResultCallback>, nullptr,
     756          30 :       v8::SideEffectType::kHasNoSideEffect);
     757          30 :   createBoundFunctionProperty(context, commandLineAPI, data, "$0",
     758             :                               &V8Console::call<&V8Console::inspectedObject0>,
     759          30 :                               nullptr, v8::SideEffectType::kHasNoSideEffect);
     760          30 :   createBoundFunctionProperty(context, commandLineAPI, data, "$1",
     761             :                               &V8Console::call<&V8Console::inspectedObject1>,
     762          30 :                               nullptr, v8::SideEffectType::kHasNoSideEffect);
     763          30 :   createBoundFunctionProperty(context, commandLineAPI, data, "$2",
     764             :                               &V8Console::call<&V8Console::inspectedObject2>,
     765          30 :                               nullptr, v8::SideEffectType::kHasNoSideEffect);
     766          30 :   createBoundFunctionProperty(context, commandLineAPI, data, "$3",
     767             :                               &V8Console::call<&V8Console::inspectedObject3>,
     768          30 :                               nullptr, v8::SideEffectType::kHasNoSideEffect);
     769          30 :   createBoundFunctionProperty(context, commandLineAPI, data, "$4",
     770             :                               &V8Console::call<&V8Console::inspectedObject4>,
     771          30 :                               nullptr, v8::SideEffectType::kHasNoSideEffect);
     772             : 
     773          30 :   m_inspector->client()->installAdditionalCommandLineAPI(context,
     774          30 :                                                          commandLineAPI);
     775          60 :   return commandLineAPI;
     776             : }
     777             : 
     778             : static bool isCommandLineAPIGetter(const String16& name) {
     779        1615 :   if (name.length() != 2) return false;
     780             :   // $0 ... $4, $_
     781         230 :   return name[0] == '$' &&
     782         115 :          ((name[1] >= '0' && name[1] <= '4') || name[1] == '_');
     783             : }
     784             : 
     785        9325 : void V8Console::CommandLineAPIScope::accessorGetterCallback(
     786             :     v8::Local<v8::Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
     787             :   CommandLineAPIScope* scope = static_cast<CommandLineAPIScope*>(
     788        9325 :       info.Data().As<v8::External>()->Value());
     789             :   DCHECK(scope);
     790             : 
     791        9325 :   v8::Local<v8::Context> context = info.GetIsolate()->GetCurrentContext();
     792        9325 :   if (scope->m_cleanup) {
     793        7710 :     bool removed = info.Holder()->Delete(context, name).FromMaybe(false);
     794             :     DCHECK(removed);
     795             :     USE(removed);
     796             :     return;
     797             :   }
     798        1615 :   v8::Local<v8::Object> commandLineAPI = scope->m_commandLineAPI;
     799             : 
     800             :   v8::Local<v8::Value> value;
     801        3230 :   if (!commandLineAPI->Get(context, name).ToLocal(&value)) return;
     802        1615 :   if (isCommandLineAPIGetter(
     803        3230 :           toProtocolStringWithTypeCheck(info.GetIsolate(), name))) {
     804             :     DCHECK(value->IsFunction());
     805             :     v8::MicrotasksScope microtasks(info.GetIsolate(),
     806         230 :                                    v8::MicrotasksScope::kDoNotRunMicrotasks);
     807         115 :     if (value.As<v8::Function>()
     808         230 :             ->Call(context, commandLineAPI, 0, nullptr)
     809             :             .ToLocal(&value))
     810             :       info.GetReturnValue().Set(value);
     811             :   } else {
     812             :     info.GetReturnValue().Set(value);
     813             :   }
     814             : }
     815             : 
     816          55 : void V8Console::CommandLineAPIScope::accessorSetterCallback(
     817             :     v8::Local<v8::Name> name, v8::Local<v8::Value> value,
     818             :     const v8::PropertyCallbackInfo<void>& info) {
     819             :   CommandLineAPIScope* scope = static_cast<CommandLineAPIScope*>(
     820          55 :       info.Data().As<v8::External>()->Value());
     821          55 :   v8::Local<v8::Context> context = info.GetIsolate()->GetCurrentContext();
     822         110 :   if (!info.Holder()->Delete(context, name).FromMaybe(false)) return;
     823         110 :   if (!info.Holder()->CreateDataProperty(context, name, value).FromMaybe(false))
     824             :     return;
     825             :   bool removed =
     826          55 :       scope->m_installedMethods->Delete(context, name).FromMaybe(false);
     827             :   DCHECK(removed);
     828             :   USE(removed);
     829             : }
     830             : 
     831         425 : V8Console::CommandLineAPIScope::CommandLineAPIScope(
     832             :     v8::Local<v8::Context> context, v8::Local<v8::Object> commandLineAPI,
     833             :     v8::Local<v8::Object> global)
     834             :     : m_context(context),
     835             :       m_commandLineAPI(commandLineAPI),
     836             :       m_global(global),
     837         425 :       m_installedMethods(v8::Set::New(context->GetIsolate())),
     838         850 :       m_cleanup(false) {
     839             :   v8::MicrotasksScope microtasksScope(context->GetIsolate(),
     840         850 :                                       v8::MicrotasksScope::kDoNotRunMicrotasks);
     841             :   v8::Local<v8::Array> names;
     842         850 :   if (!m_commandLineAPI->GetOwnPropertyNames(context).ToLocal(&names)) return;
     843             :   v8::Local<v8::External> externalThis =
     844         425 :       v8::External::New(context->GetIsolate(), this);
     845       18275 :   for (uint32_t i = 0; i < names->Length(); ++i) {
     846             :     v8::Local<v8::Value> name;
     847       17850 :     if (!names->Get(context, i).ToLocal(&name) || !name->IsName()) continue;
     848       17850 :     if (m_global->Has(context, name).FromMaybe(true)) continue;
     849       15530 :     if (!m_installedMethods->Add(context, name).ToLocal(&m_installedMethods))
     850             :       continue;
     851        7765 :     if (!m_global
     852       15530 :              ->SetAccessor(context, v8::Local<v8::Name>::Cast(name),
     853             :                            CommandLineAPIScope::accessorGetterCallback,
     854             :                            CommandLineAPIScope::accessorSetterCallback,
     855             :                            externalThis, v8::DEFAULT, v8::DontEnum,
     856        7765 :                            v8::SideEffectType::kHasNoSideEffect)
     857             :              .FromMaybe(false)) {
     858           0 :       bool removed = m_installedMethods->Delete(context, name).FromMaybe(false);
     859             :       DCHECK(removed);
     860             :       USE(removed);
     861             :       continue;
     862             :     }
     863             :   }
     864             : }
     865             : 
     866         850 : V8Console::CommandLineAPIScope::~CommandLineAPIScope() {
     867             :   v8::MicrotasksScope microtasksScope(m_context->GetIsolate(),
     868         850 :                                       v8::MicrotasksScope::kDoNotRunMicrotasks);
     869         425 :   m_cleanup = true;
     870         425 :   v8::Local<v8::Array> names = m_installedMethods->AsArray();
     871       15845 :   for (uint32_t i = 0; i < names->Length(); ++i) {
     872             :     v8::Local<v8::Value> name;
     873       15420 :     if (!names->Get(m_context, i).ToLocal(&name) || !name->IsName()) continue;
     874        7710 :     if (name->IsString()) {
     875             :       v8::Local<v8::Value> descriptor;
     876             :       bool success = m_global
     877        7710 :                          ->GetOwnPropertyDescriptor(
     878        7710 :                              m_context, v8::Local<v8::String>::Cast(name))
     879             :                          .ToLocal(&descriptor);
     880             :       DCHECK(success);
     881             :       USE(success);
     882             :     }
     883             :   }
     884         425 : }
     885             : 
     886             : }  // namespace v8_inspector

Generated by: LCOV version 1.10