LCOV - code coverage report
Current view: top level - src/inspector - v8-inspector-impl.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 134 154 87.0 %
Date: 2017-10-20 Functions: 33 39 84.6 %

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2010-2011 Google Inc. All rights reserved.
       3             :  *
       4             :  * Redistribution and use in source and binary forms, with or without
       5             :  * modification, are permitted provided that the following conditions are
       6             :  * met:
       7             :  *
       8             :  *     * Redistributions of source code must retain the above copyright
       9             :  * notice, this list of conditions and the following disclaimer.
      10             :  *     * Redistributions in binary form must reproduce the above
      11             :  * copyright notice, this list of conditions and the following disclaimer
      12             :  * in the documentation and/or other materials provided with the
      13             :  * distribution.
      14             :  *     * Neither the name of Google Inc. nor the names of its
      15             :  * contributors may be used to endorse or promote products derived from
      16             :  * this software without specific prior written permission.
      17             :  *
      18             :  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
      19             :  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
      20             :  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
      21             :  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
      22             :  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
      23             :  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
      24             :  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
      25             :  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
      26             :  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
      27             :  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
      28             :  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
      29             :  */
      30             : 
      31             : #include "src/inspector/v8-inspector-impl.h"
      32             : 
      33             : #include <vector>
      34             : 
      35             : #include "src/inspector/inspected-context.h"
      36             : #include "src/inspector/string-util.h"
      37             : #include "src/inspector/v8-console-agent-impl.h"
      38             : #include "src/inspector/v8-console-message.h"
      39             : #include "src/inspector/v8-console.h"
      40             : #include "src/inspector/v8-debugger-agent-impl.h"
      41             : #include "src/inspector/v8-debugger.h"
      42             : #include "src/inspector/v8-inspector-session-impl.h"
      43             : #include "src/inspector/v8-profiler-agent-impl.h"
      44             : #include "src/inspector/v8-runtime-agent-impl.h"
      45             : #include "src/inspector/v8-stack-trace-impl.h"
      46             : 
      47             : namespace v8_inspector {
      48             : 
      49        3261 : std::unique_ptr<V8Inspector> V8Inspector::create(v8::Isolate* isolate,
      50             :                                                  V8InspectorClient* client) {
      51        6522 :   return std::unique_ptr<V8Inspector>(new V8InspectorImpl(isolate, client));
      52             : }
      53             : 
      54        3261 : V8InspectorImpl::V8InspectorImpl(v8::Isolate* isolate,
      55             :                                  V8InspectorClient* client)
      56             :     : m_isolate(isolate),
      57             :       m_client(client),
      58        3261 :       m_debugger(new V8Debugger(isolate, this)),
      59             :       m_capturingStackTracesCount(0),
      60             :       m_lastExceptionId(0),
      61       22827 :       m_lastContextId(0) {
      62        3261 :   v8::debug::SetConsoleDelegate(m_isolate, console());
      63        3261 : }
      64             : 
      65        6522 : V8InspectorImpl::~V8InspectorImpl() {
      66        3261 :   v8::debug::SetConsoleDelegate(m_isolate, nullptr);
      67        6522 : }
      68             : 
      69      652763 : int V8InspectorImpl::contextGroupId(v8::Local<v8::Context> context) const {
      70     1305526 :   return contextGroupId(InspectedContext::contextId(context));
      71             : }
      72             : 
      73       70385 : int V8InspectorImpl::contextGroupId(int contextId) const {
      74             :   auto it = m_contextIdToGroupIdMap.find(contextId);
      75      725152 :   return it != m_contextIdToGroupIdMap.end() ? it->second : 0;
      76             : }
      77             : 
      78        3175 : v8::MaybeLocal<v8::Value> V8InspectorImpl::compileAndRunInternalScript(
      79             :     v8::Local<v8::Context> context, v8::Local<v8::String> source) {
      80             :   v8::Local<v8::UnboundScript> unboundScript;
      81        6350 :   if (!v8::debug::CompileInspectorScript(m_isolate, source)
      82        3175 :            .ToLocal(&unboundScript))
      83           0 :     return v8::MaybeLocal<v8::Value>();
      84             :   v8::MicrotasksScope microtasksScope(m_isolate,
      85        3175 :                                       v8::MicrotasksScope::kDoNotRunMicrotasks);
      86             :   v8::Context::Scope contextScope(context);
      87        9525 :   return unboundScript->BindToCurrentContext()->Run(context);
      88             : }
      89             : 
      90        6169 : v8::MaybeLocal<v8::Script> V8InspectorImpl::compileScript(
      91             :     v8::Local<v8::Context> context, const String16& code,
      92             :     const String16& fileName) {
      93             :   v8::ScriptOrigin origin(
      94             :       toV8String(m_isolate, fileName), v8::Integer::New(m_isolate, 0),
      95             :       v8::Integer::New(m_isolate, 0),
      96             :       v8::False(m_isolate),                                         // sharable
      97             :       v8::Local<v8::Integer>(), toV8String(m_isolate, String16()),  // sourceMap
      98       24676 :       v8::True(m_isolate));  // opaqueresource
      99        6169 :   v8::ScriptCompiler::Source source(toV8String(m_isolate, code), origin);
     100             :   return v8::ScriptCompiler::Compile(context, &source,
     101       12338 :                                      v8::ScriptCompiler::kNoCompileOptions);
     102             : }
     103             : 
     104         600 : void V8InspectorImpl::enableStackCapturingIfNeeded() {
     105         600 :   if (!m_capturingStackTracesCount)
     106             :     V8StackTraceImpl::setCaptureStackTraceForUncaughtExceptions(m_isolate,
     107         545 :                                                                 true);
     108         600 :   ++m_capturingStackTracesCount;
     109         600 : }
     110             : 
     111         600 : void V8InspectorImpl::disableStackCapturingIfNeeded() {
     112         600 :   if (!(--m_capturingStackTracesCount))
     113             :     V8StackTraceImpl::setCaptureStackTraceForUncaughtExceptions(m_isolate,
     114         545 :                                                                 false);
     115         600 : }
     116             : 
     117      617449 : void V8InspectorImpl::muteExceptions(int contextGroupId) {
     118      617449 :   m_muteExceptionsMap[contextGroupId]++;
     119      617449 : }
     120             : 
     121      617449 : void V8InspectorImpl::unmuteExceptions(int contextGroupId) {
     122      617449 :   m_muteExceptionsMap[contextGroupId]--;
     123      617449 : }
     124             : 
     125        7510 : V8ConsoleMessageStorage* V8InspectorImpl::ensureConsoleMessageStorage(
     126             :     int contextGroupId) {
     127             :   ConsoleStorageMap::iterator storageIt =
     128             :       m_consoleStorageMap.find(contextGroupId);
     129        7510 :   if (storageIt == m_consoleStorageMap.end())
     130             :     storageIt = m_consoleStorageMap
     131             :                     .insert(std::make_pair(
     132             :                         contextGroupId,
     133             :                         std::unique_ptr<V8ConsoleMessageStorage>(
     134         690 :                             new V8ConsoleMessageStorage(this, contextGroupId))))
     135             :                     .first;
     136        7510 :   return storageIt->second.get();
     137             : }
     138             : 
     139       19885 : bool V8InspectorImpl::hasConsoleMessageStorage(int contextGroupId) {
     140             :   ConsoleStorageMap::iterator storageIt =
     141             :       m_consoleStorageMap.find(contextGroupId);
     142       19885 :   return storageIt != m_consoleStorageMap.end();
     143             : }
     144             : 
     145         215 : std::unique_ptr<V8StackTrace> V8InspectorImpl::createStackTrace(
     146             :     v8::Local<v8::StackTrace> stackTrace) {
     147         430 :   return m_debugger->createStackTrace(stackTrace);
     148             : }
     149             : 
     150        3406 : std::unique_ptr<V8InspectorSession> V8InspectorImpl::connect(
     151             :     int contextGroupId, V8Inspector::Channel* channel,
     152             :     const StringView& state) {
     153        3406 :   int sessionId = ++m_lastSessionId;
     154             :   std::unique_ptr<V8InspectorSessionImpl> session =
     155             :       V8InspectorSessionImpl::create(this, contextGroupId, sessionId, channel,
     156        3406 :                                      state);
     157        6812 :   m_sessions[contextGroupId][sessionId] = session.get();
     158        3406 :   return std::move(session);
     159             : }
     160             : 
     161       10163 : void V8InspectorImpl::disconnect(V8InspectorSessionImpl* session) {
     162        6812 :   auto& map = m_sessions[session->contextGroupId()];
     163        6812 :   map.erase(session->sessionId());
     164       10108 :   if (map.empty()) m_sessions.erase(session->contextGroupId());
     165        3406 : }
     166             : 
     167      277606 : InspectedContext* V8InspectorImpl::getContext(int groupId,
     168             :                                               int contextId) const {
     169      277606 :   if (!groupId || !contextId) return nullptr;
     170             : 
     171             :   ContextsByGroupMap::const_iterator contextGroupIt = m_contexts.find(groupId);
     172      277576 :   if (contextGroupIt == m_contexts.end()) return nullptr;
     173             : 
     174             :   ContextByIdMap::iterator contextIt = contextGroupIt->second->find(contextId);
     175      277566 :   if (contextIt == contextGroupIt->second->end()) return nullptr;
     176             : 
     177      277556 :   return contextIt->second.get();
     178             : }
     179             : 
     180        2004 : InspectedContext* V8InspectorImpl::getContext(int contextId) const {
     181        2004 :   return getContext(contextGroupId(contextId), contextId);
     182             : }
     183             : 
     184        3326 : void V8InspectorImpl::contextCreated(const V8ContextInfo& info) {
     185        3326 :   int contextId = ++m_lastContextId;
     186        3326 :   InspectedContext* context = new InspectedContext(this, info, contextId);
     187        3326 :   m_contextIdToGroupIdMap[contextId] = info.contextGroupId;
     188             : 
     189        6652 :   ContextsByGroupMap::iterator contextIt = m_contexts.find(info.contextGroupId);
     190        3326 :   if (contextIt == m_contexts.end())
     191             :     contextIt = m_contexts
     192             :                     .insert(std::make_pair(
     193             :                         info.contextGroupId,
     194        6652 :                         std::unique_ptr<ContextByIdMap>(new ContextByIdMap())))
     195             :                     .first;
     196             :   const auto& contextById = contextIt->second;
     197             : 
     198             :   DCHECK(contextById->find(contextId) == contextById->cend());
     199        3326 :   (*contextById)[contextId].reset(context);
     200             :   forEachSession(
     201             :       info.contextGroupId, [&context](V8InspectorSessionImpl* session) {
     202        4946 :         session->runtimeAgent()->reportExecutionContextCreated(context);
     203        6652 :       });
     204        3326 : }
     205             : 
     206          15 : void V8InspectorImpl::contextDestroyed(v8::Local<v8::Context> context) {
     207          15 :   int contextId = InspectedContext::contextId(context);
     208          15 :   int groupId = contextGroupId(context);
     209          15 :   contextCollected(groupId, contextId);
     210          15 : }
     211             : 
     212          20 : void V8InspectorImpl::contextCollected(int groupId, int contextId) {
     213             :   m_contextIdToGroupIdMap.erase(contextId);
     214             : 
     215             :   ConsoleStorageMap::iterator storageIt = m_consoleStorageMap.find(groupId);
     216          20 :   if (storageIt != m_consoleStorageMap.end())
     217          40 :     storageIt->second->contextDestroyed(contextId);
     218             : 
     219          20 :   InspectedContext* inspectedContext = getContext(groupId, contextId);
     220          20 :   if (!inspectedContext) return;
     221             : 
     222             :   forEachSession(groupId, [&inspectedContext](V8InspectorSessionImpl* session) {
     223          60 :     session->runtimeAgent()->reportExecutionContextDestroyed(inspectedContext);
     224          40 :   });
     225          20 :   discardInspectedContext(groupId, contextId);
     226             : }
     227             : 
     228           0 : void V8InspectorImpl::resetContextGroup(int contextGroupId) {
     229             :   m_consoleStorageMap.erase(contextGroupId);
     230             :   m_muteExceptionsMap.erase(contextGroupId);
     231             :   forEachSession(contextGroupId,
     232           0 :                  [](V8InspectorSessionImpl* session) { session->reset(); });
     233             :   m_contexts.erase(contextGroupId);
     234             :   m_debugger->wasmTranslation()->Clear();
     235           0 : }
     236             : 
     237           0 : void V8InspectorImpl::idleStarted() {
     238           0 :   for (auto& it : m_sessions) {
     239           0 :     for (auto& it2 : it.second) {
     240           0 :       if (it2.second->profilerAgent()->idleStarted()) return;
     241             :     }
     242             :   }
     243             : }
     244             : 
     245           0 : void V8InspectorImpl::idleFinished() {
     246           0 :   for (auto& it : m_sessions) {
     247           0 :     for (auto& it2 : it.second) {
     248           0 :       if (it2.second->profilerAgent()->idleFinished()) return;
     249             :     }
     250             :   }
     251             : }
     252             : 
     253         215 : unsigned V8InspectorImpl::exceptionThrown(
     254             :     v8::Local<v8::Context> context, const StringView& message,
     255             :     v8::Local<v8::Value> exception, const StringView& detailedMessage,
     256             :     const StringView& url, unsigned lineNumber, unsigned columnNumber,
     257             :     std::unique_ptr<V8StackTrace> stackTrace, int scriptId) {
     258         215 :   int groupId = contextGroupId(context);
     259         430 :   if (!groupId || m_muteExceptionsMap[groupId]) return 0;
     260             :   std::unique_ptr<V8StackTraceImpl> stackTraceImpl(
     261             :       static_cast<V8StackTraceImpl*>(stackTrace.release()));
     262             :   unsigned exceptionId = nextExceptionId();
     263             :   std::unique_ptr<V8ConsoleMessage> consoleMessage =
     264             :       V8ConsoleMessage::createForException(
     265         215 :           m_client->currentTimeMS(), toString16(detailedMessage),
     266             :           toString16(url), lineNumber, columnNumber, std::move(stackTraceImpl),
     267             :           scriptId, m_isolate, toString16(message),
     268        1505 :           InspectedContext::contextId(context), exception, exceptionId);
     269         430 :   ensureConsoleMessageStorage(groupId)->addMessage(std::move(consoleMessage));
     270             :   return exceptionId;
     271             : }
     272             : 
     273          80 : void V8InspectorImpl::exceptionRevoked(v8::Local<v8::Context> context,
     274             :                                        unsigned exceptionId,
     275             :                                        const StringView& message) {
     276          80 :   int groupId = contextGroupId(context);
     277          80 :   if (!groupId) return;
     278             : 
     279             :   std::unique_ptr<V8ConsoleMessage> consoleMessage =
     280             :       V8ConsoleMessage::createForRevokedException(
     281         160 :           m_client->currentTimeMS(), toString16(message), exceptionId);
     282         160 :   ensureConsoleMessageStorage(groupId)->addMessage(std::move(consoleMessage));
     283             : }
     284             : 
     285           0 : std::unique_ptr<V8StackTrace> V8InspectorImpl::captureStackTrace(
     286             :     bool fullStack) {
     287           0 :   return m_debugger->captureStackTrace(fullStack);
     288             : }
     289             : 
     290        1385 : void V8InspectorImpl::asyncTaskScheduled(const StringView& taskName, void* task,
     291             :                                          bool recurring) {
     292        2770 :   if (!task) return;
     293        2770 :   m_debugger->asyncTaskScheduled(taskName, task, recurring);
     294             : }
     295             : 
     296           0 : void V8InspectorImpl::asyncTaskCanceled(void* task) {
     297           0 :   if (!task) return;
     298           0 :   m_debugger->asyncTaskCanceled(task);
     299             : }
     300             : 
     301        1385 : void V8InspectorImpl::asyncTaskStarted(void* task) {
     302        2770 :   if (!task) return;
     303        1385 :   m_debugger->asyncTaskStarted(task);
     304             : }
     305             : 
     306        1385 : void V8InspectorImpl::asyncTaskFinished(void* task) {
     307        2770 :   if (!task) return;
     308        1385 :   m_debugger->asyncTaskFinished(task);
     309             : }
     310             : 
     311           0 : void V8InspectorImpl::allAsyncTasksCanceled() {
     312           0 :   m_debugger->allAsyncTasksCanceled();
     313           0 : }
     314             : 
     315         405 : v8::Local<v8::Context> V8InspectorImpl::regexContext() {
     316         405 :   if (m_regexContext.IsEmpty())
     317         102 :     m_regexContext.Reset(m_isolate, v8::Context::New(m_isolate));
     318         810 :   return m_regexContext.Get(m_isolate);
     319             : }
     320             : 
     321          20 : void V8InspectorImpl::discardInspectedContext(int contextGroupId,
     322             :                                               int contextId) {
     323          40 :   if (!getContext(contextGroupId, contextId)) return;
     324             :   m_contexts[contextGroupId]->erase(contextId);
     325          20 :   if (m_contexts[contextGroupId]->empty()) m_contexts.erase(contextGroupId);
     326             : }
     327             : 
     328      100925 : V8InspectorSessionImpl* V8InspectorImpl::sessionById(int contextGroupId,
     329             :                                                      int sessionId) {
     330             :   auto it = m_sessions.find(contextGroupId);
     331      100925 :   if (it == m_sessions.end()) return nullptr;
     332             :   auto it2 = it->second.find(sessionId);
     333      100915 :   return it2 == it->second.end() ? nullptr : it2->second;
     334             : }
     335             : 
     336        4164 : V8Console* V8InspectorImpl::console() {
     337        4164 :   if (!m_console) m_console.reset(new V8Console(this));
     338        4164 :   return m_console.get();
     339             : }
     340             : 
     341       45902 : void V8InspectorImpl::forEachContext(
     342             :     int contextGroupId, std::function<void(InspectedContext*)> callback) {
     343             :   auto it = m_contexts.find(contextGroupId);
     344       45917 :   if (it == m_contexts.end()) return;
     345             :   std::vector<int> ids;
     346       45887 :   ids.reserve(it->second->size());
     347      137661 :   for (auto& contextIt : *(it->second)) ids.push_back(contextIt.first);
     348             : 
     349             :   // Retrieve by ids each time since |callback| may destroy some contexts.
     350      137661 :   for (auto& contextId : ids) {
     351             :     it = m_contexts.find(contextGroupId);
     352       45887 :     if (it == m_contexts.end()) continue;
     353             :     auto contextIt = it->second->find(contextId);
     354       91774 :     if (contextIt != it->second->end()) callback(contextIt->second.get());
     355             :   }
     356             : }
     357             : 
     358      195555 : void V8InspectorImpl::forEachSession(
     359             :     int contextGroupId, std::function<void(V8InspectorSessionImpl*)> callback) {
     360             :   auto it = m_sessions.find(contextGroupId);
     361      196768 :   if (it == m_sessions.end()) return;
     362             :   std::vector<int> ids;
     363      194342 :   ids.reserve(it->second.size());
     364      583691 :   for (auto& sessionIt : it->second) ids.push_back(sessionIt.first);
     365             : 
     366             :   // Retrieve by ids each time since |callback| may destroy some contexts.
     367      583691 :   for (auto& sessionId : ids) {
     368             :     it = m_sessions.find(contextGroupId);
     369      195007 :     if (it == m_sessions.end()) continue;
     370             :     auto sessionIt = it->second.find(sessionId);
     371      195007 :     if (sessionIt != it->second.end()) callback(sessionIt->second);
     372             :   }
     373             : }
     374             : 
     375             : }  // namespace v8_inspector

Generated by: LCOV version 1.10