Changeset 251366 in webkit for trunk/Source/WebCore/xml/XMLHttpRequestProgressEventThrottle.cpp
- Timestamp:
- Oct 21, 2019, 8:17:19 AM (6 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/xml/XMLHttpRequestProgressEventThrottle.cpp
r246490 r251366 36 36 const Seconds XMLHttpRequestProgressEventThrottle::minimumProgressEventDispatchingInterval { 50_ms }; // 50 ms per specification. 37 37 38 XMLHttpRequestProgressEventThrottle::XMLHttpRequestProgressEventThrottle(EventTarget *target)38 XMLHttpRequestProgressEventThrottle::XMLHttpRequestProgressEventThrottle(EventTarget& target) 39 39 : m_target(target) 40 , m_dispatchDeferredEventsTimer(*this, &XMLHttpRequestProgressEventThrottle::dispatchDeferredEvents) 40 , m_dispatchThrottledProgressEventTimer(target.scriptExecutionContext(), *this, &XMLHttpRequestProgressEventThrottle::dispatchThrottledProgressEventTimerFired) 41 , m_dispatchDeferredEventsAfterResumingTimer(target.scriptExecutionContext(), *this, &XMLHttpRequestProgressEventThrottle::dispatchDeferredEventsAfterResuming) 41 42 { 42 ASSERT(target); 43 m_dispatchThrottledProgressEventTimer.suspendIfNeeded(); 44 m_dispatchDeferredEventsAfterResumingTimer.suspendIfNeeded(); 43 45 } 44 46 … … 51 53 m_total = total; 52 54 53 if (!m_target ->hasEventListeners(eventNames().progressEvent))55 if (!m_target.hasEventListeners(eventNames().progressEvent)) 54 56 return; 55 56 if (m_deferEvents) {57 // Only store the latest progress event while suspended.58 m_deferredProgressEvent = XMLHttpRequestProgressEvent::create(eventNames().progressEvent, lengthComputable, loaded, total);59 return;60 }61 57 62 if (! isActive()) {58 if (!m_shouldDeferEventsDueToSuspension && !m_dispatchThrottledProgressEventTimer.isActive()) { 63 59 // The timer is not active so the least frequent event for now is every byte. Just dispatch the event. 64 60 65 61 // We should not have any throttled progress event. 66 ASSERT(!m_has ThrottledProgressEvent);62 ASSERT(!m_hasPendingThrottledProgressEvent); 67 63 68 dispatchEvent (XMLHttpRequestProgressEvent::create(eventNames().progressEvent, lengthComputable, loaded, total));69 startRepeating(minimumProgressEventDispatchingInterval);70 m_has ThrottledProgressEvent = false;64 dispatchEventWhenPossible(XMLHttpRequestProgressEvent::create(eventNames().progressEvent, lengthComputable, loaded, total)); 65 m_dispatchThrottledProgressEventTimer.startRepeating(minimumProgressEventDispatchingInterval); 66 m_hasPendingThrottledProgressEvent = false; 71 67 return; 72 68 } 73 69 74 70 // The timer is already active so minimumProgressEventDispatchingInterval is the least frequent event. 75 m_has ThrottledProgressEvent = true;71 m_hasPendingThrottledProgressEvent = true; 76 72 } 77 73 … … 81 77 flushProgressEvent(); 82 78 83 dispatchEvent (event);79 dispatchEventWhenPossible(event); 84 80 } 85 81 86 void XMLHttpRequestProgressEventThrottle::dispatchEvent (Event& event)82 void XMLHttpRequestProgressEventThrottle::dispatchEventWhenPossible(Event& event) 87 83 { 88 if (m_ deferEvents) {89 if (m_ deferredEvents.size() > 1 && event.type() == eventNames().readystatechangeEvent && event.type() == m_deferredEvents.last()->type()) {84 if (m_shouldDeferEventsDueToSuspension) { 85 if (m_eventsDeferredDueToSuspension.size() > 1 && event.type() == eventNames().readystatechangeEvent && event.type() == m_eventsDeferredDueToSuspension.last()->type()) { 90 86 // Readystatechange events are state-less so avoid repeating two identical events in a row on resume. 91 87 return; 92 88 } 93 m_ deferredEvents.append(event);89 m_eventsDeferredDueToSuspension.append(event); 94 90 } else 95 m_target ->dispatchEvent(event);91 m_target.dispatchEvent(event); 96 92 } 97 93 … … 106 102 } 107 103 108 if (m_target ->hasEventListeners(type))109 dispatchEvent (XMLHttpRequestProgressEvent::create(type, m_lengthComputable, m_loaded, m_total));104 if (m_target.hasEventListeners(type)) 105 dispatchEventWhenPossible(XMLHttpRequestProgressEvent::create(type, m_lengthComputable, m_loaded, m_total)); 110 106 } 111 107 112 108 void XMLHttpRequestProgressEventThrottle::flushProgressEvent() 113 109 { 114 if (m_deferEvents && m_deferredProgressEvent) { 115 // Move the progress event to the queue, to get it in the right order on resume. 116 m_deferredEvents.append(m_deferredProgressEvent.releaseNonNull()); 110 if (!m_hasPendingThrottledProgressEvent) 111 return; 112 113 m_hasPendingThrottledProgressEvent = false; 114 // We stop the timer as this is called when no more events are supposed to occur. 115 m_dispatchThrottledProgressEventTimer.cancel(); 116 117 dispatchEventWhenPossible(XMLHttpRequestProgressEvent::create(eventNames().progressEvent, m_lengthComputable, m_loaded, m_total)); 118 } 119 120 void XMLHttpRequestProgressEventThrottle::dispatchDeferredEventsAfterResuming() 121 { 122 ASSERT(m_shouldDeferEventsDueToSuspension); 123 m_shouldDeferEventsDueToSuspension = false; 124 125 // Take over the deferred events before dispatching them which can potentially add more. 126 auto eventsDeferredDueToSuspension = WTFMove(m_eventsDeferredDueToSuspension); 127 128 flushProgressEvent(); 129 130 for (auto& deferredEvent : eventsDeferredDueToSuspension) 131 dispatchEventWhenPossible(deferredEvent); 132 } 133 134 void XMLHttpRequestProgressEventThrottle::dispatchThrottledProgressEventTimerFired() 135 { 136 ASSERT(m_dispatchThrottledProgressEventTimer.isActive()); 137 if (!m_hasPendingThrottledProgressEvent) { 138 // No progress event was queued since the previous dispatch, we can safely stop the timer. 139 m_dispatchThrottledProgressEventTimer.cancel(); 117 140 return; 118 141 } 119 142 120 if (!hasEventToDispatch()) 121 return; 122 Ref<Event> event = XMLHttpRequestProgressEvent::create(eventNames().progressEvent, m_lengthComputable, m_loaded, m_total); 123 m_hasThrottledProgressEvent = false; 124 125 // We stop the timer as this is called when no more events are supposed to occur. 126 stop(); 127 128 dispatchEvent(WTFMove(event)); 129 } 130 131 void XMLHttpRequestProgressEventThrottle::dispatchDeferredEvents() 132 { 133 ASSERT(m_deferEvents); 134 m_deferEvents = false; 135 136 // Take over the deferred events before dispatching them which can potentially add more. 137 auto deferredEvents = WTFMove(m_deferredEvents); 138 139 RefPtr<Event> deferredProgressEvent = WTFMove(m_deferredProgressEvent); 140 141 for (auto& deferredEvent : deferredEvents) 142 dispatchEvent(deferredEvent); 143 144 // The progress event will be in the m_deferredEvents vector if the load was finished while suspended. 145 // If not, just send the most up-to-date progress on resume. 146 if (deferredProgressEvent) 147 dispatchEvent(*deferredProgressEvent); 148 } 149 150 void XMLHttpRequestProgressEventThrottle::fired() 151 { 152 ASSERT(isActive()); 153 if (!hasEventToDispatch()) { 154 // No progress event was queued since the previous dispatch, we can safely stop the timer. 155 stop(); 156 return; 157 } 158 159 dispatchEvent(XMLHttpRequestProgressEvent::create(eventNames().progressEvent, m_lengthComputable, m_loaded, m_total)); 160 m_hasThrottledProgressEvent = false; 161 } 162 163 bool XMLHttpRequestProgressEventThrottle::hasEventToDispatch() const 164 { 165 return m_hasThrottledProgressEvent && isActive(); 143 dispatchEventWhenPossible(XMLHttpRequestProgressEvent::create(eventNames().progressEvent, m_lengthComputable, m_loaded, m_total)); 144 m_hasPendingThrottledProgressEvent = false; 166 145 } 167 146 168 147 void XMLHttpRequestProgressEventThrottle::suspend() 169 148 { 170 // If re-suspended before deferred events have been dispatched, just stop the dispatch 171 // and continue the last suspend. 172 if (m_dispatchDeferredEventsTimer.isActive()) { 173 ASSERT(m_deferEvents); 174 m_dispatchDeferredEventsTimer.stop(); 175 return; 176 } 177 ASSERT(!m_deferredProgressEvent); 178 ASSERT(m_deferredEvents.isEmpty()); 179 ASSERT(!m_deferEvents); 180 181 m_deferEvents = true; 182 // If we have a progress event waiting to be dispatched, 183 // just defer it. 184 if (hasEventToDispatch()) { 185 m_deferredProgressEvent = XMLHttpRequestProgressEvent::create(eventNames().progressEvent, m_lengthComputable, m_loaded, m_total); 186 m_hasThrottledProgressEvent = false; 187 } 188 stop(); 149 m_shouldDeferEventsDueToSuspension = true; 189 150 } 190 151 191 152 void XMLHttpRequestProgressEventThrottle::resume() 192 153 { 193 ASSERT(!m_hasThrottledProgressEvent); 194 195 if (m_deferredEvents.isEmpty() && !m_deferredProgressEvent) { 196 m_deferEvents = false; 154 if (m_eventsDeferredDueToSuspension.isEmpty() && !m_hasPendingThrottledProgressEvent) { 155 m_shouldDeferEventsDueToSuspension = false; 197 156 return; 198 157 } 199 158 200 // Do not dispatch events inline here, since ScriptExecutionContext is iterating over 201 // the list of active DOM objects to resume them, and any activated JS event-handler 202 // could insert new active DOM objects to the list. 203 // m_deferEvents is kept true until all deferred events have been dispatched. 204 m_dispatchDeferredEventsTimer.startOneShot(0_s); 159 m_dispatchDeferredEventsAfterResumingTimer.startOneShot(0_s); 205 160 } 206 161
Note:
See TracChangeset
for help on using the changeset viewer.