Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(141)

Side by Side Diff: third_party/WebKit/Source/core/dom/ScriptLoader.cpp

Issue 2555653002: [WIP Prototype] ES6 https://html.spec.whatwg.org/#fetch-a-single-module-script implementation (Closed)
Patch Set: rebased Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) 2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3 * (C) 1999 Antti Koivisto (koivisto@kde.org) 3 * (C) 1999 Antti Koivisto (koivisto@kde.org)
4 * (C) 2001 Dirk Mueller (mueller@kde.org) 4 * (C) 2001 Dirk Mueller (mueller@kde.org)
5 * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights 5 * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights
6 * reserved. 6 * reserved.
7 * Copyright (C) 2008 Nikolas Zimmermann <zimmermann@kde.org> 7 * Copyright (C) 2008 Nikolas Zimmermann <zimmermann@kde.org>
8 * 8 *
9 * This library is free software; you can redistribute it and/or 9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Library General Public 10 * modify it under the terms of the GNU Library General Public
(...skipping 11 matching lines...) Expand all
22 * Boston, MA 02110-1301, USA. 22 * Boston, MA 02110-1301, USA.
23 */ 23 */
24 24
25 #include "core/dom/ScriptLoader.h" 25 #include "core/dom/ScriptLoader.h"
26 26
27 #include "bindings/core/v8/ScriptController.h" 27 #include "bindings/core/v8/ScriptController.h"
28 #include "bindings/core/v8/ScriptSourceCode.h" 28 #include "bindings/core/v8/ScriptSourceCode.h"
29 #include "bindings/core/v8/V8Binding.h" 29 #include "bindings/core/v8/V8Binding.h"
30 #include "core/HTMLNames.h" 30 #include "core/HTMLNames.h"
31 #include "core/SVGNames.h" 31 #include "core/SVGNames.h"
32 #include "core/dom/ClassicPendingScript.h"
32 #include "core/dom/ClassicScript.h" 33 #include "core/dom/ClassicScript.h"
33 #include "core/dom/Document.h" 34 #include "core/dom/Document.h"
34 #include "core/dom/DocumentParserTiming.h" 35 #include "core/dom/DocumentParserTiming.h"
35 #include "core/dom/IgnoreDestructiveWriteCountIncrementer.h" 36 #include "core/dom/IgnoreDestructiveWriteCountIncrementer.h"
37 #include "core/dom/Modulator.h"
38 #include "core/dom/ModulePendingScript.h"
36 #include "core/dom/Script.h" 39 #include "core/dom/Script.h"
37 #include "core/dom/ScriptElementBase.h" 40 #include "core/dom/ScriptElementBase.h"
38 #include "core/dom/ScriptRunner.h" 41 #include "core/dom/ScriptRunner.h"
39 #include "core/dom/ScriptableDocumentParser.h" 42 #include "core/dom/ScriptableDocumentParser.h"
40 #include "core/dom/Text.h" 43 #include "core/dom/Text.h"
41 #include "core/events/Event.h" 44 #include "core/events/Event.h"
42 #include "core/frame/LocalFrame.h" 45 #include "core/frame/LocalFrame.h"
43 #include "core/frame/SubresourceIntegrity.h" 46 #include "core/frame/SubresourceIntegrity.h"
44 #include "core/frame/csp/ContentSecurityPolicy.h" 47 #include "core/frame/csp/ContentSecurityPolicy.h"
45 #include "core/html/imports/HTMLImport.h" 48 #include "core/html/imports/HTMLImport.h"
46 #include "core/html/parser/HTMLParserIdioms.h" 49 #include "core/html/parser/HTMLParserIdioms.h"
50 #include "core/loader/modulescript/ModuleScriptFetchRequest.h"
47 #include "core/loader/resource/ScriptResource.h" 51 #include "core/loader/resource/ScriptResource.h"
48 #include "platform/WebFrameScheduler.h" 52 #include "platform/WebFrameScheduler.h"
49 #include "platform/loader/fetch/AccessControlStatus.h" 53 #include "platform/loader/fetch/AccessControlStatus.h"
50 #include "platform/loader/fetch/FetchParameters.h" 54 #include "platform/loader/fetch/FetchParameters.h"
51 #include "platform/loader/fetch/MemoryCache.h"
52 #include "platform/loader/fetch/ResourceFetcher.h" 55 #include "platform/loader/fetch/ResourceFetcher.h"
53 #include "platform/network/mime/MIMETypeRegistry.h" 56 #include "platform/network/mime/MIMETypeRegistry.h"
54 #include "platform/weborigin/SecurityOrigin.h" 57 #include "platform/weborigin/SecurityOrigin.h"
55 #include "platform/wtf/StdLibExtras.h" 58 #include "platform/wtf/StdLibExtras.h"
56 #include "platform/wtf/text/StringBuilder.h" 59 #include "platform/wtf/text/StringBuilder.h"
57 #include "platform/wtf/text/StringHash.h" 60 #include "platform/wtf/text/StringHash.h"
58 #include "public/platform/WebCachePolicy.h" 61 #include "public/platform/WebCachePolicy.h"
59 62
60 namespace blink { 63 namespace blink {
61 64
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
100 element_->GetDocument().GetScriptableDocumentParser()->LineNumber(); 103 element_->GetDocument().GetScriptableDocumentParser()->LineNumber();
101 } 104 }
102 } 105 }
103 106
104 ScriptLoader::~ScriptLoader() {} 107 ScriptLoader::~ScriptLoader() {}
105 108
106 DEFINE_TRACE(ScriptLoader) { 109 DEFINE_TRACE(ScriptLoader) {
107 visitor->Trace(element_); 110 visitor->Trace(element_);
108 visitor->Trace(resource_); 111 visitor->Trace(resource_);
109 visitor->Trace(pending_script_); 112 visitor->Trace(pending_script_);
113 visitor->Trace(module_tree_client_);
110 PendingScriptClient::Trace(visitor); 114 PendingScriptClient::Trace(visitor);
111 } 115 }
112 116
113 void ScriptLoader::SetFetchDocWrittenScriptDeferIdle() { 117 void ScriptLoader::SetFetchDocWrittenScriptDeferIdle() {
114 DCHECK(!created_during_document_write_); 118 DCHECK(!created_during_document_write_);
115 document_write_intervention_ = 119 document_write_intervention_ =
116 DocumentWriteIntervention::kFetchDocWrittenScriptDeferIdle; 120 DocumentWriteIntervention::kFetchDocWrittenScriptDeferIdle;
117 } 121 }
118 122
119 void ScriptLoader::DidNotifySubtreeInsertionsToDocument() { 123 void ScriptLoader::DidNotifySubtreeInsertionsToDocument() {
(...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after
302 if (!IsScriptForEventSupported()) 306 if (!IsScriptForEventSupported())
303 return false; 307 return false;
304 308
305 // 14. is handled below. 309 // 14. is handled below.
306 310
307 // 15. "Let CORS setting be the current state of the element's 311 // 15. "Let CORS setting be the current state of the element's
308 // crossorigin content attribute." 312 // crossorigin content attribute."
309 CrossOriginAttributeValue cross_origin = 313 CrossOriginAttributeValue cross_origin =
310 GetCrossOriginAttributeValue(element_->CrossOriginAttributeValue()); 314 GetCrossOriginAttributeValue(element_->CrossOriginAttributeValue());
311 315
312 // 16. will be handled below once module script support is implemented. 316 // 16. is handled below.
313 317
314 // 17. "If the script element has a nonce attribute, 318 // 17. "If the script element has a nonce attribute,
315 // then let cryptographic nonce be that attribute's value. 319 // then let cryptographic nonce be that attribute's value.
316 // Otherwise, let cryptographic nonce be the empty string." 320 // Otherwise, let cryptographic nonce be the empty string."
317 String nonce; 321 String nonce;
318 if (element_->IsNonceableElement()) 322 if (element_->IsNonceableElement())
319 nonce = element_->nonce(); 323 nonce = element_->nonce();
320 324
321 // 18. is handled below. 325 // 18. is handled below.
322 326
(...skipping 15 matching lines...) Expand all
338 // TODO(hiroshige): Make this asynchronous. Currently we fire the error 342 // TODO(hiroshige): Make this asynchronous. Currently we fire the error
339 // event synchronously to keep the existing behavior. 343 // event synchronously to keep the existing behavior.
340 DispatchErrorEvent(); 344 DispatchErrorEvent();
341 return false; 345 return false;
342 } 346 }
343 347
344 // 21.3. "Set the element's from an external file flag." 348 // 21.3. "Set the element's from an external file flag."
345 is_external_script_ = true; 349 is_external_script_ = true;
346 350
347 // 21.4. "Parse src relative to the element's node document." 351 // 21.4. "Parse src relative to the element's node document."
348 // TODO(hiroshige): Use CompleteURL(src) instead. 352 KURL url = element_document.CompleteURL(src);
349 KURL url = element_document.CompleteURL(element_->SourceAttributeValue());
350 353
351 // 21.5. "If the previous step failed, queue a task to 354 // 21.5. "If the previous step failed, queue a task to
352 // fire an event named error at the element, and abort these steps." 355 // fire an event named error at the element, and abort these steps."
353 if (!url.IsValid()) { 356 if (!url.IsValid()) {
354 // TODO(hiroshige): Make this asynchronous. Currently we fire the error 357 // TODO(hiroshige): Make this asynchronous. Currently we fire the error
355 // event synchronously to keep the existing behavior. 358 // event synchronously to keep the existing behavior.
356 DispatchErrorEvent(); 359 DispatchErrorEvent();
357 return false; 360 return false;
358 } 361 }
359 362
360 DCHECK(!resource_); 363 DCHECK(!resource_);
364 DCHECK(!module_tree_client_);
361 365
362 // 21.6. "Switch on the script's type:" 366 // 21.6. "Switch on the script's type:"
363 // - "classic": 367 if (GetScriptType() == ScriptType::kClassic) {
368 // - "classic":
364 369
365 // 14. "If the script element has a charset attribute, 370 // 14. "If the script element has a charset attribute,
366 // then let encoding be the result of 371 // then let encoding be the result of
367 // getting an encoding from the value of the charset attribute." 372 // getting an encoding from the value of the charset attribute."
368 // "If the script element does not have a charset attribute, 373 // "If the script element does not have a charset attribute,
369 // or if getting an encoding failed, let encoding 374 // or if getting an encoding failed, let encoding
370 // be the same as the encoding of the script element's node 375 // be the same as the encoding of the script element's node
371 // document." 376 // document."
372 // TODO(hiroshige): Should we handle failure in getting an encoding? 377 // TODO(hiroshige): Should we handle failure in getting an encoding?
373 String encoding; 378 String encoding;
374 if (!element_->CharsetAttributeValue().IsEmpty()) 379 if (!element_->CharsetAttributeValue().IsEmpty())
375 encoding = element_->CharsetAttributeValue(); 380 encoding = element_->CharsetAttributeValue();
376 else 381 else
377 encoding = element_document.characterSet(); 382 encoding = element_document.characterSet();
378 383
379 // Step 16 is skipped because "module script credentials" is not used 384 // Step 16 is skipped because "module script credentials" is not used
380 // for classic scripts. 385 // for classic scripts.
381 386
382 // 18. "If the script element has an integrity attribute, 387 // 18. "If the script element has an integrity attribute,
383 // then let integrity metadata be that attribute's value. 388 // then let integrity metadata be that attribute's value.
384 // Otherwise, let integrity metadata be the empty string." 389 // Otherwise, let integrity metadata be the empty string."
385 String integrity_attr = element_->IntegrityAttributeValue(); 390 String integrity_attr = element_->IntegrityAttributeValue();
386 IntegrityMetadataSet integrity_metadata; 391 IntegrityMetadataSet integrity_metadata;
387 if (!integrity_attr.IsEmpty()) { 392 if (!integrity_attr.IsEmpty()) {
388 SubresourceIntegrity::ParseIntegrityAttribute( 393 SubresourceIntegrity::ParseIntegrityAttribute(
389 integrity_attr, integrity_metadata, &element_document); 394 integrity_attr, integrity_metadata, &element_document);
395 }
396
397 if (!FetchClassicScript(url, element_document.Fetcher(), nonce,
398 integrity_metadata, parser_state, cross_origin,
399 element_document.GetSecurityOrigin(), encoding)) {
400 // TODO(hiroshige): Make this asynchronous. Currently we fire the error
401 // event synchronously to keep the existing behavior.
402 DispatchErrorEvent();
403 return false;
404 }
405
406 DCHECK(resource_);
407 DCHECK(!module_tree_client_);
408 } else {
409 // - "module":
410
411 // Steps 14 and 18 are skipped because they are not used in module
412 // scripts.
413
414 // 16. "Let module script credentials mode be determined by switching
415 // on CORS setting:"
416 WebURLRequest::FetchCredentialsMode credentials_mode =
417 WebURLRequest::kFetchCredentialsModeOmit;
418 switch (cross_origin) {
419 case kCrossOriginAttributeNotSet:
420 credentials_mode = WebURLRequest::kFetchCredentialsModeOmit;
421 break;
422 case kCrossOriginAttributeAnonymous:
423 credentials_mode = WebURLRequest::kFetchCredentialsModeSameOrigin;
424 break;
425 case kCrossOriginAttributeUseCredentials:
426 credentials_mode = WebURLRequest::kFetchCredentialsModeInclude;
427 break;
428 }
429
430 DCHECK(RuntimeEnabledFeatures::moduleScriptsEnabled());
431 Modulator* modulator = Modulator::From(
432 ToScriptStateForMainWorld(element_document.GetFrame()));
433 FetchModuleScriptTree(url, modulator, nonce, parser_state,
434 credentials_mode);
435
436 DCHECK(!resource_);
437 DCHECK(module_tree_client_);
390 } 438 }
391 439
392 if (!FetchClassicScript(url, element_document.Fetcher(), nonce,
393 integrity_metadata, parser_state, cross_origin,
394 element_document.GetSecurityOrigin(), encoding)) {
395 // TODO(hiroshige): Make this asynchronous. Currently we fire the error
396 // event synchronously to keep the existing behavior.
397 DispatchErrorEvent();
398 return false;
399 }
400
401 DCHECK(resource_);
402
403 // - "module":
404 // TODO(hiroshige): Implement this.
405
406 // "When the chosen algorithm asynchronously completes, set 440 // "When the chosen algorithm asynchronously completes, set
407 // the script's script to the result. At that time, the script is ready." 441 // the script's script to the result. At that time, the script is ready."
408 // When the script is ready, PendingScriptClient::pendingScriptFinished() 442 // When the script is ready, PendingScriptClient::pendingScriptFinished()
409 // is used as the notification, and the action to take when 443 // is used as the notification, and the action to take when
410 // the script is ready is specified later, in 444 // the script is ready is specified later, in
411 // - ScriptLoader::PrepareScript(), or 445 // - ScriptLoader::PrepareScript(), or
412 // - HTMLParserScriptRunner, 446 // - HTMLParserScriptRunner,
413 // depending on the conditions in Step 23 of "prepare a script". 447 // depending on the conditions in Step 23 of "prepare a script".
414 } 448 }
415 449
416 // 22. "If the element does not have a src content attribute, 450 // 22. "If the element does not have a src content attribute,
417 // run these substeps:" 451 // run these substeps:"
452 if (!element_->HasSourceAttribute()) {
453 // 22.1. "Let source text be the value of the text IDL attribute."
454 // This step is done later:
455 // - in ScriptLoader::pendingScript() (Step 23, 6th Clause),
456 // as Element::textFromChildren() in ScriptLoader::scriptContent(),
457 // - in HTMLParserScriptRunner::processScriptElementInternal()
458 // (Duplicated code of Step 23, 6th Clause),
459 // as Element::textContent(),
460 // - in XMLDocumentParser::endElementNs() (Step 23, 5th Clause),
461 // as Element::textFromChildren() in ScriptLoader::scriptContent(),
462 // - PendingScript::getSource() (Indirectly used via
463 // HTMLParserScriptRunner::processScriptElementInternal(),
464 // Step 23, 5th Clause),
465 // as Element::textContent().
466 // TODO(hiroshige): Make them merged or consistent.
418 467
419 // 22.1. "Let source text be the value of the text IDL attribute." 468 // 22.2. "Switch on the script's type:"
420 // This step is done later: 469 switch (GetScriptType()) {
421 // - in ScriptLoader::pendingScript() (Step 23, 6th Clause), 470 // - "classic":
422 // as Element::textFromChildren() in ScriptLoader::scriptContent(), 471 case ScriptType::kClassic:
423 // - in HTMLParserScriptRunner::processScriptElementInternal() 472 // TODO(hiroshige): Clarify how Step 22.2 is implemented for "classic".
424 // (Duplicated code of Step 23, 6th Clause), 473 break;
425 // as Element::textContent(),
426 // - in XMLDocumentParser::endElementNs() (Step 23, 5th Clause),
427 // as Element::textFromChildren() in ScriptLoader::scriptContent(),
428 // - PendingScript::getSource() (Indirectly used via
429 // HTMLParserScriptRunner::processScriptElementInternal(),
430 // Step 23, 5th Clause),
431 // as Element::textContent().
432 // TODO(hiroshige): Make them merged or consistent.
433 474
434 // 22.2. "Switch on the script's type:" 475 // - "module":
435 // TODO(hiroshige): Clarify how Step 22.2 is implemented for "classic". 476 case ScriptType::kModule:
436 // TODO(hiroshige): Implement Step 22.2 for "module". 477 // Inline module scripts are not yet supported.
478 // FOXME: (how) should we handle this? Should we fail more gracefully?
479 fprintf(
480 stderr,
481 "Inline module script is not yet supported (Document URL: %s)\n",
482 element_document.Url().GetString().Utf8().Data());
483 CHECK(false);
484 break;
485 }
486 }
437 487
438 // [Intervention] 488 // [Intervention]
439 // Since the asynchronous, low priority fetch for doc.written blocked 489 // Since the asynchronous, low priority fetch for doc.written blocked
440 // script is not for execution, return early from here. Watch for its 490 // script is not for execution, return early from here. Watch for its
441 // completion to be able to remove it from the memory cache. 491 // completion to be able to remove it from the memory cache.
442 if (document_write_intervention_ == 492 if (GetScriptType() == ScriptType::kClassic &&
443 DocumentWriteIntervention::kFetchDocWrittenScriptDeferIdle) { 493 document_write_intervention_ ==
494 DocumentWriteIntervention::kFetchDocWrittenScriptDeferIdle) {
444 pending_script_ = CreatePendingScript(); 495 pending_script_ = CreatePendingScript();
445 pending_script_->WatchForLoad(this); 496 pending_script_->WatchForLoad(this);
446 return true; 497 return true;
447 } 498 }
448 499
449 // 23. "Then, follow the first of the following options that describes the 500 // 23. "Then, follow the first of the following options that describes the
450 // situation:" 501 // situation:"
451 502
452 // Three flags are used to instruct the caller of prepareScript() to execute 503 // Three flags are used to instruct the caller of prepareScript() to execute
453 // a part of Step 23, when |m_willBeParserExecuted| is true: 504 // a part of Step 23, when |m_willBeParserExecuted| is true:
454 // - |m_willBeParserExecuted| 505 // - |m_willBeParserExecuted|
455 // - |m_willExecuteWhenDocumentFinishedParsing| 506 // - |m_willExecuteWhenDocumentFinishedParsing|
456 // - |m_readyToBeParserExecuted| 507 // - |m_readyToBeParserExecuted|
457 // TODO(hiroshige): Clean up the dependency. 508 // TODO(hiroshige): Clean up the dependency.
458 509
459 // 1st Clause: 510 // 1st Clause:
460 // - "If the script's type is "classic", and 511 // - "If the script's type is "classic", and
461 // the element has a src attribute, and the element has a defer attribute, 512 // the element has a src attribute, and the element has a defer attribute,
462 // and the element has been flagged as "parser-inserted", 513 // and the element has been flagged as "parser-inserted",
463 // and the element does not have an async attribute" 514 // and the element does not have an async attribute"
464 // TODO(hiroshige): Check the script's type and implement "module" case. 515 // - "If the script's type is "module",
465 if (element_->HasSourceAttribute() && element_->DeferAttributeValue() && 516 // and the element has been flagged as "parser-inserted",
466 parser_inserted_ && !element_->AsyncAttributeValue()) { 517 // and the element does not have an async attribute"
518 if ((GetScriptType() == ScriptType::kClassic &&
519 element_->HasSourceAttribute() && element_->DeferAttributeValue() &&
520 parser_inserted_ && !element_->AsyncAttributeValue()) ||
521 (GetScriptType() == ScriptType::kModule && parser_inserted_ &&
522 !element_->AsyncAttributeValue())) {
467 // This clause is implemented by the caller-side of prepareScript(): 523 // This clause is implemented by the caller-side of prepareScript():
468 // - HTMLParserScriptRunner::requestDeferredScript(), and 524 // - HTMLParserScriptRunner::requestDeferredScript(), and
469 // - TODO(hiroshige): Investigate XMLDocumentParser::endElementNs() 525 // - TODO(hiroshige): Investigate XMLDocumentParser::endElementNs()
470 will_execute_when_document_finished_parsing_ = true; 526 will_execute_when_document_finished_parsing_ = true;
471 will_be_parser_executed_ = true; 527 will_be_parser_executed_ = true;
472 528
473 return true; 529 return true;
474 } 530 }
475 531
476 // 2nd Clause: 532 // 2nd Clause:
477 // - "If the script's type is "classic", 533 // - "If the script's type is "classic",
478 // and the element has a src attribute, 534 // and the element has a src attribute,
479 // and the element has been flagged as "parser-inserted", 535 // and the element has been flagged as "parser-inserted",
480 // and the element does not have an async attribute" 536 // and the element does not have an async attribute"
481 // TODO(hiroshige): Check the script's type. 537 // TODO(hiroshige): Check the script's type.
482 if (element_->HasSourceAttribute() && parser_inserted_ && 538 if (GetScriptType() == ScriptType::kClassic &&
539 element_->HasSourceAttribute() && parser_inserted_ &&
483 !element_->AsyncAttributeValue()) { 540 !element_->AsyncAttributeValue()) {
484 // This clause is implemented by the caller-side of prepareScript(): 541 // This clause is implemented by the caller-side of prepareScript():
485 // - HTMLParserScriptRunner::requestParsingBlockingScript() 542 // - HTMLParserScriptRunner::requestParsingBlockingScript()
486 // - TODO(hiroshige): Investigate XMLDocumentParser::endElementNs() 543 // - TODO(hiroshige): Investigate XMLDocumentParser::endElementNs()
487 will_be_parser_executed_ = true; 544 will_be_parser_executed_ = true;
488 545
489 return true; 546 return true;
490 } 547 }
491 548
492 // 5th Clause: 549 // 5th Clause:
493 // TODO(hiroshige): Reorder the clauses to match the spec. 550 // TODO(hiroshige): Reorder the clauses to match the spec.
494 // - "If the element does not have a src attribute, 551 // - "If the element does not have a src attribute,
495 // and the element has been flagged as "parser-inserted", 552 // and the element has been flagged as "parser-inserted",
496 // and either the parser that created the script is an XML parser 553 // and either the parser that created the script is an XML parser
497 // or it's an HTML parser whose script nesting level is not greater than 554 // or it's an HTML parser whose script nesting level is not greater than
498 // one, 555 // one,
499 // and the Document of the HTML parser or XML parser that created 556 // and the Document of the HTML parser or XML parser that created
500 // the script element has a style sheet that is blocking scripts" 557 // the script element has a style sheet that is blocking scripts"
501 // The last part "... has a style sheet that is blocking scripts" 558 // The last part "... has a style sheet that is blocking scripts"
502 // is implemented in Document::isScriptExecutionReady(). 559 // is implemented in Document::isScriptExecutionReady().
503 // Part of the condition check is done in 560 // Part of the condition check is done in
504 // HTMLParserScriptRunner::processScriptElementInternal(). 561 // HTMLParserScriptRunner::processScriptElementInternal().
505 // TODO(hiroshige): Clean up the split condition check. 562 // TODO(hiroshige): Clean up the split condition check.
506 if (!element_->HasSourceAttribute() && parser_inserted_ && 563 // We check that the type is "classic" here, because according to the spec
564 // a "module" script doesn't reach the 5th Clause because the 4th Clause
565 // catches all "module" scripts.
566 if (GetScriptType() == ScriptType::kClassic &&
567 !element_->HasSourceAttribute() && parser_inserted_ &&
507 !element_document.IsScriptExecutionReady()) { 568 !element_document.IsScriptExecutionReady()) {
508 // The former part of this clause is 569 // The former part of this clause is
509 // implemented by the caller-side of prepareScript(): 570 // implemented by the caller-side of prepareScript():
510 // - HTMLParserScriptRunner::requestParsingBlockingScript() 571 // - HTMLParserScriptRunner::requestParsingBlockingScript()
511 // - TODO(hiroshige): Investigate XMLDocumentParser::endElementNs() 572 // - TODO(hiroshige): Investigate XMLDocumentParser::endElementNs()
512 will_be_parser_executed_ = true; 573 will_be_parser_executed_ = true;
513 // "Set the element's "ready to be parser-executed" flag." 574 // "Set the element's "ready to be parser-executed" flag."
514 ready_to_be_parser_executed_ = true; 575 ready_to_be_parser_executed_ = true;
515 576
516 return true; 577 return true;
517 } 578 }
518 579
519 // 3rd Clause: 580 // 3rd Clause:
520 // - "If the script's type is "classic", 581 // - "If the script's type is "classic",
521 // and the element has a src attribute, 582 // and the element has a src attribute,
522 // and the element does not have an async attribute, 583 // and the element does not have an async attribute,
523 // and the element does not have the "non-blocking" flag set" 584 // and the element does not have the "non-blocking" flag set"
585 // - "If the script's type is "module",
586 // and the element does not have an async attribute,
587 // and the element does not have the "non-blocking" flag set"
524 // TODO(hiroshige): Check the script's type and implement "module" case. 588 // TODO(hiroshige): Check the script's type and implement "module" case.
525 if (element_->HasSourceAttribute() && !element_->AsyncAttributeValue() && 589 if ((GetScriptType() == ScriptType::kClassic &&
526 !non_blocking_) { 590 element_->HasSourceAttribute() && !element_->AsyncAttributeValue() &&
591 !non_blocking_) ||
592 (GetScriptType() == ScriptType::kModule &&
593 !element_->AsyncAttributeValue() && !non_blocking_)) {
527 // "Add the element to the end of the list of scripts that will execute 594 // "Add the element to the end of the list of scripts that will execute
528 // in order as soon as possible associated with the node document of the 595 // in order as soon as possible associated with the node document of the
529 // script element at the time the prepare a script algorithm started." 596 // script element at the time the prepare a script algorithm started."
530 pending_script_ = CreatePendingScript(); 597 pending_script_ = CreatePendingScript();
531 async_exec_type_ = ScriptRunner::kInOrder; 598 async_exec_type_ = ScriptRunner::kInOrder;
532 // TODO(hiroshige): Here |contextDocument| is used as "node document" 599 // TODO(hiroshige): Here |contextDocument| is used as "node document"
533 // while Step 14 uses |elementDocument| as "node document". Fix this. 600 // while Step 14 uses |elementDocument| as "node document". Fix this.
534 context_document->GetScriptRunner()->QueueScriptForExecution( 601 context_document->GetScriptRunner()->QueueScriptForExecution(
535 this, async_exec_type_); 602 this, async_exec_type_);
536 // Note that watchForLoad can immediately call pendingScriptFinished. 603 // Note that watchForLoad can immediately call pendingScriptFinished.
537 pending_script_->WatchForLoad(this); 604 pending_script_->WatchForLoad(this);
538 // The part "When the script is ready..." is implemented in 605 // The part "When the script is ready..." is implemented in
539 // ScriptRunner::notifyScriptReady(). 606 // ScriptRunner::notifyScriptReady().
540 // TODO(hiroshige): Annotate it. 607 // TODO(hiroshige): Annotate it.
541 608
542 return true; 609 return true;
543 } 610 }
544 611
545 // 4th Clause: 612 // 4th Clause:
546 // - "If the script's type is "classic", and the element has a src attribute" 613 // - "If the script's type is "classic", and the element has a src attribute"
547 // TODO(hiroshige): Check the script's type and implement "module" case. 614 // - "If the script's type is "module""
548 if (element_->HasSourceAttribute()) { 615 if ((GetScriptType() == ScriptType::kClassic &&
616 element_->HasSourceAttribute()) ||
617 GetScriptType() == ScriptType::kModule) {
549 // "The element must be added to the set of scripts that will execute 618 // "The element must be added to the set of scripts that will execute
550 // as soon as possible of the node document of the script element at the 619 // as soon as possible of the node document of the script element at the
551 // time the prepare a script algorithm started." 620 // time the prepare a script algorithm started."
552 pending_script_ = CreatePendingScript(); 621 pending_script_ = CreatePendingScript();
553 async_exec_type_ = ScriptRunner::kAsync; 622 async_exec_type_ = ScriptRunner::kAsync;
554 pending_script_->StartStreamingIfPossible(&element_->GetDocument(), 623 pending_script_->StartStreamingIfPossible(&element_->GetDocument(),
555 ScriptStreamer::kAsync); 624 ScriptStreamer::kAsync);
556 // TODO(hiroshige): Here |contextDocument| is used as "node document" 625 // TODO(hiroshige): Here |contextDocument| is used as "node document"
557 // while Step 14 uses |elementDocument| as "node document". Fix this. 626 // while Step 14 uses |elementDocument| as "node document". Fix this.
558 context_document->GetScriptRunner()->QueueScriptForExecution( 627 context_document->GetScriptRunner()->QueueScriptForExecution(
(...skipping 10 matching lines...) Expand all
569 // 6th Clause: 638 // 6th Clause:
570 // - "Otherwise" 639 // - "Otherwise"
571 // "Immediately execute the script block, 640 // "Immediately execute the script block,
572 // even if other scripts are already executing." 641 // even if other scripts are already executing."
573 // Note: this block is also duplicated in 642 // Note: this block is also duplicated in
574 // HTMLParserScriptRunner::processScriptElementInternal(). 643 // HTMLParserScriptRunner::processScriptElementInternal().
575 // TODO(hiroshige): Merge the duplicated code. 644 // TODO(hiroshige): Merge the duplicated code.
576 645
577 // This clause is executed only if the script's type is "classic" 646 // This clause is executed only if the script's type is "classic"
578 // and the element doesn't have a src attribute. 647 // and the element doesn't have a src attribute.
648 DCHECK_EQ(GetScriptType(), ScriptType::kClassic);
649 DCHECK(!is_external_script_);
579 650
580 // Reset line numbering for nested writes. 651 // Reset line numbering for nested writes.
581 TextPosition position = element_document.IsInDocumentWrite() 652 TextPosition position = element_document.IsInDocumentWrite()
582 ? TextPosition() 653 ? TextPosition()
583 : script_start_position; 654 : script_start_position;
584 KURL script_url = (!element_document.IsInDocumentWrite() && parser_inserted_) 655 KURL script_url = (!element_document.IsInDocumentWrite() && parser_inserted_)
585 ? element_document.Url() 656 ? element_document.Url()
586 : KURL(); 657 : KURL();
587 658
588 if (!ExecuteScript(ClassicScript::Create( 659 if (!ExecuteScript(ClassicScript::Create(
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
655 if (created_during_document_write_ && 726 if (created_during_document_write_ &&
656 resource_->GetResourceRequest().GetCachePolicy() == 727 resource_->GetResourceRequest().GetCachePolicy() ==
657 WebCachePolicy::kReturnCacheDataDontLoad) { 728 WebCachePolicy::kReturnCacheDataDontLoad) {
658 document_write_intervention_ = 729 document_write_intervention_ =
659 DocumentWriteIntervention::kDoNotFetchDocWrittenScript; 730 DocumentWriteIntervention::kDoNotFetchDocWrittenScript;
660 } 731 }
661 732
662 return true; 733 return true;
663 } 734 }
664 735
736 void ScriptLoader::FetchModuleScriptTree(
737 const KURL& url,
738 Modulator* modulator,
739 const String& nonce,
740 ParserDisposition parser_state,
741 WebURLRequest::FetchCredentialsMode credentials_mode) {
742 // https://html.spec.whatwg.org/#prepare-a-script
743 // 21.6, "module":
744 // "Fetch a module script graph given url, settings, "script",
745 // cryptographic nonce, parser state, and
746 // module script credentials mode."
747 ModuleScriptFetchRequest module_request(url, nonce, parser_state,
748 credentials_mode);
749
750 module_tree_client_ = ModulePendingScriptTreeClient::Create();
751
752 modulator->FetchTree(module_request, module_tree_client_);
753 }
754
665 PendingScript* ScriptLoader::CreatePendingScript() { 755 PendingScript* ScriptLoader::CreatePendingScript() {
666 CHECK(resource_); 756 switch (GetScriptType()) {
667 return PendingScript::Create(element_, resource_); 757 case ScriptType::kClassic:
758 CHECK(resource_);
759 return ClassicPendingScript::Create(element_, resource_);
760 case ScriptType::kModule:
761 CHECK(module_tree_client_);
762 return ModulePendingScript::Create(element_, module_tree_client_);
763 }
764 NOTREACHED();
765 return nullptr;
668 } 766 }
669 767
670 bool ScriptLoader::ExecuteScript(const Script* script) { 768 bool ScriptLoader::ExecuteScript(const Script* script) {
671 double script_exec_start_time = MonotonicallyIncreasingTime(); 769 double script_exec_start_time = MonotonicallyIncreasingTime();
672 bool result = DoExecuteScript(script); 770 bool result = DoExecuteScript(script);
673 771
674 // NOTE: we do not check m_willBeParserExecuted here, since 772 // NOTE: we do not check m_willBeParserExecuted here, since
675 // m_willBeParserExecuted is false for inline scripts, and we want to 773 // m_willBeParserExecuted is false for inline scripts, and we want to
676 // include inline script execution time as part of parser blocked script 774 // include inline script execution time as part of parser blocked script
677 // execution time. 775 // execution time.
678 if (async_exec_type_ == ScriptRunner::kNone) 776 if (async_exec_type_ == ScriptRunner::kNone)
679 DocumentParserTiming::From(element_->GetDocument()) 777 DocumentParserTiming::From(element_->GetDocument())
680 .RecordParserBlockedOnScriptExecutionDuration( 778 .RecordParserBlockedOnScriptExecutionDuration(
681 MonotonicallyIncreasingTime() - script_exec_start_time, 779 MonotonicallyIncreasingTime() - script_exec_start_time,
682 WasCreatedDuringDocumentWrite()); 780 WasCreatedDuringDocumentWrite());
683 return result; 781 return result;
684 } 782 }
685 783
686 // https://html.spec.whatwg.org/#execute-the-script-block 784 // https://html.spec.whatwg.org/#execute-the-script-block
687 // with additional support for HTML imports. 785 // with additional support for HTML imports.
688 // Note that Steps 2 and 8 must be handled by the caller of doExecuteScript(), 786 // Note that Steps 2 and 8 must be handled by the caller of doExecuteScript(),
689 // i.e. load/error events are dispatched by the caller. 787 // i.e. load/error events are dispatched by the caller.
690 // Steps 3--7 are implemented here in doExecuteScript(). 788 // Steps 3--7 are implemented here in doExecuteScript().
691 // TODO(hiroshige): Move event dispatching code to doExecuteScript(). 789 // TODO(hiroshige): Move event dispatching code to doExecuteScript().
692 bool ScriptLoader::DoExecuteScript(const Script* script) { 790 bool ScriptLoader::DoExecuteScript(const Script* script) {
693 DCHECK(already_started_); 791 DCHECK(already_started_);
792 CHECK_EQ(script->GetScriptType(), GetScriptType());
694 793
695 if (script->IsEmpty()) 794 if (script->IsEmpty())
696 return true; 795 return true;
697 796
698 Document* element_document = &(element_->GetDocument()); 797 Document* element_document = &(element_->GetDocument());
699 Document* context_document = element_document->ContextDocument(); 798 Document* context_document = element_document->ContextDocument();
700 if (!context_document) 799 if (!context_document)
701 return true; 800 return true;
702 801
703 LocalFrame* frame = context_document->GetFrame(); 802 LocalFrame* frame = context_document->GetFrame();
(...skipping 22 matching lines...) Expand all
726 context_document, element_->GetDocument().GetSecurityOrigin())) 825 context_document, element_->GetDocument().GetSecurityOrigin()))
727 return false; 826 return false;
728 } 827 }
729 828
730 const bool is_imported_script = context_document != element_document; 829 const bool is_imported_script = context_document != element_document;
731 830
732 // 3. "If the script is from an external file, 831 // 3. "If the script is from an external file,
733 // or the script's type is module", 832 // or the script's type is module",
734 // then increment the ignore-destructive-writes counter of the 833 // then increment the ignore-destructive-writes counter of the
735 // script element's node document. Let neutralized doc be that Document." 834 // script element's node document. Let neutralized doc be that Document."
736 // TODO(hiroshige): Implement "module" case.
737 IgnoreDestructiveWriteCountIncrementer 835 IgnoreDestructiveWriteCountIncrementer
738 ignore_destructive_write_count_incrementer( 836 ignore_destructive_write_count_incrementer(
739 is_external_script_ || is_imported_script ? context_document : 0); 837 is_external_script_ ||
838 script->GetScriptType() == ScriptType::kModule ||
839 is_imported_script
840 ? context_document
841 : 0);
740 842
741 // 4. "Let old script element be the value to which the script element's 843 // 4. "Let old script element be the value to which the script element's
742 // node document's currentScript object was most recently set." 844 // node document's currentScript object was most recently set."
743 // This is implemented as push/popCurrentScript(). 845 // This is implemented as push/popCurrentScript().
744 846
745 // 5. "Switch on the script's type:" 847 // 5. "Switch on the script's type:"
746 // - "classic": 848 // - "classic":
747 // 1. "If the script element's root is not a shadow root, 849 // 1. "If the script element's root is not a shadow root,
748 // then set the script element's node document's currentScript 850 // then set the script element's node document's currentScript
749 // attribute to the script element. Otherwise, set it to null." 851 // attribute to the script element. Otherwise, set it to null."
750 context_document->PushCurrentScript(element_.Get()); 852 // - "module":
853 // 1. "Set the script element's node document's currentScript attribute
854 // to null."
855 ScriptElementBase* current_script = nullptr;
856 if (script->GetScriptType() == ScriptType::kClassic)
857 current_script = element_;
858 context_document->PushCurrentScript(current_script);
751 859
860 // - "classic":
752 // 2. "Run the classic script given by the script's script." 861 // 2. "Run the classic script given by the script's script."
753 // Note: This is where the script is compiled and actually executed. 862 // Note: This is where the script is compiled and actually executed.
863 // - "module":
864 // 2. "Run the module script given by the script's script."
754 script->RunScript(frame, element_->GetDocument().GetSecurityOrigin()); 865 script->RunScript(frame, element_->GetDocument().GetSecurityOrigin());
755 866
756 // - "module":
757 // TODO(hiroshige): Implement this.
758
759 // 6. "Set the script element's node document's currentScript attribute 867 // 6. "Set the script element's node document's currentScript attribute
760 // to old script element." 868 // to old script element."
761 context_document->PopCurrentScript(element_.Get()); 869 context_document->PopCurrentScript(current_script);
762 870
763 return true; 871 return true;
764 872
765 // 7. "Decrement the ignore-destructive-writes counter of neutralized doc, 873 // 7. "Decrement the ignore-destructive-writes counter of neutralized doc,
766 // if it was incremented in the earlier step." 874 // if it was incremented in the earlier step."
767 // Implemented as the scope out of IgnoreDestructiveWriteCountIncrementer. 875 // Implemented as the scope out of IgnoreDestructiveWriteCountIncrementer.
768 } 876 }
769 877
770 void ScriptLoader::Execute() { 878 void ScriptLoader::Execute() {
771 DCHECK(!will_be_parser_executed_); 879 DCHECK(!will_be_parser_executed_);
772 DCHECK(async_exec_type_ != ScriptRunner::kNone); 880 DCHECK(async_exec_type_ != ScriptRunner::kNone);
773 DCHECK(pending_script_->GetResource()); 881 DCHECK(pending_script_->IsExternal());
774 bool error_occurred = false; 882 bool error_occurred = false;
775 Script* script = pending_script_->GetSource(KURL(), error_occurred); 883 Script* script = pending_script_->GetSource(KURL(), error_occurred);
884 const bool wasCanceled = pending_script_->WasCanceled();
776 DetachPendingScript(); 885 DetachPendingScript();
777 if (error_occurred) { 886 if (error_occurred) {
778 DispatchErrorEvent(); 887 DispatchErrorEvent();
779 } else if (!resource_->WasCanceled()) { 888 } else if (!wasCanceled) {
780 if (ExecuteScript(script)) 889 if (ExecuteScript(script))
781 DispatchLoadEvent(); 890 DispatchLoadEvent();
782 else 891 else
783 DispatchErrorEvent(); 892 DispatchErrorEvent();
784 } 893 }
785 resource_ = nullptr; 894 resource_ = nullptr;
895 module_tree_client_ = nullptr;
786 } 896 }
787 897
788 void ScriptLoader::PendingScriptFinished(PendingScript* pending_script) { 898 void ScriptLoader::PendingScriptFinished(PendingScript* pending_script) {
789 DCHECK(!will_be_parser_executed_); 899 DCHECK(!will_be_parser_executed_);
790 DCHECK_EQ(pending_script_, pending_script); 900 DCHECK_EQ(pending_script_, pending_script);
791 DCHECK_EQ(pending_script->GetResource(), resource_); 901 DCHECK_EQ(pending_script_->GetScriptType(), GetScriptType());
792 902
793 // We do not need this script in the memory cache. The primary goals of 903 // We do not need this script in the memory cache. The primary goals of
794 // sending this fetch request are to let the third party server know 904 // sending this fetch request are to let the third party server know
795 // about the document.write scripts intervention and populate the http 905 // about the document.write scripts intervention and populate the http
796 // cache for subsequent uses. 906 // cache for subsequent uses.
797 if (document_write_intervention_ == 907 if (document_write_intervention_ ==
798 DocumentWriteIntervention::kFetchDocWrittenScriptDeferIdle) { 908 DocumentWriteIntervention::kFetchDocWrittenScriptDeferIdle) {
799 GetMemoryCache()->Remove(pending_script_->GetResource()); 909 DCHECK_EQ(pending_script_->GetScriptType(), ScriptType::kClassic);
910 pending_script_->RemoveFromMemoryCache();
800 pending_script_->StopWatchingForLoad(); 911 pending_script_->StopWatchingForLoad();
801 return; 912 return;
802 } 913 }
803 914
804 DCHECK(async_exec_type_ != ScriptRunner::kNone); 915 DCHECK(async_exec_type_ != ScriptRunner::kNone);
805 916
806 Document* context_document = element_->GetDocument().ContextDocument(); 917 Document* context_document = element_->GetDocument().ContextDocument();
807 if (!context_document) { 918 if (!context_document) {
808 DetachPendingScript(); 919 DetachPendingScript();
809 return; 920 return;
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
852 // then abort these steps at this point. The script is not executed. 963 // then abort these steps at this point. The script is not executed.
853 return DeprecatedEqualIgnoringCase(event_attribute, "onload") || 964 return DeprecatedEqualIgnoringCase(event_attribute, "onload") ||
854 DeprecatedEqualIgnoringCase(event_attribute, "onload()"); 965 DeprecatedEqualIgnoringCase(event_attribute, "onload()");
855 } 966 }
856 967
857 String ScriptLoader::ScriptContent() const { 968 String ScriptLoader::ScriptContent() const {
858 return element_->TextFromChildren(); 969 return element_->TextFromChildren();
859 } 970 }
860 971
861 } // namespace blink 972 } // namespace blink
OLDNEW
« no previous file with comments | « third_party/WebKit/Source/core/dom/ScriptLoader.h ('k') | third_party/WebKit/Source/core/dom/ScriptModuleResolver.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698