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