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 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
68 , m_hasScriptsWaitingForStylesheets(false) | 68 , m_hasScriptsWaitingForStylesheets(false) |
69 { | 69 { |
70 ASSERT(m_host); | 70 ASSERT(m_host); |
71 } | 71 } |
72 | 72 |
73 HTMLScriptRunner::~HTMLScriptRunner() | 73 HTMLScriptRunner::~HTMLScriptRunner() |
74 { | 74 { |
75 // FIXME: Should we be passed a "done loading/parsing" callback sooner than
destruction? | 75 // FIXME: Should we be passed a "done loading/parsing" callback sooner than
destruction? |
76 if (m_parsingBlockingScript.cachedScript() && m_parsingBlockingScript.watchi
ngForLoad()) | 76 if (m_parsingBlockingScript.cachedScript() && m_parsingBlockingScript.watchi
ngForLoad()) |
77 stopWatchingForLoad(m_parsingBlockingScript); | 77 stopWatchingForLoad(m_parsingBlockingScript); |
78 | |
79 while (!m_scriptsToExecuteAfterParsing.isEmpty()) { | |
80 PendingScript pendingScript = m_scriptsToExecuteAfterParsing.takeFirst()
; | |
81 if (pendingScript.cachedScript() && pendingScript.watchingForLoad()) | |
82 stopWatchingForLoad(pendingScript); | |
83 } | |
84 } | 78 } |
85 | 79 |
86 void HTMLScriptRunner::detach() | 80 void HTMLScriptRunner::detach() |
87 { | 81 { |
88 m_document = 0; | 82 m_document = 0; |
89 } | 83 } |
90 | 84 |
91 static KURL documentURLForScriptExecution(Document* document) | 85 static KURL documentURLForScriptExecution(Document* document) |
92 { | 86 { |
93 if (!document || !document->frame()) | 87 if (!document || !document->frame()) |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
128 return true; | 122 return true; |
129 } | 123 } |
130 | 124 |
131 void HTMLScriptRunner::executeParsingBlockingScript() | 125 void HTMLScriptRunner::executeParsingBlockingScript() |
132 { | 126 { |
133 ASSERT(m_document); | 127 ASSERT(m_document); |
134 ASSERT(!m_scriptNestingLevel); | 128 ASSERT(!m_scriptNestingLevel); |
135 ASSERT(m_document->haveStylesheetsLoaded()); | 129 ASSERT(m_document->haveStylesheetsLoaded()); |
136 ASSERT(isPendingScriptReady(m_parsingBlockingScript)); | 130 ASSERT(isPendingScriptReady(m_parsingBlockingScript)); |
137 | 131 |
| 132 // Stop watching loads before executeScript to prevent recursion if the scri
pt reloads itself. |
| 133 if (m_parsingBlockingScript.cachedScript() && m_parsingBlockingScript.watchi
ngForLoad()) |
| 134 stopWatchingForLoad(m_parsingBlockingScript); |
| 135 |
138 InsertionPointRecord insertionPointRecord(m_host->inputStream()); | 136 InsertionPointRecord insertionPointRecord(m_host->inputStream()); |
139 executePendingScriptAndDispatchEvent(m_parsingBlockingScript); | 137 executePendingScriptAndDispatchEvent(m_parsingBlockingScript); |
140 } | 138 } |
141 | 139 |
142 void HTMLScriptRunner::executePendingScriptAndDispatchEvent(PendingScript& pendi
ngScript) | 140 void HTMLScriptRunner::executePendingScriptAndDispatchEvent(PendingScript& pendi
ngScript) |
143 { | 141 { |
144 bool errorOccurred = false; | 142 bool errorOccurred = false; |
145 ScriptSourceCode sourceCode = sourceFromPendingScript(pendingScript, errorOc
curred); | 143 ScriptSourceCode sourceCode = sourceFromPendingScript(pendingScript, errorOc
curred); |
146 | 144 |
147 // Stop watching loads before executeScript to prevent recursion if the scri
pt reloads itself. | |
148 if (pendingScript.cachedScript() && pendingScript.watchingForLoad()) | |
149 stopWatchingForLoad(pendingScript); | |
150 | |
151 // Clear the pending script before possible rentrancy from executeScript() | 145 // Clear the pending script before possible rentrancy from executeScript() |
152 RefPtr<Element> scriptElement = pendingScript.releaseElementAndClear(); | 146 RefPtr<Element> scriptElement = pendingScript.releaseElementAndClear(); |
153 { | 147 { |
154 NestingLevelIncrementer nestingLevelIncrementer(m_scriptNestingLevel); | 148 NestingLevelIncrementer nestingLevelIncrementer(m_scriptNestingLevel); |
155 if (errorOccurred) | 149 if (errorOccurred) |
156 scriptElement->dispatchEvent(createScriptErrorEvent()); | 150 scriptElement->dispatchEvent(createScriptErrorEvent()); |
157 else { | 151 else { |
158 executeScript(scriptElement.get(), sourceCode); | 152 executeScript(scriptElement.get(), sourceCode); |
159 scriptElement->dispatchEvent(createScriptLoadEvent()); | 153 scriptElement->dispatchEvent(createScriptLoadEvent()); |
160 } | 154 } |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
237 { | 231 { |
238 ASSERT(m_document); | 232 ASSERT(m_document); |
239 // Callers should check hasScriptsWaitingForStylesheets() before calling | 233 // Callers should check hasScriptsWaitingForStylesheets() before calling |
240 // to prevent parser or script re-entry during </style> parsing. | 234 // to prevent parser or script re-entry during </style> parsing. |
241 ASSERT(hasScriptsWaitingForStylesheets()); | 235 ASSERT(hasScriptsWaitingForStylesheets()); |
242 ASSERT(!m_scriptNestingLevel); | 236 ASSERT(!m_scriptNestingLevel); |
243 ASSERT(m_document->haveStylesheetsLoaded()); | 237 ASSERT(m_document->haveStylesheetsLoaded()); |
244 return executeParsingBlockingScripts(); | 238 return executeParsingBlockingScripts(); |
245 } | 239 } |
246 | 240 |
247 bool HTMLScriptRunner::executeScriptsWaitingForParsing() | |
248 { | |
249 while (!m_scriptsToExecuteAfterParsing.isEmpty()) { | |
250 ASSERT(!m_scriptNestingLevel); | |
251 ASSERT(!haveParsingBlockingScript()); | |
252 ASSERT(m_scriptsToExecuteAfterParsing.first().cachedScript()); | |
253 if (!m_scriptsToExecuteAfterParsing.first().cachedScript()->isLoaded())
{ | |
254 watchForLoad(m_scriptsToExecuteAfterParsing.first()); | |
255 return false; | |
256 } | |
257 PendingScript first = m_scriptsToExecuteAfterParsing.takeFirst(); | |
258 executePendingScriptAndDispatchEvent(first); | |
259 if (!m_document) | |
260 return false; | |
261 } | |
262 return true; | |
263 } | |
264 | |
265 void HTMLScriptRunner::requestParsingBlockingScript(Element* element) | 241 void HTMLScriptRunner::requestParsingBlockingScript(Element* element) |
266 { | 242 { |
267 if (!requestPendingScript(m_parsingBlockingScript, element)) | 243 if (!requestPendingScript(m_parsingBlockingScript, element)) |
268 return; | 244 return; |
269 | 245 |
270 ASSERT(m_parsingBlockingScript.cachedScript()); | 246 ASSERT(m_parsingBlockingScript.cachedScript()); |
271 | 247 |
272 // We only care about a load callback if cachedScript is not already | 248 // We only care about a load callback if cachedScript is not already |
273 // in the cache. Callers will attempt to run the m_parsingBlockingScript | 249 // in the cache. Callers will attempt to run the m_parsingBlockingScript |
274 // if possible before returning control to the parser. | 250 // if possible before returning control to the parser. |
275 if (!m_parsingBlockingScript.cachedScript()->isLoaded()) | 251 if (!m_parsingBlockingScript.cachedScript()->isLoaded()) |
276 watchForLoad(m_parsingBlockingScript); | 252 watchForLoad(m_parsingBlockingScript); |
277 } | 253 } |
278 | 254 |
279 void HTMLScriptRunner::requestDeferredScript(Element* element) | |
280 { | |
281 PendingScript pendingScript; | |
282 if (!requestPendingScript(pendingScript, element)) | |
283 return; | |
284 | |
285 ASSERT(pendingScript.cachedScript()); | |
286 m_scriptsToExecuteAfterParsing.append(pendingScript); | |
287 } | |
288 | |
289 bool HTMLScriptRunner::requestPendingScript(PendingScript& pendingScript, Elemen
t* script) const | 255 bool HTMLScriptRunner::requestPendingScript(PendingScript& pendingScript, Elemen
t* script) const |
290 { | 256 { |
291 ASSERT(!pendingScript.element()); | 257 ASSERT(!pendingScript.element()); |
292 const AtomicString& srcValue = script->getAttribute(srcAttr); | 258 const AtomicString& srcValue = script->getAttribute(srcAttr); |
293 // Allow the host to disllow script loads (using the XSSAuditor, etc.) | 259 // Allow the host to disllow script loads (using the XSSAuditor, etc.) |
294 if (!m_host->shouldLoadExternalScriptFromSrc(srcValue)) | 260 if (!m_host->shouldLoadExternalScriptFromSrc(srcValue)) |
295 return false; | 261 return false; |
296 // FIXME: We need to resolve the url relative to the element. | 262 // FIXME: We need to resolve the url relative to the element. |
297 if (!script->dispatchBeforeLoadEvent(srcValue)) | 263 if (!script->dispatchBeforeLoadEvent(srcValue)) |
298 return false; | 264 return false; |
(...skipping 15 matching lines...) Expand all Loading... |
314 ASSERT(m_document); | 280 ASSERT(m_document); |
315 ASSERT(!haveParsingBlockingScript()); | 281 ASSERT(!haveParsingBlockingScript()); |
316 { | 282 { |
317 InsertionPointRecord insertionPointRecord(m_host->inputStream()); | 283 InsertionPointRecord insertionPointRecord(m_host->inputStream()); |
318 NestingLevelIncrementer nestingLevelIncrementer(m_scriptNestingLevel); | 284 NestingLevelIncrementer nestingLevelIncrementer(m_scriptNestingLevel); |
319 | 285 |
320 // Check script type and language, current code uses ScriptElement::shou
ldExecuteAsJavaScript(), but that may not be HTML5 compliant. | 286 // Check script type and language, current code uses ScriptElement::shou
ldExecuteAsJavaScript(), but that may not be HTML5 compliant. |
321 notImplemented(); // event for support | 287 notImplemented(); // event for support |
322 | 288 |
323 if (script->hasAttribute(srcAttr)) { | 289 if (script->hasAttribute(srcAttr)) { |
324 // FIXME: Handle async. | 290 // FIXME: Handle defer and async |
325 if (script->hasAttribute(deferAttr)) | 291 requestParsingBlockingScript(script); |
326 requestDeferredScript(script); | |
327 else | |
328 requestParsingBlockingScript(script); | |
329 } else { | 292 } else { |
330 // FIXME: We do not block inline <script> tags on stylesheets to mat
ch the | 293 // FIXME: We do not block inline <script> tags on stylesheets to mat
ch the |
331 // old parser for now. When we do, the ASSERT below should be added
. | 294 // old parser for now. When we do, the ASSERT below should be added
. |
332 // See https://bugs.webkit.org/show_bug.cgi?id=40047 | 295 // See https://bugs.webkit.org/show_bug.cgi?id=40047 |
333 // ASSERT(document()->haveStylesheetsLoaded()); | 296 // ASSERT(document()->haveStylesheetsLoaded()); |
334 ASSERT(isExecutingScript()); | 297 ASSERT(isExecutingScript()); |
335 ScriptSourceCode sourceCode(script->textContent(), documentURLForScr
iptExecution(m_document), startingLineNumber); | 298 ScriptSourceCode sourceCode(script->textContent(), documentURLForScr
iptExecution(m_document), startingLineNumber); |
336 executeScript(script, sourceCode); | 299 executeScript(script, sourceCode); |
337 } | 300 } |
338 } | 301 } |
339 } | 302 } |
340 | 303 |
341 } | 304 } |
OLD | NEW |