Chromium Code Reviews| 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 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 152 ASSERT(m_haveBackgroundParser); | 152 ASSERT(m_haveBackgroundParser); |
| 153 pumpPendingChunks(); | 153 pumpPendingChunks(); |
| 154 } | 154 } |
| 155 | 155 |
| 156 void HTMLDocumentParser::runScriptsForPausedTreeBuilder() | 156 void HTMLDocumentParser::runScriptsForPausedTreeBuilder() |
| 157 { | 157 { |
| 158 if (m_isFragment) | 158 if (m_isFragment) |
| 159 return; | 159 return; |
| 160 TextPosition scriptStartPosition = TextPosition::belowRangePosition(); | 160 TextPosition scriptStartPosition = TextPosition::belowRangePosition(); |
| 161 RefPtr<Element> scriptToProcess = m_treeBuilder->takeScriptToProcess(scriptS tartPosition); | 161 RefPtr<Element> scriptToProcess = m_treeBuilder->takeScriptToProcess(scriptS tartPosition); |
| 162 m_scriptRunner.runScript(toHTMLScriptElement(scriptToProcess.get()), scriptS tartPosition); | 162 |
| 163 // Sending the script to dart may find additional 'import' declarations | |
| 164 // which need to load before the script can execute. HTMLScriptRunner | |
| 165 // always calls scriptExecutionCompleted regardless of success/failure. | |
| 166 m_scriptRunner = HTMLScriptRunner::createForScript( | |
| 167 toHTMLScriptElement(scriptToProcess.get()), scriptStartPosition, this); | |
| 168 m_scriptRunner->start(); | |
| 163 } | 169 } |
| 164 | 170 |
| 165 void HTMLDocumentParser::didReceiveParsedChunkFromBackgroundParser(PassOwnPtr<Pa rsedChunk> chunk) | 171 void HTMLDocumentParser::didReceiveParsedChunkFromBackgroundParser(PassOwnPtr<Pa rsedChunk> chunk) |
| 166 { | 172 { |
| 167 TRACE_EVENT0("blink", "HTMLDocumentParser::didReceiveParsedChunkFromBackgrou ndParser"); | 173 TRACE_EVENT0("blink", "HTMLDocumentParser::didReceiveParsedChunkFromBackgrou ndParser"); |
| 168 // Sky should not need nested parsers. | 174 // Sky should not need nested parsers. |
| 169 ASSERT(document()->activeParserCount() == 0); | 175 ASSERT(document()->activeParserCount() == 0); |
| 170 | 176 |
| 171 if (isWaitingForScripts() || !m_pendingChunks.isEmpty() || document()->activ eParserCount() > 0 || !document()->haveImportsLoaded()) { | 177 if (isWaitingForScripts() || !m_pendingChunks.isEmpty() || |
| 178 document()->activeParserCount() > 0) { | |
| 172 m_pendingChunks.append(chunk); | 179 m_pendingChunks.append(chunk); |
| 173 return; | 180 return; |
| 174 } | 181 } |
| 175 | 182 |
| 176 // processParsedChunkFromBackgroundParser can cause this parser to be detach ed from the Document, | 183 // processParsedChunkFromBackgroundParser can cause this parser to be detach ed from the Document, |
| 177 // but we need to ensure it isn't deleted yet. | 184 // but we need to ensure it isn't deleted yet. |
| 178 RefPtr<HTMLDocumentParser> protect(this); | 185 RefPtr<HTMLDocumentParser> protect(this); |
| 179 | 186 |
| 180 ASSERT(m_pendingChunks.isEmpty()); | 187 ASSERT(m_pendingChunks.isEmpty()); |
| 181 m_pendingChunks.append(chunk); | 188 m_pendingChunks.append(chunk); |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 193 ASSERT(!isStopped()); | 200 ASSERT(!isStopped()); |
| 194 | 201 |
| 195 // ASSERT that this object is both attached to the Document and protected. | 202 // ASSERT that this object is both attached to the Document and protected. |
| 196 ASSERT(refCount() >= 2); | 203 ASSERT(refCount() >= 2); |
| 197 | 204 |
| 198 ActiveParserSession session(contextForParsingSession()); | 205 ActiveParserSession session(contextForParsingSession()); |
| 199 | 206 |
| 200 OwnPtr<ParsedChunk> chunk(popChunk); | 207 OwnPtr<ParsedChunk> chunk(popChunk); |
| 201 OwnPtr<CompactHTMLTokenStream> tokens = chunk->tokens.release(); | 208 OwnPtr<CompactHTMLTokenStream> tokens = chunk->tokens.release(); |
| 202 | 209 |
| 203 for (Vector<CompactHTMLToken>::const_iterator it = tokens->begin(); it != to kens->end(); ++it) { | 210 Vector<CompactHTMLToken>::const_iterator it; |
| 204 ASSERT(!isWaitingForScripts()); | 211 for (it = tokens->begin(); it != tokens->end(); ++it) { |
| 212 // A chunk can issue import loads causing us to be isWaitingForScripts | |
| 213 // but we don't stop processing in that case. | |
| 214 ASSERT(!m_treeBuilder->hasParserBlockingScript()); | |
| 215 ASSERT(!m_scriptRunner); | |
| 205 | 216 |
| 206 m_textPosition = it->textPosition(); | 217 m_textPosition = it->textPosition(); |
| 207 | 218 |
| 208 constructTreeFromCompactHTMLToken(*it); | 219 constructTreeFromCompactHTMLToken(*it); |
| 209 | 220 |
| 210 if (isStopped()) | 221 if (isStopped()) |
| 211 break; | 222 break; |
| 212 | 223 |
| 213 if (isWaitingForScripts()) { | 224 if (m_treeBuilder->hasParserBlockingScript()) { |
| 214 ASSERT(it + 1 == tokens->end()); // The </script> is assumed to be t he last token of this bunch. | 225 ASSERT(++it == tokens->end()); // The </script> is assumed to be the |
|
abarth-chromium
2015/02/19 02:51:40
s/++it/it + 1/ ?
It seems very dangerous to mutat
| |
| 226 // last token of this bunch. | |
| 215 runScriptsForPausedTreeBuilder(); | 227 runScriptsForPausedTreeBuilder(); |
| 216 break; | 228 break; |
| 217 } | 229 } |
| 218 | 230 |
| 219 if (it->type() == HTMLToken::EndOfFile) { | 231 if (it->type() == HTMLToken::EndOfFile) { |
| 220 ASSERT(it + 1 == tokens->end()); // The EOF is assumed to be the las t token of this bunch. | 232 ASSERT(++it == tokens->end()); // The EOF is assumed to be the last |
|
abarth-chromium
2015/02/19 02:51:40
Ditto
| |
| 233 // token of this bunch. | |
| 221 ASSERT(m_pendingChunks.isEmpty()); // There should never be any chun ks after the EOF. | 234 ASSERT(m_pendingChunks.isEmpty()); // There should never be any chun ks after the EOF. |
| 222 prepareToStopParsing(); | 235 prepareToStopParsing(); |
| 223 break; | 236 break; |
| 224 } | 237 } |
| 225 } | 238 } |
| 226 | 239 |
| 240 // Either we aborted due to stopping or we processed all tokens. | |
| 241 ASSERT(isStopped() || it == tokens->end()); | |
|
abarth-chromium
2015/02/19 02:51:40
I see... Maybe move the ++it outside of the ASSER
| |
| 242 | |
| 227 // Make sure any pending text nodes are emitted before returning. | 243 // Make sure any pending text nodes are emitted before returning. |
| 228 if (!isStopped()) | 244 if (!isStopped()) |
| 229 m_treeBuilder->flush(); | 245 m_treeBuilder->flush(); |
| 230 } | 246 } |
| 231 | 247 |
| 232 void HTMLDocumentParser::pumpPendingChunks() | 248 void HTMLDocumentParser::pumpPendingChunks() |
| 233 { | 249 { |
| 234 // FIXME: Share this constant with the parser scheduler. | 250 // FIXME: Share this constant with the parser scheduler. |
| 235 const double parserTimeLimit = 0.500; | 251 const double parserTimeLimit = 0.500; |
| 236 | 252 |
| 237 // ASSERT that this object is both attached to the Document and protected. | 253 // ASSERT that this object is both attached to the Document and protected. |
| 238 ASSERT(refCount() >= 2); | 254 ASSERT(refCount() >= 2); |
| 239 ASSERT(!isWaitingForScripts()); | 255 ASSERT(!isWaitingForScripts()); |
| 240 ASSERT(!isStopped()); | 256 ASSERT(!isStopped()); |
| 241 ASSERT(document()->haveImportsLoaded()); | |
| 242 | 257 |
| 243 double startTime = currentTime(); | 258 double startTime = currentTime(); |
| 244 | 259 |
| 245 while (!m_pendingChunks.isEmpty()) { | 260 while (!m_pendingChunks.isEmpty()) { |
| 246 processParsedChunkFromBackgroundParser(m_pendingChunks.takeFirst()); | 261 processParsedChunkFromBackgroundParser(m_pendingChunks.takeFirst()); |
| 247 | 262 |
| 248 // Always check isStopped first as m_document may be null. | 263 // Always check isStopped first as m_document may be null. |
| 249 if (isStopped() || isWaitingForScripts() || !document()->haveImportsLoad ed()) | 264 if (isStopped() || isWaitingForScripts()) |
| 250 break; | 265 break; |
| 251 | 266 |
| 252 if (currentTime() - startTime > parserTimeLimit && !m_pendingChunks.isEm pty()) { | 267 if (currentTime() - startTime > parserTimeLimit && !m_pendingChunks.isEm pty()) { |
| 253 m_parserScheduler->scheduleForResume(); | 268 m_parserScheduler->scheduleForResume(); |
| 254 break; | 269 break; |
| 255 } | 270 } |
| 256 } | 271 } |
| 257 } | 272 } |
| 258 | 273 |
| 259 Document* HTMLDocumentParser::contextForParsingSession() | 274 Document* HTMLDocumentParser::contextForParsingSession() |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 346 | 361 |
| 347 if (!m_endWasDelayed || shouldDelayEnd()) | 362 if (!m_endWasDelayed || shouldDelayEnd()) |
| 348 return; | 363 return; |
| 349 | 364 |
| 350 m_endWasDelayed = false; | 365 m_endWasDelayed = false; |
| 351 prepareToStopParsing(); | 366 prepareToStopParsing(); |
| 352 } | 367 } |
| 353 | 368 |
| 354 bool HTMLDocumentParser::isExecutingScript() const | 369 bool HTMLDocumentParser::isExecutingScript() const |
| 355 { | 370 { |
| 356 return m_scriptRunner.isExecutingScript(); | 371 // TODO(eseidel): Callers may need updates now that scripts can be async. |
| 372 return m_scriptRunner && m_scriptRunner->isExecutingScript(); | |
|
abarth-chromium
2015/02/19 02:51:40
four-space indent
| |
| 357 } | 373 } |
| 358 | 374 |
| 359 OrdinalNumber HTMLDocumentParser::lineNumber() const | 375 OrdinalNumber HTMLDocumentParser::lineNumber() const |
| 360 { | 376 { |
| 361 ASSERT(m_haveBackgroundParser); | 377 ASSERT(m_haveBackgroundParser); |
| 362 return m_textPosition.m_line; | 378 return m_textPosition.m_line; |
| 363 } | 379 } |
| 364 | 380 |
| 365 TextPosition HTMLDocumentParser::textPosition() const | 381 TextPosition HTMLDocumentParser::textPosition() const |
| 366 { | 382 { |
| 367 ASSERT(m_haveBackgroundParser); | 383 ASSERT(m_haveBackgroundParser); |
| 368 return m_textPosition; | 384 return m_textPosition; |
| 369 } | 385 } |
| 370 | 386 |
| 371 bool HTMLDocumentParser::isWaitingForScripts() const | 387 bool HTMLDocumentParser::isWaitingForScripts() const |
| 372 { | 388 { |
| 373 return m_treeBuilder->hasParserBlockingScript(); | 389 return m_treeBuilder->hasParserBlockingScript() || m_scriptRunner || |
| 390 !document()->haveImportsLoaded(); | |
| 374 } | 391 } |
| 375 | 392 |
| 376 void HTMLDocumentParser::resumeAfterWaitingForImports() | 393 void HTMLDocumentParser::resumeAfterWaitingForImports() |
| 377 { | 394 { |
| 378 RefPtr<HTMLDocumentParser> protect(this); | 395 RefPtr<HTMLDocumentParser> protect(this); |
| 379 ASSERT(!isExecutingScript()); | |
| 380 ASSERT(!isWaitingForScripts()); | 396 ASSERT(!isWaitingForScripts()); |
| 381 if (m_pendingChunks.isEmpty()) | 397 if (m_pendingChunks.isEmpty()) |
| 382 return; | 398 return; |
| 383 ASSERT(m_haveBackgroundParser); | 399 ASSERT(m_haveBackgroundParser); |
| 384 pumpPendingChunks(); | 400 pumpPendingChunks(); |
| 385 } | 401 } |
| 386 | 402 |
| 403 // HTMLScriptRunner has finished executing a script. | |
| 404 // Just call resumeAfterWaitingForImports since it happens to do what we need. | |
| 405 void HTMLDocumentParser::scriptExecutionCompleted() { | |
| 406 ASSERT(m_scriptRunner); | |
| 407 m_scriptRunner.clear(); | |
| 408 // To avoid re-entering the parser for synchronous scripts, we use a postTask. | |
| 409 base::MessageLoop::current()->PostTask( | |
| 410 FROM_HERE, base::Bind(&HTMLDocumentParser::resumeAfterWaitingForImports, | |
| 411 m_weakFactory.GetWeakPtr())); | |
| 387 } | 412 } |
| 413 } | |
| OLD | NEW |