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 TRACE_EVENT_BEGIN1( | 669 TRACE_EVENT_BEGIN1( |
670 "devtools.timeline", "ParseHTML", "beginData", | 670 "devtools.timeline", "ParseHTML", "beginData", |
(...skipping 20 matching lines...) Expand all Loading... |
691 token(), m_sourceTracker, m_tokenizer->shouldAllowCDATA()))) { | 691 token(), m_sourceTracker, m_tokenizer->shouldAllowCDATA()))) { |
692 m_xssAuditorDelegate.didBlockScript(*xssInfo); | 692 m_xssAuditorDelegate.didBlockScript(*xssInfo); |
693 // If we're in blocking mode, we might stop the parser in | 693 // If we're in blocking mode, we might stop the parser in |
694 // 'didBlockScript()'. In that case, exit early. | 694 // 'didBlockScript()'. In that case, exit early. |
695 if (!isParsing()) | 695 if (!isParsing()) |
696 return; | 696 return; |
697 } | 697 } |
698 } | 698 } |
699 | 699 |
700 constructTreeFromHTMLToken(); | 700 constructTreeFromHTMLToken(); |
701 ASSERT(isStopped() || token().isUninitialized()); | 701 DCHECK(isStopped() || token().isUninitialized()); |
702 } | 702 } |
703 | 703 |
704 if (isStopped()) | 704 if (isStopped()) |
705 return; | 705 return; |
706 | 706 |
707 // There should only be PendingText left since the tree-builder always flushes | 707 // There should only be PendingText left since the tree-builder always flushes |
708 // the task queue before returning. In case that ever changes, crash. | 708 // the task queue before returning. In case that ever changes, crash. |
709 m_treeBuilder->flush(FlushAlways); | 709 m_treeBuilder->flush(FlushAlways); |
710 RELEASE_ASSERT(!isStopped()); | 710 CHECK(!isStopped()); |
711 | 711 |
712 if (isPaused()) { | 712 if (isPaused()) { |
713 ASSERT(m_tokenizer->getState() == HTMLTokenizer::DataState); | 713 DCHECK_EQ(m_tokenizer->getState(), HTMLTokenizer::DataState); |
714 | 714 |
715 ASSERT(m_preloader); | 715 DCHECK(m_preloader); |
716 // TODO(kouhei): m_preloader should be always available for synchronous | 716 // TODO(kouhei): m_preloader should be always available for synchronous |
717 // parsing case, adding paranoia if for speculative crash fix for | 717 // parsing case, adding paranoia if for speculative crash fix for |
718 // crbug.com/465478 | 718 // crbug.com/465478 |
719 if (m_preloader) { | 719 if (m_preloader) { |
720 if (!m_preloadScanner) { | 720 if (!m_preloadScanner) { |
721 m_preloadScanner = createPreloadScanner(); | 721 m_preloadScanner = createPreloadScanner(); |
722 m_preloadScanner->appendToEnd(m_input.current()); | 722 m_preloadScanner->appendToEnd(m_input.current()); |
723 } | 723 } |
724 scanAndPreload(m_preloadScanner.get()); | 724 scanAndPreload(m_preloadScanner.get()); |
725 } | 725 } |
(...skipping 21 matching lines...) Expand all Loading... |
747 token().clear(); | 747 token().clear(); |
748 | 748 |
749 m_treeBuilder->constructTree(&atomicToken); | 749 m_treeBuilder->constructTree(&atomicToken); |
750 checkIfBodyStylesheetAdded(); | 750 checkIfBodyStylesheetAdded(); |
751 | 751 |
752 // FIXME: constructTree may synchronously cause Document to be detached. | 752 // FIXME: constructTree may synchronously cause Document to be detached. |
753 if (!m_token) | 753 if (!m_token) |
754 return; | 754 return; |
755 | 755 |
756 if (!token().isUninitialized()) { | 756 if (!token().isUninitialized()) { |
757 ASSERT(token().type() == HTMLToken::Character); | 757 DCHECK_EQ(token().type(), HTMLToken::Character); |
758 token().clear(); | 758 token().clear(); |
759 } | 759 } |
760 } | 760 } |
761 | 761 |
762 void HTMLDocumentParser::constructTreeFromCompactHTMLToken( | 762 void HTMLDocumentParser::constructTreeFromCompactHTMLToken( |
763 const CompactHTMLToken& compactToken) { | 763 const CompactHTMLToken& compactToken) { |
764 AtomicHTMLToken token(compactToken); | 764 AtomicHTMLToken token(compactToken); |
765 m_treeBuilder->constructTree(&token); | 765 m_treeBuilder->constructTree(&token); |
766 checkIfBodyStylesheetAdded(); | 766 checkIfBodyStylesheetAdded(); |
767 } | 767 } |
768 | 768 |
769 bool HTMLDocumentParser::hasInsertionPoint() { | 769 bool HTMLDocumentParser::hasInsertionPoint() { |
770 // FIXME: The wasCreatedByScript() branch here might not be fully correct. Our | 770 // FIXME: The wasCreatedByScript() branch here might not be fully correct. Our |
771 // model of the EOF character differs slightly from the one in the spec | 771 // model of the EOF character differs slightly from the one in the spec |
772 // because our treatment is uniform between network-sourced and script-sourced | 772 // because our treatment is uniform between network-sourced and script-sourced |
773 // input streams whereas the spec treats them differently. | 773 // input streams whereas the spec treats them differently. |
774 return m_input.hasInsertionPoint() || | 774 return m_input.hasInsertionPoint() || |
775 (wasCreatedByScript() && !m_input.haveSeenEndOfFile()); | 775 (wasCreatedByScript() && !m_input.haveSeenEndOfFile()); |
776 } | 776 } |
777 | 777 |
778 void HTMLDocumentParser::insert(const SegmentedString& source) { | 778 void HTMLDocumentParser::insert(const SegmentedString& source) { |
779 if (isStopped()) | 779 if (isStopped()) |
780 return; | 780 return; |
781 | 781 |
782 TRACE_EVENT1("blink", "HTMLDocumentParser::insert", "source_length", | 782 TRACE_EVENT1("blink", "HTMLDocumentParser::insert", "source_length", |
783 source.length()); | 783 source.length()); |
784 | 784 |
785 if (!m_tokenizer) { | 785 if (!m_tokenizer) { |
786 ASSERT(!inPumpSession()); | 786 DCHECK(!inPumpSession()); |
787 ASSERT(m_haveBackgroundParser || wasCreatedByScript()); | 787 DCHECK(m_haveBackgroundParser || wasCreatedByScript()); |
788 m_token = WTF::wrapUnique(new HTMLToken); | 788 m_token = WTF::wrapUnique(new HTMLToken); |
789 m_tokenizer = HTMLTokenizer::create(m_options); | 789 m_tokenizer = HTMLTokenizer::create(m_options); |
790 } | 790 } |
791 | 791 |
792 SegmentedString excludedLineNumberSource(source); | 792 SegmentedString excludedLineNumberSource(source); |
793 excludedLineNumberSource.setExcludeLineNumbers(); | 793 excludedLineNumberSource.setExcludeLineNumbers(); |
794 m_input.insertAtCurrentInsertionPoint(excludedLineNumberSource); | 794 m_input.insertAtCurrentInsertionPoint(excludedLineNumberSource); |
795 pumpTokenizerIfPossible(); | 795 pumpTokenizerIfPossible(); |
796 | 796 |
797 if (isPaused()) { | 797 if (isPaused()) { |
798 // Check the document.write() output with a separate preload scanner as | 798 // Check the document.write() output with a separate preload scanner as |
799 // the main scanner can't deal with insertions. | 799 // the main scanner can't deal with insertions. |
800 if (!m_insertionPreloadScanner) | 800 if (!m_insertionPreloadScanner) |
801 m_insertionPreloadScanner = createPreloadScanner(); | 801 m_insertionPreloadScanner = createPreloadScanner(); |
802 m_insertionPreloadScanner->appendToEnd(source); | 802 m_insertionPreloadScanner->appendToEnd(source); |
803 scanAndPreload(m_insertionPreloadScanner.get()); | 803 scanAndPreload(m_insertionPreloadScanner.get()); |
804 } | 804 } |
805 | 805 |
806 endIfDelayed(); | 806 endIfDelayed(); |
807 } | 807 } |
808 | 808 |
809 void HTMLDocumentParser::startBackgroundParser() { | 809 void HTMLDocumentParser::startBackgroundParser() { |
810 ASSERT(!isStopped()); | 810 DCHECK(!isStopped()); |
811 ASSERT(shouldUseThreading()); | 811 DCHECK(shouldUseThreading()); |
812 ASSERT(!m_haveBackgroundParser); | 812 DCHECK(!m_haveBackgroundParser); |
813 ASSERT(document()); | 813 DCHECK(document()); |
814 m_haveBackgroundParser = true; | 814 m_haveBackgroundParser = true; |
815 | 815 |
816 // TODO(alexclarke): Remove WebFrameScheduler::setDocumentParsingInBackground | 816 // TODO(alexclarke): Remove WebFrameScheduler::setDocumentParsingInBackground |
817 // when background parser goes away. | 817 // when background parser goes away. |
818 if (document()->frame() && document()->frame()->frameScheduler()) | 818 if (document()->frame() && document()->frame()->frameScheduler()) |
819 document()->frame()->frameScheduler()->setDocumentParsingInBackground(true); | 819 document()->frame()->frameScheduler()->setDocumentParsingInBackground(true); |
820 | 820 |
821 // Make sure that a resolver is set up, so that the correct viewport | 821 // Make sure that a resolver is set up, so that the correct viewport |
822 // dimensions will be fed to the background parser and preload scanner. | 822 // dimensions will be fed to the background parser and preload scanner. |
823 if (document()->loader()) | 823 if (document()->loader()) |
(...skipping 16 matching lines...) Expand all Loading... |
840 document() | 840 document() |
841 ->settings() | 841 ->settings() |
842 ->getBackgroundHtmlParserOutstandingTokenLimit(); | 842 ->getBackgroundHtmlParserOutstandingTokenLimit(); |
843 } | 843 } |
844 if (document()->settings()->getBackgroundHtmlParserPendingTokenLimit()) { | 844 if (document()->settings()->getBackgroundHtmlParserPendingTokenLimit()) { |
845 config->pendingTokenLimit = | 845 config->pendingTokenLimit = |
846 document()->settings()->getBackgroundHtmlParserPendingTokenLimit(); | 846 document()->settings()->getBackgroundHtmlParserPendingTokenLimit(); |
847 } | 847 } |
848 } | 848 } |
849 | 849 |
850 ASSERT(config->xssAuditor->isSafeToSendToAnotherThread()); | 850 DCHECK(config->xssAuditor->isSafeToSendToAnotherThread()); |
851 | 851 |
852 // The background parser is created on the main thread, but may otherwise | 852 // The background parser is created on the main thread, but may otherwise |
853 // only be used from the parser thread. | 853 // only be used from the parser thread. |
854 m_backgroundParser = | 854 m_backgroundParser = |
855 BackgroundHTMLParser::create(std::move(config), m_loadingTaskRunner); | 855 BackgroundHTMLParser::create(std::move(config), m_loadingTaskRunner); |
856 // TODO(csharrison): This is a hack to initialize MediaValuesCached on the | 856 // TODO(csharrison): This is a hack to initialize MediaValuesCached on the |
857 // correct thread. We should get rid of it. | 857 // correct thread. We should get rid of it. |
858 m_backgroundParser->init( | 858 m_backgroundParser->init( |
859 document()->url(), CachedDocumentParameters::create(document()), | 859 document()->url(), CachedDocumentParameters::create(document()), |
860 MediaValuesCached::MediaValuesCachedData(*document())); | 860 MediaValuesCached::MediaValuesCachedData(*document())); |
861 } | 861 } |
862 | 862 |
863 void HTMLDocumentParser::stopBackgroundParser() { | 863 void HTMLDocumentParser::stopBackgroundParser() { |
864 ASSERT(shouldUseThreading()); | 864 DCHECK(shouldUseThreading()); |
865 ASSERT(m_haveBackgroundParser); | 865 DCHECK(m_haveBackgroundParser); |
866 | 866 |
867 if (m_haveBackgroundParser && document()->frame() && | 867 if (m_haveBackgroundParser && document()->frame() && |
868 document()->frame()->frameScheduler()) | 868 document()->frame()->frameScheduler()) |
869 document()->frame()->frameScheduler()->setDocumentParsingInBackground( | 869 document()->frame()->frameScheduler()->setDocumentParsingInBackground( |
870 false); | 870 false); |
871 | 871 |
872 m_haveBackgroundParser = false; | 872 m_haveBackgroundParser = false; |
873 | 873 |
874 // Make this sync, as lsan triggers on some unittests if the task runner is | 874 // Make this sync, as lsan triggers on some unittests if the task runner is |
875 // used. | 875 // used. |
876 m_backgroundParser->stop(); | 876 m_backgroundParser->stop(); |
877 m_weakFactory.revokeAll(); | 877 m_weakFactory.revokeAll(); |
878 } | 878 } |
879 | 879 |
880 void HTMLDocumentParser::append(const String& inputSource) { | 880 void HTMLDocumentParser::append(const String& inputSource) { |
881 if (isStopped()) | 881 if (isStopped()) |
882 return; | 882 return; |
883 | 883 |
884 // We should never reach this point if we're using a parser thread, as | 884 // We should never reach this point if we're using a parser thread, as |
885 // appendBytes() will directly ship the data to the thread. | 885 // appendBytes() will directly ship the data to the thread. |
886 ASSERT(!shouldUseThreading()); | 886 DCHECK(!shouldUseThreading()); |
887 | 887 |
888 TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("blink.debug"), | 888 TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("blink.debug"), |
889 "HTMLDocumentParser::append", "size", inputSource.length()); | 889 "HTMLDocumentParser::append", "size", inputSource.length()); |
890 const SegmentedString source(inputSource); | 890 const SegmentedString source(inputSource); |
891 | 891 |
892 if (document()->isPrefetchOnly()) { | 892 if (document()->isPrefetchOnly()) { |
893 if (!m_preloadScanner) | 893 if (!m_preloadScanner) |
894 m_preloadScanner = createPreloadScanner(); | 894 m_preloadScanner = createPreloadScanner(); |
895 | 895 |
896 m_preloadScanner->appendToEnd(source); | 896 m_preloadScanner->appendToEnd(source); |
(...skipping 24 matching lines...) Expand all Loading... |
921 // this data in a less-nested write(). | 921 // this data in a less-nested write(). |
922 return; | 922 return; |
923 } | 923 } |
924 | 924 |
925 pumpTokenizerIfPossible(); | 925 pumpTokenizerIfPossible(); |
926 | 926 |
927 endIfDelayed(); | 927 endIfDelayed(); |
928 } | 928 } |
929 | 929 |
930 void HTMLDocumentParser::end() { | 930 void HTMLDocumentParser::end() { |
931 ASSERT(!isDetached()); | 931 DCHECK(!isDetached()); |
932 ASSERT(!isScheduledForResume()); | 932 DCHECK(!isScheduledForResume()); |
933 | 933 |
934 if (m_haveBackgroundParser) | 934 if (m_haveBackgroundParser) |
935 stopBackgroundParser(); | 935 stopBackgroundParser(); |
936 | 936 |
937 // Informs the the rest of WebCore that parsing is really finished (and | 937 // Informs the the rest of WebCore that parsing is really finished (and |
938 // deletes this). | 938 // deletes this). |
939 m_treeBuilder->finished(); | 939 m_treeBuilder->finished(); |
940 | 940 |
941 DocumentParser::stopParsing(); | 941 DocumentParser::stopParsing(); |
942 } | 942 } |
943 | 943 |
944 void HTMLDocumentParser::attemptToRunDeferredScriptsAndEnd() { | 944 void HTMLDocumentParser::attemptToRunDeferredScriptsAndEnd() { |
945 ASSERT(isStopping()); | 945 DCHECK(isStopping()); |
946 // FIXME: It may not be correct to disable this for the background parser. | 946 // FIXME: It may not be correct to disable this for the background parser. |
947 // That means hasInsertionPoint() may not be correct in some cases. | 947 // That means hasInsertionPoint() may not be correct in some cases. |
948 ASSERT(!hasInsertionPoint() || m_haveBackgroundParser); | 948 DCHECK(!hasInsertionPoint() || m_haveBackgroundParser); |
949 if (m_scriptRunner && !m_scriptRunner->executeScriptsWaitingForParsing()) | 949 if (m_scriptRunner && !m_scriptRunner->executeScriptsWaitingForParsing()) |
950 return; | 950 return; |
951 end(); | 951 end(); |
952 } | 952 } |
953 | 953 |
954 void HTMLDocumentParser::attemptToEnd() { | 954 void HTMLDocumentParser::attemptToEnd() { |
955 // finish() indicates we will not receive any more data. If we are waiting on | 955 // finish() indicates we will not receive any more data. If we are waiting on |
956 // an external script to load, we can't finish parsing quite yet. | 956 // an external script to load, we can't finish parsing quite yet. |
957 | 957 |
958 if (shouldDelayEnd()) { | 958 if (shouldDelayEnd()) { |
(...skipping 30 matching lines...) Expand all Loading... |
989 if (m_haveBackgroundParser) { | 989 if (m_haveBackgroundParser) { |
990 if (!m_input.haveSeenEndOfFile()) | 990 if (!m_input.haveSeenEndOfFile()) |
991 m_input.closeWithoutMarkingEndOfFile(); | 991 m_input.closeWithoutMarkingEndOfFile(); |
992 m_loadingTaskRunner->postTask( | 992 m_loadingTaskRunner->postTask( |
993 BLINK_FROM_HERE, | 993 BLINK_FROM_HERE, |
994 WTF::bind(&BackgroundHTMLParser::finish, m_backgroundParser)); | 994 WTF::bind(&BackgroundHTMLParser::finish, m_backgroundParser)); |
995 return; | 995 return; |
996 } | 996 } |
997 | 997 |
998 if (!m_tokenizer) { | 998 if (!m_tokenizer) { |
999 ASSERT(!m_token); | 999 DCHECK(!m_token); |
1000 // We're finishing before receiving any data. Rather than booting up the | 1000 // We're finishing before receiving any data. Rather than booting up the |
1001 // background parser just to spin it down, we finish parsing synchronously. | 1001 // background parser just to spin it down, we finish parsing synchronously. |
1002 m_token = WTF::wrapUnique(new HTMLToken); | 1002 m_token = WTF::wrapUnique(new HTMLToken); |
1003 m_tokenizer = HTMLTokenizer::create(m_options); | 1003 m_tokenizer = HTMLTokenizer::create(m_options); |
1004 } | 1004 } |
1005 | 1005 |
1006 // We're not going to get any more data off the network, so we tell the input | 1006 // We're not going to get any more data off the network, so we tell the input |
1007 // stream we've reached the end of file. finish() can be called more than | 1007 // stream we've reached the end of file. finish() can be called more than |
1008 // once, if the first time does not call end(). | 1008 // once, if the first time does not call end(). |
1009 if (!m_input.haveSeenEndOfFile()) | 1009 if (!m_input.haveSeenEndOfFile()) |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1047 // the script runner. The script runner will hold the script until its loaded | 1047 // the script runner. The script runner will hold the script until its loaded |
1048 // and run. During any of this time, we want to count ourselves as "waiting | 1048 // and run. During any of this time, we want to count ourselves as "waiting |
1049 // for a script" and thus run the preload scanner, as well as delay completion | 1049 // for a script" and thus run the preload scanner, as well as delay completion |
1050 // of parsing. | 1050 // of parsing. |
1051 bool treeBuilderHasBlockingScript = m_treeBuilder->hasParserBlockingScript(); | 1051 bool treeBuilderHasBlockingScript = m_treeBuilder->hasParserBlockingScript(); |
1052 bool scriptRunnerHasBlockingScript = | 1052 bool scriptRunnerHasBlockingScript = |
1053 m_scriptRunner && m_scriptRunner->hasParserBlockingScript(); | 1053 m_scriptRunner && m_scriptRunner->hasParserBlockingScript(); |
1054 // Since the parser is paused while a script runner has a blocking script, it | 1054 // Since the parser is paused while a script runner has a blocking script, it |
1055 // should never be possible to end up with both objects holding a blocking | 1055 // should never be possible to end up with both objects holding a blocking |
1056 // script. | 1056 // script. |
1057 ASSERT(!(treeBuilderHasBlockingScript && scriptRunnerHasBlockingScript)); | 1057 DCHECK(!(treeBuilderHasBlockingScript && scriptRunnerHasBlockingScript)); |
1058 // If either object has a blocking script, the parser should be paused. | 1058 // If either object has a blocking script, the parser should be paused. |
1059 return treeBuilderHasBlockingScript || scriptRunnerHasBlockingScript || | 1059 return treeBuilderHasBlockingScript || scriptRunnerHasBlockingScript || |
1060 m_reentryPermit->parserPauseFlag(); | 1060 m_reentryPermit->parserPauseFlag(); |
1061 } | 1061 } |
1062 | 1062 |
1063 void HTMLDocumentParser::resumeParsingAfterPause() { | 1063 void HTMLDocumentParser::resumeParsingAfterPause() { |
1064 ASSERT(!isExecutingScript()); | 1064 DCHECK(!isExecutingScript()); |
1065 DCHECK(!isPaused()); | 1065 DCHECK(!isPaused()); |
1066 | 1066 |
1067 checkIfBodyStylesheetAdded(); | 1067 checkIfBodyStylesheetAdded(); |
1068 if (isPaused()) | 1068 if (isPaused()) |
1069 return; | 1069 return; |
1070 | 1070 |
1071 if (m_haveBackgroundParser) { | 1071 if (m_haveBackgroundParser) { |
1072 if (m_lastChunkBeforePause) { | 1072 if (m_lastChunkBeforePause) { |
1073 validateSpeculations(std::move(m_lastChunkBeforePause)); | 1073 validateSpeculations(std::move(m_lastChunkBeforePause)); |
1074 DCHECK(!m_lastChunkBeforePause); | 1074 DCHECK(!m_lastChunkBeforePause); |
1075 pumpPendingSpeculations(); | 1075 pumpPendingSpeculations(); |
1076 } | 1076 } |
1077 return; | 1077 return; |
1078 } | 1078 } |
1079 | 1079 |
1080 m_insertionPreloadScanner.reset(); | 1080 m_insertionPreloadScanner.reset(); |
1081 if (m_tokenizer) { | 1081 if (m_tokenizer) { |
1082 pumpTokenizerIfPossible(); | 1082 pumpTokenizerIfPossible(); |
1083 } | 1083 } |
1084 endIfDelayed(); | 1084 endIfDelayed(); |
1085 } | 1085 } |
1086 | 1086 |
1087 void HTMLDocumentParser::appendCurrentInputStreamToPreloadScannerAndScan() { | 1087 void HTMLDocumentParser::appendCurrentInputStreamToPreloadScannerAndScan() { |
1088 ASSERT(m_preloadScanner); | 1088 DCHECK(m_preloadScanner); |
1089 m_preloadScanner->appendToEnd(m_input.current()); | 1089 m_preloadScanner->appendToEnd(m_input.current()); |
1090 scanAndPreload(m_preloadScanner.get()); | 1090 scanAndPreload(m_preloadScanner.get()); |
1091 } | 1091 } |
1092 | 1092 |
1093 void HTMLDocumentParser::notifyScriptLoaded(PendingScript* pendingScript) { | 1093 void HTMLDocumentParser::notifyScriptLoaded(PendingScript* pendingScript) { |
1094 ASSERT(m_scriptRunner); | 1094 DCHECK(m_scriptRunner); |
1095 ASSERT(!isExecutingScript()); | 1095 DCHECK(!isExecutingScript()); |
1096 | 1096 |
1097 if (isStopped()) { | 1097 if (isStopped()) { |
1098 return; | 1098 return; |
1099 } | 1099 } |
1100 | 1100 |
1101 if (isStopping()) { | 1101 if (isStopping()) { |
1102 attemptToRunDeferredScriptsAndEnd(); | 1102 attemptToRunDeferredScriptsAndEnd(); |
1103 return; | 1103 return; |
1104 } | 1104 } |
1105 | 1105 |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1155 ParserContentPolicy parserContentPolicy) { | 1155 ParserContentPolicy parserContentPolicy) { |
1156 HTMLDocumentParser* parser = | 1156 HTMLDocumentParser* parser = |
1157 HTMLDocumentParser::create(fragment, contextElement, parserContentPolicy); | 1157 HTMLDocumentParser::create(fragment, contextElement, parserContentPolicy); |
1158 parser->append(source); | 1158 parser->append(source); |
1159 parser->finish(); | 1159 parser->finish(); |
1160 // Allows ~DocumentParser to assert it was detached before destruction. | 1160 // Allows ~DocumentParser to assert it was detached before destruction. |
1161 parser->detach(); | 1161 parser->detach(); |
1162 } | 1162 } |
1163 | 1163 |
1164 void HTMLDocumentParser::suspendScheduledTasks() { | 1164 void HTMLDocumentParser::suspendScheduledTasks() { |
1165 ASSERT(!m_tasksWereSuspended); | 1165 DCHECK(!m_tasksWereSuspended); |
1166 m_tasksWereSuspended = true; | 1166 m_tasksWereSuspended = true; |
1167 if (m_parserScheduler) | 1167 if (m_parserScheduler) |
1168 m_parserScheduler->suspend(); | 1168 m_parserScheduler->suspend(); |
1169 } | 1169 } |
1170 | 1170 |
1171 void HTMLDocumentParser::resumeScheduledTasks() { | 1171 void HTMLDocumentParser::resumeScheduledTasks() { |
1172 ASSERT(m_tasksWereSuspended); | 1172 DCHECK(m_tasksWereSuspended); |
1173 m_tasksWereSuspended = false; | 1173 m_tasksWereSuspended = false; |
1174 if (m_parserScheduler) | 1174 if (m_parserScheduler) |
1175 m_parserScheduler->resume(); | 1175 m_parserScheduler->resume(); |
1176 } | 1176 } |
1177 | 1177 |
1178 void HTMLDocumentParser::appendBytes(const char* data, size_t length) { | 1178 void HTMLDocumentParser::appendBytes(const char* data, size_t length) { |
1179 if (!length || isStopped()) | 1179 if (!length || isStopped()) |
1180 return; | 1180 return; |
1181 | 1181 |
1182 if (shouldUseThreading()) { | 1182 if (shouldUseThreading()) { |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1220 m_loadingTaskRunner->postTask( | 1220 m_loadingTaskRunner->postTask( |
1221 BLINK_FROM_HERE, | 1221 BLINK_FROM_HERE, |
1222 WTF::bind(&BackgroundHTMLParser::flush, m_backgroundParser)); | 1222 WTF::bind(&BackgroundHTMLParser::flush, m_backgroundParser)); |
1223 } else { | 1223 } else { |
1224 DecodedDataDocumentParser::flush(); | 1224 DecodedDataDocumentParser::flush(); |
1225 } | 1225 } |
1226 } | 1226 } |
1227 | 1227 |
1228 void HTMLDocumentParser::setDecoder( | 1228 void HTMLDocumentParser::setDecoder( |
1229 std::unique_ptr<TextResourceDecoder> decoder) { | 1229 std::unique_ptr<TextResourceDecoder> decoder) { |
1230 ASSERT(decoder); | 1230 DCHECK(decoder); |
1231 DecodedDataDocumentParser::setDecoder(std::move(decoder)); | 1231 DecodedDataDocumentParser::setDecoder(std::move(decoder)); |
1232 | 1232 |
1233 if (m_haveBackgroundParser) { | 1233 if (m_haveBackgroundParser) { |
1234 m_loadingTaskRunner->postTask( | 1234 m_loadingTaskRunner->postTask( |
1235 BLINK_FROM_HERE, | 1235 BLINK_FROM_HERE, |
1236 WTF::bind(&BackgroundHTMLParser::setDecoder, m_backgroundParser, | 1236 WTF::bind(&BackgroundHTMLParser::setDecoder, m_backgroundParser, |
1237 WTF::passed(takeDecoder()))); | 1237 WTF::passed(takeDecoder()))); |
1238 } | 1238 } |
1239 } | 1239 } |
1240 | 1240 |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1320 successHistogram.count(duration); | 1320 successHistogram.count(duration); |
1321 } else { | 1321 } else { |
1322 DEFINE_STATIC_LOCAL( | 1322 DEFINE_STATIC_LOCAL( |
1323 CustomCountHistogram, failureHistogram, | 1323 CustomCountHistogram, failureHistogram, |
1324 ("PreloadScanner.DocumentWrite.ExecutionTime.Failure", 1, 10000, 50)); | 1324 ("PreloadScanner.DocumentWrite.ExecutionTime.Failure", 1, 10000, 50)); |
1325 failureHistogram.count(duration); | 1325 failureHistogram.count(duration); |
1326 } | 1326 } |
1327 } | 1327 } |
1328 | 1328 |
1329 } // namespace blink | 1329 } // namespace blink |
OLD | NEW |