| OLD | NEW | 
 | (Empty) | 
|    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/V8InspectorImpl.h" |  | 
|   32  |  | 
|   33 #include "src/inspector/InspectedContext.h" |  | 
|   34 #include "src/inspector/StringUtil.h" |  | 
|   35 #include "src/inspector/V8ConsoleAgentImpl.h" |  | 
|   36 #include "src/inspector/V8ConsoleMessage.h" |  | 
|   37 #include "src/inspector/V8Debugger.h" |  | 
|   38 #include "src/inspector/V8DebuggerAgentImpl.h" |  | 
|   39 #include "src/inspector/V8InspectorSessionImpl.h" |  | 
|   40 #include "src/inspector/V8ProfilerAgentImpl.h" |  | 
|   41 #include "src/inspector/V8RuntimeAgentImpl.h" |  | 
|   42 #include "src/inspector/V8StackTraceImpl.h" |  | 
|   43 #include "src/inspector/protocol/Protocol.h" |  | 
|   44  |  | 
|   45 namespace v8_inspector { |  | 
|   46  |  | 
|   47 std::unique_ptr<V8Inspector> V8Inspector::create(v8::Isolate* isolate, |  | 
|   48                                                  V8InspectorClient* client) { |  | 
|   49   return wrapUnique(new V8InspectorImpl(isolate, client)); |  | 
|   50 } |  | 
|   51  |  | 
|   52 V8InspectorImpl::V8InspectorImpl(v8::Isolate* isolate, |  | 
|   53                                  V8InspectorClient* client) |  | 
|   54     : m_isolate(isolate), |  | 
|   55       m_client(client), |  | 
|   56       m_debugger(new V8Debugger(isolate, this)), |  | 
|   57       m_capturingStackTracesCount(0), |  | 
|   58       m_lastExceptionId(0) {} |  | 
|   59  |  | 
|   60 V8InspectorImpl::~V8InspectorImpl() {} |  | 
|   61  |  | 
|   62 V8DebuggerAgentImpl* V8InspectorImpl::enabledDebuggerAgentForGroup( |  | 
|   63     int contextGroupId) { |  | 
|   64   V8InspectorSessionImpl* session = sessionForContextGroup(contextGroupId); |  | 
|   65   V8DebuggerAgentImpl* agent = session ? session->debuggerAgent() : nullptr; |  | 
|   66   return agent && agent->enabled() ? agent : nullptr; |  | 
|   67 } |  | 
|   68  |  | 
|   69 V8RuntimeAgentImpl* V8InspectorImpl::enabledRuntimeAgentForGroup( |  | 
|   70     int contextGroupId) { |  | 
|   71   V8InspectorSessionImpl* session = sessionForContextGroup(contextGroupId); |  | 
|   72   V8RuntimeAgentImpl* agent = session ? session->runtimeAgent() : nullptr; |  | 
|   73   return agent && agent->enabled() ? agent : nullptr; |  | 
|   74 } |  | 
|   75  |  | 
|   76 V8ProfilerAgentImpl* V8InspectorImpl::enabledProfilerAgentForGroup( |  | 
|   77     int contextGroupId) { |  | 
|   78   V8InspectorSessionImpl* session = sessionForContextGroup(contextGroupId); |  | 
|   79   V8ProfilerAgentImpl* agent = session ? session->profilerAgent() : nullptr; |  | 
|   80   return agent && agent->enabled() ? agent : nullptr; |  | 
|   81 } |  | 
|   82  |  | 
|   83 v8::MaybeLocal<v8::Value> V8InspectorImpl::runCompiledScript( |  | 
|   84     v8::Local<v8::Context> context, v8::Local<v8::Script> script) { |  | 
|   85   v8::MicrotasksScope microtasksScope(m_isolate, |  | 
|   86                                       v8::MicrotasksScope::kRunMicrotasks); |  | 
|   87   int groupId = V8Debugger::getGroupId(context); |  | 
|   88   if (V8DebuggerAgentImpl* agent = enabledDebuggerAgentForGroup(groupId)) |  | 
|   89     agent->willExecuteScript(script->GetUnboundScript()->GetId()); |  | 
|   90   v8::MaybeLocal<v8::Value> result = script->Run(context); |  | 
|   91   // Get agent from the map again, since it could have detached during script |  | 
|   92   // execution. |  | 
|   93   if (V8DebuggerAgentImpl* agent = enabledDebuggerAgentForGroup(groupId)) |  | 
|   94     agent->didExecuteScript(); |  | 
|   95   return result; |  | 
|   96 } |  | 
|   97  |  | 
|   98 v8::MaybeLocal<v8::Value> V8InspectorImpl::callFunction( |  | 
|   99     v8::Local<v8::Function> function, v8::Local<v8::Context> context, |  | 
|  100     v8::Local<v8::Value> receiver, int argc, v8::Local<v8::Value> info[]) { |  | 
|  101   v8::MicrotasksScope microtasksScope(m_isolate, |  | 
|  102                                       v8::MicrotasksScope::kRunMicrotasks); |  | 
|  103   int groupId = V8Debugger::getGroupId(context); |  | 
|  104   if (V8DebuggerAgentImpl* agent = enabledDebuggerAgentForGroup(groupId)) |  | 
|  105     agent->willExecuteScript(function->ScriptId()); |  | 
|  106   v8::MaybeLocal<v8::Value> result = |  | 
|  107       function->Call(context, receiver, argc, info); |  | 
|  108   // Get agent from the map again, since it could have detached during script |  | 
|  109   // execution. |  | 
|  110   if (V8DebuggerAgentImpl* agent = enabledDebuggerAgentForGroup(groupId)) |  | 
|  111     agent->didExecuteScript(); |  | 
|  112   return result; |  | 
|  113 } |  | 
|  114  |  | 
|  115 v8::MaybeLocal<v8::Value> V8InspectorImpl::compileAndRunInternalScript( |  | 
|  116     v8::Local<v8::Context> context, v8::Local<v8::String> source) { |  | 
|  117   v8::Local<v8::Script> script = |  | 
|  118       compileScript(context, source, String16(), true); |  | 
|  119   if (script.IsEmpty()) return v8::MaybeLocal<v8::Value>(); |  | 
|  120   v8::MicrotasksScope microtasksScope(m_isolate, |  | 
|  121                                       v8::MicrotasksScope::kDoNotRunMicrotasks); |  | 
|  122   return script->Run(context); |  | 
|  123 } |  | 
|  124  |  | 
|  125 v8::Local<v8::Script> V8InspectorImpl::compileScript( |  | 
|  126     v8::Local<v8::Context> context, v8::Local<v8::String> code, |  | 
|  127     const String16& fileName, bool markAsInternal) { |  | 
|  128   v8::ScriptOrigin origin( |  | 
|  129       toV8String(m_isolate, fileName), v8::Integer::New(m_isolate, 0), |  | 
|  130       v8::Integer::New(m_isolate, 0), |  | 
|  131       v8::False(m_isolate),  // sharable |  | 
|  132       v8::Local<v8::Integer>(), |  | 
|  133       v8::Boolean::New(m_isolate, markAsInternal),  // internal |  | 
|  134       toV8String(m_isolate, String16()),            // sourceMap |  | 
|  135       v8::True(m_isolate));                         // opaqueresource |  | 
|  136   v8::ScriptCompiler::Source source(code, origin); |  | 
|  137   v8::Local<v8::Script> script; |  | 
|  138   if (!v8::ScriptCompiler::Compile(context, &source, |  | 
|  139                                    v8::ScriptCompiler::kNoCompileOptions) |  | 
|  140            .ToLocal(&script)) |  | 
|  141     return v8::Local<v8::Script>(); |  | 
|  142   return script; |  | 
|  143 } |  | 
|  144  |  | 
|  145 void V8InspectorImpl::enableStackCapturingIfNeeded() { |  | 
|  146   if (!m_capturingStackTracesCount) |  | 
|  147     V8StackTraceImpl::setCaptureStackTraceForUncaughtExceptions(m_isolate, |  | 
|  148                                                                 true); |  | 
|  149   ++m_capturingStackTracesCount; |  | 
|  150 } |  | 
|  151  |  | 
|  152 void V8InspectorImpl::disableStackCapturingIfNeeded() { |  | 
|  153   if (!(--m_capturingStackTracesCount)) |  | 
|  154     V8StackTraceImpl::setCaptureStackTraceForUncaughtExceptions(m_isolate, |  | 
|  155                                                                 false); |  | 
|  156 } |  | 
|  157  |  | 
|  158 void V8InspectorImpl::muteExceptions(int contextGroupId) { |  | 
|  159   m_muteExceptionsMap[contextGroupId]++; |  | 
|  160 } |  | 
|  161  |  | 
|  162 void V8InspectorImpl::unmuteExceptions(int contextGroupId) { |  | 
|  163   m_muteExceptionsMap[contextGroupId]--; |  | 
|  164 } |  | 
|  165  |  | 
|  166 V8ConsoleMessageStorage* V8InspectorImpl::ensureConsoleMessageStorage( |  | 
|  167     int contextGroupId) { |  | 
|  168   ConsoleStorageMap::iterator storageIt = |  | 
|  169       m_consoleStorageMap.find(contextGroupId); |  | 
|  170   if (storageIt == m_consoleStorageMap.end()) |  | 
|  171     storageIt = |  | 
|  172         m_consoleStorageMap |  | 
|  173             .insert(std::make_pair( |  | 
|  174                 contextGroupId, |  | 
|  175                 wrapUnique(new V8ConsoleMessageStorage(this, contextGroupId)))) |  | 
|  176             .first; |  | 
|  177   return storageIt->second.get(); |  | 
|  178 } |  | 
|  179  |  | 
|  180 bool V8InspectorImpl::hasConsoleMessageStorage(int contextGroupId) { |  | 
|  181   ConsoleStorageMap::iterator storageIt = |  | 
|  182       m_consoleStorageMap.find(contextGroupId); |  | 
|  183   return storageIt != m_consoleStorageMap.end(); |  | 
|  184 } |  | 
|  185  |  | 
|  186 std::unique_ptr<V8StackTrace> V8InspectorImpl::createStackTrace( |  | 
|  187     v8::Local<v8::StackTrace> stackTrace) { |  | 
|  188   return m_debugger->createStackTrace(stackTrace); |  | 
|  189 } |  | 
|  190  |  | 
|  191 std::unique_ptr<V8InspectorSession> V8InspectorImpl::connect( |  | 
|  192     int contextGroupId, V8Inspector::Channel* channel, |  | 
|  193     const StringView& state) { |  | 
|  194   DCHECK(m_sessions.find(contextGroupId) == m_sessions.cend()); |  | 
|  195   std::unique_ptr<V8InspectorSessionImpl> session = |  | 
|  196       V8InspectorSessionImpl::create(this, contextGroupId, channel, state); |  | 
|  197   m_sessions[contextGroupId] = session.get(); |  | 
|  198   return std::move(session); |  | 
|  199 } |  | 
|  200  |  | 
|  201 void V8InspectorImpl::disconnect(V8InspectorSessionImpl* session) { |  | 
|  202   DCHECK(m_sessions.find(session->contextGroupId()) != m_sessions.end()); |  | 
|  203   m_sessions.erase(session->contextGroupId()); |  | 
|  204 } |  | 
|  205  |  | 
|  206 InspectedContext* V8InspectorImpl::getContext(int groupId, |  | 
|  207                                               int contextId) const { |  | 
|  208   if (!groupId || !contextId) return nullptr; |  | 
|  209  |  | 
|  210   ContextsByGroupMap::const_iterator contextGroupIt = m_contexts.find(groupId); |  | 
|  211   if (contextGroupIt == m_contexts.end()) return nullptr; |  | 
|  212  |  | 
|  213   ContextByIdMap::iterator contextIt = contextGroupIt->second->find(contextId); |  | 
|  214   if (contextIt == contextGroupIt->second->end()) return nullptr; |  | 
|  215  |  | 
|  216   return contextIt->second.get(); |  | 
|  217 } |  | 
|  218  |  | 
|  219 void V8InspectorImpl::contextCreated(const V8ContextInfo& info) { |  | 
|  220   int contextId = m_debugger->markContext(info); |  | 
|  221  |  | 
|  222   ContextsByGroupMap::iterator contextIt = m_contexts.find(info.contextGroupId); |  | 
|  223   if (contextIt == m_contexts.end()) |  | 
|  224     contextIt = m_contexts |  | 
|  225                     .insert(std::make_pair(info.contextGroupId, |  | 
|  226                                            wrapUnique(new ContextByIdMap()))) |  | 
|  227                     .first; |  | 
|  228  |  | 
|  229   const auto& contextById = contextIt->second; |  | 
|  230  |  | 
|  231   DCHECK(contextById->find(contextId) == contextById->cend()); |  | 
|  232   InspectedContext* context = new InspectedContext(this, info, contextId); |  | 
|  233   (*contextById)[contextId] = wrapUnique(context); |  | 
|  234   SessionMap::iterator sessionIt = m_sessions.find(info.contextGroupId); |  | 
|  235   if (sessionIt != m_sessions.end()) |  | 
|  236     sessionIt->second->runtimeAgent()->reportExecutionContextCreated(context); |  | 
|  237 } |  | 
|  238  |  | 
|  239 void V8InspectorImpl::contextDestroyed(v8::Local<v8::Context> context) { |  | 
|  240   int contextId = V8Debugger::contextId(context); |  | 
|  241   int contextGroupId = V8Debugger::getGroupId(context); |  | 
|  242  |  | 
|  243   ConsoleStorageMap::iterator storageIt = |  | 
|  244       m_consoleStorageMap.find(contextGroupId); |  | 
|  245   if (storageIt != m_consoleStorageMap.end()) |  | 
|  246     storageIt->second->contextDestroyed(contextId); |  | 
|  247  |  | 
|  248   InspectedContext* inspectedContext = getContext(contextGroupId, contextId); |  | 
|  249   if (!inspectedContext) return; |  | 
|  250  |  | 
|  251   SessionMap::iterator iter = m_sessions.find(contextGroupId); |  | 
|  252   if (iter != m_sessions.end()) |  | 
|  253     iter->second->runtimeAgent()->reportExecutionContextDestroyed( |  | 
|  254         inspectedContext); |  | 
|  255   discardInspectedContext(contextGroupId, contextId); |  | 
|  256 } |  | 
|  257  |  | 
|  258 void V8InspectorImpl::resetContextGroup(int contextGroupId) { |  | 
|  259   m_consoleStorageMap.erase(contextGroupId); |  | 
|  260   m_muteExceptionsMap.erase(contextGroupId); |  | 
|  261   SessionMap::iterator session = m_sessions.find(contextGroupId); |  | 
|  262   if (session != m_sessions.end()) session->second->reset(); |  | 
|  263   m_contexts.erase(contextGroupId); |  | 
|  264 } |  | 
|  265  |  | 
|  266 void V8InspectorImpl::willExecuteScript(v8::Local<v8::Context> context, |  | 
|  267                                         int scriptId) { |  | 
|  268   if (V8DebuggerAgentImpl* agent = |  | 
|  269           enabledDebuggerAgentForGroup(V8Debugger::getGroupId(context))) |  | 
|  270     agent->willExecuteScript(scriptId); |  | 
|  271 } |  | 
|  272  |  | 
|  273 void V8InspectorImpl::didExecuteScript(v8::Local<v8::Context> context) { |  | 
|  274   if (V8DebuggerAgentImpl* agent = |  | 
|  275           enabledDebuggerAgentForGroup(V8Debugger::getGroupId(context))) |  | 
|  276     agent->didExecuteScript(); |  | 
|  277 } |  | 
|  278  |  | 
|  279 void V8InspectorImpl::idleStarted() { |  | 
|  280   for (auto it = m_sessions.begin(); it != m_sessions.end(); ++it) { |  | 
|  281     if (it->second->profilerAgent()->idleStarted()) return; |  | 
|  282   } |  | 
|  283 } |  | 
|  284  |  | 
|  285 void V8InspectorImpl::idleFinished() { |  | 
|  286   for (auto it = m_sessions.begin(); it != m_sessions.end(); ++it) { |  | 
|  287     if (it->second->profilerAgent()->idleFinished()) return; |  | 
|  288   } |  | 
|  289 } |  | 
|  290  |  | 
|  291 unsigned V8InspectorImpl::exceptionThrown( |  | 
|  292     v8::Local<v8::Context> context, const StringView& message, |  | 
|  293     v8::Local<v8::Value> exception, const StringView& detailedMessage, |  | 
|  294     const StringView& url, unsigned lineNumber, unsigned columnNumber, |  | 
|  295     std::unique_ptr<V8StackTrace> stackTrace, int scriptId) { |  | 
|  296   int contextGroupId = V8Debugger::getGroupId(context); |  | 
|  297   if (!contextGroupId || m_muteExceptionsMap[contextGroupId]) return 0; |  | 
|  298   std::unique_ptr<V8StackTraceImpl> stackTraceImpl = |  | 
|  299       wrapUnique(static_cast<V8StackTraceImpl*>(stackTrace.release())); |  | 
|  300   unsigned exceptionId = nextExceptionId(); |  | 
|  301   std::unique_ptr<V8ConsoleMessage> consoleMessage = |  | 
|  302       V8ConsoleMessage::createForException( |  | 
|  303           m_client->currentTimeMS(), toString16(detailedMessage), |  | 
|  304           toString16(url), lineNumber, columnNumber, std::move(stackTraceImpl), |  | 
|  305           scriptId, m_isolate, toString16(message), |  | 
|  306           V8Debugger::contextId(context), exception, exceptionId); |  | 
|  307   ensureConsoleMessageStorage(contextGroupId) |  | 
|  308       ->addMessage(std::move(consoleMessage)); |  | 
|  309   return exceptionId; |  | 
|  310 } |  | 
|  311  |  | 
|  312 void V8InspectorImpl::exceptionRevoked(v8::Local<v8::Context> context, |  | 
|  313                                        unsigned exceptionId, |  | 
|  314                                        const StringView& message) { |  | 
|  315   int contextGroupId = V8Debugger::getGroupId(context); |  | 
|  316   if (!contextGroupId) return; |  | 
|  317  |  | 
|  318   std::unique_ptr<V8ConsoleMessage> consoleMessage = |  | 
|  319       V8ConsoleMessage::createForRevokedException( |  | 
|  320           m_client->currentTimeMS(), toString16(message), exceptionId); |  | 
|  321   ensureConsoleMessageStorage(contextGroupId) |  | 
|  322       ->addMessage(std::move(consoleMessage)); |  | 
|  323 } |  | 
|  324  |  | 
|  325 std::unique_ptr<V8StackTrace> V8InspectorImpl::captureStackTrace( |  | 
|  326     bool fullStack) { |  | 
|  327   return m_debugger->captureStackTrace(fullStack); |  | 
|  328 } |  | 
|  329  |  | 
|  330 void V8InspectorImpl::asyncTaskScheduled(const StringView& taskName, void* task, |  | 
|  331                                          bool recurring) { |  | 
|  332   m_debugger->asyncTaskScheduled(taskName, task, recurring); |  | 
|  333 } |  | 
|  334  |  | 
|  335 void V8InspectorImpl::asyncTaskCanceled(void* task) { |  | 
|  336   m_debugger->asyncTaskCanceled(task); |  | 
|  337 } |  | 
|  338  |  | 
|  339 void V8InspectorImpl::asyncTaskStarted(void* task) { |  | 
|  340   m_debugger->asyncTaskStarted(task); |  | 
|  341 } |  | 
|  342  |  | 
|  343 void V8InspectorImpl::asyncTaskFinished(void* task) { |  | 
|  344   m_debugger->asyncTaskFinished(task); |  | 
|  345 } |  | 
|  346  |  | 
|  347 void V8InspectorImpl::allAsyncTasksCanceled() { |  | 
|  348   m_debugger->allAsyncTasksCanceled(); |  | 
|  349 } |  | 
|  350  |  | 
|  351 v8::Local<v8::Context> V8InspectorImpl::regexContext() { |  | 
|  352   if (m_regexContext.IsEmpty()) |  | 
|  353     m_regexContext.Reset(m_isolate, v8::Context::New(m_isolate)); |  | 
|  354   return m_regexContext.Get(m_isolate); |  | 
|  355 } |  | 
|  356  |  | 
|  357 void V8InspectorImpl::discardInspectedContext(int contextGroupId, |  | 
|  358                                               int contextId) { |  | 
|  359   if (!getContext(contextGroupId, contextId)) return; |  | 
|  360   m_contexts[contextGroupId]->erase(contextId); |  | 
|  361   if (m_contexts[contextGroupId]->empty()) m_contexts.erase(contextGroupId); |  | 
|  362 } |  | 
|  363  |  | 
|  364 const V8InspectorImpl::ContextByIdMap* V8InspectorImpl::contextGroup( |  | 
|  365     int contextGroupId) { |  | 
|  366   ContextsByGroupMap::iterator iter = m_contexts.find(contextGroupId); |  | 
|  367   return iter == m_contexts.end() ? nullptr : iter->second.get(); |  | 
|  368 } |  | 
|  369  |  | 
|  370 V8InspectorSessionImpl* V8InspectorImpl::sessionForContextGroup( |  | 
|  371     int contextGroupId) { |  | 
|  372   if (!contextGroupId) return nullptr; |  | 
|  373   SessionMap::iterator iter = m_sessions.find(contextGroupId); |  | 
|  374   return iter == m_sessions.end() ? nullptr : iter->second; |  | 
|  375 } |  | 
|  376  |  | 
|  377 }  // namespace v8_inspector |  | 
| OLD | NEW |