| OLD | NEW | 
|---|
|  | (Empty) | 
| 1 /* |  | 
| 2  * Copyright (C) 2013 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 "core/inspector/AsyncCallTracker.h" |  | 
| 32 |  | 
| 33 #include "core/dom/ContextLifecycleObserver.h" |  | 
| 34 #include "core/dom/ExecutionContext.h" |  | 
| 35 #include "core/dom/ExecutionContextTask.h" |  | 
| 36 #include "core/events/Event.h" |  | 
| 37 #include "core/events/EventTarget.h" |  | 
| 38 #include "core/inspector/AsyncOperationMap.h" |  | 
| 39 #include "core/xmlhttprequest/XMLHttpRequest.h" |  | 
| 40 #include "core/xmlhttprequest/XMLHttpRequestUpload.h" |  | 
| 41 #include "platform/ScriptForbiddenScope.h" |  | 
| 42 #include "wtf/text/StringBuilder.h" |  | 
| 43 #include "wtf/text/StringHash.h" |  | 
| 44 |  | 
| 45 namespace { |  | 
| 46 |  | 
| 47 static const char setTimeoutName[] = "setTimeout"; |  | 
| 48 static const char setIntervalName[] = "setInterval"; |  | 
| 49 static const char requestAnimationFrameName[] = "requestAnimationFrame"; |  | 
| 50 static const char xhrSendName[] = "XMLHttpRequest.send"; |  | 
| 51 static const char enqueueMutationRecordName[] = "Mutation"; |  | 
| 52 |  | 
| 53 } |  | 
| 54 |  | 
| 55 namespace blink { |  | 
| 56 |  | 
| 57 class AsyncCallTracker::ExecutionContextData final : public GarbageCollectedFina
     lized<ExecutionContextData>, public ContextLifecycleObserver { |  | 
| 58     USING_GARBAGE_COLLECTED_MIXIN(AsyncCallTracker::ExecutionContextData); |  | 
| 59 public: |  | 
| 60     ExecutionContextData(AsyncCallTracker* tracker, ExecutionContext* executionC
     ontext) |  | 
| 61         : ContextLifecycleObserver(executionContext) |  | 
| 62         , m_tracker(tracker) |  | 
| 63         , m_timerCallChains(tracker->m_debuggerAgent) |  | 
| 64         , m_animationFrameCallChains(tracker->m_debuggerAgent) |  | 
| 65         , m_eventCallChains(tracker->m_debuggerAgent) |  | 
| 66         , m_xhrCallChains(tracker->m_debuggerAgent) |  | 
| 67         , m_mutationObserverCallChains(tracker->m_debuggerAgent) |  | 
| 68         , m_executionContextTaskCallChains(tracker->m_debuggerAgent) |  | 
| 69         , m_asyncOperations(tracker->m_debuggerAgent) |  | 
| 70     { |  | 
| 71     } |  | 
| 72 |  | 
| 73     void contextDestroyed() override |  | 
| 74     { |  | 
| 75         ASSERT(getExecutionContext()); |  | 
| 76         RawPtr<ExecutionContextData> self = m_tracker->m_executionContextDataMap
     .take(getExecutionContext()); |  | 
| 77         ASSERT_UNUSED(self, self == this); |  | 
| 78         ContextLifecycleObserver::contextDestroyed(); |  | 
| 79         disposeCallChains(); |  | 
| 80     } |  | 
| 81 |  | 
| 82     void unobserve() |  | 
| 83     { |  | 
| 84         disposeCallChains(); |  | 
| 85         ContextLifecycleObserver::clearContext(); |  | 
| 86     } |  | 
| 87 |  | 
| 88     DEFINE_INLINE_VIRTUAL_TRACE() |  | 
| 89     { |  | 
| 90         visitor->trace(m_tracker); |  | 
| 91         visitor->trace(m_timerCallChains); |  | 
| 92         visitor->trace(m_animationFrameCallChains); |  | 
| 93         visitor->trace(m_eventCallChains); |  | 
| 94         visitor->trace(m_xhrCallChains); |  | 
| 95         visitor->trace(m_mutationObserverCallChains); |  | 
| 96         visitor->trace(m_executionContextTaskCallChains); |  | 
| 97         visitor->trace(m_asyncOperations); |  | 
| 98         ContextLifecycleObserver::trace(visitor); |  | 
| 99     } |  | 
| 100 |  | 
| 101     Member<AsyncCallTracker> m_tracker; |  | 
| 102     HashSet<int> m_intervalTimerIds; |  | 
| 103     AsyncOperationMap<int> m_timerCallChains; |  | 
| 104     AsyncOperationMap<int> m_animationFrameCallChains; |  | 
| 105     AsyncOperationMap<Member<Event>> m_eventCallChains; |  | 
| 106     AsyncOperationMap<Member<EventTarget>> m_xhrCallChains; |  | 
| 107     AsyncOperationMap<Member<MutationObserver>> m_mutationObserverCallChains; |  | 
| 108     AsyncOperationMap<ExecutionContextTask*> m_executionContextTaskCallChains; |  | 
| 109     AsyncOperationMap<int> m_asyncOperations; |  | 
| 110 |  | 
| 111 private: |  | 
| 112     void disposeCallChains() |  | 
| 113     { |  | 
| 114         m_timerCallChains.dispose(); |  | 
| 115         m_animationFrameCallChains.dispose(); |  | 
| 116         m_eventCallChains.dispose(); |  | 
| 117         m_xhrCallChains.dispose(); |  | 
| 118         m_mutationObserverCallChains.dispose(); |  | 
| 119         m_executionContextTaskCallChains.dispose(); |  | 
| 120         m_asyncOperations.dispose(); |  | 
| 121     } |  | 
| 122 }; |  | 
| 123 |  | 
| 124 static XMLHttpRequest* toXmlHttpRequest(EventTarget* eventTarget) |  | 
| 125 { |  | 
| 126     const AtomicString& interfaceName = eventTarget->interfaceName(); |  | 
| 127     if (interfaceName == EventTargetNames::XMLHttpRequest) |  | 
| 128         return static_cast<XMLHttpRequest*>(eventTarget); |  | 
| 129     if (interfaceName == EventTargetNames::XMLHttpRequestUpload) |  | 
| 130         return static_cast<XMLHttpRequestUpload*>(eventTarget)->xmlHttpRequest()
     ; |  | 
| 131     return nullptr; |  | 
| 132 } |  | 
| 133 |  | 
| 134 AsyncCallTracker::AsyncCallTracker(V8DebuggerAgent* debuggerAgent, Instrumenting
     Agents* instrumentingAgents) |  | 
| 135     : m_debuggerAgent(debuggerAgent) |  | 
| 136     , m_instrumentingAgents(instrumentingAgents) |  | 
| 137 { |  | 
| 138 } |  | 
| 139 |  | 
| 140 AsyncCallTracker::~AsyncCallTracker() |  | 
| 141 { |  | 
| 142 } |  | 
| 143 |  | 
| 144 void AsyncCallTracker::asyncCallTrackingStateChanged(bool tracking) |  | 
| 145 { |  | 
| 146     m_instrumentingAgents->setAsyncCallTracker(tracking ? this : nullptr); |  | 
| 147 } |  | 
| 148 |  | 
| 149 void AsyncCallTracker::resetAsyncOperations() |  | 
| 150 { |  | 
| 151     for (auto& it : m_executionContextDataMap) |  | 
| 152         it.value->unobserve(); |  | 
| 153     m_executionContextDataMap.clear(); |  | 
| 154 } |  | 
| 155 |  | 
| 156 void AsyncCallTracker::didInstallTimer(ExecutionContext* context, int timerId, i
     nt timeout, bool singleShot) |  | 
| 157 { |  | 
| 158     ASSERT(context); |  | 
| 159     ASSERT(m_debuggerAgent->trackingAsyncCalls()); |  | 
| 160     int operationId = m_debuggerAgent->traceAsyncOperationStarting(singleShot ? 
     setTimeoutName : setIntervalName); |  | 
| 161     ASSERT(timerId > 0); |  | 
| 162     ExecutionContextData* data = createContextDataIfNeeded(context); |  | 
| 163     data->m_timerCallChains.set(timerId, operationId); |  | 
| 164     if (!singleShot) |  | 
| 165         data->m_intervalTimerIds.add(timerId); |  | 
| 166 } |  | 
| 167 |  | 
| 168 void AsyncCallTracker::didRemoveTimer(ExecutionContext* context, int timerId) |  | 
| 169 { |  | 
| 170     ASSERT(context); |  | 
| 171     ASSERT(m_debuggerAgent->trackingAsyncCalls()); |  | 
| 172     if (timerId <= 0) |  | 
| 173         return; |  | 
| 174     ExecutionContextData* data = m_executionContextDataMap.get(context); |  | 
| 175     if (!data) |  | 
| 176         return; |  | 
| 177     data->m_intervalTimerIds.remove(timerId); |  | 
| 178     data->m_timerCallChains.remove(timerId); |  | 
| 179 } |  | 
| 180 |  | 
| 181 bool AsyncCallTracker::willFireTimer(ExecutionContext* context, int timerId) |  | 
| 182 { |  | 
| 183     ASSERT(context); |  | 
| 184     ASSERT(m_debuggerAgent->trackingAsyncCalls()); |  | 
| 185     ASSERT(timerId > 0); |  | 
| 186     if (ExecutionContextData* data = m_executionContextDataMap.get(context)) { |  | 
| 187         willFireAsyncCall(data->m_timerCallChains.get(timerId)); |  | 
| 188         if (!data->m_intervalTimerIds.contains(timerId)) |  | 
| 189             data->m_timerCallChains.remove(timerId); |  | 
| 190     } else { |  | 
| 191         willFireAsyncCall(V8DebuggerAgent::unknownAsyncOperationId); |  | 
| 192     } |  | 
| 193     return true; |  | 
| 194 } |  | 
| 195 |  | 
| 196 void AsyncCallTracker::didRequestAnimationFrame(ExecutionContext* context, int c
     allbackId) |  | 
| 197 { |  | 
| 198     ASSERT(context); |  | 
| 199     ASSERT(m_debuggerAgent->trackingAsyncCalls()); |  | 
| 200     int operationId = m_debuggerAgent->traceAsyncOperationStarting(requestAnimat
     ionFrameName); |  | 
| 201     ASSERT(callbackId > 0); |  | 
| 202     ExecutionContextData* data = createContextDataIfNeeded(context); |  | 
| 203     data->m_animationFrameCallChains.set(callbackId, operationId); |  | 
| 204 } |  | 
| 205 |  | 
| 206 void AsyncCallTracker::didCancelAnimationFrame(ExecutionContext* context, int ca
     llbackId) |  | 
| 207 { |  | 
| 208     ASSERT(context); |  | 
| 209     ASSERT(m_debuggerAgent->trackingAsyncCalls()); |  | 
| 210     if (callbackId <= 0) |  | 
| 211         return; |  | 
| 212     if (ExecutionContextData* data = m_executionContextDataMap.get(context)) |  | 
| 213         data->m_animationFrameCallChains.remove(callbackId); |  | 
| 214 } |  | 
| 215 |  | 
| 216 bool AsyncCallTracker::willFireAnimationFrame(ExecutionContext* context, int cal
     lbackId) |  | 
| 217 { |  | 
| 218     ASSERT(context); |  | 
| 219     ASSERT(m_debuggerAgent->trackingAsyncCalls()); |  | 
| 220     ASSERT(callbackId > 0); |  | 
| 221     if (ExecutionContextData* data = m_executionContextDataMap.get(context)) { |  | 
| 222         willFireAsyncCall(data->m_animationFrameCallChains.get(callbackId)); |  | 
| 223         data->m_animationFrameCallChains.remove(callbackId); |  | 
| 224     } else { |  | 
| 225         willFireAsyncCall(V8DebuggerAgent::unknownAsyncOperationId); |  | 
| 226     } |  | 
| 227     return true; |  | 
| 228 } |  | 
| 229 |  | 
| 230 void AsyncCallTracker::didEnqueueEvent(EventTarget* eventTarget, Event* event) |  | 
| 231 { |  | 
| 232     ASSERT(eventTarget->getExecutionContext()); |  | 
| 233     ASSERT(m_debuggerAgent->trackingAsyncCalls()); |  | 
| 234     ScriptForbiddenScope::AllowUserAgentScript allowScripting; |  | 
| 235     int operationId = m_debuggerAgent->traceAsyncOperationStarting(event->type()
     ); |  | 
| 236     ExecutionContextData* data = createContextDataIfNeeded(eventTarget->getExecu
     tionContext()); |  | 
| 237     data->m_eventCallChains.set(event, operationId); |  | 
| 238 } |  | 
| 239 |  | 
| 240 void AsyncCallTracker::didRemoveEvent(EventTarget* eventTarget, Event* event) |  | 
| 241 { |  | 
| 242     ASSERT(eventTarget->getExecutionContext()); |  | 
| 243     ASSERT(m_debuggerAgent->trackingAsyncCalls()); |  | 
| 244     if (ExecutionContextData* data = m_executionContextDataMap.get(eventTarget->
     getExecutionContext())) |  | 
| 245         data->m_eventCallChains.remove(event); |  | 
| 246 } |  | 
| 247 |  | 
| 248 void AsyncCallTracker::willHandleEvent(EventTarget* eventTarget, Event* event, E
     ventListener* listener, bool useCapture) |  | 
| 249 { |  | 
| 250     ASSERT(eventTarget->getExecutionContext()); |  | 
| 251     ASSERT(m_debuggerAgent->trackingAsyncCalls()); |  | 
| 252     if (XMLHttpRequest* xhr = toXmlHttpRequest(eventTarget)) { |  | 
| 253         willHandleXHREvent(xhr, event); |  | 
| 254     } else { |  | 
| 255         ExecutionContext* context = eventTarget->getExecutionContext(); |  | 
| 256         if (ExecutionContextData* data = m_executionContextDataMap.get(context)) |  | 
| 257             willFireAsyncCall(data->m_eventCallChains.get(event)); |  | 
| 258         else |  | 
| 259             willFireAsyncCall(V8DebuggerAgent::unknownAsyncOperationId); |  | 
| 260     } |  | 
| 261 } |  | 
| 262 |  | 
| 263 void AsyncCallTracker::willLoadXHR(XMLHttpRequest* xhr, ThreadableLoaderClient*,
      const AtomicString&, const KURL&, bool async, PassRefPtr<EncodedFormData>, cons
     t HTTPHeaderMap&, bool) |  | 
| 264 { |  | 
| 265     ASSERT(xhr->getExecutionContext()); |  | 
| 266     ASSERT(m_debuggerAgent->trackingAsyncCalls()); |  | 
| 267     if (!async) |  | 
| 268         return; |  | 
| 269     int operationId = m_debuggerAgent->traceAsyncOperationStarting(xhrSendName); |  | 
| 270     ExecutionContextData* data = createContextDataIfNeeded(xhr->getExecutionCont
     ext()); |  | 
| 271     data->m_xhrCallChains.set(xhr, operationId); |  | 
| 272 } |  | 
| 273 |  | 
| 274 void AsyncCallTracker::didDispatchXHRLoadendEvent(XMLHttpRequest* xhr) |  | 
| 275 { |  | 
| 276     ASSERT(xhr->getExecutionContext()); |  | 
| 277     ASSERT(m_debuggerAgent->trackingAsyncCalls()); |  | 
| 278     if (ExecutionContextData* data = m_executionContextDataMap.get(xhr->getExecu
     tionContext())) |  | 
| 279         data->m_xhrCallChains.remove(xhr); |  | 
| 280 } |  | 
| 281 |  | 
| 282 void AsyncCallTracker::willHandleXHREvent(XMLHttpRequest* xhr, Event* event) |  | 
| 283 { |  | 
| 284     ExecutionContext* context = xhr->getExecutionContext(); |  | 
| 285     ASSERT(context); |  | 
| 286     ASSERT(m_debuggerAgent->trackingAsyncCalls()); |  | 
| 287     if (ExecutionContextData* data = m_executionContextDataMap.get(context)) |  | 
| 288         willFireAsyncCall(data->m_xhrCallChains.get(xhr)); |  | 
| 289     else |  | 
| 290         willFireAsyncCall(V8DebuggerAgent::unknownAsyncOperationId); |  | 
| 291 } |  | 
| 292 |  | 
| 293 void AsyncCallTracker::didEnqueueMutationRecord(ExecutionContext* context, Mutat
     ionObserver* observer) |  | 
| 294 { |  | 
| 295     ASSERT(context); |  | 
| 296     ASSERT(m_debuggerAgent->trackingAsyncCalls()); |  | 
| 297     ExecutionContextData* data = createContextDataIfNeeded(context); |  | 
| 298     if (data->m_mutationObserverCallChains.contains(observer)) |  | 
| 299         return; |  | 
| 300     ScriptForbiddenScope::AllowUserAgentScript allowScripting; |  | 
| 301     int operationId = m_debuggerAgent->traceAsyncOperationStarting(enqueueMutati
     onRecordName); |  | 
| 302     data->m_mutationObserverCallChains.set(observer, operationId); |  | 
| 303 } |  | 
| 304 |  | 
| 305 void AsyncCallTracker::didClearAllMutationRecords(ExecutionContext* context, Mut
     ationObserver* observer) |  | 
| 306 { |  | 
| 307     ASSERT(context); |  | 
| 308     ASSERT(m_debuggerAgent->trackingAsyncCalls()); |  | 
| 309     if (ExecutionContextData* data = m_executionContextDataMap.get(context)) |  | 
| 310         data->m_mutationObserverCallChains.remove(observer); |  | 
| 311 } |  | 
| 312 |  | 
| 313 void AsyncCallTracker::willDeliverMutationRecords(ExecutionContext* context, Mut
     ationObserver* observer) |  | 
| 314 { |  | 
| 315     ASSERT(context); |  | 
| 316     ASSERT(m_debuggerAgent->trackingAsyncCalls()); |  | 
| 317     if (ExecutionContextData* data = m_executionContextDataMap.get(context)) { |  | 
| 318         willFireAsyncCall(data->m_mutationObserverCallChains.get(observer)); |  | 
| 319         data->m_mutationObserverCallChains.remove(observer); |  | 
| 320     } else { |  | 
| 321         willFireAsyncCall(V8DebuggerAgent::unknownAsyncOperationId); |  | 
| 322     } |  | 
| 323 } |  | 
| 324 |  | 
| 325 void AsyncCallTracker::didPostExecutionContextTask(ExecutionContext* context, Ex
     ecutionContextTask* task) |  | 
| 326 { |  | 
| 327     ASSERT(context); |  | 
| 328     ASSERT(m_debuggerAgent->trackingAsyncCalls()); |  | 
| 329     if (task->taskNameForInstrumentation().isEmpty()) |  | 
| 330         return; |  | 
| 331     int operationId = m_debuggerAgent->traceAsyncOperationStarting(task->taskNam
     eForInstrumentation()); |  | 
| 332     ExecutionContextData* data = createContextDataIfNeeded(context); |  | 
| 333     data->m_executionContextTaskCallChains.set(task, operationId); |  | 
| 334 } |  | 
| 335 |  | 
| 336 void AsyncCallTracker::didKillAllExecutionContextTasks(ExecutionContext* context
     ) |  | 
| 337 { |  | 
| 338     ASSERT(context); |  | 
| 339     ASSERT(m_debuggerAgent->trackingAsyncCalls()); |  | 
| 340     if (ExecutionContextData* data = m_executionContextDataMap.get(context)) |  | 
| 341         data->m_executionContextTaskCallChains.clear(); |  | 
| 342 } |  | 
| 343 |  | 
| 344 void AsyncCallTracker::willPerformExecutionContextTask(ExecutionContext* context
     , ExecutionContextTask* task) |  | 
| 345 { |  | 
| 346     ASSERT(context); |  | 
| 347     ASSERT(m_debuggerAgent->trackingAsyncCalls()); |  | 
| 348     if (ExecutionContextData* data = m_executionContextDataMap.get(context)) { |  | 
| 349         willFireAsyncCall(data->m_executionContextTaskCallChains.get(task)); |  | 
| 350         data->m_executionContextTaskCallChains.remove(task); |  | 
| 351     } else { |  | 
| 352         willFireAsyncCall(V8DebuggerAgent::unknownAsyncOperationId); |  | 
| 353     } |  | 
| 354 } |  | 
| 355 |  | 
| 356 int AsyncCallTracker::traceAsyncOperationStarting(ExecutionContext* context, con
     st String& operationName, int prevOperationId) |  | 
| 357 { |  | 
| 358     ScriptForbiddenScope::AllowUserAgentScript allowScripting; |  | 
| 359     ASSERT(context); |  | 
| 360     ASSERT(m_debuggerAgent->trackingAsyncCalls()); |  | 
| 361     if (prevOperationId) |  | 
| 362         traceAsyncOperationCompleted(context, prevOperationId); |  | 
| 363     int operationId = m_debuggerAgent->traceAsyncOperationStarting(operationName
     ); |  | 
| 364     ExecutionContextData* data = createContextDataIfNeeded(context); |  | 
| 365     data->m_asyncOperations.set(operationId, operationId); |  | 
| 366     return operationId; |  | 
| 367 } |  | 
| 368 |  | 
| 369 void AsyncCallTracker::traceAsyncOperationCompleted(ExecutionContext* context, i
     nt operationId) |  | 
| 370 { |  | 
| 371     ASSERT(context); |  | 
| 372     ASSERT(m_debuggerAgent->trackingAsyncCalls()); |  | 
| 373     if (operationId <= 0) |  | 
| 374         return; |  | 
| 375     if (ExecutionContextData* data = m_executionContextDataMap.get(context)) |  | 
| 376         data->m_asyncOperations.remove(operationId); |  | 
| 377 } |  | 
| 378 |  | 
| 379 void AsyncCallTracker::traceAsyncOperationCompletedCallbackStarting(ExecutionCon
     text* context, int operationId) |  | 
| 380 { |  | 
| 381     traceAsyncCallbackStarting(context, operationId); |  | 
| 382     traceAsyncOperationCompleted(context, operationId); |  | 
| 383 } |  | 
| 384 |  | 
| 385 bool AsyncCallTracker::isKnownAsyncOperationId(ExecutionContext* context, int op
     erationId) const |  | 
| 386 { |  | 
| 387     if (operationId <= 0) |  | 
| 388         return false; |  | 
| 389     if (ExecutionContextData* data = m_executionContextDataMap.get(context)) |  | 
| 390         return data->m_asyncOperations.contains(operationId); |  | 
| 391     return false; |  | 
| 392 } |  | 
| 393 |  | 
| 394 void AsyncCallTracker::traceAsyncCallbackStarting(ExecutionContext* context, int
      operationId) |  | 
| 395 { |  | 
| 396     ASSERT(context); |  | 
| 397     ASSERT(m_debuggerAgent->trackingAsyncCalls()); |  | 
| 398     ASSERT(operationId <= 0 || isKnownAsyncOperationId(context, operationId)); |  | 
| 399     willFireAsyncCall(operationId > 0 ? operationId : V8DebuggerAgent::unknownAs
     yncOperationId); |  | 
| 400 } |  | 
| 401 |  | 
| 402 void AsyncCallTracker::didFireAsyncCall() |  | 
| 403 { |  | 
| 404     m_debuggerAgent->traceAsyncCallbackCompleted(); |  | 
| 405 } |  | 
| 406 |  | 
| 407 void AsyncCallTracker::willFireAsyncCall(int operationId) |  | 
| 408 { |  | 
| 409     m_debuggerAgent->traceAsyncCallbackStarting(operationId); |  | 
| 410 } |  | 
| 411 |  | 
| 412 AsyncCallTracker::ExecutionContextData* AsyncCallTracker::createContextDataIfNee
     ded(ExecutionContext* context) |  | 
| 413 { |  | 
| 414     ExecutionContextData* data = m_executionContextDataMap.get(context); |  | 
| 415     if (!data) { |  | 
| 416         data = m_executionContextDataMap.set(context, new AsyncCallTracker::Exec
     utionContextData(this, context)) |  | 
| 417             .storedValue->value.get(); |  | 
| 418     } |  | 
| 419     return data; |  | 
| 420 } |  | 
| 421 |  | 
| 422 DEFINE_TRACE(AsyncCallTracker) |  | 
| 423 { |  | 
| 424     visitor->trace(m_executionContextDataMap); |  | 
| 425     visitor->trace(m_instrumentingAgents); |  | 
| 426 } |  | 
| 427 |  | 
| 428 } // namespace blink |  | 
| OLD | NEW | 
|---|