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 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
146 m_shouldUseThreading(syncPolicy == AllowAsynchronousParsing), | 146 m_shouldUseThreading(syncPolicy == AllowAsynchronousParsing), |
147 m_endWasDelayed(false), | 147 m_endWasDelayed(false), |
148 m_haveBackgroundParser(false), | 148 m_haveBackgroundParser(false), |
149 m_tasksWereSuspended(false), | 149 m_tasksWereSuspended(false), |
150 m_pumpSessionNestingLevel(0), | 150 m_pumpSessionNestingLevel(0), |
151 m_pumpSpeculationsSessionNestingLevel(0), | 151 m_pumpSpeculationsSessionNestingLevel(0), |
152 m_isParsingAtLineNumber(false), | 152 m_isParsingAtLineNumber(false), |
153 m_triedLoadingLinkHeaders(false), | 153 m_triedLoadingLinkHeaders(false), |
154 m_addedPendingStylesheetInBody(false), | 154 m_addedPendingStylesheetInBody(false), |
155 m_isWaitingForStylesheets(false) { | 155 m_isWaitingForStylesheets(false) { |
156 ASSERT(shouldUseThreading() || (m_token && m_tokenizer)); | 156 DCHECK(shouldUseThreading() || (m_token && m_tokenizer)); |
157 // Threading is not allowed in prefetch mode. | 157 // Threading is not allowed in prefetch mode. |
158 DCHECK(!document.isPrefetchOnly() || !shouldUseThreading()); | 158 DCHECK(!document.isPrefetchOnly() || !shouldUseThreading()); |
159 } | 159 } |
160 | 160 |
161 HTMLDocumentParser::~HTMLDocumentParser() {} | 161 HTMLDocumentParser::~HTMLDocumentParser() {} |
162 | 162 |
163 void HTMLDocumentParser::dispose() { | 163 void HTMLDocumentParser::dispose() { |
164 // In Oilpan, HTMLDocumentParser can die together with Document, and detach() | 164 // In Oilpan, HTMLDocumentParser can die together with Document, and detach() |
165 // is not called in this case. | 165 // is not called in this case. |
166 if (m_haveBackgroundParser) | 166 if (m_haveBackgroundParser) |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
220 } | 220 } |
221 if (m_haveBackgroundParser) | 221 if (m_haveBackgroundParser) |
222 stopBackgroundParser(); | 222 stopBackgroundParser(); |
223 } | 223 } |
224 | 224 |
225 // This kicks off "Once the user agent stops parsing" as described by: | 225 // This kicks off "Once the user agent stops parsing" as described by: |
226 // http://www.whatwg.org/specs/web-apps/current-work/multipage/the-end.html#the-
end | 226 // http://www.whatwg.org/specs/web-apps/current-work/multipage/the-end.html#the-
end |
227 void HTMLDocumentParser::prepareToStopParsing() { | 227 void HTMLDocumentParser::prepareToStopParsing() { |
228 // FIXME: It may not be correct to disable this for the background parser. | 228 // FIXME: It may not be correct to disable this for the background parser. |
229 // That means hasInsertionPoint() may not be correct in some cases. | 229 // That means hasInsertionPoint() may not be correct in some cases. |
230 ASSERT(!hasInsertionPoint() || m_haveBackgroundParser); | 230 DCHECK(!hasInsertionPoint() || m_haveBackgroundParser); |
231 | 231 |
232 // NOTE: This pump should only ever emit buffered character tokens. | 232 // NOTE: This pump should only ever emit buffered character tokens. |
233 if (m_tokenizer) { | 233 if (m_tokenizer) { |
234 ASSERT(!m_haveBackgroundParser); | 234 DCHECK(!m_haveBackgroundParser); |
235 pumpTokenizerIfPossible(); | 235 pumpTokenizerIfPossible(); |
236 } | 236 } |
237 | 237 |
238 if (isStopped()) | 238 if (isStopped()) |
239 return; | 239 return; |
240 | 240 |
241 DocumentParser::prepareToStopParsing(); | 241 DocumentParser::prepareToStopParsing(); |
242 | 242 |
243 // We will not have a scriptRunner when parsing a DocumentFragment. | 243 // We will not have a scriptRunner when parsing a DocumentFragment. |
244 if (m_scriptRunner) | 244 if (m_scriptRunner) |
(...skipping 18 matching lines...) Expand all Loading... |
263 | 263 |
264 pumpTokenizer(); | 264 pumpTokenizer(); |
265 } | 265 } |
266 | 266 |
267 bool HTMLDocumentParser::isScheduledForResume() const { | 267 bool HTMLDocumentParser::isScheduledForResume() const { |
268 return m_parserScheduler && m_parserScheduler->isScheduledForResume(); | 268 return m_parserScheduler && m_parserScheduler->isScheduledForResume(); |
269 } | 269 } |
270 | 270 |
271 // Used by HTMLParserScheduler | 271 // Used by HTMLParserScheduler |
272 void HTMLDocumentParser::resumeParsingAfterYield() { | 272 void HTMLDocumentParser::resumeParsingAfterYield() { |
273 ASSERT(shouldUseThreading()); | 273 DCHECK(shouldUseThreading()); |
274 ASSERT(m_haveBackgroundParser); | 274 DCHECK(m_haveBackgroundParser); |
275 | 275 |
276 checkIfBodyStylesheetAdded(); | 276 checkIfBodyStylesheetAdded(); |
277 if (isStopped() || isPaused()) | 277 if (isStopped() || isPaused()) |
278 return; | 278 return; |
279 | 279 |
280 pumpPendingSpeculations(); | 280 pumpPendingSpeculations(); |
281 } | 281 } |
282 | 282 |
283 void HTMLDocumentParser::runScriptsForPausedTreeBuilder() { | 283 void HTMLDocumentParser::runScriptsForPausedTreeBuilder() { |
284 ASSERT(scriptingContentIsAllowed(getParserContentPolicy())); | 284 DCHECK(scriptingContentIsAllowed(getParserContentPolicy())); |
285 | 285 |
286 TextPosition scriptStartPosition = TextPosition::belowRangePosition(); | 286 TextPosition scriptStartPosition = TextPosition::belowRangePosition(); |
287 Element* scriptElement = | 287 Element* scriptElement = |
288 m_treeBuilder->takeScriptToProcess(scriptStartPosition); | 288 m_treeBuilder->takeScriptToProcess(scriptStartPosition); |
289 // We will not have a scriptRunner when parsing a DocumentFragment. | 289 // We will not have a scriptRunner when parsing a DocumentFragment. |
290 if (m_scriptRunner) | 290 if (m_scriptRunner) |
291 m_scriptRunner->processScriptElement(scriptElement, scriptStartPosition); | 291 m_scriptRunner->processScriptElement(scriptElement, scriptStartPosition); |
292 checkIfBodyStylesheetAdded(); | 292 checkIfBodyStylesheetAdded(); |
293 } | 293 } |
294 | 294 |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
353 for (auto& request : chunk->preloads) { | 353 for (auto& request : chunk->preloads) { |
354 // Link rel preloads don't need to wait for AppCache but they | 354 // Link rel preloads don't need to wait for AppCache but they |
355 // should probably wait for CSP. | 355 // should probably wait for CSP. |
356 if (!m_pendingCSPMetaToken && request->isLinkRelPreload()) | 356 if (!m_pendingCSPMetaToken && request->isLinkRelPreload()) |
357 linkRelPreloads.push_back(std::move(request)); | 357 linkRelPreloads.push_back(std::move(request)); |
358 else | 358 else |
359 m_queuedPreloads.push_back(std::move(request)); | 359 m_queuedPreloads.push_back(std::move(request)); |
360 } | 360 } |
361 for (auto& index : chunk->likelyDocumentWriteScriptIndices) { | 361 for (auto& index : chunk->likelyDocumentWriteScriptIndices) { |
362 const CompactHTMLToken& token = chunk->tokens->at(index); | 362 const CompactHTMLToken& token = chunk->tokens->at(index); |
363 ASSERT(token.type() == HTMLToken::TokenType::Character); | 363 DCHECK_EQ(token.type(), HTMLToken::TokenType::Character); |
364 m_queuedDocumentWriteScripts.push_back(token.data()); | 364 m_queuedDocumentWriteScripts.push_back(token.data()); |
365 } | 365 } |
366 } | 366 } |
367 m_preloader->takeAndPreload(linkRelPreloads); | 367 m_preloader->takeAndPreload(linkRelPreloads); |
368 } else { | 368 } else { |
369 // We can safely assume that there are no queued preloads request after the | 369 // We can safely assume that there are no queued preloads request after the |
370 // document element is available, as we empty the queue immediately after | 370 // document element is available, as we empty the queue immediately after |
371 // the document element is created in documentElementAvailable(). | 371 // the document element is created in documentElementAvailable(). |
372 ASSERT(m_queuedPreloads.isEmpty()); | 372 DCHECK(m_queuedPreloads.isEmpty()); |
373 ASSERT(m_queuedDocumentWriteScripts.isEmpty()); | 373 DCHECK(m_queuedDocumentWriteScripts.isEmpty()); |
374 // Loop through the chunks to generate preloads before any document.write | 374 // Loop through the chunks to generate preloads before any document.write |
375 // script evaluation takes place. Preloading these scripts is valuable and | 375 // script evaluation takes place. Preloading these scripts is valuable and |
376 // comparably cheap, while evaluating JS can be expensive. | 376 // comparably cheap, while evaluating JS can be expensive. |
377 for (auto& chunk : pendingChunks) | 377 for (auto& chunk : pendingChunks) |
378 m_preloader->takeAndPreload(chunk->preloads); | 378 m_preloader->takeAndPreload(chunk->preloads); |
379 for (auto& chunk : pendingChunks) { | 379 for (auto& chunk : pendingChunks) { |
380 for (auto& index : chunk->likelyDocumentWriteScriptIndices) { | 380 for (auto& index : chunk->likelyDocumentWriteScriptIndices) { |
381 const CompactHTMLToken& token = chunk->tokens->at(index); | 381 const CompactHTMLToken& token = chunk->tokens->at(index); |
382 ASSERT(token.type() == HTMLToken::TokenType::Character); | 382 DCHECK_EQ(token.type(), HTMLToken::TokenType::Character); |
383 evaluateAndPreloadScriptForDocumentWrite(token.data()); | 383 evaluateAndPreloadScriptForDocumentWrite(token.data()); |
384 } | 384 } |
385 } | 385 } |
386 } | 386 } |
387 | 387 |
388 for (auto& chunk : pendingChunks) | 388 for (auto& chunk : pendingChunks) |
389 m_speculations.push_back(std::move(chunk)); | 389 m_speculations.push_back(std::move(chunk)); |
390 | 390 |
391 if (!isPaused() && !isScheduledForResume()) { | 391 if (!isPaused() && !isScheduledForResume()) { |
392 if (m_tasksWereSuspended) | 392 if (m_tasksWereSuspended) |
393 m_parserScheduler->forceResumeAfterYield(); | 393 m_parserScheduler->forceResumeAfterYield(); |
394 else | 394 else |
395 m_parserScheduler->scheduleForResume(); | 395 m_parserScheduler->scheduleForResume(); |
396 } | 396 } |
397 } | 397 } |
398 | 398 |
399 void HTMLDocumentParser::didReceiveEncodingDataFromBackgroundParser( | 399 void HTMLDocumentParser::didReceiveEncodingDataFromBackgroundParser( |
400 const DocumentEncodingData& data) { | 400 const DocumentEncodingData& data) { |
401 document()->setEncodingData(data); | 401 document()->setEncodingData(data); |
402 } | 402 } |
403 | 403 |
404 void HTMLDocumentParser::validateSpeculations( | 404 void HTMLDocumentParser::validateSpeculations( |
405 std::unique_ptr<TokenizedChunk> chunk) { | 405 std::unique_ptr<TokenizedChunk> chunk) { |
406 ASSERT(chunk); | 406 DCHECK(chunk); |
407 // TODO(kouhei): We should simplify codepath here by disallowing | 407 // TODO(kouhei): We should simplify codepath here by disallowing |
408 // validateSpeculations | 408 // validateSpeculations |
409 // while isPaused, and m_lastChunkBeforePause can simply be | 409 // while isPaused, and m_lastChunkBeforePause can simply be |
410 // pushed to m_speculations. | 410 // pushed to m_speculations. |
411 if (isPaused()) { | 411 if (isPaused()) { |
412 // We're waiting on a network script or stylesheet, just save the chunk, | 412 // We're waiting on a network script or stylesheet, just save the chunk, |
413 // we'll get a second validateSpeculations call after the script or | 413 // we'll get a second validateSpeculations call after the script or |
414 // stylesheet completes. This call should have been made immediately after | 414 // stylesheet completes. This call should have been made immediately after |
415 // runScriptsForPausedTreeBuilder in the script case which may have started | 415 // runScriptsForPausedTreeBuilder in the script case which may have started |
416 // a network load and left us waiting. | 416 // a network load and left us waiting. |
(...skipping 15 matching lines...) Expand all Loading... |
432 // Currently we're only smart enough to reuse the speculation buffer if the | 432 // Currently we're only smart enough to reuse the speculation buffer if the |
433 // tokenizer both starts and ends in the DataState. That state is simplest | 433 // tokenizer both starts and ends in the DataState. That state is simplest |
434 // because the HTMLToken is always in the Uninitialized state. We should | 434 // because the HTMLToken is always in the Uninitialized state. We should |
435 // consider whether we can reuse the speculation buffer in other states, but | 435 // consider whether we can reuse the speculation buffer in other states, but |
436 // we'd likely need to do something more sophisticated with the HTMLToken. | 436 // we'd likely need to do something more sophisticated with the HTMLToken. |
437 if (chunk->tokenizerState == HTMLTokenizer::DataState && | 437 if (chunk->tokenizerState == HTMLTokenizer::DataState && |
438 tokenizer->getState() == HTMLTokenizer::DataState && | 438 tokenizer->getState() == HTMLTokenizer::DataState && |
439 m_input.current().isEmpty() && | 439 m_input.current().isEmpty() && |
440 chunk->treeBuilderState == | 440 chunk->treeBuilderState == |
441 HTMLTreeBuilderSimulator::stateFor(m_treeBuilder.get())) { | 441 HTMLTreeBuilderSimulator::stateFor(m_treeBuilder.get())) { |
442 ASSERT(token->isUninitialized()); | 442 DCHECK(token->isUninitialized()); |
443 return; | 443 return; |
444 } | 444 } |
445 | 445 |
446 discardSpeculationsAndResumeFrom(std::move(chunk), std::move(token), | 446 discardSpeculationsAndResumeFrom(std::move(chunk), std::move(token), |
447 std::move(tokenizer)); | 447 std::move(tokenizer)); |
448 } | 448 } |
449 | 449 |
450 void HTMLDocumentParser::discardSpeculationsAndResumeFrom( | 450 void HTMLDocumentParser::discardSpeculationsAndResumeFrom( |
451 std::unique_ptr<TokenizedChunk> lastChunkBeforeScript, | 451 std::unique_ptr<TokenizedChunk> lastChunkBeforeScript, |
452 std::unique_ptr<HTMLToken> token, | 452 std::unique_ptr<HTMLToken> token, |
(...skipping 19 matching lines...) Expand all Loading... |
472 checkpoint->tokenizer = std::move(tokenizer); | 472 checkpoint->tokenizer = std::move(tokenizer); |
473 checkpoint->treeBuilderState = | 473 checkpoint->treeBuilderState = |
474 HTMLTreeBuilderSimulator::stateFor(m_treeBuilder.get()); | 474 HTMLTreeBuilderSimulator::stateFor(m_treeBuilder.get()); |
475 checkpoint->inputCheckpoint = lastChunkBeforeScript->inputCheckpoint; | 475 checkpoint->inputCheckpoint = lastChunkBeforeScript->inputCheckpoint; |
476 checkpoint->preloadScannerCheckpoint = | 476 checkpoint->preloadScannerCheckpoint = |
477 lastChunkBeforeScript->preloadScannerCheckpoint; | 477 lastChunkBeforeScript->preloadScannerCheckpoint; |
478 checkpoint->unparsedInput = m_input.current().toString().isolatedCopy(); | 478 checkpoint->unparsedInput = m_input.current().toString().isolatedCopy(); |
479 // FIXME: This should be passed in instead of cleared. | 479 // FIXME: This should be passed in instead of cleared. |
480 m_input.current().clear(); | 480 m_input.current().clear(); |
481 | 481 |
482 ASSERT(checkpoint->unparsedInput.isSafeToSendToAnotherThread()); | 482 DCHECK(checkpoint->unparsedInput.isSafeToSendToAnotherThread()); |
483 m_loadingTaskRunner->postTask( | 483 m_loadingTaskRunner->postTask( |
484 BLINK_FROM_HERE, | 484 BLINK_FROM_HERE, |
485 WTF::bind(&BackgroundHTMLParser::resumeFrom, m_backgroundParser, | 485 WTF::bind(&BackgroundHTMLParser::resumeFrom, m_backgroundParser, |
486 WTF::passed(std::move(checkpoint)))); | 486 WTF::passed(std::move(checkpoint)))); |
487 } | 487 } |
488 | 488 |
489 size_t HTMLDocumentParser::processTokenizedChunkFromBackgroundParser( | 489 size_t HTMLDocumentParser::processTokenizedChunkFromBackgroundParser( |
490 std::unique_ptr<TokenizedChunk> popChunk) { | 490 std::unique_ptr<TokenizedChunk> popChunk) { |
491 TRACE_EVENT_WITH_FLOW0( | 491 TRACE_EVENT_WITH_FLOW0( |
492 "blink,loading", | 492 "blink,loading", |
493 "HTMLDocumentParser::processTokenizedChunkFromBackgroundParser", | 493 "HTMLDocumentParser::processTokenizedChunkFromBackgroundParser", |
494 popChunk.get(), TRACE_EVENT_FLAG_FLOW_IN); | 494 popChunk.get(), TRACE_EVENT_FLAG_FLOW_IN); |
495 AutoReset<bool> hasLineNumber(&m_isParsingAtLineNumber, true); | 495 AutoReset<bool> hasLineNumber(&m_isParsingAtLineNumber, true); |
496 | 496 |
497 SECURITY_DCHECK(m_pumpSpeculationsSessionNestingLevel == 1); | 497 SECURITY_DCHECK(m_pumpSpeculationsSessionNestingLevel == 1); |
498 SECURITY_DCHECK(!inPumpSession()); | 498 SECURITY_DCHECK(!inPumpSession()); |
499 ASSERT(!isParsingFragment()); | 499 DCHECK(!isParsingFragment()); |
500 DCHECK(!isPaused()); | 500 DCHECK(!isPaused()); |
501 ASSERT(!isStopped()); | 501 DCHECK(!isStopped()); |
502 ASSERT(shouldUseThreading()); | 502 DCHECK(shouldUseThreading()); |
503 ASSERT(!m_tokenizer); | 503 DCHECK(!m_tokenizer); |
504 ASSERT(!m_token); | 504 DCHECK(!m_token); |
505 DCHECK(!m_lastChunkBeforePause); | 505 DCHECK(!m_lastChunkBeforePause); |
506 | 506 |
507 std::unique_ptr<TokenizedChunk> chunk(std::move(popChunk)); | 507 std::unique_ptr<TokenizedChunk> chunk(std::move(popChunk)); |
508 std::unique_ptr<CompactHTMLTokenStream> tokens = std::move(chunk->tokens); | 508 std::unique_ptr<CompactHTMLTokenStream> tokens = std::move(chunk->tokens); |
509 size_t elementTokenCount = 0; | 509 size_t elementTokenCount = 0; |
510 | 510 |
511 m_loadingTaskRunner->postTask( | 511 m_loadingTaskRunner->postTask( |
512 BLINK_FROM_HERE, | 512 BLINK_FROM_HERE, |
513 WTF::bind(&BackgroundHTMLParser::startedChunkWithCheckpoint, | 513 WTF::bind(&BackgroundHTMLParser::startedChunkWithCheckpoint, |
514 m_backgroundParser, chunk->inputCheckpoint)); | 514 m_backgroundParser, chunk->inputCheckpoint)); |
515 | 515 |
516 for (const auto& xssInfo : chunk->xssInfos) { | 516 for (const auto& xssInfo : chunk->xssInfos) { |
517 m_textPosition = xssInfo->m_textPosition; | 517 m_textPosition = xssInfo->m_textPosition; |
518 m_xssAuditorDelegate.didBlockScript(*xssInfo); | 518 m_xssAuditorDelegate.didBlockScript(*xssInfo); |
519 if (isStopped()) | 519 if (isStopped()) |
520 break; | 520 break; |
521 } | 521 } |
522 // XSSAuditorDelegate can detach the parser if it decides to block the entire | 522 // XSSAuditorDelegate can detach the parser if it decides to block the entire |
523 // current document. | 523 // current document. |
524 if (isDetached()) | 524 if (isDetached()) |
525 return elementTokenCount; | 525 return elementTokenCount; |
526 | 526 |
527 for (Vector<CompactHTMLToken>::const_iterator it = tokens->begin(); | 527 for (Vector<CompactHTMLToken>::const_iterator it = tokens->begin(); |
528 it != tokens->end(); ++it) { | 528 it != tokens->end(); ++it) { |
529 ASSERT(!isWaitingForScripts()); | 529 DCHECK(!isWaitingForScripts()); |
530 | 530 |
531 if (!chunk->startingScript && | 531 if (!chunk->startingScript && |
532 (it->type() == HTMLToken::StartTag || it->type() == HTMLToken::EndTag)) | 532 (it->type() == HTMLToken::StartTag || it->type() == HTMLToken::EndTag)) |
533 elementTokenCount++; | 533 elementTokenCount++; |
534 | 534 |
535 if (document()->frame() && | 535 if (document()->frame() && |
536 document()->frame()->navigationScheduler().locationChangePending()) { | 536 document()->frame()->navigationScheduler().locationChangePending()) { |
537 // To match main-thread parser behavior (which never checks | 537 // To match main-thread parser behavior (which never checks |
538 // locationChangePending on the EOF path) we peek to see if this chunk has | 538 // locationChangePending on the EOF path) we peek to see if this chunk has |
539 // an EOF and process it anyway. | 539 // an EOF and process it anyway. |
540 if (tokens->back().type() == HTMLToken::EndOfFile) { | 540 if (tokens->back().type() == HTMLToken::EndOfFile) { |
541 ASSERT( | 541 DCHECK( |
542 m_speculations | 542 m_speculations |
543 .isEmpty()); // There should never be any chunks after the EOF. | 543 .isEmpty()); // There should never be any chunks after the EOF. |
544 prepareToStopParsing(); | 544 prepareToStopParsing(); |
545 } | 545 } |
546 break; | 546 break; |
547 } | 547 } |
548 | 548 |
549 m_textPosition = it->textPosition(); | 549 m_textPosition = it->textPosition(); |
550 | 550 |
551 constructTreeFromCompactHTMLToken(*it); | 551 constructTreeFromCompactHTMLToken(*it); |
552 | 552 |
553 if (isStopped()) | 553 if (isStopped()) |
554 break; | 554 break; |
555 | 555 |
556 // Preloads were queued if there was a <meta> csp token in a tokenized | 556 // Preloads were queued if there was a <meta> csp token in a tokenized |
557 // chunk. | 557 // chunk. |
558 if (m_pendingCSPMetaToken && it == m_pendingCSPMetaToken) { | 558 if (m_pendingCSPMetaToken && it == m_pendingCSPMetaToken) { |
559 m_pendingCSPMetaToken = nullptr; | 559 m_pendingCSPMetaToken = nullptr; |
560 fetchQueuedPreloads(); | 560 fetchQueuedPreloads(); |
561 } | 561 } |
562 | 562 |
563 if (isPaused()) { | 563 if (isPaused()) { |
564 // The script or stylesheet should be the last token of this bunch. | 564 // The script or stylesheet should be the last token of this bunch. |
565 ASSERT(it + 1 == tokens->end()); | 565 DCHECK_EQ(it + 1, tokens->end()); |
566 if (isWaitingForScripts()) | 566 if (isWaitingForScripts()) |
567 runScriptsForPausedTreeBuilder(); | 567 runScriptsForPausedTreeBuilder(); |
568 validateSpeculations(std::move(chunk)); | 568 validateSpeculations(std::move(chunk)); |
569 break; | 569 break; |
570 } | 570 } |
571 | 571 |
572 if (it->type() == HTMLToken::EndOfFile) { | 572 if (it->type() == HTMLToken::EndOfFile) { |
573 // The EOF is assumed to be the last token of this bunch. | 573 // The EOF is assumed to be the last token of this bunch. |
574 ASSERT(it + 1 == tokens->end()); | 574 DCHECK_EQ(it + 1, tokens->end()); |
575 // There should never be any chunks after the EOF. | 575 // There should never be any chunks after the EOF. |
576 ASSERT(m_speculations.isEmpty()); | 576 DCHECK(m_speculations.isEmpty()); |
577 prepareToStopParsing(); | 577 prepareToStopParsing(); |
578 break; | 578 break; |
579 } | 579 } |
580 | 580 |
581 ASSERT(!m_tokenizer); | 581 DCHECK(!m_tokenizer); |
582 ASSERT(!m_token); | 582 DCHECK(!m_token); |
583 } | 583 } |
584 | 584 |
585 // Make sure all required pending text nodes are emitted before returning. | 585 // Make sure all required pending text nodes are emitted before returning. |
586 // This leaves "script", "style" and "svg" nodes text nodes intact. | 586 // This leaves "script", "style" and "svg" nodes text nodes intact. |
587 if (!isStopped()) | 587 if (!isStopped()) |
588 m_treeBuilder->flush(FlushIfAtTextLimit); | 588 m_treeBuilder->flush(FlushIfAtTextLimit); |
589 | 589 |
590 m_isParsingAtLineNumber = false; | 590 m_isParsingAtLineNumber = false; |
591 | 591 |
592 return elementTokenCount; | 592 return elementTokenCount; |
593 } | 593 } |
594 | 594 |
595 void HTMLDocumentParser::pumpPendingSpeculations() { | 595 void HTMLDocumentParser::pumpPendingSpeculations() { |
596 // If this assert fails, you need to call validateSpeculations to make sure | 596 // If this assert fails, you need to call validateSpeculations to make sure |
597 // m_tokenizer and m_token don't have state that invalidates m_speculations. | 597 // m_tokenizer and m_token don't have state that invalidates m_speculations. |
598 ASSERT(!m_tokenizer); | 598 DCHECK(!m_tokenizer); |
599 ASSERT(!m_token); | 599 DCHECK(!m_token); |
600 DCHECK(!m_lastChunkBeforePause); | 600 DCHECK(!m_lastChunkBeforePause); |
601 DCHECK(!isPaused()); | 601 DCHECK(!isPaused()); |
602 ASSERT(!isStopped()); | 602 DCHECK(!isStopped()); |
603 ASSERT(!isScheduledForResume()); | 603 DCHECK(!isScheduledForResume()); |
604 ASSERT(!inPumpSession()); | 604 DCHECK(!inPumpSession()); |
605 | 605 |
606 // FIXME: Here should never be reached when there is a blocking script, | 606 // FIXME: Here should never be reached when there is a blocking script, |
607 // but it happens in unknown scenarios. See https://crbug.com/440901 | 607 // but it happens in unknown scenarios. See https://crbug.com/440901 |
608 if (isWaitingForScripts()) { | 608 if (isWaitingForScripts()) { |
609 m_parserScheduler->scheduleForResume(); | 609 m_parserScheduler->scheduleForResume(); |
610 return; | 610 return; |
611 } | 611 } |
612 | 612 |
613 // Do not allow pumping speculations in nested event loops. | 613 // Do not allow pumping speculations in nested event loops. |
614 if (m_pumpSpeculationsSessionNestingLevel) { | 614 if (m_pumpSpeculationsSessionNestingLevel) { |
615 m_parserScheduler->scheduleForResume(); | 615 m_parserScheduler->scheduleForResume(); |
616 return; | 616 return; |
617 } | 617 } |
618 | 618 |
619 probe::ParseHTML probe(document(), this); | 619 probe::ParseHTML probe(document(), this); |
620 | 620 |
621 SpeculationsPumpSession session(m_pumpSpeculationsSessionNestingLevel); | 621 SpeculationsPumpSession session(m_pumpSpeculationsSessionNestingLevel); |
622 while (!m_speculations.isEmpty()) { | 622 while (!m_speculations.isEmpty()) { |
623 ASSERT(!isScheduledForResume()); | 623 DCHECK(!isScheduledForResume()); |
624 size_t elementTokenCount = | 624 size_t elementTokenCount = |
625 processTokenizedChunkFromBackgroundParser(m_speculations.takeFirst()); | 625 processTokenizedChunkFromBackgroundParser(m_speculations.takeFirst()); |
626 session.addedElementTokens(elementTokenCount); | 626 session.addedElementTokens(elementTokenCount); |
627 | 627 |
628 // Always check isParsing first as m_document may be null. Surprisingly, | 628 // Always check isParsing first as m_document may be null. Surprisingly, |
629 // isScheduledForResume() may be set here as a result of | 629 // isScheduledForResume() may be set here as a result of |
630 // processTokenizedChunkFromBackgroundParser running arbitrary javascript | 630 // processTokenizedChunkFromBackgroundParser running arbitrary javascript |
631 // which invokes nested event loops. (e.g. inspector breakpoints) | 631 // which invokes nested event loops. (e.g. inspector breakpoints) |
632 checkIfBodyStylesheetAdded(); | 632 checkIfBodyStylesheetAdded(); |
633 if (!isParsing() || isPaused() || isScheduledForResume()) | 633 if (!isParsing() || isPaused() || isScheduledForResume()) |
(...skipping 14 matching lines...) Expand all Loading... |
648 startBackgroundParser(); | 648 startBackgroundParser(); |
649 | 649 |
650 // This task should be synchronous, because otherwise synchronous | 650 // This task should be synchronous, because otherwise synchronous |
651 // tokenizing can happen before plaintext is forced. | 651 // tokenizing can happen before plaintext is forced. |
652 m_backgroundParser->forcePlaintextForTextDocument(); | 652 m_backgroundParser->forcePlaintextForTextDocument(); |
653 } else | 653 } else |
654 m_tokenizer->setState(HTMLTokenizer::PLAINTEXTState); | 654 m_tokenizer->setState(HTMLTokenizer::PLAINTEXTState); |
655 } | 655 } |
656 | 656 |
657 void HTMLDocumentParser::pumpTokenizer() { | 657 void HTMLDocumentParser::pumpTokenizer() { |
658 ASSERT(!isStopped()); | 658 DCHECK(!isStopped()); |
659 ASSERT(m_tokenizer); | 659 DCHECK(m_tokenizer); |
660 ASSERT(m_token); | 660 DCHECK(m_token); |
661 | 661 |
662 PumpSession session(m_pumpSessionNestingLevel); | 662 PumpSession session(m_pumpSessionNestingLevel); |
663 | 663 |
664 // We tell the InspectorInstrumentation about every pump, even if we end up | 664 // We tell the InspectorInstrumentation about every pump, even if we end up |
665 // pumping nothing. It can filter out empty pumps itself. | 665 // pumping nothing. It can filter out empty pumps itself. |
666 // FIXME: m_input.current().length() is only accurate if we end up parsing the | 666 // FIXME: m_input.current().length() is only accurate if we end up parsing the |
667 // whole buffer in this pump. We should pass how much we parsed as part of | 667 // whole buffer in this pump. We should pass how much we parsed as part of |
668 // didWriteHTML instead of willWriteHTML. | 668 // didWriteHTML instead of willWriteHTML. |
669 probe::ParseHTML probe(document(), this); | 669 probe::ParseHTML probe(document(), this); |
670 | 670 |
(...skipping 17 matching lines...) Expand all Loading... |
688 token(), m_sourceTracker, m_tokenizer->shouldAllowCDATA()))) { | 688 token(), m_sourceTracker, m_tokenizer->shouldAllowCDATA()))) { |
689 m_xssAuditorDelegate.didBlockScript(*xssInfo); | 689 m_xssAuditorDelegate.didBlockScript(*xssInfo); |
690 // If we're in blocking mode, we might stop the parser in | 690 // If we're in blocking mode, we might stop the parser in |
691 // 'didBlockScript()'. In that case, exit early. | 691 // 'didBlockScript()'. In that case, exit early. |
692 if (!isParsing()) | 692 if (!isParsing()) |
693 return; | 693 return; |
694 } | 694 } |
695 } | 695 } |
696 | 696 |
697 constructTreeFromHTMLToken(); | 697 constructTreeFromHTMLToken(); |
698 ASSERT(isStopped() || token().isUninitialized()); | 698 DCHECK(isStopped() || token().isUninitialized()); |
699 } | 699 } |
700 | 700 |
701 if (isStopped()) | 701 if (isStopped()) |
702 return; | 702 return; |
703 | 703 |
704 // There should only be PendingText left since the tree-builder always flushes | 704 // There should only be PendingText left since the tree-builder always flushes |
705 // the task queue before returning. In case that ever changes, crash. | 705 // the task queue before returning. In case that ever changes, crash. |
706 m_treeBuilder->flush(FlushAlways); | 706 m_treeBuilder->flush(FlushAlways); |
707 RELEASE_ASSERT(!isStopped()); | 707 CHECK(!isStopped()); |
708 | 708 |
709 if (isPaused()) { | 709 if (isPaused()) { |
710 ASSERT(m_tokenizer->getState() == HTMLTokenizer::DataState); | 710 DCHECK_EQ(m_tokenizer->getState(), HTMLTokenizer::DataState); |
711 | 711 |
712 ASSERT(m_preloader); | 712 DCHECK(m_preloader); |
713 // TODO(kouhei): m_preloader should be always available for synchronous | 713 // TODO(kouhei): m_preloader should be always available for synchronous |
714 // parsing case, adding paranoia if for speculative crash fix for | 714 // parsing case, adding paranoia if for speculative crash fix for |
715 // crbug.com/465478 | 715 // crbug.com/465478 |
716 if (m_preloader) { | 716 if (m_preloader) { |
717 if (!m_preloadScanner) { | 717 if (!m_preloadScanner) { |
718 m_preloadScanner = createPreloadScanner(); | 718 m_preloadScanner = createPreloadScanner(); |
719 m_preloadScanner->appendToEnd(m_input.current()); | 719 m_preloadScanner->appendToEnd(m_input.current()); |
720 } | 720 } |
721 scanAndPreload(m_preloadScanner.get()); | 721 scanAndPreload(m_preloadScanner.get()); |
722 } | 722 } |
(...skipping 17 matching lines...) Expand all Loading... |
740 token().clear(); | 740 token().clear(); |
741 | 741 |
742 m_treeBuilder->constructTree(&atomicToken); | 742 m_treeBuilder->constructTree(&atomicToken); |
743 checkIfBodyStylesheetAdded(); | 743 checkIfBodyStylesheetAdded(); |
744 | 744 |
745 // FIXME: constructTree may synchronously cause Document to be detached. | 745 // FIXME: constructTree may synchronously cause Document to be detached. |
746 if (!m_token) | 746 if (!m_token) |
747 return; | 747 return; |
748 | 748 |
749 if (!token().isUninitialized()) { | 749 if (!token().isUninitialized()) { |
750 ASSERT(token().type() == HTMLToken::Character); | 750 DCHECK_EQ(token().type(), HTMLToken::Character); |
751 token().clear(); | 751 token().clear(); |
752 } | 752 } |
753 } | 753 } |
754 | 754 |
755 void HTMLDocumentParser::constructTreeFromCompactHTMLToken( | 755 void HTMLDocumentParser::constructTreeFromCompactHTMLToken( |
756 const CompactHTMLToken& compactToken) { | 756 const CompactHTMLToken& compactToken) { |
757 AtomicHTMLToken token(compactToken); | 757 AtomicHTMLToken token(compactToken); |
758 m_treeBuilder->constructTree(&token); | 758 m_treeBuilder->constructTree(&token); |
759 checkIfBodyStylesheetAdded(); | 759 checkIfBodyStylesheetAdded(); |
760 } | 760 } |
761 | 761 |
762 bool HTMLDocumentParser::hasInsertionPoint() { | 762 bool HTMLDocumentParser::hasInsertionPoint() { |
763 // FIXME: The wasCreatedByScript() branch here might not be fully correct. Our | 763 // FIXME: The wasCreatedByScript() branch here might not be fully correct. Our |
764 // model of the EOF character differs slightly from the one in the spec | 764 // model of the EOF character differs slightly from the one in the spec |
765 // because our treatment is uniform between network-sourced and script-sourced | 765 // because our treatment is uniform between network-sourced and script-sourced |
766 // input streams whereas the spec treats them differently. | 766 // input streams whereas the spec treats them differently. |
767 return m_input.hasInsertionPoint() || | 767 return m_input.hasInsertionPoint() || |
768 (wasCreatedByScript() && !m_input.haveSeenEndOfFile()); | 768 (wasCreatedByScript() && !m_input.haveSeenEndOfFile()); |
769 } | 769 } |
770 | 770 |
771 void HTMLDocumentParser::insert(const SegmentedString& source) { | 771 void HTMLDocumentParser::insert(const SegmentedString& source) { |
772 if (isStopped()) | 772 if (isStopped()) |
773 return; | 773 return; |
774 | 774 |
775 TRACE_EVENT1("blink", "HTMLDocumentParser::insert", "source_length", | 775 TRACE_EVENT1("blink", "HTMLDocumentParser::insert", "source_length", |
776 source.length()); | 776 source.length()); |
777 | 777 |
778 if (!m_tokenizer) { | 778 if (!m_tokenizer) { |
779 ASSERT(!inPumpSession()); | 779 DCHECK(!inPumpSession()); |
780 ASSERT(m_haveBackgroundParser || wasCreatedByScript()); | 780 DCHECK(m_haveBackgroundParser || wasCreatedByScript()); |
781 m_token = WTF::wrapUnique(new HTMLToken); | 781 m_token = WTF::wrapUnique(new HTMLToken); |
782 m_tokenizer = HTMLTokenizer::create(m_options); | 782 m_tokenizer = HTMLTokenizer::create(m_options); |
783 } | 783 } |
784 | 784 |
785 SegmentedString excludedLineNumberSource(source); | 785 SegmentedString excludedLineNumberSource(source); |
786 excludedLineNumberSource.setExcludeLineNumbers(); | 786 excludedLineNumberSource.setExcludeLineNumbers(); |
787 m_input.insertAtCurrentInsertionPoint(excludedLineNumberSource); | 787 m_input.insertAtCurrentInsertionPoint(excludedLineNumberSource); |
788 pumpTokenizerIfPossible(); | 788 pumpTokenizerIfPossible(); |
789 | 789 |
790 if (isPaused()) { | 790 if (isPaused()) { |
791 // Check the document.write() output with a separate preload scanner as | 791 // Check the document.write() output with a separate preload scanner as |
792 // the main scanner can't deal with insertions. | 792 // the main scanner can't deal with insertions. |
793 if (!m_insertionPreloadScanner) | 793 if (!m_insertionPreloadScanner) |
794 m_insertionPreloadScanner = createPreloadScanner(); | 794 m_insertionPreloadScanner = createPreloadScanner(); |
795 m_insertionPreloadScanner->appendToEnd(source); | 795 m_insertionPreloadScanner->appendToEnd(source); |
796 scanAndPreload(m_insertionPreloadScanner.get()); | 796 scanAndPreload(m_insertionPreloadScanner.get()); |
797 } | 797 } |
798 | 798 |
799 endIfDelayed(); | 799 endIfDelayed(); |
800 } | 800 } |
801 | 801 |
802 void HTMLDocumentParser::startBackgroundParser() { | 802 void HTMLDocumentParser::startBackgroundParser() { |
803 ASSERT(!isStopped()); | 803 DCHECK(!isStopped()); |
804 ASSERT(shouldUseThreading()); | 804 DCHECK(shouldUseThreading()); |
805 ASSERT(!m_haveBackgroundParser); | 805 DCHECK(!m_haveBackgroundParser); |
806 ASSERT(document()); | 806 DCHECK(document()); |
807 m_haveBackgroundParser = true; | 807 m_haveBackgroundParser = true; |
808 | 808 |
809 // TODO(alexclarke): Remove WebFrameScheduler::setDocumentParsingInBackground | 809 // TODO(alexclarke): Remove WebFrameScheduler::setDocumentParsingInBackground |
810 // when background parser goes away. | 810 // when background parser goes away. |
811 if (document()->frame() && document()->frame()->frameScheduler()) | 811 if (document()->frame() && document()->frame()->frameScheduler()) |
812 document()->frame()->frameScheduler()->setDocumentParsingInBackground(true); | 812 document()->frame()->frameScheduler()->setDocumentParsingInBackground(true); |
813 | 813 |
814 // Make sure that a resolver is set up, so that the correct viewport | 814 // Make sure that a resolver is set up, so that the correct viewport |
815 // dimensions will be fed to the background parser and preload scanner. | 815 // dimensions will be fed to the background parser and preload scanner. |
816 if (document()->loader()) | 816 if (document()->loader()) |
(...skipping 16 matching lines...) Expand all Loading... |
833 document() | 833 document() |
834 ->settings() | 834 ->settings() |
835 ->getBackgroundHtmlParserOutstandingTokenLimit(); | 835 ->getBackgroundHtmlParserOutstandingTokenLimit(); |
836 } | 836 } |
837 if (document()->settings()->getBackgroundHtmlParserPendingTokenLimit()) { | 837 if (document()->settings()->getBackgroundHtmlParserPendingTokenLimit()) { |
838 config->pendingTokenLimit = | 838 config->pendingTokenLimit = |
839 document()->settings()->getBackgroundHtmlParserPendingTokenLimit(); | 839 document()->settings()->getBackgroundHtmlParserPendingTokenLimit(); |
840 } | 840 } |
841 } | 841 } |
842 | 842 |
843 ASSERT(config->xssAuditor->isSafeToSendToAnotherThread()); | 843 DCHECK(config->xssAuditor->isSafeToSendToAnotherThread()); |
844 | 844 |
845 // The background parser is created on the main thread, but may otherwise | 845 // The background parser is created on the main thread, but may otherwise |
846 // only be used from the parser thread. | 846 // only be used from the parser thread. |
847 m_backgroundParser = | 847 m_backgroundParser = |
848 BackgroundHTMLParser::create(std::move(config), m_loadingTaskRunner); | 848 BackgroundHTMLParser::create(std::move(config), m_loadingTaskRunner); |
849 // TODO(csharrison): This is a hack to initialize MediaValuesCached on the | 849 // TODO(csharrison): This is a hack to initialize MediaValuesCached on the |
850 // correct thread. We should get rid of it. | 850 // correct thread. We should get rid of it. |
851 m_backgroundParser->init( | 851 m_backgroundParser->init( |
852 document()->url(), CachedDocumentParameters::create(document()), | 852 document()->url(), CachedDocumentParameters::create(document()), |
853 MediaValuesCached::MediaValuesCachedData(*document())); | 853 MediaValuesCached::MediaValuesCachedData(*document())); |
854 } | 854 } |
855 | 855 |
856 void HTMLDocumentParser::stopBackgroundParser() { | 856 void HTMLDocumentParser::stopBackgroundParser() { |
857 ASSERT(shouldUseThreading()); | 857 DCHECK(shouldUseThreading()); |
858 ASSERT(m_haveBackgroundParser); | 858 DCHECK(m_haveBackgroundParser); |
859 | 859 |
860 if (m_haveBackgroundParser && document()->frame() && | 860 if (m_haveBackgroundParser && document()->frame() && |
861 document()->frame()->frameScheduler()) | 861 document()->frame()->frameScheduler()) |
862 document()->frame()->frameScheduler()->setDocumentParsingInBackground( | 862 document()->frame()->frameScheduler()->setDocumentParsingInBackground( |
863 false); | 863 false); |
864 | 864 |
865 m_haveBackgroundParser = false; | 865 m_haveBackgroundParser = false; |
866 | 866 |
867 // Make this sync, as lsan triggers on some unittests if the task runner is | 867 // Make this sync, as lsan triggers on some unittests if the task runner is |
868 // used. | 868 // used. |
869 m_backgroundParser->stop(); | 869 m_backgroundParser->stop(); |
870 m_weakFactory.revokeAll(); | 870 m_weakFactory.revokeAll(); |
871 } | 871 } |
872 | 872 |
873 void HTMLDocumentParser::append(const String& inputSource) { | 873 void HTMLDocumentParser::append(const String& inputSource) { |
874 if (isStopped()) | 874 if (isStopped()) |
875 return; | 875 return; |
876 | 876 |
877 // We should never reach this point if we're using a parser thread, as | 877 // We should never reach this point if we're using a parser thread, as |
878 // appendBytes() will directly ship the data to the thread. | 878 // appendBytes() will directly ship the data to the thread. |
879 ASSERT(!shouldUseThreading()); | 879 DCHECK(!shouldUseThreading()); |
880 | 880 |
881 TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("blink.debug"), | 881 TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("blink.debug"), |
882 "HTMLDocumentParser::append", "size", inputSource.length()); | 882 "HTMLDocumentParser::append", "size", inputSource.length()); |
883 const SegmentedString source(inputSource); | 883 const SegmentedString source(inputSource); |
884 | 884 |
885 if (document()->isPrefetchOnly()) { | 885 if (document()->isPrefetchOnly()) { |
886 if (!m_preloadScanner) | 886 if (!m_preloadScanner) |
887 m_preloadScanner = createPreloadScanner(); | 887 m_preloadScanner = createPreloadScanner(); |
888 | 888 |
889 m_preloadScanner->appendToEnd(source); | 889 m_preloadScanner->appendToEnd(source); |
(...skipping 24 matching lines...) Expand all Loading... |
914 // this data in a less-nested write(). | 914 // this data in a less-nested write(). |
915 return; | 915 return; |
916 } | 916 } |
917 | 917 |
918 pumpTokenizerIfPossible(); | 918 pumpTokenizerIfPossible(); |
919 | 919 |
920 endIfDelayed(); | 920 endIfDelayed(); |
921 } | 921 } |
922 | 922 |
923 void HTMLDocumentParser::end() { | 923 void HTMLDocumentParser::end() { |
924 ASSERT(!isDetached()); | 924 DCHECK(!isDetached()); |
925 ASSERT(!isScheduledForResume()); | 925 DCHECK(!isScheduledForResume()); |
926 | 926 |
927 if (m_haveBackgroundParser) | 927 if (m_haveBackgroundParser) |
928 stopBackgroundParser(); | 928 stopBackgroundParser(); |
929 | 929 |
930 // Informs the the rest of WebCore that parsing is really finished (and | 930 // Informs the the rest of WebCore that parsing is really finished (and |
931 // deletes this). | 931 // deletes this). |
932 m_treeBuilder->finished(); | 932 m_treeBuilder->finished(); |
933 | 933 |
934 DocumentParser::stopParsing(); | 934 DocumentParser::stopParsing(); |
935 } | 935 } |
936 | 936 |
937 void HTMLDocumentParser::attemptToRunDeferredScriptsAndEnd() { | 937 void HTMLDocumentParser::attemptToRunDeferredScriptsAndEnd() { |
938 ASSERT(isStopping()); | 938 DCHECK(isStopping()); |
939 // FIXME: It may not be correct to disable this for the background parser. | 939 // FIXME: It may not be correct to disable this for the background parser. |
940 // That means hasInsertionPoint() may not be correct in some cases. | 940 // That means hasInsertionPoint() may not be correct in some cases. |
941 ASSERT(!hasInsertionPoint() || m_haveBackgroundParser); | 941 DCHECK(!hasInsertionPoint() || m_haveBackgroundParser); |
942 if (m_scriptRunner && !m_scriptRunner->executeScriptsWaitingForParsing()) | 942 if (m_scriptRunner && !m_scriptRunner->executeScriptsWaitingForParsing()) |
943 return; | 943 return; |
944 end(); | 944 end(); |
945 } | 945 } |
946 | 946 |
947 void HTMLDocumentParser::attemptToEnd() { | 947 void HTMLDocumentParser::attemptToEnd() { |
948 // finish() indicates we will not receive any more data. If we are waiting on | 948 // finish() indicates we will not receive any more data. If we are waiting on |
949 // an external script to load, we can't finish parsing quite yet. | 949 // an external script to load, we can't finish parsing quite yet. |
950 | 950 |
951 if (shouldDelayEnd()) { | 951 if (shouldDelayEnd()) { |
(...skipping 30 matching lines...) Expand all Loading... |
982 if (m_haveBackgroundParser) { | 982 if (m_haveBackgroundParser) { |
983 if (!m_input.haveSeenEndOfFile()) | 983 if (!m_input.haveSeenEndOfFile()) |
984 m_input.closeWithoutMarkingEndOfFile(); | 984 m_input.closeWithoutMarkingEndOfFile(); |
985 m_loadingTaskRunner->postTask( | 985 m_loadingTaskRunner->postTask( |
986 BLINK_FROM_HERE, | 986 BLINK_FROM_HERE, |
987 WTF::bind(&BackgroundHTMLParser::finish, m_backgroundParser)); | 987 WTF::bind(&BackgroundHTMLParser::finish, m_backgroundParser)); |
988 return; | 988 return; |
989 } | 989 } |
990 | 990 |
991 if (!m_tokenizer) { | 991 if (!m_tokenizer) { |
992 ASSERT(!m_token); | 992 DCHECK(!m_token); |
993 // We're finishing before receiving any data. Rather than booting up the | 993 // We're finishing before receiving any data. Rather than booting up the |
994 // background parser just to spin it down, we finish parsing synchronously. | 994 // background parser just to spin it down, we finish parsing synchronously. |
995 m_token = WTF::wrapUnique(new HTMLToken); | 995 m_token = WTF::wrapUnique(new HTMLToken); |
996 m_tokenizer = HTMLTokenizer::create(m_options); | 996 m_tokenizer = HTMLTokenizer::create(m_options); |
997 } | 997 } |
998 | 998 |
999 // We're not going to get any more data off the network, so we tell the input | 999 // We're not going to get any more data off the network, so we tell the input |
1000 // stream we've reached the end of file. finish() can be called more than | 1000 // stream we've reached the end of file. finish() can be called more than |
1001 // once, if the first time does not call end(). | 1001 // once, if the first time does not call end(). |
1002 if (!m_input.haveSeenEndOfFile()) | 1002 if (!m_input.haveSeenEndOfFile()) |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1040 // the script runner. The script runner will hold the script until its loaded | 1040 // the script runner. The script runner will hold the script until its loaded |
1041 // and run. During any of this time, we want to count ourselves as "waiting | 1041 // and run. During any of this time, we want to count ourselves as "waiting |
1042 // for a script" and thus run the preload scanner, as well as delay completion | 1042 // for a script" and thus run the preload scanner, as well as delay completion |
1043 // of parsing. | 1043 // of parsing. |
1044 bool treeBuilderHasBlockingScript = m_treeBuilder->hasParserBlockingScript(); | 1044 bool treeBuilderHasBlockingScript = m_treeBuilder->hasParserBlockingScript(); |
1045 bool scriptRunnerHasBlockingScript = | 1045 bool scriptRunnerHasBlockingScript = |
1046 m_scriptRunner && m_scriptRunner->hasParserBlockingScript(); | 1046 m_scriptRunner && m_scriptRunner->hasParserBlockingScript(); |
1047 // Since the parser is paused while a script runner has a blocking script, it | 1047 // Since the parser is paused while a script runner has a blocking script, it |
1048 // should never be possible to end up with both objects holding a blocking | 1048 // should never be possible to end up with both objects holding a blocking |
1049 // script. | 1049 // script. |
1050 ASSERT(!(treeBuilderHasBlockingScript && scriptRunnerHasBlockingScript)); | 1050 DCHECK(!(treeBuilderHasBlockingScript && scriptRunnerHasBlockingScript)); |
1051 // If either object has a blocking script, the parser should be paused. | 1051 // If either object has a blocking script, the parser should be paused. |
1052 return treeBuilderHasBlockingScript || scriptRunnerHasBlockingScript || | 1052 return treeBuilderHasBlockingScript || scriptRunnerHasBlockingScript || |
1053 m_reentryPermit->parserPauseFlag(); | 1053 m_reentryPermit->parserPauseFlag(); |
1054 } | 1054 } |
1055 | 1055 |
1056 void HTMLDocumentParser::resumeParsingAfterPause() { | 1056 void HTMLDocumentParser::resumeParsingAfterPause() { |
1057 ASSERT(!isExecutingScript()); | 1057 DCHECK(!isExecutingScript()); |
1058 DCHECK(!isPaused()); | 1058 DCHECK(!isPaused()); |
1059 | 1059 |
1060 checkIfBodyStylesheetAdded(); | 1060 checkIfBodyStylesheetAdded(); |
1061 if (isPaused()) | 1061 if (isPaused()) |
1062 return; | 1062 return; |
1063 | 1063 |
1064 if (m_haveBackgroundParser) { | 1064 if (m_haveBackgroundParser) { |
1065 if (m_lastChunkBeforePause) { | 1065 if (m_lastChunkBeforePause) { |
1066 validateSpeculations(std::move(m_lastChunkBeforePause)); | 1066 validateSpeculations(std::move(m_lastChunkBeforePause)); |
1067 DCHECK(!m_lastChunkBeforePause); | 1067 DCHECK(!m_lastChunkBeforePause); |
1068 pumpPendingSpeculations(); | 1068 pumpPendingSpeculations(); |
1069 } | 1069 } |
1070 return; | 1070 return; |
1071 } | 1071 } |
1072 | 1072 |
1073 m_insertionPreloadScanner.reset(); | 1073 m_insertionPreloadScanner.reset(); |
1074 if (m_tokenizer) { | 1074 if (m_tokenizer) { |
1075 pumpTokenizerIfPossible(); | 1075 pumpTokenizerIfPossible(); |
1076 } | 1076 } |
1077 endIfDelayed(); | 1077 endIfDelayed(); |
1078 } | 1078 } |
1079 | 1079 |
1080 void HTMLDocumentParser::appendCurrentInputStreamToPreloadScannerAndScan() { | 1080 void HTMLDocumentParser::appendCurrentInputStreamToPreloadScannerAndScan() { |
1081 ASSERT(m_preloadScanner); | 1081 DCHECK(m_preloadScanner); |
1082 m_preloadScanner->appendToEnd(m_input.current()); | 1082 m_preloadScanner->appendToEnd(m_input.current()); |
1083 scanAndPreload(m_preloadScanner.get()); | 1083 scanAndPreload(m_preloadScanner.get()); |
1084 } | 1084 } |
1085 | 1085 |
1086 void HTMLDocumentParser::notifyScriptLoaded(PendingScript* pendingScript) { | 1086 void HTMLDocumentParser::notifyScriptLoaded(PendingScript* pendingScript) { |
1087 ASSERT(m_scriptRunner); | 1087 DCHECK(m_scriptRunner); |
1088 ASSERT(!isExecutingScript()); | 1088 DCHECK(!isExecutingScript()); |
1089 | 1089 |
1090 if (isStopped()) { | 1090 if (isStopped()) { |
1091 return; | 1091 return; |
1092 } | 1092 } |
1093 | 1093 |
1094 if (isStopping()) { | 1094 if (isStopping()) { |
1095 attemptToRunDeferredScriptsAndEnd(); | 1095 attemptToRunDeferredScriptsAndEnd(); |
1096 return; | 1096 return; |
1097 } | 1097 } |
1098 | 1098 |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1148 ParserContentPolicy parserContentPolicy) { | 1148 ParserContentPolicy parserContentPolicy) { |
1149 HTMLDocumentParser* parser = | 1149 HTMLDocumentParser* parser = |
1150 HTMLDocumentParser::create(fragment, contextElement, parserContentPolicy); | 1150 HTMLDocumentParser::create(fragment, contextElement, parserContentPolicy); |
1151 parser->append(source); | 1151 parser->append(source); |
1152 parser->finish(); | 1152 parser->finish(); |
1153 // Allows ~DocumentParser to assert it was detached before destruction. | 1153 // Allows ~DocumentParser to assert it was detached before destruction. |
1154 parser->detach(); | 1154 parser->detach(); |
1155 } | 1155 } |
1156 | 1156 |
1157 void HTMLDocumentParser::suspendScheduledTasks() { | 1157 void HTMLDocumentParser::suspendScheduledTasks() { |
1158 ASSERT(!m_tasksWereSuspended); | 1158 DCHECK(!m_tasksWereSuspended); |
1159 m_tasksWereSuspended = true; | 1159 m_tasksWereSuspended = true; |
1160 if (m_parserScheduler) | 1160 if (m_parserScheduler) |
1161 m_parserScheduler->suspend(); | 1161 m_parserScheduler->suspend(); |
1162 } | 1162 } |
1163 | 1163 |
1164 void HTMLDocumentParser::resumeScheduledTasks() { | 1164 void HTMLDocumentParser::resumeScheduledTasks() { |
1165 ASSERT(m_tasksWereSuspended); | 1165 DCHECK(m_tasksWereSuspended); |
1166 m_tasksWereSuspended = false; | 1166 m_tasksWereSuspended = false; |
1167 if (m_parserScheduler) | 1167 if (m_parserScheduler) |
1168 m_parserScheduler->resume(); | 1168 m_parserScheduler->resume(); |
1169 } | 1169 } |
1170 | 1170 |
1171 void HTMLDocumentParser::appendBytes(const char* data, size_t length) { | 1171 void HTMLDocumentParser::appendBytes(const char* data, size_t length) { |
1172 if (!length || isStopped()) | 1172 if (!length || isStopped()) |
1173 return; | 1173 return; |
1174 | 1174 |
1175 if (shouldUseThreading()) { | 1175 if (shouldUseThreading()) { |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1213 m_loadingTaskRunner->postTask( | 1213 m_loadingTaskRunner->postTask( |
1214 BLINK_FROM_HERE, | 1214 BLINK_FROM_HERE, |
1215 WTF::bind(&BackgroundHTMLParser::flush, m_backgroundParser)); | 1215 WTF::bind(&BackgroundHTMLParser::flush, m_backgroundParser)); |
1216 } else { | 1216 } else { |
1217 DecodedDataDocumentParser::flush(); | 1217 DecodedDataDocumentParser::flush(); |
1218 } | 1218 } |
1219 } | 1219 } |
1220 | 1220 |
1221 void HTMLDocumentParser::setDecoder( | 1221 void HTMLDocumentParser::setDecoder( |
1222 std::unique_ptr<TextResourceDecoder> decoder) { | 1222 std::unique_ptr<TextResourceDecoder> decoder) { |
1223 ASSERT(decoder); | 1223 DCHECK(decoder); |
1224 DecodedDataDocumentParser::setDecoder(std::move(decoder)); | 1224 DecodedDataDocumentParser::setDecoder(std::move(decoder)); |
1225 | 1225 |
1226 if (m_haveBackgroundParser) { | 1226 if (m_haveBackgroundParser) { |
1227 m_loadingTaskRunner->postTask( | 1227 m_loadingTaskRunner->postTask( |
1228 BLINK_FROM_HERE, | 1228 BLINK_FROM_HERE, |
1229 WTF::bind(&BackgroundHTMLParser::setDecoder, m_backgroundParser, | 1229 WTF::bind(&BackgroundHTMLParser::setDecoder, m_backgroundParser, |
1230 WTF::passed(takeDecoder()))); | 1230 WTF::passed(takeDecoder()))); |
1231 } | 1231 } |
1232 } | 1232 } |
1233 | 1233 |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1313 successHistogram.count(duration); | 1313 successHistogram.count(duration); |
1314 } else { | 1314 } else { |
1315 DEFINE_STATIC_LOCAL( | 1315 DEFINE_STATIC_LOCAL( |
1316 CustomCountHistogram, failureHistogram, | 1316 CustomCountHistogram, failureHistogram, |
1317 ("PreloadScanner.DocumentWrite.ExecutionTime.Failure", 1, 10000, 50)); | 1317 ("PreloadScanner.DocumentWrite.ExecutionTime.Failure", 1, 10000, 50)); |
1318 failureHistogram.count(duration); | 1318 failureHistogram.count(duration); |
1319 } | 1319 } |
1320 } | 1320 } |
1321 | 1321 |
1322 } // namespace blink | 1322 } // namespace blink |
OLD | NEW |