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

Generated by: LCOV version 1.10