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