OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2010 Google, Inc. All Rights Reserved. | 2 * Copyright (C) 2010 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 | 5 * modification, are permitted provided that the following conditions |
6 * are met: | 6 * are met: |
7 * 1. Redistributions of source code must retain the above copyright | 7 * 1. Redistributions of source code must retain the above copyright |
8 * notice, this list of conditions and the following disclaimer. | 8 * notice, this list of conditions and the following disclaimer. |
9 * 2. Redistributions in binary form must reproduce the above copyright | 9 * 2. Redistributions in binary form must reproduce the above copyright |
10 * notice, this list of conditions and the following disclaimer in the | 10 * notice, this list of conditions and the following disclaimer in the |
(...skipping 12 matching lines...) Expand all Loading... |
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
24 */ | 24 */ |
25 | 25 |
26 #include "config.h" | 26 #include "config.h" |
27 #include "core/dom/ScriptRunner.h" | 27 #include "core/dom/ScriptRunner.h" |
28 | 28 |
29 #include "core/dom/Document.h" | 29 #include "core/dom/Document.h" |
30 #include "core/dom/Element.h" | 30 #include "core/dom/Element.h" |
31 #include "core/dom/ScriptLoader.h" | 31 #include "core/dom/ScriptLoader.h" |
32 #include "platform/heap/Handle.h" | 32 #include "platform/heap/Handle.h" |
33 #include "platform/scheduler/Scheduler.h" | |
34 #include "wtf/Functional.h" | |
35 | 33 |
36 namespace blink { | 34 namespace blink { |
37 | 35 |
38 ScriptRunner::ScriptRunner(Document* document) | 36 ScriptRunner::ScriptRunner(Document* document) |
39 : m_document(document) | 37 : m_document(document) |
40 , m_executeScriptsTaskFactory(WTF::bind(&ScriptRunner::executeScripts, this)
) | 38 , m_timer(this, &ScriptRunner::timerFired) |
41 { | 39 { |
42 ASSERT(document); | 40 ASSERT(document); |
43 } | 41 } |
44 | 42 |
45 ScriptRunner::~ScriptRunner() | 43 ScriptRunner::~ScriptRunner() |
46 { | 44 { |
47 #if !ENABLE(OILPAN) | 45 #if !ENABLE(OILPAN) |
48 // Make sure that ScriptLoaders don't keep their PendingScripts alive. | 46 // Make sure that ScriptLoaders don't keep their PendingScripts alive. |
49 for (ScriptLoader* scriptLoader : m_scriptsToExecuteInOrder) | 47 for (ScriptLoader* scriptLoader : m_scriptsToExecuteInOrder) |
50 scriptLoader->detach(); | 48 scriptLoader->detach(); |
(...skipping 21 matching lines...) Expand all Loading... |
72 | 70 |
73 case IN_ORDER_EXECUTION: | 71 case IN_ORDER_EXECUTION: |
74 m_document->incrementLoadEventDelayCount(); | 72 m_document->incrementLoadEventDelayCount(); |
75 m_scriptsToExecuteInOrder.append(scriptLoader); | 73 m_scriptsToExecuteInOrder.append(scriptLoader); |
76 break; | 74 break; |
77 } | 75 } |
78 } | 76 } |
79 | 77 |
80 void ScriptRunner::suspend() | 78 void ScriptRunner::suspend() |
81 { | 79 { |
82 m_executeScriptsTaskFactory.cancel(); | 80 m_timer.stop(); |
83 } | 81 } |
84 | 82 |
85 void ScriptRunner::resume() | 83 void ScriptRunner::resume() |
86 { | 84 { |
87 if (hasPendingScripts()) | 85 if (hasPendingScripts()) |
88 postTaskIfOneIsNotAlreadyInFlight(); | 86 m_timer.startOneShot(0, FROM_HERE); |
89 } | 87 } |
90 | 88 |
91 void ScriptRunner::notifyScriptReady(ScriptLoader* scriptLoader, ExecutionType e
xecutionType) | 89 void ScriptRunner::notifyScriptReady(ScriptLoader* scriptLoader, ExecutionType e
xecutionType) |
92 { | 90 { |
93 switch (executionType) { | 91 switch (executionType) { |
94 case ASYNC_EXECUTION: | 92 case ASYNC_EXECUTION: |
95 ASSERT(m_pendingAsyncScripts.contains(scriptLoader)); | 93 ASSERT(m_pendingAsyncScripts.contains(scriptLoader)); |
96 m_scriptsToExecuteSoon.append(scriptLoader); | 94 m_scriptsToExecuteSoon.append(scriptLoader); |
97 m_pendingAsyncScripts.remove(scriptLoader); | 95 m_pendingAsyncScripts.remove(scriptLoader); |
98 break; | 96 break; |
99 | 97 |
100 case IN_ORDER_EXECUTION: | 98 case IN_ORDER_EXECUTION: |
101 ASSERT(!m_scriptsToExecuteInOrder.isEmpty()); | 99 ASSERT(!m_scriptsToExecuteInOrder.isEmpty()); |
102 break; | 100 break; |
103 } | 101 } |
104 postTaskIfOneIsNotAlreadyInFlight(); | 102 m_timer.startOneShot(0, FROM_HERE); |
105 } | 103 } |
106 | 104 |
107 void ScriptRunner::notifyScriptLoadError(ScriptLoader* scriptLoader, ExecutionTy
pe executionType) | 105 void ScriptRunner::notifyScriptLoadError(ScriptLoader* scriptLoader, ExecutionTy
pe executionType) |
108 { | 106 { |
109 switch (executionType) { | 107 switch (executionType) { |
110 case ASYNC_EXECUTION: | 108 case ASYNC_EXECUTION: |
111 ASSERT(m_pendingAsyncScripts.contains(scriptLoader)); | 109 ASSERT(m_pendingAsyncScripts.contains(scriptLoader)); |
112 m_pendingAsyncScripts.remove(scriptLoader); | 110 m_pendingAsyncScripts.remove(scriptLoader); |
113 scriptLoader->detach(); | 111 scriptLoader->detach(); |
114 m_document->decrementLoadEventDelayCount(); | 112 m_document->decrementLoadEventDelayCount(); |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
148 | 146 |
149 void ScriptRunner::movePendingAsyncScript(ScriptRunner* newRunner, ScriptLoader*
scriptLoader) | 147 void ScriptRunner::movePendingAsyncScript(ScriptRunner* newRunner, ScriptLoader*
scriptLoader) |
150 { | 148 { |
151 if (m_pendingAsyncScripts.contains(scriptLoader)) { | 149 if (m_pendingAsyncScripts.contains(scriptLoader)) { |
152 newRunner->addPendingAsyncScript(scriptLoader); | 150 newRunner->addPendingAsyncScript(scriptLoader); |
153 m_pendingAsyncScripts.remove(scriptLoader); | 151 m_pendingAsyncScripts.remove(scriptLoader); |
154 m_document->decrementLoadEventDelayCount(); | 152 m_document->decrementLoadEventDelayCount(); |
155 } | 153 } |
156 } | 154 } |
157 | 155 |
158 void ScriptRunner::executeScripts() | 156 void ScriptRunner::timerFired(Timer<ScriptRunner>* timer) |
159 { | 157 { |
| 158 ASSERT_UNUSED(timer, timer == &m_timer); |
| 159 |
160 RefPtrWillBeRawPtr<Document> protect(m_document.get()); | 160 RefPtrWillBeRawPtr<Document> protect(m_document.get()); |
161 | 161 |
162 // New scripts are always appended to m_scriptsToExecuteSoon and m_scriptsTo
ExecuteInOrder (never prepended) | 162 WillBeHeapVector<RawPtrWillBeMember<ScriptLoader> > scriptLoaders; |
163 // so as long as we keep track of the current totals, we can ensure the orde
r of execution if new scripts | 163 scriptLoaders.swap(m_scriptsToExecuteSoon); |
164 // are added while executing the current ones. | 164 |
165 // NOTE a yield followed by a notifyScriptReady(... ASYNC_EXECUTION) will re
sult in that script executing | 165 size_t numInOrderScriptsToExecute = 0; |
166 // before any pre-existing ScriptsToExecuteInOrder. | 166 for (; numInOrderScriptsToExecute < m_scriptsToExecuteInOrder.size() && m_sc
riptsToExecuteInOrder[numInOrderScriptsToExecute]->isReady(); ++numInOrderScript
sToExecute) |
167 size_t numScriptsToExecuteSoon = m_scriptsToExecuteSoon.size(); | 167 scriptLoaders.append(m_scriptsToExecuteInOrder[numInOrderScriptsToExecut
e]); |
168 size_t numScriptsToExecuteInOrder = m_scriptsToExecuteInOrder.size(); | 168 if (numInOrderScriptsToExecute) |
169 for (size_t i = 0; i < numScriptsToExecuteSoon; i++) { | 169 m_scriptsToExecuteInOrder.remove(0, numInOrderScriptsToExecute); |
170 ASSERT(!m_scriptsToExecuteSoon.isEmpty()); | 170 |
171 m_scriptsToExecuteSoon.takeFirst()->execute(); | 171 size_t size = scriptLoaders.size(); |
| 172 for (size_t i = 0; i < size; ++i) { |
| 173 scriptLoaders[i]->execute(); |
172 m_document->decrementLoadEventDelayCount(); | 174 m_document->decrementLoadEventDelayCount(); |
173 if (yieldForHighPriorityWork()) | |
174 return; | |
175 } | |
176 | |
177 for (size_t i = 0; i < numScriptsToExecuteInOrder; i++) { | |
178 ASSERT(!m_scriptsToExecuteInOrder.isEmpty()); | |
179 if (!m_scriptsToExecuteInOrder.first()->isReady()) | |
180 break; | |
181 m_scriptsToExecuteInOrder.takeFirst()->execute(); | |
182 m_document->decrementLoadEventDelayCount(); | |
183 if (yieldForHighPriorityWork()) | |
184 return; | |
185 } | 175 } |
186 } | 176 } |
187 | 177 |
188 bool ScriptRunner::yieldForHighPriorityWork() | |
189 { | |
190 if (!Scheduler::shared()->shouldYieldForHighPriorityWork()) | |
191 return false; | |
192 | |
193 postTaskIfOneIsNotAlreadyInFlight(); | |
194 return true; | |
195 } | |
196 | |
197 void ScriptRunner::postTaskIfOneIsNotAlreadyInFlight() | |
198 { | |
199 if (m_executeScriptsTaskFactory.isPending()) | |
200 return; | |
201 | |
202 // FIXME: Rename task() so that it's obvious it cancels any pending task. | |
203 Scheduler::shared()->postLoadingTask(FROM_HERE, m_executeScriptsTaskFactory.
task()); | |
204 } | |
205 | |
206 void ScriptRunner::trace(Visitor* visitor) | 178 void ScriptRunner::trace(Visitor* visitor) |
207 { | 179 { |
208 #if ENABLE(OILPAN) | 180 #if ENABLE(OILPAN) |
209 visitor->trace(m_document); | 181 visitor->trace(m_document); |
210 visitor->trace(m_scriptsToExecuteInOrder); | 182 visitor->trace(m_scriptsToExecuteInOrder); |
211 visitor->trace(m_scriptsToExecuteSoon); | 183 visitor->trace(m_scriptsToExecuteSoon); |
212 visitor->trace(m_pendingAsyncScripts); | 184 visitor->trace(m_pendingAsyncScripts); |
213 #endif | 185 #endif |
214 } | 186 } |
215 | 187 |
216 } | 188 } |
OLD | NEW |