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 13 matching lines...) Expand all Loading... |
24 */ | 24 */ |
25 | 25 |
26 #include "core/html/parser/HTMLParserScriptRunner.h" | 26 #include "core/html/parser/HTMLParserScriptRunner.h" |
27 | 27 |
28 #include <inttypes.h> | 28 #include <inttypes.h> |
29 #include <memory> | 29 #include <memory> |
30 #include "bindings/core/v8/Microtask.h" | 30 #include "bindings/core/v8/Microtask.h" |
31 #include "bindings/core/v8/ScriptSourceCode.h" | 31 #include "bindings/core/v8/ScriptSourceCode.h" |
32 #include "bindings/core/v8/V8BindingForCore.h" | 32 #include "bindings/core/v8/V8BindingForCore.h" |
33 #include "bindings/core/v8/V8PerIsolateData.h" | 33 #include "bindings/core/v8/V8PerIsolateData.h" |
| 34 #include "core/dom/ClassicPendingScript.h" |
34 #include "core/dom/ClassicScript.h" | 35 #include "core/dom/ClassicScript.h" |
35 #include "core/dom/DocumentParserTiming.h" | 36 #include "core/dom/DocumentParserTiming.h" |
36 #include "core/dom/Element.h" | 37 #include "core/dom/Element.h" |
37 #include "core/dom/IgnoreDestructiveWriteCountIncrementer.h" | 38 #include "core/dom/IgnoreDestructiveWriteCountIncrementer.h" |
38 #include "core/dom/ScriptLoader.h" | 39 #include "core/dom/ScriptLoader.h" |
39 #include "core/dom/TaskRunnerHelper.h" | 40 #include "core/dom/TaskRunnerHelper.h" |
40 #include "core/events/Event.h" | 41 #include "core/events/Event.h" |
41 #include "core/frame/LocalFrame.h" | 42 #include "core/frame/LocalFrame.h" |
42 #include "core/html/parser/HTMLInputStream.h" | 43 #include "core/html/parser/HTMLInputStream.h" |
43 #include "core/html/parser/HTMLParserScriptRunnerHost.h" | 44 #include "core/html/parser/HTMLParserScriptRunnerHost.h" |
44 #include "core/html/parser/NestingLevelIncrementer.h" | 45 #include "core/html/parser/NestingLevelIncrementer.h" |
45 #include "core/inspector/ConsoleMessage.h" | 46 #include "core/inspector/ConsoleMessage.h" |
46 #include "core/loader/resource/ScriptResource.h" | 47 #include "core/loader/resource/ScriptResource.h" |
47 #include "platform/Histogram.h" | 48 #include "platform/Histogram.h" |
48 #include "platform/WebFrameScheduler.h" | 49 #include "platform/WebFrameScheduler.h" |
49 #include "platform/instrumentation/tracing/TraceEvent.h" | 50 #include "platform/instrumentation/tracing/TraceEvent.h" |
50 #include "platform/instrumentation/tracing/TracedValue.h" | 51 #include "platform/instrumentation/tracing/TracedValue.h" |
51 #include "platform/loader/fetch/MemoryCache.h" | |
52 #include "public/platform/Platform.h" | 52 #include "public/platform/Platform.h" |
53 | 53 |
54 namespace blink { | 54 namespace blink { |
55 | 55 |
56 namespace { | 56 namespace { |
57 | 57 |
58 // TODO(bmcquade): move this to a shared location if we find ourselves wanting | 58 // TODO(bmcquade): move this to a shared location if we find ourselves wanting |
59 // to trace similar data elsewhere in the codebase. | 59 // to trace similar data elsewhere in the codebase. |
60 std::unique_ptr<TracedValue> GetTraceArgsForScriptElement( | 60 std::unique_ptr<TracedValue> GetTraceArgsForScriptElement( |
61 ScriptElementBase* element, | 61 ScriptElementBase* element, |
(...skipping 266 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
328 | 328 |
329 if (ParserBlockingScript() != pending_script) | 329 if (ParserBlockingScript() != pending_script) |
330 return; | 330 return; |
331 | 331 |
332 ScriptElementBase* element = ParserBlockingScript()->GetElement(); | 332 ScriptElementBase* element = ParserBlockingScript()->GetElement(); |
333 | 333 |
334 ScriptLoader* script_loader = element->Loader(); | 334 ScriptLoader* script_loader = element->Loader(); |
335 if (!script_loader || !script_loader->DisallowedFetchForDocWrittenScript()) | 335 if (!script_loader || !script_loader->DisallowedFetchForDocWrittenScript()) |
336 return; | 336 return; |
337 | 337 |
| 338 // We don't allow document.write() and its intervention with module scripts. |
| 339 CHECK_EQ(pending_script->GetScriptType(), ScriptType::kClassic); |
| 340 |
338 if (!pending_script->ErrorOccurred()) { | 341 if (!pending_script->ErrorOccurred()) { |
339 EmitWarningForDocWriteScripts( | 342 EmitWarningForDocWriteScripts(pending_script->Url().GetString(), |
340 pending_script->GetResource()->Url().GetString(), *document_); | 343 *document_); |
341 return; | 344 return; |
342 } | 345 } |
343 | 346 |
344 // Due to dependency violation, not able to check the exact error to be | 347 // Due to dependency violation, not able to check the exact error to be |
345 // ERR_CACHE_MISS but other errors are rare with | 348 // ERR_CACHE_MISS but other errors are rare with |
346 // WebCachePolicy::ReturnCacheDataDontLoad. | 349 // WebCachePolicy::ReturnCacheDataDontLoad. |
347 | 350 |
348 EmitErrorForDocWriteScripts(pending_script->GetResource()->Url().GetString(), | 351 EmitErrorForDocWriteScripts(pending_script->Url().GetString(), *document_); |
349 *document_); | |
350 TextPosition starting_position = ParserBlockingScript()->StartingPosition(); | 352 TextPosition starting_position = ParserBlockingScript()->StartingPosition(); |
351 bool is_parser_inserted = script_loader->IsParserInserted(); | 353 bool is_parser_inserted = script_loader->IsParserInserted(); |
352 // Remove this resource entry from memory cache as the new request | 354 // Remove this resource entry from memory cache as the new request |
353 // should not join onto this existing entry. | 355 // should not join onto this existing entry. |
354 GetMemoryCache()->Remove(pending_script->GetResource()); | 356 pending_script->RemoveFromMemoryCache(); |
355 FetchBlockedDocWriteScript(element, is_parser_inserted, starting_position); | 357 FetchBlockedDocWriteScript(element, is_parser_inserted, starting_position); |
356 } | 358 } |
357 | 359 |
358 void HTMLParserScriptRunner::PendingScriptFinished( | 360 void HTMLParserScriptRunner::PendingScriptFinished( |
359 PendingScript* pending_script) { | 361 PendingScript* pending_script) { |
360 // Handle cancellations of parser-blocking script loads without | 362 // Handle cancellations of parser-blocking script loads without |
361 // notifying the host (i.e., parser) if these were initiated by nested | 363 // notifying the host (i.e., parser) if these were initiated by nested |
362 // document.write()s. The cancellation may have been triggered by | 364 // document.write()s. The cancellation may have been triggered by |
363 // script execution to signal an abrupt stop (e.g., window.close().) | 365 // script execution to signal an abrupt stop (e.g., window.close().) |
364 // | 366 // |
365 // The parser is unprepared to be told, and doesn't need to be. | 367 // The parser is unprepared to be told, and doesn't need to be. |
366 if (IsExecutingScript() && pending_script->GetResource()->WasCanceled()) { | 368 if (IsExecutingScript() && pending_script->WasCanceled()) { |
367 pending_script->Dispose(); | 369 pending_script->Dispose(); |
368 | 370 |
369 if (pending_script == ParserBlockingScript()) { | 371 if (pending_script == ParserBlockingScript()) { |
370 parser_blocking_script_ = nullptr; | 372 parser_blocking_script_ = nullptr; |
371 } else { | 373 } else { |
372 CHECK_EQ(pending_script, scripts_to_execute_after_parsing_.front()); | 374 CHECK_EQ(pending_script, scripts_to_execute_after_parsing_.front()); |
373 | 375 |
374 // TODO(hiroshige): Remove this CHECK() before going to beta. | 376 // TODO(hiroshige): Remove this CHECK() before going to beta. |
375 // This is only to make clusterfuzz to find a test case that executes | 377 // This is only to make clusterfuzz to find a test case that executes |
376 // this code path. | 378 // this code path. |
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
498 // Step 3 of https://html.spec.whatwg.org/#the-end: | 500 // Step 3 of https://html.spec.whatwg.org/#the-end: |
499 // "If the list of scripts that will execute when the document has | 501 // "If the list of scripts that will execute when the document has |
500 // finished parsing is not empty, run these substeps:" | 502 // finished parsing is not empty, run these substeps:" |
501 bool HTMLParserScriptRunner::ExecuteScriptsWaitingForParsing() { | 503 bool HTMLParserScriptRunner::ExecuteScriptsWaitingForParsing() { |
502 TRACE_EVENT0("blink", | 504 TRACE_EVENT0("blink", |
503 "HTMLParserScriptRunner::executeScriptsWaitingForParsing"); | 505 "HTMLParserScriptRunner::executeScriptsWaitingForParsing"); |
504 | 506 |
505 while (!scripts_to_execute_after_parsing_.IsEmpty()) { | 507 while (!scripts_to_execute_after_parsing_.IsEmpty()) { |
506 DCHECK(!IsExecutingScript()); | 508 DCHECK(!IsExecutingScript()); |
507 DCHECK(!HasParserBlockingScript()); | 509 DCHECK(!HasParserBlockingScript()); |
508 DCHECK(scripts_to_execute_after_parsing_.front()->GetResource()); | 510 DCHECK(scripts_to_execute_after_parsing_.front()->IsExternal()); |
509 | 511 |
510 // 1. "Spin the event loop until the first script in the list of scripts | 512 // 1. "Spin the event loop until the first script in the list of scripts |
511 // that will execute when the document has finished parsing | 513 // that will execute when the document has finished parsing |
512 // has its "ready to be parser-executed" flag set and | 514 // has its "ready to be parser-executed" flag set and |
513 // the parser's Document has no style sheet that is blocking scripts." | 515 // the parser's Document has no style sheet that is blocking scripts." |
514 // TODO(hiroshige): Is the latter part checked anywhere? | 516 // TODO(hiroshige): Is the latter part checked anywhere? |
515 if (!scripts_to_execute_after_parsing_.front()->IsReady()) { | 517 if (!scripts_to_execute_after_parsing_.front()->IsReady()) { |
516 scripts_to_execute_after_parsing_.front()->WatchForLoad(this); | 518 scripts_to_execute_after_parsing_.front()->WatchForLoad(this); |
517 TraceParserBlockingScript(scripts_to_execute_after_parsing_.front().Get(), | 519 TraceParserBlockingScript(scripts_to_execute_after_parsing_.front().Get(), |
518 !document_->IsScriptExecutionReady()); | 520 !document_->IsScriptExecutionReady()); |
(...skipping 25 matching lines...) Expand all Loading... |
544 // 2nd Clause, Step 23 of https://html.spec.whatwg.org/#prepare-a-script | 546 // 2nd Clause, Step 23 of https://html.spec.whatwg.org/#prepare-a-script |
545 void HTMLParserScriptRunner::RequestParsingBlockingScript(Element* element) { | 547 void HTMLParserScriptRunner::RequestParsingBlockingScript(Element* element) { |
546 // "The element is the pending parsing-blocking script of the Document of | 548 // "The element is the pending parsing-blocking script of the Document of |
547 // the parser that created the element. | 549 // the parser that created the element. |
548 // (There can only be one such script per Document at a time.)" | 550 // (There can only be one such script per Document at a time.)" |
549 CHECK(!ParserBlockingScript()); | 551 CHECK(!ParserBlockingScript()); |
550 parser_blocking_script_ = RequestPendingScript(element); | 552 parser_blocking_script_ = RequestPendingScript(element); |
551 if (!ParserBlockingScript()) | 553 if (!ParserBlockingScript()) |
552 return; | 554 return; |
553 | 555 |
554 DCHECK(ParserBlockingScript()->GetResource()); | 556 DCHECK(ParserBlockingScript()->IsExternal()); |
555 | 557 |
556 // We only care about a load callback if resource is not already in the cache. | 558 // We only care about a load callback if resource is not already in the cache. |
557 // Callers will attempt to run the m_parserBlockingScript if possible before | 559 // Callers will attempt to run the m_parserBlockingScript if possible before |
558 // returning control to the parser. | 560 // returning control to the parser. |
559 if (!ParserBlockingScript()->IsReady()) { | 561 if (!ParserBlockingScript()->IsReady()) { |
560 parser_blocking_script_->StartStreamingIfPossible( | 562 parser_blocking_script_->StartStreamingIfPossible( |
561 document_, ScriptStreamer::kParsingBlocking); | 563 document_, ScriptStreamer::kParsingBlocking); |
562 parser_blocking_script_->WatchForLoad(this); | 564 parser_blocking_script_->WatchForLoad(this); |
563 } | 565 } |
564 } | 566 } |
565 | 567 |
566 // 1st Clause, Step 23 of https://html.spec.whatwg.org/#prepare-a-script | 568 // 1st Clause, Step 23 of https://html.spec.whatwg.org/#prepare-a-script |
567 void HTMLParserScriptRunner::RequestDeferredScript(Element* element) { | 569 void HTMLParserScriptRunner::RequestDeferredScript(Element* element) { |
568 PendingScript* pending_script = RequestPendingScript(element); | 570 PendingScript* pending_script = RequestPendingScript(element); |
569 if (!pending_script) | 571 if (!pending_script) |
570 return; | 572 return; |
571 | 573 |
572 if (!pending_script->IsReady()) { | 574 if (!pending_script->IsReady()) { |
573 pending_script->StartStreamingIfPossible(document_, | 575 pending_script->StartStreamingIfPossible(document_, |
574 ScriptStreamer::kDeferred); | 576 ScriptStreamer::kDeferred); |
575 } | 577 } |
576 | 578 |
577 DCHECK(pending_script->GetResource()); | 579 DCHECK(pending_script->IsExternal()); |
578 | 580 |
579 // "Add the element to the end of the list of scripts that will execute | 581 // "Add the element to the end of the list of scripts that will execute |
580 // when the document has finished parsing associated with the Document | 582 // when the document has finished parsing associated with the Document |
581 // of the parser that created the element." | 583 // of the parser that created the element." |
582 scripts_to_execute_after_parsing_.push_back(pending_script); | 584 scripts_to_execute_after_parsing_.push_back(pending_script); |
583 } | 585 } |
584 | 586 |
585 PendingScript* HTMLParserScriptRunner::RequestPendingScript( | 587 PendingScript* HTMLParserScriptRunner::RequestPendingScript( |
586 Element* element) const { | 588 Element* element) const { |
587 ScriptElementBase* script_element = | 589 ScriptElementBase* script_element = |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
637 } else if (script_loader->ReadyToBeParserExecuted()) { | 639 } else if (script_loader->ReadyToBeParserExecuted()) { |
638 // 5th Clause of Step 23. | 640 // 5th Clause of Step 23. |
639 // "If ... it's an HTML parser | 641 // "If ... it's an HTML parser |
640 // whose script nesting level is not greater than one" | 642 // whose script nesting level is not greater than one" |
641 if (reentry_permit_->ScriptNestingLevel() == 1u) { | 643 if (reentry_permit_->ScriptNestingLevel() == 1u) { |
642 // "The element is the pending parsing-blocking script of the | 644 // "The element is the pending parsing-blocking script of the |
643 // Document of the parser that created the element. | 645 // Document of the parser that created the element. |
644 // (There can only be one such script per Document at a time.)" | 646 // (There can only be one such script per Document at a time.)" |
645 CHECK(!parser_blocking_script_); | 647 CHECK(!parser_blocking_script_); |
646 parser_blocking_script_ = | 648 parser_blocking_script_ = |
647 PendingScript::Create(element, script_start_position); | 649 ClassicPendingScript::Create(element, script_start_position); |
648 } else { | 650 } else { |
649 // 6th Clause of Step 23. | 651 // 6th Clause of Step 23. |
650 // "Immediately execute the script block, | 652 // "Immediately execute the script block, |
651 // even if other scripts are already executing." | 653 // even if other scripts are already executing." |
652 // TODO(hiroshige): Merge the block into ScriptLoader::prepareScript(). | 654 // TODO(hiroshige): Merge the block into ScriptLoader::prepareScript(). |
653 DCHECK_GT(reentry_permit_->ScriptNestingLevel(), 1u); | 655 DCHECK_GT(reentry_permit_->ScriptNestingLevel(), 1u); |
654 if (parser_blocking_script_) | 656 if (parser_blocking_script_) |
655 parser_blocking_script_->Dispose(); | 657 parser_blocking_script_->Dispose(); |
656 parser_blocking_script_ = nullptr; | 658 parser_blocking_script_ = nullptr; |
657 ScriptSourceCode source_code(script->textContent(), | 659 ScriptSourceCode source_code(script->textContent(), |
(...skipping 19 matching lines...) Expand all Loading... |
677 | 679 |
678 DEFINE_TRACE(HTMLParserScriptRunner) { | 680 DEFINE_TRACE(HTMLParserScriptRunner) { |
679 visitor->Trace(document_); | 681 visitor->Trace(document_); |
680 visitor->Trace(host_); | 682 visitor->Trace(host_); |
681 visitor->Trace(parser_blocking_script_); | 683 visitor->Trace(parser_blocking_script_); |
682 visitor->Trace(scripts_to_execute_after_parsing_); | 684 visitor->Trace(scripts_to_execute_after_parsing_); |
683 PendingScriptClient::Trace(visitor); | 685 PendingScriptClient::Trace(visitor); |
684 } | 686 } |
685 | 687 |
686 } // namespace blink | 688 } // namespace blink |
OLD | NEW |