| 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 |
| 36 // This bit of magic is needed by oilpan to prevent the ScriptRunner from leakin
g. |
| 37 namespace WTF { |
| 38 template<> |
| 39 struct ParamStorageTraits<blink::ScriptRunner*> : public PointerParamStorageTrai
ts<blink::ScriptRunner*, false> { |
| 40 }; |
| 41 } |
| 33 | 42 |
| 34 namespace blink { | 43 namespace blink { |
| 35 | 44 |
| 45 |
| 36 ScriptRunner::ScriptRunner(Document* document) | 46 ScriptRunner::ScriptRunner(Document* document) |
| 37 : m_document(document) | 47 : m_document(document) |
| 38 , m_timer(this, &ScriptRunner::timerFired) | 48 , m_executeScriptsTaskFactory(WTF::bind(&ScriptRunner::executeScripts, this)
) |
| 39 { | 49 { |
| 40 ASSERT(document); | 50 ASSERT(document); |
| 41 } | 51 } |
| 42 | 52 |
| 43 ScriptRunner::~ScriptRunner() | 53 ScriptRunner::~ScriptRunner() |
| 44 { | 54 { |
| 45 #if !ENABLE(OILPAN) | 55 #if !ENABLE(OILPAN) |
| 46 // Make sure that ScriptLoaders don't keep their PendingScripts alive. | 56 // Make sure that ScriptLoaders don't keep their PendingScripts alive. |
| 47 for (ScriptLoader* scriptLoader : m_scriptsToExecuteInOrder) | 57 for (ScriptLoader* scriptLoader : m_scriptsToExecuteInOrder) |
| 48 scriptLoader->detach(); | 58 scriptLoader->detach(); |
| (...skipping 21 matching lines...) Expand all Loading... |
| 70 | 80 |
| 71 case IN_ORDER_EXECUTION: | 81 case IN_ORDER_EXECUTION: |
| 72 m_document->incrementLoadEventDelayCount(); | 82 m_document->incrementLoadEventDelayCount(); |
| 73 m_scriptsToExecuteInOrder.append(scriptLoader); | 83 m_scriptsToExecuteInOrder.append(scriptLoader); |
| 74 break; | 84 break; |
| 75 } | 85 } |
| 76 } | 86 } |
| 77 | 87 |
| 78 void ScriptRunner::suspend() | 88 void ScriptRunner::suspend() |
| 79 { | 89 { |
| 80 m_timer.stop(); | 90 m_executeScriptsTaskFactory.cancel(); |
| 81 } | 91 } |
| 82 | 92 |
| 83 void ScriptRunner::resume() | 93 void ScriptRunner::resume() |
| 84 { | 94 { |
| 85 if (hasPendingScripts()) | 95 if (hasPendingScripts()) |
| 86 m_timer.startOneShot(0, FROM_HERE); | 96 postTaskIfOneIsNotAlreadyInFlight(); |
| 87 } | 97 } |
| 88 | 98 |
| 89 void ScriptRunner::notifyScriptReady(ScriptLoader* scriptLoader, ExecutionType e
xecutionType) | 99 void ScriptRunner::notifyScriptReady(ScriptLoader* scriptLoader, ExecutionType e
xecutionType) |
| 90 { | 100 { |
| 91 switch (executionType) { | 101 switch (executionType) { |
| 92 case ASYNC_EXECUTION: | 102 case ASYNC_EXECUTION: |
| 93 // RELEASE_ASSERT makes us crash in a controlled way in error cases | 103 // RELEASE_ASSERT makes us crash in a controlled way in error cases |
| 94 // where the ScriptLoader is associated with the wrong ScriptRunner | 104 // where the ScriptLoader is associated with the wrong ScriptRunner |
| 95 // (otherwise we'd cause a use-after-free in ~ScriptRunner when it tries | 105 // (otherwise we'd cause a use-after-free in ~ScriptRunner when it tries |
| 96 // to detach). | 106 // to detach). |
| 97 RELEASE_ASSERT_WITH_SECURITY_IMPLICATION(m_pendingAsyncScripts.contains(
scriptLoader)); | 107 RELEASE_ASSERT_WITH_SECURITY_IMPLICATION(m_pendingAsyncScripts.contains(
scriptLoader)); |
| 98 m_scriptsToExecuteSoon.append(scriptLoader); | 108 m_scriptsToExecuteSoon.append(scriptLoader); |
| 99 m_pendingAsyncScripts.remove(scriptLoader); | 109 m_pendingAsyncScripts.remove(scriptLoader); |
| 100 break; | 110 break; |
| 101 | 111 |
| 102 case IN_ORDER_EXECUTION: | 112 case IN_ORDER_EXECUTION: |
| 103 RELEASE_ASSERT_WITH_SECURITY_IMPLICATION(!m_scriptsToExecuteInOrder.isEm
pty()); | 113 RELEASE_ASSERT_WITH_SECURITY_IMPLICATION(!m_scriptsToExecuteInOrder.isEm
pty()); |
| 104 break; | 114 break; |
| 105 } | 115 } |
| 106 m_timer.startOneShot(0, FROM_HERE); | 116 postTaskIfOneIsNotAlreadyInFlight(); |
| 107 } | 117 } |
| 108 | 118 |
| 109 void ScriptRunner::notifyScriptLoadError(ScriptLoader* scriptLoader, ExecutionTy
pe executionType) | 119 void ScriptRunner::notifyScriptLoadError(ScriptLoader* scriptLoader, ExecutionTy
pe executionType) |
| 110 { | 120 { |
| 111 switch (executionType) { | 121 switch (executionType) { |
| 112 case ASYNC_EXECUTION: | 122 case ASYNC_EXECUTION: |
| 113 // RELEASE_ASSERT makes us crash in a controlled way in error cases | 123 // RELEASE_ASSERT makes us crash in a controlled way in error cases |
| 114 // where the ScriptLoader is associated with the wrong ScriptRunner | 124 // where the ScriptLoader is associated with the wrong ScriptRunner |
| 115 // (otherwise we'd cause a use-after-free in ~ScriptRunner when it tries | 125 // (otherwise we'd cause a use-after-free in ~ScriptRunner when it tries |
| 116 // to detach). | 126 // to detach). |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 154 | 164 |
| 155 void ScriptRunner::movePendingAsyncScript(ScriptRunner* newRunner, ScriptLoader*
scriptLoader) | 165 void ScriptRunner::movePendingAsyncScript(ScriptRunner* newRunner, ScriptLoader*
scriptLoader) |
| 156 { | 166 { |
| 157 if (m_pendingAsyncScripts.contains(scriptLoader)) { | 167 if (m_pendingAsyncScripts.contains(scriptLoader)) { |
| 158 newRunner->addPendingAsyncScript(scriptLoader); | 168 newRunner->addPendingAsyncScript(scriptLoader); |
| 159 m_pendingAsyncScripts.remove(scriptLoader); | 169 m_pendingAsyncScripts.remove(scriptLoader); |
| 160 m_document->decrementLoadEventDelayCount(); | 170 m_document->decrementLoadEventDelayCount(); |
| 161 } | 171 } |
| 162 } | 172 } |
| 163 | 173 |
| 164 void ScriptRunner::timerFired(Timer<ScriptRunner>* timer) | 174 void ScriptRunner::executeScripts() |
| 165 { | 175 { |
| 166 ASSERT_UNUSED(timer, timer == &m_timer); | |
| 167 | |
| 168 RefPtrWillBeRawPtr<Document> protect(m_document.get()); | 176 RefPtrWillBeRawPtr<Document> protect(m_document.get()); |
| 169 | 177 |
| 170 WillBeHeapVector<RawPtrWillBeMember<ScriptLoader> > scriptLoaders; | 178 // New scripts are always appended to m_scriptsToExecuteSoon and m_scriptsTo
ExecuteInOrder (never prepended) |
| 171 scriptLoaders.swap(m_scriptsToExecuteSoon); | 179 // so as long as we keep track of the current totals, we can ensure the orde
r of execution if new scripts |
| 180 // are added while executing the current ones. |
| 181 // NOTE a yield followed by a notifyScriptReady(... ASYNC_EXECUTION) will re
sult in that script executing |
| 182 // before any pre-existing ScriptsToExecuteInOrder. |
| 183 size_t numScriptsToExecuteSoon = m_scriptsToExecuteSoon.size(); |
| 184 size_t numScriptsToExecuteInOrder = m_scriptsToExecuteInOrder.size(); |
| 185 for (size_t i = 0; i < numScriptsToExecuteSoon; i++) { |
| 186 ASSERT(!m_scriptsToExecuteSoon.isEmpty()); |
| 187 m_scriptsToExecuteSoon.takeFirst()->execute(); |
| 188 m_document->decrementLoadEventDelayCount(); |
| 189 if (yieldForHighPriorityWork()) |
| 190 return; |
| 191 } |
| 172 | 192 |
| 173 size_t numInOrderScriptsToExecute = 0; | 193 for (size_t i = 0; i < numScriptsToExecuteInOrder; i++) { |
| 174 for (; numInOrderScriptsToExecute < m_scriptsToExecuteInOrder.size() && m_sc
riptsToExecuteInOrder[numInOrderScriptsToExecute]->isReady(); ++numInOrderScript
sToExecute) | 194 ASSERT(!m_scriptsToExecuteInOrder.isEmpty()); |
| 175 scriptLoaders.append(m_scriptsToExecuteInOrder[numInOrderScriptsToExecut
e]); | 195 if (!m_scriptsToExecuteInOrder.first()->isReady()) |
| 176 if (numInOrderScriptsToExecute) | 196 break; |
| 177 m_scriptsToExecuteInOrder.remove(0, numInOrderScriptsToExecute); | 197 m_scriptsToExecuteInOrder.takeFirst()->execute(); |
| 198 m_document->decrementLoadEventDelayCount(); |
| 199 if (yieldForHighPriorityWork()) |
| 200 return; |
| 201 } |
| 202 } |
| 178 | 203 |
| 179 size_t size = scriptLoaders.size(); | 204 bool ScriptRunner::yieldForHighPriorityWork() |
| 180 for (size_t i = 0; i < size; ++i) { | 205 { |
| 181 scriptLoaders[i]->execute(); | 206 if (!Scheduler::shared()->shouldYieldForHighPriorityWork()) |
| 182 m_document->decrementLoadEventDelayCount(); | 207 return false; |
| 183 } | 208 |
| 209 postTaskIfOneIsNotAlreadyInFlight(); |
| 210 return true; |
| 211 } |
| 212 |
| 213 void ScriptRunner::postTaskIfOneIsNotAlreadyInFlight() |
| 214 { |
| 215 if (m_executeScriptsTaskFactory.isPending()) |
| 216 return; |
| 217 |
| 218 // FIXME: Rename task() so that it's obvious it cancels any pending task. |
| 219 Scheduler::shared()->postLoadingTask(FROM_HERE, m_executeScriptsTaskFactory.
task()); |
| 184 } | 220 } |
| 185 | 221 |
| 186 DEFINE_TRACE(ScriptRunner) | 222 DEFINE_TRACE(ScriptRunner) |
| 187 { | 223 { |
| 188 #if ENABLE(OILPAN) | 224 #if ENABLE(OILPAN) |
| 189 visitor->trace(m_document); | 225 visitor->trace(m_document); |
| 190 visitor->trace(m_scriptsToExecuteInOrder); | 226 visitor->trace(m_scriptsToExecuteInOrder); |
| 191 visitor->trace(m_scriptsToExecuteSoon); | 227 visitor->trace(m_scriptsToExecuteSoon); |
| 192 visitor->trace(m_pendingAsyncScripts); | 228 visitor->trace(m_pendingAsyncScripts); |
| 193 #endif | 229 #endif |
| 194 } | 230 } |
| 195 | 231 |
| 196 } | 232 } |
| OLD | NEW |