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 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
65 // Verify that detach() has been called. | 65 // Verify that detach() has been called. |
66 ASSERT(!m_document); | 66 ASSERT(!m_document); |
67 #endif | 67 #endif |
68 } | 68 } |
69 | 69 |
70 void HTMLScriptRunner::detach() | 70 void HTMLScriptRunner::detach() |
71 { | 71 { |
72 if (!m_document) | 72 if (!m_document) |
73 return; | 73 return; |
74 | 74 |
75 if (m_parserBlockingScript.resource() && m_parserBlockingScript.watchingForL
oad()) | 75 m_parserBlockingScript.stopWatchingForLoad(this); |
76 stopWatchingForLoad(m_parserBlockingScript); | |
77 | 76 |
78 while (!m_scriptsToExecuteAfterParsing.isEmpty()) { | 77 while (!m_scriptsToExecuteAfterParsing.isEmpty()) { |
79 PendingScript pendingScript = m_scriptsToExecuteAfterParsing.takeFirst()
; | 78 PendingScript pendingScript = m_scriptsToExecuteAfterParsing.takeFirst()
; |
80 if (pendingScript.resource() && pendingScript.watchingForLoad()) | 79 pendingScript.stopWatchingForLoad(this); |
81 stopWatchingForLoad(pendingScript); | |
82 } | 80 } |
83 m_document = nullptr; | 81 m_document = nullptr; |
84 } | 82 } |
85 | 83 |
86 static KURL documentURLForScriptExecution(Document* document) | 84 static KURL documentURLForScriptExecution(Document* document) |
87 { | 85 { |
88 if (!document) | 86 if (!document) |
89 return KURL(); | 87 return KURL(); |
90 | 88 |
91 if (!document->frame()) { | 89 if (!document->frame()) { |
92 if (document->importsController()) | 90 if (document->importsController()) |
93 return document->url(); | 91 return document->url(); |
94 return KURL(); | 92 return KURL(); |
95 } | 93 } |
96 | 94 |
97 // Use the URL of the currently active document for this frame. | 95 // Use the URL of the currently active document for this frame. |
98 return document->frame()->document()->url(); | 96 return document->frame()->document()->url(); |
99 } | 97 } |
100 | 98 |
101 inline PassRefPtrWillBeRawPtr<Event> createScriptLoadEvent() | 99 inline PassRefPtrWillBeRawPtr<Event> createScriptLoadEvent() |
102 { | 100 { |
103 return Event::create(EventTypeNames::load); | 101 return Event::create(EventTypeNames::load); |
104 } | 102 } |
105 | 103 |
106 ScriptSourceCode HTMLScriptRunner::sourceFromPendingScript(const PendingScript&
script, bool& errorOccurred) const | |
107 { | |
108 if (script.resource()) { | |
109 errorOccurred = script.resource()->errorOccurred(); | |
110 ASSERT(script.resource()->isLoaded()); | |
111 return ScriptSourceCode(script.resource()); | |
112 } | |
113 errorOccurred = false; | |
114 return ScriptSourceCode(script.element()->textContent(), documentURLForScrip
tExecution(m_document), script.startingPosition()); | |
115 } | |
116 | |
117 bool HTMLScriptRunner::isPendingScriptReady(const PendingScript& script) | 104 bool HTMLScriptRunner::isPendingScriptReady(const PendingScript& script) |
118 { | 105 { |
119 m_hasScriptsWaitingForResources = !m_document->isScriptExecutionReady(); | 106 m_hasScriptsWaitingForResources = !m_document->isScriptExecutionReady(); |
120 if (m_hasScriptsWaitingForResources) | 107 if (m_hasScriptsWaitingForResources) |
121 return false; | 108 return false; |
122 if (script.resource() && !script.resource()->isLoaded()) | 109 if (script.resource() && !script.resource()->isLoaded()) |
123 return false; | 110 return false; |
124 return true; | 111 return true; |
125 } | 112 } |
126 | 113 |
127 void HTMLScriptRunner::executeParsingBlockingScript() | 114 void HTMLScriptRunner::executeParsingBlockingScript() |
128 { | 115 { |
129 ASSERT(m_document); | 116 ASSERT(m_document); |
130 ASSERT(!isExecutingScript()); | 117 ASSERT(!isExecutingScript()); |
131 ASSERT(m_document->isScriptExecutionReady()); | 118 ASSERT(m_document->isScriptExecutionReady()); |
132 ASSERT(isPendingScriptReady(m_parserBlockingScript)); | 119 ASSERT(isPendingScriptReady(m_parserBlockingScript)); |
133 | 120 |
134 InsertionPointRecord insertionPointRecord(m_host->inputStream()); | 121 InsertionPointRecord insertionPointRecord(m_host->inputStream()); |
135 executePendingScriptAndDispatchEvent(m_parserBlockingScript, PendingScriptBl
ockingParser); | 122 executePendingScriptAndDispatchEvent(m_parserBlockingScript, PendingScriptBl
ockingParser); |
136 } | 123 } |
137 | 124 |
138 void HTMLScriptRunner::executePendingScriptAndDispatchEvent(PendingScript& pendi
ngScript, PendingScriptType pendingScriptType) | 125 void HTMLScriptRunner::executePendingScriptAndDispatchEvent(PendingScript& pendi
ngScript, PendingScriptType pendingScriptType) |
139 { | 126 { |
140 bool errorOccurred = false; | 127 bool errorOccurred = false; |
141 ScriptSourceCode sourceCode = sourceFromPendingScript(pendingScript, errorOc
curred); | 128 ScriptSourceCode sourceCode = pendingScript.getSource(documentURLForScriptEx
ecution(m_document), errorOccurred); |
142 | 129 |
143 // Stop watching loads before executeScript to prevent recursion if the scri
pt reloads itself. | 130 // Stop watching loads before executeScript to prevent recursion if the scri
pt reloads itself. |
144 if (pendingScript.resource() && pendingScript.watchingForLoad()) | 131 pendingScript.stopWatchingForLoad(this); |
145 stopWatchingForLoad(pendingScript); | |
146 | 132 |
147 if (!isExecutingScript()) { | 133 if (!isExecutingScript()) { |
148 Microtask::performCheckpoint(); | 134 Microtask::performCheckpoint(); |
149 if (pendingScriptType == PendingScriptBlockingParser) { | 135 if (pendingScriptType == PendingScriptBlockingParser) { |
150 m_hasScriptsWaitingForResources = !m_document->isScriptExecutionRead
y(); | 136 m_hasScriptsWaitingForResources = !m_document->isScriptExecutionRead
y(); |
151 // The parser cannot be unblocked as a microtask requested another r
esource | 137 // The parser cannot be unblocked as a microtask requested another r
esource |
152 if (m_hasScriptsWaitingForResources) | 138 if (m_hasScriptsWaitingForResources) |
153 return; | 139 return; |
154 } | 140 } |
155 } | 141 } |
(...skipping 13 matching lines...) Expand all Loading... |
169 } | 155 } |
170 if (sourceCode.resource()) { | 156 if (sourceCode.resource()) { |
171 double timeBetweenLoadedAndCompiledMs = (WTF::monotonicallyIncreasingTim
e() - sourceCode.resource()->loadFinishTime()) * 1000; | 157 double timeBetweenLoadedAndCompiledMs = (WTF::monotonicallyIncreasingTim
e() - sourceCode.resource()->loadFinishTime()) * 1000; |
172 const char* histogramName = pendingScriptType == PendingScriptBlockingPa
rser ? "WebCore.Scripts.ParsingBlocking.TimeBetweenLoadedAndCompiled" : "WebCore
.Scripts.Deferred.TimeBetweenLoadedAndCompiled"; | 158 const char* histogramName = pendingScriptType == PendingScriptBlockingPa
rser ? "WebCore.Scripts.ParsingBlocking.TimeBetweenLoadedAndCompiled" : "WebCore
.Scripts.Deferred.TimeBetweenLoadedAndCompiled"; |
173 blink::Platform::current()->histogramCustomCounts(histogramName, timeBet
weenLoadedAndCompiledMs, 0, 10000, 50); | 159 blink::Platform::current()->histogramCustomCounts(histogramName, timeBet
weenLoadedAndCompiledMs, 0, 10000, 50); |
174 } | 160 } |
175 | 161 |
176 ASSERT(!isExecutingScript()); | 162 ASSERT(!isExecutingScript()); |
177 } | 163 } |
178 | 164 |
179 void HTMLScriptRunner::watchForLoad(PendingScript& pendingScript) | |
180 { | |
181 ASSERT(!pendingScript.watchingForLoad()); | |
182 ASSERT(!pendingScript.resource()->isLoaded()); | |
183 // addClient() will call notifyFinished() if the load is complete. | |
184 // Callers do not expect to be re-entered from this call, so they | |
185 // should not become a client of an already-loaded Resource. | |
186 pendingScript.resource()->addClient(this); | |
187 pendingScript.setWatchingForLoad(true); | |
188 } | |
189 | |
190 void HTMLScriptRunner::stopWatchingForLoad(PendingScript& pendingScript) | |
191 { | |
192 ASSERT(pendingScript.watchingForLoad()); | |
193 pendingScript.resource()->removeClient(this); | |
194 pendingScript.setWatchingForLoad(false); | |
195 } | |
196 | |
197 void HTMLScriptRunner::notifyFinished(Resource* cachedResource) | 165 void HTMLScriptRunner::notifyFinished(Resource* cachedResource) |
198 { | 166 { |
199 m_host->notifyScriptLoaded(cachedResource); | 167 m_host->notifyScriptLoaded(cachedResource); |
200 } | 168 } |
201 | 169 |
202 // Implements the steps for 'An end tag whose tag name is "script"' | 170 // Implements the steps for 'An end tag whose tag name is "script"' |
203 // http://whatwg.org/html#scriptEndTag | 171 // http://whatwg.org/html#scriptEndTag |
204 // Script handling lives outside the tree builder to keep each class simple. | 172 // Script handling lives outside the tree builder to keep each class simple. |
205 void HTMLScriptRunner::execute(PassRefPtrWillBeRawPtr<Element> scriptElement, co
nst TextPosition& scriptStartPosition) | 173 void HTMLScriptRunner::execute(PassRefPtrWillBeRawPtr<Element> scriptElement, co
nst TextPosition& scriptStartPosition) |
206 { | 174 { |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
253 executeParsingBlockingScripts(); | 221 executeParsingBlockingScripts(); |
254 } | 222 } |
255 | 223 |
256 bool HTMLScriptRunner::executeScriptsWaitingForParsing() | 224 bool HTMLScriptRunner::executeScriptsWaitingForParsing() |
257 { | 225 { |
258 while (!m_scriptsToExecuteAfterParsing.isEmpty()) { | 226 while (!m_scriptsToExecuteAfterParsing.isEmpty()) { |
259 ASSERT(!isExecutingScript()); | 227 ASSERT(!isExecutingScript()); |
260 ASSERT(!hasParserBlockingScript()); | 228 ASSERT(!hasParserBlockingScript()); |
261 ASSERT(m_scriptsToExecuteAfterParsing.first().resource()); | 229 ASSERT(m_scriptsToExecuteAfterParsing.first().resource()); |
262 if (!m_scriptsToExecuteAfterParsing.first().resource()->isLoaded()) { | 230 if (!m_scriptsToExecuteAfterParsing.first().resource()->isLoaded()) { |
263 watchForLoad(m_scriptsToExecuteAfterParsing.first()); | 231 m_scriptsToExecuteAfterParsing.first().watchForLoad(this); |
264 return false; | 232 return false; |
265 } | 233 } |
266 PendingScript first = m_scriptsToExecuteAfterParsing.takeFirst(); | 234 PendingScript first = m_scriptsToExecuteAfterParsing.takeFirst(); |
267 executePendingScriptAndDispatchEvent(first, PendingScriptDeferred); | 235 executePendingScriptAndDispatchEvent(first, PendingScriptDeferred); |
268 // FIXME: What is this m_document check for? | 236 // FIXME: What is this m_document check for? |
269 if (!m_document) | 237 if (!m_document) |
270 return false; | 238 return false; |
271 } | 239 } |
272 return true; | 240 return true; |
273 } | 241 } |
274 | 242 |
275 void HTMLScriptRunner::requestParsingBlockingScript(Element* element) | 243 void HTMLScriptRunner::requestParsingBlockingScript(Element* element) |
276 { | 244 { |
277 if (!requestPendingScript(m_parserBlockingScript, element)) | 245 if (!requestPendingScript(m_parserBlockingScript, element)) |
278 return; | 246 return; |
279 | 247 |
280 ASSERT(m_parserBlockingScript.resource()); | 248 ASSERT(m_parserBlockingScript.resource()); |
281 | 249 |
282 blink::Platform::current()->histogramEnumeration("WebCore.Scripts.ParsingBlo
cking.AlreadyLoaded", m_parserBlockingScript.resource()->isLoaded() ? 1 : 0, 2); | 250 blink::Platform::current()->histogramEnumeration("WebCore.Scripts.ParsingBlo
cking.AlreadyLoaded", m_parserBlockingScript.resource()->isLoaded() ? 1 : 0, 2); |
283 // We only care about a load callback if resource is not already | 251 // We only care about a load callback if resource is not already |
284 // in the cache. Callers will attempt to run the m_parserBlockingScript | 252 // in the cache. Callers will attempt to run the m_parserBlockingScript |
285 // if possible before returning control to the parser. | 253 // if possible before returning control to the parser. |
286 if (!m_parserBlockingScript.resource()->isLoaded()) | 254 if (!m_parserBlockingScript.resource()->isLoaded()) |
287 watchForLoad(m_parserBlockingScript); | 255 m_parserBlockingScript.watchForLoad(this); |
288 } | 256 } |
289 | 257 |
290 void HTMLScriptRunner::requestDeferredScript(Element* element) | 258 void HTMLScriptRunner::requestDeferredScript(Element* element) |
291 { | 259 { |
292 PendingScript pendingScript; | 260 PendingScript pendingScript; |
293 if (!requestPendingScript(pendingScript, element)) | 261 if (!requestPendingScript(pendingScript, element)) |
294 return; | 262 return; |
295 | 263 |
296 ASSERT(pendingScript.resource()); | 264 ASSERT(pendingScript.resource()); |
297 m_scriptsToExecuteAfterParsing.append(pendingScript); | 265 m_scriptsToExecuteAfterParsing.append(pendingScript); |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
359 | 327 |
360 void HTMLScriptRunner::trace(Visitor* visitor) | 328 void HTMLScriptRunner::trace(Visitor* visitor) |
361 { | 329 { |
362 visitor->trace(m_document); | 330 visitor->trace(m_document); |
363 visitor->trace(m_host); | 331 visitor->trace(m_host); |
364 visitor->trace(m_parserBlockingScript); | 332 visitor->trace(m_parserBlockingScript); |
365 visitor->trace(m_scriptsToExecuteAfterParsing); | 333 visitor->trace(m_scriptsToExecuteAfterParsing); |
366 } | 334 } |
367 | 335 |
368 } | 336 } |
OLD | NEW |