| 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 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 147 } // namespace | 147 } // namespace |
| 148 | 148 |
| 149 using namespace HTMLNames; | 149 using namespace HTMLNames; |
| 150 | 150 |
| 151 HTMLScriptRunner::HTMLScriptRunner(HTMLParserReentryPermit* reentryPermit, | 151 HTMLScriptRunner::HTMLScriptRunner(HTMLParserReentryPermit* reentryPermit, |
| 152 Document* document, | 152 Document* document, |
| 153 HTMLScriptRunnerHost* host) | 153 HTMLScriptRunnerHost* host) |
| 154 : m_reentryPermit(reentryPermit), | 154 : m_reentryPermit(reentryPermit), |
| 155 m_document(document), | 155 m_document(document), |
| 156 m_host(host), | 156 m_host(host), |
| 157 m_parserBlockingScript(PendingScript::create(nullptr, nullptr)), | 157 m_parserBlockingScript(PendingScript::create(nullptr, nullptr)) { |
| 158 m_hasScriptsWaitingForResources(false) { | |
| 159 ASSERT(m_host); | 158 ASSERT(m_host); |
| 160 ThreadState::current()->registerPreFinalizer(this); | 159 ThreadState::current()->registerPreFinalizer(this); |
| 161 } | 160 } |
| 162 | 161 |
| 163 HTMLScriptRunner::~HTMLScriptRunner() { | 162 HTMLScriptRunner::~HTMLScriptRunner() { |
| 164 // Verify that detach() has been called. | 163 // Verify that detach() has been called. |
| 165 ASSERT(!m_document); | 164 ASSERT(!m_document); |
| 166 } | 165 } |
| 167 | 166 |
| 168 void HTMLScriptRunner::detach() { | 167 void HTMLScriptRunner::detach() { |
| 169 if (!m_document) | 168 if (!m_document) |
| 170 return; | 169 return; |
| 171 | 170 |
| 172 m_parserBlockingScript->dispose(); | 171 m_parserBlockingScript->dispose(); |
| 173 | 172 |
| 174 while (!m_scriptsToExecuteAfterParsing.isEmpty()) { | 173 while (!m_scriptsToExecuteAfterParsing.isEmpty()) { |
| 175 PendingScript* pendingScript = m_scriptsToExecuteAfterParsing.takeFirst(); | 174 PendingScript* pendingScript = m_scriptsToExecuteAfterParsing.takeFirst(); |
| 176 pendingScript->dispose(); | 175 pendingScript->dispose(); |
| 177 } | 176 } |
| 178 m_document = nullptr; | 177 m_document = nullptr; |
| 179 // m_reentryPermit is not cleared here, because the script runner | 178 // m_reentryPermit is not cleared here, because the script runner |
| 180 // may continue to run pending scripts after the parser has | 179 // may continue to run pending scripts after the parser has |
| 181 // detached. | 180 // detached. |
| 182 } | 181 } |
| 183 | 182 |
| 184 bool HTMLScriptRunner::isPendingScriptReady(const PendingScript* script) { | 183 bool HTMLScriptRunner::isPendingScriptReady() { |
| 185 m_hasScriptsWaitingForResources = !m_document->isScriptExecutionReady(); | 184 if (!m_document->isScriptExecutionReady()) |
| 186 if (m_hasScriptsWaitingForResources) | |
| 187 return false; | 185 return false; |
| 188 return script->isReady(); | 186 return m_parserBlockingScript->isReady(); |
| 189 } | 187 } |
| 190 | 188 |
| 191 void HTMLScriptRunner::executeParsingBlockingScript() { | 189 void HTMLScriptRunner::executeParsingBlockingScript() { |
| 192 ASSERT(m_document); | 190 DCHECK(m_document); |
| 193 ASSERT(!isExecutingScript()); | 191 DCHECK(!isExecutingScript()); |
| 194 ASSERT(m_document->isScriptExecutionReady()); | 192 DCHECK(m_document->isScriptExecutionReady()); |
| 195 ASSERT(isPendingScriptReady(m_parserBlockingScript.get())); | 193 DCHECK(isPendingScriptReady()); |
| 196 | 194 |
| 197 InsertionPointRecord insertionPointRecord(m_host->inputStream()); | 195 InsertionPointRecord insertionPointRecord(m_host->inputStream()); |
| 198 executePendingScriptAndDispatchEvent(m_parserBlockingScript.get(), | 196 executePendingScriptAndDispatchEvent(m_parserBlockingScript.get(), |
| 199 ScriptStreamer::ParsingBlocking); | 197 ScriptStreamer::ParsingBlocking); |
| 200 } | 198 } |
| 201 | 199 |
| 202 void HTMLScriptRunner::executePendingScriptAndDispatchEvent( | 200 void HTMLScriptRunner::executePendingScriptAndDispatchEvent( |
| 203 PendingScript* pendingScript, | 201 PendingScript* pendingScript, |
| 204 ScriptStreamer::Type pendingScriptType) { | 202 ScriptStreamer::Type pendingScriptType) { |
| 205 bool errorOccurred = false; | 203 bool errorOccurred = false; |
| 206 ScriptSourceCode sourceCode = pendingScript->getSource( | 204 ScriptSourceCode sourceCode = pendingScript->getSource( |
| 207 documentURLForScriptExecution(m_document), errorOccurred); | 205 documentURLForScriptExecution(m_document), errorOccurred); |
| 208 | 206 |
| 209 // Stop watching loads before executeScript to prevent recursion if the script | 207 // Stop watching loads before executeScript to prevent recursion if the script |
| 210 // reloads itself. | 208 // reloads itself. |
| 211 // TODO(kouhei): Consider merging this w/ pendingScript->dispose() after the | 209 // TODO(kouhei): Consider merging this w/ pendingScript->dispose() after the |
| 212 // if block. | 210 // if block. |
| 213 pendingScript->stopWatchingForLoad(); | 211 pendingScript->stopWatchingForLoad(); |
| 214 | 212 |
| 215 if (!isExecutingScript()) { | 213 if (!isExecutingScript()) { |
| 216 Microtask::performCheckpoint(V8PerIsolateData::mainThreadIsolate()); | 214 Microtask::performCheckpoint(V8PerIsolateData::mainThreadIsolate()); |
| 217 if (pendingScriptType == ScriptStreamer::ParsingBlocking) { | 215 if (pendingScriptType == ScriptStreamer::ParsingBlocking) { |
| 218 m_hasScriptsWaitingForResources = !m_document->isScriptExecutionReady(); | |
| 219 // The parser cannot be unblocked as a microtask requested another | 216 // The parser cannot be unblocked as a microtask requested another |
| 220 // resource | 217 // resource |
| 221 if (m_hasScriptsWaitingForResources) | 218 if (!m_document->isScriptExecutionReady()) |
| 222 return; | 219 return; |
| 223 } | 220 } |
| 224 } | 221 } |
| 225 | 222 |
| 226 TextPosition scriptStartPosition = pendingScript->startingPosition(); | 223 TextPosition scriptStartPosition = pendingScript->startingPosition(); |
| 227 double scriptParserBlockingTime = | 224 double scriptParserBlockingTime = |
| 228 pendingScript->parserBlockingLoadStartTime(); | 225 pendingScript->parserBlockingLoadStartTime(); |
| 229 // Clear the pending script before possible re-entrancy from executeScript() | 226 // Clear the pending script before possible re-entrancy from executeScript() |
| 230 Element* element = pendingScript->element(); | 227 Element* element = pendingScript->element(); |
| 231 pendingScript->dispose(); | 228 pendingScript->dispose(); |
| (...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 366 m_host->appendCurrentInputStreamToPreloadScannerAndScan(); | 363 m_host->appendCurrentInputStreamToPreloadScannerAndScan(); |
| 367 executeParsingBlockingScripts(); | 364 executeParsingBlockingScripts(); |
| 368 } | 365 } |
| 369 } | 366 } |
| 370 | 367 |
| 371 bool HTMLScriptRunner::hasParserBlockingScript() const { | 368 bool HTMLScriptRunner::hasParserBlockingScript() const { |
| 372 return !!m_parserBlockingScript->element(); | 369 return !!m_parserBlockingScript->element(); |
| 373 } | 370 } |
| 374 | 371 |
| 375 void HTMLScriptRunner::executeParsingBlockingScripts() { | 372 void HTMLScriptRunner::executeParsingBlockingScripts() { |
| 376 while (hasParserBlockingScript() && | 373 while (hasParserBlockingScript() && isPendingScriptReady()) |
| 377 isPendingScriptReady(m_parserBlockingScript.get())) | |
| 378 executeParsingBlockingScript(); | 374 executeParsingBlockingScript(); |
| 379 } | 375 } |
| 380 | 376 |
| 381 void HTMLScriptRunner::executeScriptsWaitingForLoad(Resource* resource) { | 377 void HTMLScriptRunner::executeScriptsWaitingForLoad(Resource* resource) { |
| 382 TRACE_EVENT0("blink", "HTMLScriptRunner::executeScriptsWaitingForLoad"); | 378 TRACE_EVENT0("blink", "HTMLScriptRunner::executeScriptsWaitingForLoad"); |
| 383 ASSERT(!isExecutingScript()); | 379 ASSERT(!isExecutingScript()); |
| 384 ASSERT(hasParserBlockingScript()); | 380 ASSERT(hasParserBlockingScript()); |
| 385 DCHECK_EQ(resource, m_parserBlockingScript->resource()); | 381 DCHECK_EQ(resource, m_parserBlockingScript->resource()); |
| 386 ASSERT(m_parserBlockingScript->isReady()); | 382 ASSERT(m_parserBlockingScript->isReady()); |
| 387 executeParsingBlockingScripts(); | 383 executeParsingBlockingScripts(); |
| 388 } | 384 } |
| 389 | 385 |
| 390 void HTMLScriptRunner::executeScriptsWaitingForResources() { | 386 void HTMLScriptRunner::executeScriptsWaitingForResources() { |
| 391 TRACE_EVENT0("blink", "HTMLScriptRunner::executeScriptsWaitingForResources"); | 387 TRACE_EVENT0("blink", "HTMLScriptRunner::executeScriptsWaitingForResources"); |
| 392 ASSERT(m_document); | 388 ASSERT(m_document); |
| 393 // Callers should check hasScriptsWaitingForResources() before calling | |
| 394 // to prevent parser or script re-entry during </style> parsing. | |
| 395 ASSERT(hasScriptsWaitingForResources()); | |
| 396 ASSERT(!isExecutingScript()); | 389 ASSERT(!isExecutingScript()); |
| 397 ASSERT(m_document->isScriptExecutionReady()); | 390 ASSERT(m_document->isScriptExecutionReady()); |
| 398 executeParsingBlockingScripts(); | 391 executeParsingBlockingScripts(); |
| 399 } | 392 } |
| 400 | 393 |
| 401 bool HTMLScriptRunner::executeScriptsWaitingForParsing() { | 394 bool HTMLScriptRunner::executeScriptsWaitingForParsing() { |
| 402 TRACE_EVENT0("blink", "HTMLScriptRunner::executeScriptsWaitingForParsing"); | 395 TRACE_EVENT0("blink", "HTMLScriptRunner::executeScriptsWaitingForParsing"); |
| 403 while (!m_scriptsToExecuteAfterParsing.isEmpty()) { | 396 while (!m_scriptsToExecuteAfterParsing.isEmpty()) { |
| 404 ASSERT(!isExecutingScript()); | 397 ASSERT(!isExecutingScript()); |
| 405 ASSERT(!hasParserBlockingScript()); | 398 ASSERT(!hasParserBlockingScript()); |
| (...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 529 | 522 |
| 530 DEFINE_TRACE(HTMLScriptRunner) { | 523 DEFINE_TRACE(HTMLScriptRunner) { |
| 531 visitor->trace(m_document); | 524 visitor->trace(m_document); |
| 532 visitor->trace(m_host); | 525 visitor->trace(m_host); |
| 533 visitor->trace(m_parserBlockingScript); | 526 visitor->trace(m_parserBlockingScript); |
| 534 visitor->trace(m_scriptsToExecuteAfterParsing); | 527 visitor->trace(m_scriptsToExecuteAfterParsing); |
| 535 ScriptResourceClient::trace(visitor); | 528 ScriptResourceClient::trace(visitor); |
| 536 } | 529 } |
| 537 | 530 |
| 538 } // namespace blink | 531 } // namespace blink |
| OLD | NEW |