| 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 17 matching lines...) Expand all Loading... |
| 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 29 */ | 29 */ |
| 30 | 30 |
| 31 #include "config.h" | 31 #include "config.h" |
| 32 #include "core/inspector/AsyncCallStackTracker.h" | 32 #include "core/inspector/AsyncCallStackTracker.h" |
| 33 | 33 |
| 34 #include "core/dom/ContextLifecycleObserver.h" | 34 #include "core/dom/ContextLifecycleObserver.h" |
| 35 #include "core/dom/ExecutionContext.h" | 35 #include "core/dom/ExecutionContext.h" |
| 36 #include "core/events/EventTarget.h" | 36 #include "core/events/EventTarget.h" |
| 37 #include "core/events/RegisteredEventListener.h" | 37 #include "core/events/RegisteredEventListener.h" |
| 38 #include "core/xml/XMLHttpRequest.h" |
| 39 #include "core/xml/XMLHttpRequestUpload.h" |
| 40 #include "wtf/text/AtomicStringHash.h" |
| 38 #include "wtf/text/StringBuilder.h" | 41 #include "wtf/text/StringBuilder.h" |
| 39 | 42 |
| 43 namespace { |
| 44 |
| 45 static const char setTimeoutName[] = "setTimeout"; |
| 46 static const char setIntervalName[] = "setInterval"; |
| 47 static const char requestAnimationFrameName[] = "requestAnimationFrame"; |
| 48 static const char xhrSendName[] = "XMLHttpRequest.send"; |
| 49 |
| 50 } |
| 51 |
| 40 namespace WebCore { | 52 namespace WebCore { |
| 41 | 53 |
| 42 class AsyncCallStackTracker::ExecutionContextData : public ContextLifecycleObser
ver { | 54 class AsyncCallStackTracker::ExecutionContextData : public ContextLifecycleObser
ver { |
| 43 WTF_MAKE_FAST_ALLOCATED; | 55 WTF_MAKE_FAST_ALLOCATED; |
| 44 public: | 56 public: |
| 45 typedef std::pair<RegisteredEventListener, RefPtr<AsyncCallChain> > EventLis
tenerAsyncCallChain; | 57 typedef std::pair<RegisteredEventListener, RefPtr<AsyncCallChain> > EventLis
tenerAsyncCallChain; |
| 46 typedef Vector<EventListenerAsyncCallChain, 1> EventListenerAsyncCallChainVe
ctor; | 58 typedef Vector<EventListenerAsyncCallChain, 1> EventListenerAsyncCallChainVe
ctor; |
| 47 typedef HashMap<AtomicString, EventListenerAsyncCallChainVector> EventListen
erAsyncCallChainVectorHashMap; | 59 typedef HashMap<AtomicString, EventListenerAsyncCallChainVector> EventListen
erAsyncCallChainVectorHashMap; |
| 48 | 60 |
| 49 ExecutionContextData(AsyncCallStackTracker* tracker, ExecutionContext* execu
tionContext) | 61 ExecutionContextData(AsyncCallStackTracker* tracker, ExecutionContext* execu
tionContext) |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 104 } | 116 } |
| 105 return result.release(); | 117 return result.release(); |
| 106 } | 118 } |
| 107 | 119 |
| 108 public: | 120 public: |
| 109 AsyncCallStackTracker* m_tracker; | 121 AsyncCallStackTracker* m_tracker; |
| 110 HashSet<int> m_intervalTimerIds; | 122 HashSet<int> m_intervalTimerIds; |
| 111 HashMap<int, RefPtr<AsyncCallChain> > m_timerCallChains; | 123 HashMap<int, RefPtr<AsyncCallChain> > m_timerCallChains; |
| 112 HashMap<int, RefPtr<AsyncCallChain> > m_animationFrameCallChains; | 124 HashMap<int, RefPtr<AsyncCallChain> > m_animationFrameCallChains; |
| 113 HashMap<EventTarget*, EventListenerAsyncCallChainVectorHashMap> m_eventTarge
tCallChains; | 125 HashMap<EventTarget*, EventListenerAsyncCallChainVectorHashMap> m_eventTarge
tCallChains; |
| 126 HashMap<EventTarget*, RefPtr<AsyncCallChain> > m_xhrCallChains; |
| 114 }; | 127 }; |
| 115 | 128 |
| 129 static XMLHttpRequest* toXmlHttpRequest(EventTarget* eventTarget) |
| 130 { |
| 131 const AtomicString& interfaceName = eventTarget->interfaceName(); |
| 132 if (interfaceName == EventTargetNames::XMLHttpRequest) |
| 133 return static_cast<XMLHttpRequest*>(eventTarget); |
| 134 if (interfaceName == EventTargetNames::XMLHttpRequestUpload) |
| 135 return static_cast<XMLHttpRequestUpload*>(eventTarget)->xmlHttpRequest()
; |
| 136 return 0; |
| 137 } |
| 138 |
| 116 AsyncCallStackTracker::AsyncCallStack::AsyncCallStack(const String& description,
const ScriptValue& callFrames) | 139 AsyncCallStackTracker::AsyncCallStack::AsyncCallStack(const String& description,
const ScriptValue& callFrames) |
| 117 : m_description(description) | 140 : m_description(description) |
| 118 , m_callFrames(callFrames) | 141 , m_callFrames(callFrames) |
| 119 { | 142 { |
| 120 } | 143 } |
| 121 | 144 |
| 122 AsyncCallStackTracker::AsyncCallStack::~AsyncCallStack() | 145 AsyncCallStackTracker::AsyncCallStack::~AsyncCallStack() |
| 123 { | 146 { |
| 124 } | 147 } |
| 125 | 148 |
| (...skipping 14 matching lines...) Expand all Loading... |
| 140 | 163 |
| 141 const AsyncCallStackTracker::AsyncCallChain* AsyncCallStackTracker::currentAsync
CallChain() const | 164 const AsyncCallStackTracker::AsyncCallChain* AsyncCallStackTracker::currentAsync
CallChain() const |
| 142 { | 165 { |
| 143 if (m_currentAsyncCallChain) | 166 if (m_currentAsyncCallChain) |
| 144 ensureMaxAsyncCallChainDepth(m_currentAsyncCallChain.get(), m_maxAsyncCa
llStackDepth); | 167 ensureMaxAsyncCallChainDepth(m_currentAsyncCallChain.get(), m_maxAsyncCa
llStackDepth); |
| 145 return m_currentAsyncCallChain.get(); | 168 return m_currentAsyncCallChain.get(); |
| 146 } | 169 } |
| 147 | 170 |
| 148 void AsyncCallStackTracker::didInstallTimer(ExecutionContext* context, int timer
Id, bool singleShot, const ScriptValue& callFrames) | 171 void AsyncCallStackTracker::didInstallTimer(ExecutionContext* context, int timer
Id, bool singleShot, const ScriptValue& callFrames) |
| 149 { | 172 { |
| 150 DEFINE_STATIC_LOCAL(String, setTimeoutName, ("setTimeout")); | |
| 151 DEFINE_STATIC_LOCAL(String, setIntervalName, ("setInterval")); | |
| 152 | |
| 153 ASSERT(context); | 173 ASSERT(context); |
| 154 ASSERT(isEnabled()); | 174 ASSERT(isEnabled()); |
| 155 if (!validateCallFrames(callFrames)) | 175 if (!validateCallFrames(callFrames)) |
| 156 return; | 176 return; |
| 157 ASSERT(timerId > 0); | 177 ASSERT(timerId > 0); |
| 158 ExecutionContextData* data = createContextDataIfNeeded(context); | 178 ExecutionContextData* data = createContextDataIfNeeded(context); |
| 159 data->m_timerCallChains.set(timerId, createAsyncCallChain(singleShot ? setTi
meoutName : setIntervalName, callFrames)); | 179 data->m_timerCallChains.set(timerId, createAsyncCallChain(singleShot ? setTi
meoutName : setIntervalName, callFrames)); |
| 160 if (!singleShot) | 180 if (!singleShot) |
| 161 data->m_intervalTimerIds.add(timerId); | 181 data->m_intervalTimerIds.add(timerId); |
| 162 } | 182 } |
| (...skipping 10 matching lines...) Expand all Loading... |
| 173 data->m_intervalTimerIds.remove(timerId); | 193 data->m_intervalTimerIds.remove(timerId); |
| 174 data->m_timerCallChains.remove(timerId); | 194 data->m_timerCallChains.remove(timerId); |
| 175 } | 195 } |
| 176 | 196 |
| 177 void AsyncCallStackTracker::willFireTimer(ExecutionContext* context, int timerId
) | 197 void AsyncCallStackTracker::willFireTimer(ExecutionContext* context, int timerId
) |
| 178 { | 198 { |
| 179 ASSERT(context); | 199 ASSERT(context); |
| 180 ASSERT(isEnabled()); | 200 ASSERT(isEnabled()); |
| 181 ASSERT(timerId > 0); | 201 ASSERT(timerId > 0); |
| 182 ASSERT(!m_currentAsyncCallChain); | 202 ASSERT(!m_currentAsyncCallChain); |
| 183 ExecutionContextData* data = m_executionContextDataMap.get(context); | 203 if (ExecutionContextData* data = m_executionContextDataMap.get(context)) { |
| 184 if (!data) | 204 if (data->m_intervalTimerIds.contains(timerId)) |
| 185 return; | 205 setCurrentAsyncCallChain(data->m_timerCallChains.get(timerId)); |
| 186 if (data->m_intervalTimerIds.contains(timerId)) | 206 else |
| 187 setCurrentAsyncCallChain(data->m_timerCallChains.get(timerId)); | 207 setCurrentAsyncCallChain(data->m_timerCallChains.take(timerId)); |
| 188 else | 208 } else { |
| 189 setCurrentAsyncCallChain(data->m_timerCallChains.take(timerId)); | 209 setCurrentAsyncCallChain(0); |
| 210 } |
| 190 } | 211 } |
| 191 | 212 |
| 192 void AsyncCallStackTracker::didRequestAnimationFrame(ExecutionContext* context,
int callbackId, const ScriptValue& callFrames) | 213 void AsyncCallStackTracker::didRequestAnimationFrame(ExecutionContext* context,
int callbackId, const ScriptValue& callFrames) |
| 193 { | 214 { |
| 194 DEFINE_STATIC_LOCAL(String, requestAnimationFrameName, ("requestAnimationFra
me")); | |
| 195 | |
| 196 ASSERT(context); | 215 ASSERT(context); |
| 197 ASSERT(isEnabled()); | 216 ASSERT(isEnabled()); |
| 198 if (!validateCallFrames(callFrames)) | 217 if (!validateCallFrames(callFrames)) |
| 199 return; | 218 return; |
| 200 ASSERT(callbackId > 0); | 219 ASSERT(callbackId > 0); |
| 201 ExecutionContextData* data = createContextDataIfNeeded(context); | 220 ExecutionContextData* data = createContextDataIfNeeded(context); |
| 202 data->m_animationFrameCallChains.set(callbackId, createAsyncCallChain(reques
tAnimationFrameName, callFrames)); | 221 data->m_animationFrameCallChains.set(callbackId, createAsyncCallChain(reques
tAnimationFrameName, callFrames)); |
| 203 } | 222 } |
| 204 | 223 |
| 205 void AsyncCallStackTracker::didCancelAnimationFrame(ExecutionContext* context, i
nt callbackId) | 224 void AsyncCallStackTracker::didCancelAnimationFrame(ExecutionContext* context, i
nt callbackId) |
| 206 { | 225 { |
| 207 ASSERT(context); | 226 ASSERT(context); |
| 208 ASSERT(isEnabled()); | 227 ASSERT(isEnabled()); |
| 209 if (callbackId <= 0) | 228 if (callbackId <= 0) |
| 210 return; | 229 return; |
| 211 if (ExecutionContextData* data = m_executionContextDataMap.get(context)) | 230 if (ExecutionContextData* data = m_executionContextDataMap.get(context)) |
| 212 data->m_animationFrameCallChains.remove(callbackId); | 231 data->m_animationFrameCallChains.remove(callbackId); |
| 213 } | 232 } |
| 214 | 233 |
| 215 void AsyncCallStackTracker::willFireAnimationFrame(ExecutionContext* context, in
t callbackId) | 234 void AsyncCallStackTracker::willFireAnimationFrame(ExecutionContext* context, in
t callbackId) |
| 216 { | 235 { |
| 217 ASSERT(context); | 236 ASSERT(context); |
| 218 ASSERT(isEnabled()); | 237 ASSERT(isEnabled()); |
| 219 ASSERT(callbackId > 0); | 238 ASSERT(callbackId > 0); |
| 220 ASSERT(!m_currentAsyncCallChain); | 239 ASSERT(!m_currentAsyncCallChain); |
| 221 if (ExecutionContextData* data = m_executionContextDataMap.get(context)) | 240 if (ExecutionContextData* data = m_executionContextDataMap.get(context)) |
| 222 setCurrentAsyncCallChain(data->m_animationFrameCallChains.take(callbackI
d)); | 241 setCurrentAsyncCallChain(data->m_animationFrameCallChains.take(callbackI
d)); |
| 242 else |
| 243 setCurrentAsyncCallChain(0); |
| 223 } | 244 } |
| 224 | 245 |
| 225 void AsyncCallStackTracker::didAddEventListener(EventTarget* eventTarget, const
AtomicString& eventType, EventListener* listener, bool useCapture, const ScriptV
alue& callFrames) | 246 void AsyncCallStackTracker::didAddEventListener(EventTarget* eventTarget, const
AtomicString& eventType, EventListener* listener, bool useCapture, const ScriptV
alue& callFrames) |
| 226 { | 247 { |
| 227 ASSERT(eventTarget->executionContext()); | 248 ASSERT(eventTarget->executionContext()); |
| 228 ASSERT(isEnabled()); | 249 ASSERT(isEnabled()); |
| 229 if (!validateCallFrames(callFrames)) | 250 if (!validateCallFrames(callFrames) || toXmlHttpRequest(eventTarget)) |
| 230 return; | 251 return; |
| 231 | 252 |
| 232 StringBuilder description; | 253 StringBuilder description; |
| 233 description.append(eventTarget->interfaceName()); | 254 description.append(eventTarget->interfaceName()); |
| 234 if (!description.isEmpty()) | 255 if (!description.isEmpty()) |
| 235 description.append("."); | 256 description.append("."); |
| 236 if (listener->isAttribute()) { | 257 if (listener->isAttribute()) { |
| 237 description.append("on"); | 258 description.append("on"); |
| 238 description.append(eventType); | 259 description.append(eventType); |
| 239 } else { | 260 } else { |
| (...skipping 19 matching lines...) Expand all Loading... |
| 259 ASSERT(eventTarget->executionContext()); | 280 ASSERT(eventTarget->executionContext()); |
| 260 ASSERT(isEnabled()); | 281 ASSERT(isEnabled()); |
| 261 if (ExecutionContextData* data = m_executionContextDataMap.get(eventTarget->
executionContext())) | 282 if (ExecutionContextData* data = m_executionContextDataMap.get(eventTarget->
executionContext())) |
| 262 data->m_eventTargetCallChains.remove(eventTarget); | 283 data->m_eventTargetCallChains.remove(eventTarget); |
| 263 } | 284 } |
| 264 | 285 |
| 265 void AsyncCallStackTracker::willHandleEvent(EventTarget* eventTarget, const Atom
icString& eventType, EventListener* listener, bool useCapture) | 286 void AsyncCallStackTracker::willHandleEvent(EventTarget* eventTarget, const Atom
icString& eventType, EventListener* listener, bool useCapture) |
| 266 { | 287 { |
| 267 ASSERT(eventTarget->executionContext()); | 288 ASSERT(eventTarget->executionContext()); |
| 268 ASSERT(isEnabled()); | 289 ASSERT(isEnabled()); |
| 290 if (XMLHttpRequest* xhr = toXmlHttpRequest(eventTarget)) { |
| 291 willHandleXHREvent(xhr, eventTarget, eventType); |
| 292 return; |
| 293 } |
| 269 if (ExecutionContextData* data = m_executionContextDataMap.get(eventTarget->
executionContext())) | 294 if (ExecutionContextData* data = m_executionContextDataMap.get(eventTarget->
executionContext())) |
| 270 setCurrentAsyncCallChain(data->findEventListenerData(eventTarget, eventT
ype, RegisteredEventListener(listener, useCapture))); | 295 setCurrentAsyncCallChain(data->findEventListenerData(eventTarget, eventT
ype, RegisteredEventListener(listener, useCapture))); |
| 296 else |
| 297 setCurrentAsyncCallChain(0); |
| 298 } |
| 299 |
| 300 void AsyncCallStackTracker::willLoadXHR(XMLHttpRequest* xhr, const ScriptValue&
callFrames) |
| 301 { |
| 302 ASSERT(xhr->executionContext()); |
| 303 ASSERT(isEnabled()); |
| 304 if (!validateCallFrames(callFrames)) |
| 305 return; |
| 306 ExecutionContextData* data = createContextDataIfNeeded(xhr->executionContext
()); |
| 307 data->m_xhrCallChains.set(xhr, createAsyncCallChain(xhrSendName, callFrames)
); |
| 308 } |
| 309 |
| 310 void AsyncCallStackTracker::willHandleXHREvent(XMLHttpRequest* xhr, EventTarget*
eventTarget, const AtomicString& eventType) |
| 311 { |
| 312 ASSERT(xhr->executionContext()); |
| 313 ASSERT(isEnabled()); |
| 314 if (ExecutionContextData* data = m_executionContextDataMap.get(xhr->executio
nContext())) { |
| 315 bool isXHRDownload = (xhr == eventTarget); |
| 316 if (isXHRDownload && eventType == EventTypeNames::loadend) |
| 317 setCurrentAsyncCallChain(data->m_xhrCallChains.take(xhr)); |
| 318 else |
| 319 setCurrentAsyncCallChain(data->m_xhrCallChains.get(xhr)); |
| 320 } else { |
| 321 setCurrentAsyncCallChain(0); |
| 322 } |
| 271 } | 323 } |
| 272 | 324 |
| 273 void AsyncCallStackTracker::didFireAsyncCall() | 325 void AsyncCallStackTracker::didFireAsyncCall() |
| 274 { | 326 { |
| 275 setCurrentAsyncCallChain(0); | 327 clearCurrentAsyncCallChain(); |
| 276 } | 328 } |
| 277 | 329 |
| 278 PassRefPtr<AsyncCallStackTracker::AsyncCallChain> AsyncCallStackTracker::createA
syncCallChain(const String& description, const ScriptValue& callFrames) | 330 PassRefPtr<AsyncCallStackTracker::AsyncCallChain> AsyncCallStackTracker::createA
syncCallChain(const String& description, const ScriptValue& callFrames) |
| 279 { | 331 { |
| 280 RefPtr<AsyncCallChain> chain = adoptRef(m_currentAsyncCallChain ? new AsyncC
allStackTracker::AsyncCallChain(*m_currentAsyncCallChain) : new AsyncCallStackTr
acker::AsyncCallChain()); | 332 RefPtr<AsyncCallChain> chain = adoptRef(m_currentAsyncCallChain ? new AsyncC
allStackTracker::AsyncCallChain(*m_currentAsyncCallChain) : new AsyncCallStackTr
acker::AsyncCallChain()); |
| 281 ensureMaxAsyncCallChainDepth(chain.get(), m_maxAsyncCallStackDepth - 1); | 333 ensureMaxAsyncCallChainDepth(chain.get(), m_maxAsyncCallStackDepth - 1); |
| 282 chain->m_callStacks.prepend(adoptRef(new AsyncCallStackTracker::AsyncCallSta
ck(description, callFrames))); | 334 chain->m_callStacks.prepend(adoptRef(new AsyncCallStackTracker::AsyncCallSta
ck(description, callFrames))); |
| 283 return chain.release(); | 335 return chain.release(); |
| 284 } | 336 } |
| 285 | 337 |
| 286 void AsyncCallStackTracker::setCurrentAsyncCallChain(PassRefPtr<AsyncCallChain>
chain) | 338 void AsyncCallStackTracker::setCurrentAsyncCallChain(PassRefPtr<AsyncCallChain>
chain) |
| 287 { | 339 { |
| 288 if (m_currentAsyncCallChain) { | 340 if (m_currentAsyncCallChain) { |
| 289 m_nestedAsyncCallCount += chain ? 1 : -1; | 341 ++m_nestedAsyncCallCount; |
| 290 if (!m_nestedAsyncCallCount) | |
| 291 m_currentAsyncCallChain = 0; | |
| 292 } else if (chain) { | 342 } else if (chain) { |
| 293 m_currentAsyncCallChain = chain; | 343 m_currentAsyncCallChain = chain; |
| 294 m_nestedAsyncCallCount = 1; | 344 m_nestedAsyncCallCount = 1; |
| 295 } | 345 } |
| 296 } | 346 } |
| 297 | 347 |
| 348 void AsyncCallStackTracker::clearCurrentAsyncCallChain() |
| 349 { |
| 350 if (!m_nestedAsyncCallCount) |
| 351 return; |
| 352 --m_nestedAsyncCallCount; |
| 353 if (!m_nestedAsyncCallCount) |
| 354 m_currentAsyncCallChain.clear(); |
| 355 } |
| 356 |
| 298 void AsyncCallStackTracker::ensureMaxAsyncCallChainDepth(AsyncCallChain* chain,
unsigned maxDepth) | 357 void AsyncCallStackTracker::ensureMaxAsyncCallChainDepth(AsyncCallChain* chain,
unsigned maxDepth) |
| 299 { | 358 { |
| 300 while (chain->m_callStacks.size() > maxDepth) | 359 while (chain->m_callStacks.size() > maxDepth) |
| 301 chain->m_callStacks.removeLast(); | 360 chain->m_callStacks.removeLast(); |
| 302 } | 361 } |
| 303 | 362 |
| 304 bool AsyncCallStackTracker::validateCallFrames(const ScriptValue& callFrames) | 363 bool AsyncCallStackTracker::validateCallFrames(const ScriptValue& callFrames) |
| 305 { | 364 { |
| 306 return !callFrames.hasNoValue(); | 365 return !callFrames.hasNoValue(); |
| 307 } | 366 } |
| 308 | 367 |
| 309 AsyncCallStackTracker::ExecutionContextData* AsyncCallStackTracker::createContex
tDataIfNeeded(ExecutionContext* context) | 368 AsyncCallStackTracker::ExecutionContextData* AsyncCallStackTracker::createContex
tDataIfNeeded(ExecutionContext* context) |
| 310 { | 369 { |
| 311 ExecutionContextData* data = m_executionContextDataMap.get(context); | 370 ExecutionContextData* data = m_executionContextDataMap.get(context); |
| 312 if (!data) { | 371 if (!data) { |
| 313 data = new AsyncCallStackTracker::ExecutionContextData(this, context); | 372 data = new AsyncCallStackTracker::ExecutionContextData(this, context); |
| 314 m_executionContextDataMap.set(context, data); | 373 m_executionContextDataMap.set(context, data); |
| 315 } | 374 } |
| 316 return data; | 375 return data; |
| 317 } | 376 } |
| 318 | 377 |
| 319 void AsyncCallStackTracker::clear() | 378 void AsyncCallStackTracker::clear() |
| 320 { | 379 { |
| 321 m_currentAsyncCallChain = 0; | 380 m_currentAsyncCallChain.clear(); |
| 322 m_nestedAsyncCallCount = 0; | 381 m_nestedAsyncCallCount = 0; |
| 323 ExecutionContextDataMap copy; | 382 ExecutionContextDataMap copy; |
| 324 m_executionContextDataMap.swap(copy); | 383 m_executionContextDataMap.swap(copy); |
| 325 for (ExecutionContextDataMap::const_iterator it = copy.begin(); it != copy.e
nd(); ++it) | 384 for (ExecutionContextDataMap::const_iterator it = copy.begin(); it != copy.e
nd(); ++it) |
| 326 delete it->value; | 385 delete it->value; |
| 327 } | 386 } |
| 328 | 387 |
| 329 } // namespace WebCore | 388 } // namespace WebCore |
| OLD | NEW |