| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2013 Google Inc. All rights reserved. | 2 * Copyright (C) 2013 Google Inc. All rights reserved. |
| 3 * | 3 * |
| 4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
| 5 * modification, are permitted provided that the following conditions are | 5 * modification, are permitted provided that the following conditions are |
| 6 * met: | 6 * met: |
| 7 * | 7 * |
| 8 * * Redistributions of source code must retain the above copyright | 8 * * Redistributions of source code must retain the above copyright |
| 9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
| 10 * * Redistributions in binary form must reproduce the above | 10 * * Redistributions in binary form must reproduce the above |
| (...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 139 static XMLHttpRequest* toXmlHttpRequest(EventTarget* eventTarget) | 139 static XMLHttpRequest* toXmlHttpRequest(EventTarget* eventTarget) |
| 140 { | 140 { |
| 141 const AtomicString& interfaceName = eventTarget->interfaceName(); | 141 const AtomicString& interfaceName = eventTarget->interfaceName(); |
| 142 if (interfaceName == EventTargetNames::XMLHttpRequest) | 142 if (interfaceName == EventTargetNames::XMLHttpRequest) |
| 143 return static_cast<XMLHttpRequest*>(eventTarget); | 143 return static_cast<XMLHttpRequest*>(eventTarget); |
| 144 if (interfaceName == EventTargetNames::XMLHttpRequestUpload) | 144 if (interfaceName == EventTargetNames::XMLHttpRequestUpload) |
| 145 return static_cast<XMLHttpRequestUpload*>(eventTarget)->xmlHttpRequest()
; | 145 return static_cast<XMLHttpRequestUpload*>(eventTarget)->xmlHttpRequest()
; |
| 146 return 0; | 146 return 0; |
| 147 } | 147 } |
| 148 | 148 |
| 149 AsyncCallStackTracker::AsyncCallStack::AsyncCallStack(const String& description,
const ScriptValue& callFrames) | 149 AsyncCallStackTracker::AsyncCallStack::AsyncCallStack(const String& description,
const StackTrace& callFrames) |
| 150 : m_description(description) | 150 : m_description(description) |
| 151 , m_callFrames(callFrames) | 151 , m_callFrames(callFrames) |
| 152 { | 152 { |
| 153 } | 153 } |
| 154 | 154 |
| 155 AsyncCallStackTracker::AsyncCallStack::~AsyncCallStack() | 155 AsyncCallStackTracker::AsyncCallStack::~AsyncCallStack() |
| 156 { | 156 { |
| 157 } | 157 } |
| 158 | 158 |
| 159 AsyncCallStackTracker::AsyncCallStackTracker() | 159 AsyncCallStackTracker::AsyncCallStackTracker() |
| (...skipping 11 matching lines...) Expand all Loading... |
| 171 } | 171 } |
| 172 } | 172 } |
| 173 | 173 |
| 174 const AsyncCallStackTracker::AsyncCallChain* AsyncCallStackTracker::currentAsync
CallChain() const | 174 const AsyncCallStackTracker::AsyncCallChain* AsyncCallStackTracker::currentAsync
CallChain() const |
| 175 { | 175 { |
| 176 if (m_currentAsyncCallChain) | 176 if (m_currentAsyncCallChain) |
| 177 ensureMaxAsyncCallChainDepth(m_currentAsyncCallChain.get(), m_maxAsyncCa
llStackDepth); | 177 ensureMaxAsyncCallChainDepth(m_currentAsyncCallChain.get(), m_maxAsyncCa
llStackDepth); |
| 178 return m_currentAsyncCallChain.get(); | 178 return m_currentAsyncCallChain.get(); |
| 179 } | 179 } |
| 180 | 180 |
| 181 void AsyncCallStackTracker::didInstallTimer(ExecutionContext* context, int timer
Id, bool singleShot, const ScriptValue& callFrames) | 181 void AsyncCallStackTracker::didInstallTimer(ExecutionContext* context, int timer
Id, bool singleShot, const StackTrace& callFrames) |
| 182 { | 182 { |
| 183 ASSERT(context); | 183 ASSERT(context); |
| 184 ASSERT(isEnabled()); | 184 ASSERT(isEnabled()); |
| 185 if (!validateCallFrames(callFrames)) | 185 if (!validateCallFrames(callFrames)) |
| 186 return; | 186 return; |
| 187 ASSERT(timerId > 0); | 187 ASSERT(timerId > 0); |
| 188 ExecutionContextData* data = createContextDataIfNeeded(context); | 188 ExecutionContextData* data = createContextDataIfNeeded(context); |
| 189 data->m_timerCallChains.set(timerId, createAsyncCallChain(singleShot ? setTi
meoutName : setIntervalName, callFrames)); | 189 data->m_timerCallChains.set(timerId, createAsyncCallChain(singleShot ? setTi
meoutName : setIntervalName, callFrames)); |
| 190 if (!singleShot) | 190 if (!singleShot) |
| 191 data->m_intervalTimerIds.add(timerId); | 191 data->m_intervalTimerIds.add(timerId); |
| (...skipping 21 matching lines...) Expand all Loading... |
| 213 if (ExecutionContextData* data = m_executionContextDataMap.get(context)) { | 213 if (ExecutionContextData* data = m_executionContextDataMap.get(context)) { |
| 214 if (data->m_intervalTimerIds.contains(timerId)) | 214 if (data->m_intervalTimerIds.contains(timerId)) |
| 215 setCurrentAsyncCallChain(data->m_timerCallChains.get(timerId)); | 215 setCurrentAsyncCallChain(data->m_timerCallChains.get(timerId)); |
| 216 else | 216 else |
| 217 setCurrentAsyncCallChain(data->m_timerCallChains.take(timerId)); | 217 setCurrentAsyncCallChain(data->m_timerCallChains.take(timerId)); |
| 218 } else { | 218 } else { |
| 219 setCurrentAsyncCallChain(nullptr); | 219 setCurrentAsyncCallChain(nullptr); |
| 220 } | 220 } |
| 221 } | 221 } |
| 222 | 222 |
| 223 void AsyncCallStackTracker::didRequestAnimationFrame(ExecutionContext* context,
int callbackId, const ScriptValue& callFrames) | 223 void AsyncCallStackTracker::didRequestAnimationFrame(ExecutionContext* context,
int callbackId, const StackTrace& callFrames) |
| 224 { | 224 { |
| 225 ASSERT(context); | 225 ASSERT(context); |
| 226 ASSERT(isEnabled()); | 226 ASSERT(isEnabled()); |
| 227 if (!validateCallFrames(callFrames)) | 227 if (!validateCallFrames(callFrames)) |
| 228 return; | 228 return; |
| 229 ASSERT(callbackId > 0); | 229 ASSERT(callbackId > 0); |
| 230 ExecutionContextData* data = createContextDataIfNeeded(context); | 230 ExecutionContextData* data = createContextDataIfNeeded(context); |
| 231 data->m_animationFrameCallChains.set(callbackId, createAsyncCallChain(reques
tAnimationFrameName, callFrames)); | 231 data->m_animationFrameCallChains.set(callbackId, createAsyncCallChain(reques
tAnimationFrameName, callFrames)); |
| 232 } | 232 } |
| 233 | 233 |
| (...skipping 12 matching lines...) Expand all Loading... |
| 246 ASSERT(context); | 246 ASSERT(context); |
| 247 ASSERT(isEnabled()); | 247 ASSERT(isEnabled()); |
| 248 ASSERT(callbackId > 0); | 248 ASSERT(callbackId > 0); |
| 249 ASSERT(!m_currentAsyncCallChain); | 249 ASSERT(!m_currentAsyncCallChain); |
| 250 if (ExecutionContextData* data = m_executionContextDataMap.get(context)) | 250 if (ExecutionContextData* data = m_executionContextDataMap.get(context)) |
| 251 setCurrentAsyncCallChain(data->m_animationFrameCallChains.take(callbackI
d)); | 251 setCurrentAsyncCallChain(data->m_animationFrameCallChains.take(callbackI
d)); |
| 252 else | 252 else |
| 253 setCurrentAsyncCallChain(nullptr); | 253 setCurrentAsyncCallChain(nullptr); |
| 254 } | 254 } |
| 255 | 255 |
| 256 void AsyncCallStackTracker::didAddEventListener(EventTarget* eventTarget, const
AtomicString& eventType, EventListener* listener, bool useCapture, const ScriptV
alue& callFrames) | 256 void AsyncCallStackTracker::didAddEventListener(EventTarget* eventTarget, const
AtomicString& eventType, EventListener* listener, bool useCapture, const StackTr
ace& callFrames) |
| 257 { | 257 { |
| 258 ASSERT(eventTarget->executionContext()); | 258 ASSERT(eventTarget->executionContext()); |
| 259 ASSERT(isEnabled()); | 259 ASSERT(isEnabled()); |
| 260 if (!validateCallFrames(callFrames) || toXmlHttpRequest(eventTarget)) | 260 if (!validateCallFrames(callFrames) || toXmlHttpRequest(eventTarget)) |
| 261 return; | 261 return; |
| 262 | 262 |
| 263 StringBuilder description; | 263 StringBuilder description; |
| 264 description.append(eventTarget->interfaceName()); | 264 description.append(eventTarget->interfaceName()); |
| 265 if (!description.isEmpty()) | 265 if (!description.isEmpty()) |
| 266 description.append("."); | 266 description.append("."); |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 300 if (XMLHttpRequest* xhr = toXmlHttpRequest(eventTarget)) { | 300 if (XMLHttpRequest* xhr = toXmlHttpRequest(eventTarget)) { |
| 301 willHandleXHREvent(xhr, eventTarget, eventType); | 301 willHandleXHREvent(xhr, eventTarget, eventType); |
| 302 return; | 302 return; |
| 303 } | 303 } |
| 304 if (ExecutionContextData* data = m_executionContextDataMap.get(eventTarget->
executionContext())) | 304 if (ExecutionContextData* data = m_executionContextDataMap.get(eventTarget->
executionContext())) |
| 305 setCurrentAsyncCallChain(data->findEventListenerData(eventTarget, eventT
ype, RegisteredEventListener(listener, useCapture))); | 305 setCurrentAsyncCallChain(data->findEventListenerData(eventTarget, eventT
ype, RegisteredEventListener(listener, useCapture))); |
| 306 else | 306 else |
| 307 setCurrentAsyncCallChain(nullptr); | 307 setCurrentAsyncCallChain(nullptr); |
| 308 } | 308 } |
| 309 | 309 |
| 310 void AsyncCallStackTracker::willLoadXHR(XMLHttpRequest* xhr, const ScriptValue&
callFrames) | 310 void AsyncCallStackTracker::willLoadXHR(XMLHttpRequest* xhr, const StackTrace& c
allFrames) |
| 311 { | 311 { |
| 312 ASSERT(xhr->executionContext()); | 312 ASSERT(xhr->executionContext()); |
| 313 ASSERT(isEnabled()); | 313 ASSERT(isEnabled()); |
| 314 if (!validateCallFrames(callFrames)) | 314 if (!validateCallFrames(callFrames)) |
| 315 return; | 315 return; |
| 316 ExecutionContextData* data = createContextDataIfNeeded(xhr->executionContext
()); | 316 ExecutionContextData* data = createContextDataIfNeeded(xhr->executionContext
()); |
| 317 data->m_xhrCallChains.set(xhr, createAsyncCallChain(xhrSendName, callFrames)
); | 317 data->m_xhrCallChains.set(xhr, createAsyncCallChain(xhrSendName, callFrames)
); |
| 318 } | 318 } |
| 319 | 319 |
| 320 void AsyncCallStackTracker::willHandleXHREvent(XMLHttpRequest* xhr, EventTarget*
eventTarget, const AtomicString& eventType) | 320 void AsyncCallStackTracker::willHandleXHREvent(XMLHttpRequest* xhr, EventTarget*
eventTarget, const AtomicString& eventType) |
| 321 { | 321 { |
| 322 ASSERT(xhr->executionContext()); | 322 ASSERT(xhr->executionContext()); |
| 323 ASSERT(isEnabled()); | 323 ASSERT(isEnabled()); |
| 324 if (ExecutionContextData* data = m_executionContextDataMap.get(xhr->executio
nContext())) { | 324 if (ExecutionContextData* data = m_executionContextDataMap.get(xhr->executio
nContext())) { |
| 325 bool isXHRDownload = (xhr == eventTarget); | 325 bool isXHRDownload = (xhr == eventTarget); |
| 326 if (isXHRDownload && eventType == EventTypeNames::loadend) | 326 if (isXHRDownload && eventType == EventTypeNames::loadend) |
| 327 setCurrentAsyncCallChain(data->m_xhrCallChains.take(xhr)); | 327 setCurrentAsyncCallChain(data->m_xhrCallChains.take(xhr)); |
| 328 else | 328 else |
| 329 setCurrentAsyncCallChain(data->m_xhrCallChains.get(xhr)); | 329 setCurrentAsyncCallChain(data->m_xhrCallChains.get(xhr)); |
| 330 } else { | 330 } else { |
| 331 setCurrentAsyncCallChain(nullptr); | 331 setCurrentAsyncCallChain(nullptr); |
| 332 } | 332 } |
| 333 } | 333 } |
| 334 | 334 |
| 335 void AsyncCallStackTracker::didEnqueueMutationRecord(ExecutionContext* context,
MutationObserver* observer, const ScriptValue& callFrames) | 335 void AsyncCallStackTracker::didEnqueueMutationRecord(ExecutionContext* context,
MutationObserver* observer, const StackTrace& callFrames) |
| 336 { | 336 { |
| 337 ASSERT(context); | 337 ASSERT(context); |
| 338 ASSERT(isEnabled()); | 338 ASSERT(isEnabled()); |
| 339 if (!validateCallFrames(callFrames)) | 339 if (!validateCallFrames(callFrames)) |
| 340 return; | 340 return; |
| 341 ExecutionContextData* data = createContextDataIfNeeded(context); | 341 ExecutionContextData* data = createContextDataIfNeeded(context); |
| 342 data->m_mutationObserverCallChains.set(observer, createAsyncCallChain(enqueu
eMutationRecordName, callFrames)); | 342 data->m_mutationObserverCallChains.set(observer, createAsyncCallChain(enqueu
eMutationRecordName, callFrames)); |
| 343 } | 343 } |
| 344 | 344 |
| 345 bool AsyncCallStackTracker::hasEnqueuedMutationRecord(ExecutionContext* context,
MutationObserver* observer) | 345 bool AsyncCallStackTracker::hasEnqueuedMutationRecord(ExecutionContext* context,
MutationObserver* observer) |
| (...skipping 16 matching lines...) Expand all Loading... |
| 362 void AsyncCallStackTracker::willDeliverMutationRecords(ExecutionContext* context
, MutationObserver* observer) | 362 void AsyncCallStackTracker::willDeliverMutationRecords(ExecutionContext* context
, MutationObserver* observer) |
| 363 { | 363 { |
| 364 ASSERT(context); | 364 ASSERT(context); |
| 365 ASSERT(isEnabled()); | 365 ASSERT(isEnabled()); |
| 366 if (ExecutionContextData* data = m_executionContextDataMap.get(context)) | 366 if (ExecutionContextData* data = m_executionContextDataMap.get(context)) |
| 367 setCurrentAsyncCallChain(data->m_mutationObserverCallChains.take(observe
r)); | 367 setCurrentAsyncCallChain(data->m_mutationObserverCallChains.take(observe
r)); |
| 368 else | 368 else |
| 369 setCurrentAsyncCallChain(nullptr); | 369 setCurrentAsyncCallChain(nullptr); |
| 370 } | 370 } |
| 371 | 371 |
| 372 void AsyncCallStackTracker::didPostPromiseTask(ExecutionContext* context, Execut
ionContextTask* task, bool isResolved, const ScriptValue& callFrames) | 372 void AsyncCallStackTracker::didPostPromiseTask(ExecutionContext* context, Execut
ionContextTask* task, bool isResolved, const StackTrace& callFrames) |
| 373 { | 373 { |
| 374 ASSERT(context); | 374 ASSERT(context); |
| 375 ASSERT(isEnabled()); | 375 ASSERT(isEnabled()); |
| 376 if (validateCallFrames(callFrames)) { | 376 if (validateCallFrames(callFrames)) { |
| 377 ExecutionContextData* data = createContextDataIfNeeded(context); | 377 ExecutionContextData* data = createContextDataIfNeeded(context); |
| 378 data->m_promiseTaskCallChains.set(task, createAsyncCallChain(isResolved
? promiseResolved : promiseRejected, callFrames)); | 378 data->m_promiseTaskCallChains.set(task, createAsyncCallChain(isResolved
? promiseResolved : promiseRejected, callFrames)); |
| 379 } else if (m_currentAsyncCallChain) { | 379 } else if (m_currentAsyncCallChain) { |
| 380 // Propagate async call stack to the re-posted task to update a derived
Promise. | 380 // Propagate async call stack to the re-posted task to update a derived
Promise. |
| 381 ExecutionContextData* data = createContextDataIfNeeded(context); | 381 ExecutionContextData* data = createContextDataIfNeeded(context); |
| 382 data->m_promiseTaskCallChains.set(task, m_currentAsyncCallChain); | 382 data->m_promiseTaskCallChains.set(task, m_currentAsyncCallChain); |
| 383 } | 383 } |
| 384 } | 384 } |
| 385 | 385 |
| 386 void AsyncCallStackTracker::willPerformPromiseTask(ExecutionContext* context, Ex
ecutionContextTask* task) | 386 void AsyncCallStackTracker::willPerformPromiseTask(ExecutionContext* context, Ex
ecutionContextTask* task) |
| 387 { | 387 { |
| 388 ASSERT(context); | 388 ASSERT(context); |
| 389 ASSERT(isEnabled()); | 389 ASSERT(isEnabled()); |
| 390 if (ExecutionContextData* data = m_executionContextDataMap.get(context)) | 390 if (ExecutionContextData* data = m_executionContextDataMap.get(context)) |
| 391 setCurrentAsyncCallChain(data->m_promiseTaskCallChains.take(task)); | 391 setCurrentAsyncCallChain(data->m_promiseTaskCallChains.take(task)); |
| 392 else | 392 else |
| 393 setCurrentAsyncCallChain(nullptr); | 393 setCurrentAsyncCallChain(nullptr); |
| 394 } | 394 } |
| 395 | 395 |
| 396 void AsyncCallStackTracker::didFireAsyncCall() | 396 void AsyncCallStackTracker::didFireAsyncCall() |
| 397 { | 397 { |
| 398 clearCurrentAsyncCallChain(); | 398 clearCurrentAsyncCallChain(); |
| 399 } | 399 } |
| 400 | 400 |
| 401 PassRefPtr<AsyncCallStackTracker::AsyncCallChain> AsyncCallStackTracker::createA
syncCallChain(const String& description, const ScriptValue& callFrames) | 401 PassRefPtr<AsyncCallStackTracker::AsyncCallChain> AsyncCallStackTracker::createA
syncCallChain(const String& description, const StackTrace& callFrames) |
| 402 { | 402 { |
| 403 RefPtr<AsyncCallChain> chain = adoptRef(m_currentAsyncCallChain ? new AsyncC
allStackTracker::AsyncCallChain(*m_currentAsyncCallChain) : new AsyncCallStackTr
acker::AsyncCallChain()); | 403 RefPtr<AsyncCallChain> chain = adoptRef(m_currentAsyncCallChain ? new AsyncC
allStackTracker::AsyncCallChain(*m_currentAsyncCallChain) : new AsyncCallStackTr
acker::AsyncCallChain()); |
| 404 ensureMaxAsyncCallChainDepth(chain.get(), m_maxAsyncCallStackDepth - 1); | 404 ensureMaxAsyncCallChainDepth(chain.get(), m_maxAsyncCallStackDepth - 1); |
| 405 chain->m_callStacks.prepend(adoptRef(new AsyncCallStackTracker::AsyncCallSta
ck(description, callFrames))); | 405 chain->m_callStacks.prepend(adoptRef(new AsyncCallStackTracker::AsyncCallSta
ck(description, callFrames))); |
| 406 return chain.release(); | 406 return chain.release(); |
| 407 } | 407 } |
| 408 | 408 |
| 409 void AsyncCallStackTracker::setCurrentAsyncCallChain(PassRefPtr<AsyncCallChain>
chain) | 409 void AsyncCallStackTracker::setCurrentAsyncCallChain(PassRefPtr<AsyncCallChain>
chain) |
| 410 { | 410 { |
| 411 if (V8RecursionScope::recursionLevel(v8::Isolate::GetCurrent())) { | 411 if (V8RecursionScope::recursionLevel(v8::Isolate::GetCurrent())) { |
| (...skipping 14 matching lines...) Expand all Loading... |
| 426 if (!m_nestedAsyncCallCount) | 426 if (!m_nestedAsyncCallCount) |
| 427 m_currentAsyncCallChain.clear(); | 427 m_currentAsyncCallChain.clear(); |
| 428 } | 428 } |
| 429 | 429 |
| 430 void AsyncCallStackTracker::ensureMaxAsyncCallChainDepth(AsyncCallChain* chain,
unsigned maxDepth) | 430 void AsyncCallStackTracker::ensureMaxAsyncCallChainDepth(AsyncCallChain* chain,
unsigned maxDepth) |
| 431 { | 431 { |
| 432 while (chain->m_callStacks.size() > maxDepth) | 432 while (chain->m_callStacks.size() > maxDepth) |
| 433 chain->m_callStacks.removeLast(); | 433 chain->m_callStacks.removeLast(); |
| 434 } | 434 } |
| 435 | 435 |
| 436 bool AsyncCallStackTracker::validateCallFrames(const ScriptValue& callFrames) | 436 bool AsyncCallStackTracker::validateCallFrames(const StackTrace& callFrames) |
| 437 { | 437 { |
| 438 return !callFrames.isEmpty(); | 438 return !callFrames.isNull(); |
| 439 } | 439 } |
| 440 | 440 |
| 441 AsyncCallStackTracker::ExecutionContextData* AsyncCallStackTracker::createContex
tDataIfNeeded(ExecutionContext* context) | 441 AsyncCallStackTracker::ExecutionContextData* AsyncCallStackTracker::createContex
tDataIfNeeded(ExecutionContext* context) |
| 442 { | 442 { |
| 443 ExecutionContextData* data = m_executionContextDataMap.get(context); | 443 ExecutionContextData* data = m_executionContextDataMap.get(context); |
| 444 if (!data) { | 444 if (!data) { |
| 445 data = new AsyncCallStackTracker::ExecutionContextData(this, context); | 445 data = new AsyncCallStackTracker::ExecutionContextData(this, context); |
| 446 m_executionContextDataMap.set(context, data); | 446 m_executionContextDataMap.set(context, data); |
| 447 } | 447 } |
| 448 return data; | 448 return data; |
| 449 } | 449 } |
| 450 | 450 |
| 451 void AsyncCallStackTracker::clear() | 451 void AsyncCallStackTracker::clear() |
| 452 { | 452 { |
| 453 m_currentAsyncCallChain.clear(); | 453 m_currentAsyncCallChain.clear(); |
| 454 m_nestedAsyncCallCount = 0; | 454 m_nestedAsyncCallCount = 0; |
| 455 ExecutionContextDataMap copy; | 455 ExecutionContextDataMap copy; |
| 456 m_executionContextDataMap.swap(copy); | 456 m_executionContextDataMap.swap(copy); |
| 457 for (ExecutionContextDataMap::const_iterator it = copy.begin(); it != copy.e
nd(); ++it) | 457 for (ExecutionContextDataMap::const_iterator it = copy.begin(); it != copy.e
nd(); ++it) |
| 458 delete it->value; | 458 delete it->value; |
| 459 } | 459 } |
| 460 | 460 |
| 461 } // namespace WebCore | 461 } // namespace WebCore |
| OLD | NEW |