| 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 |