OLD | NEW |
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 |
11 * License as published by the Free Software Foundation; either | 11 * License as published by the Free Software Foundation; either |
12 * version 2 of the License, or (at your option) any later version. | 12 * version 2 of the License, or (at your option) any later version. |
13 * | 13 * |
14 * This library is distributed in the hope that it will be useful, | 14 * This library is distributed in the hope that it will be useful, |
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of | 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
17 * Library General Public License for more details. | 17 * Library General Public License for more details. |
18 * | 18 * |
19 * You should have received a copy of the GNU Library General Public License | 19 * You should have received a copy of the GNU Library General Public License |
20 * along with this library; see the file COPYING.LIB. If not, write to | 20 * along with this library; see the file COPYING.LIB. If not, write to |
21 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | 21 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
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/V8BindingForCore.h" |
29 #include "core/HTMLNames.h" | 30 #include "core/HTMLNames.h" |
30 #include "core/SVGNames.h" | 31 #include "core/SVGNames.h" |
31 #include "core/dom/ClassicPendingScript.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/DocumentWriteIntervention.h" | 36 #include "core/dom/DocumentWriteIntervention.h" |
36 #include "core/dom/IgnoreDestructiveWriteCountIncrementer.h" | 37 #include "core/dom/IgnoreDestructiveWriteCountIncrementer.h" |
| 38 #include "core/dom/Modulator.h" |
| 39 #include "core/dom/ModulePendingScript.h" |
37 #include "core/dom/Script.h" | 40 #include "core/dom/Script.h" |
38 #include "core/dom/ScriptElementBase.h" | 41 #include "core/dom/ScriptElementBase.h" |
39 #include "core/dom/ScriptRunner.h" | 42 #include "core/dom/ScriptRunner.h" |
40 #include "core/dom/ScriptableDocumentParser.h" | 43 #include "core/dom/ScriptableDocumentParser.h" |
41 #include "core/dom/Text.h" | 44 #include "core/dom/Text.h" |
42 #include "core/events/Event.h" | 45 #include "core/events/Event.h" |
43 #include "core/frame/LocalFrame.h" | 46 #include "core/frame/LocalFrame.h" |
44 #include "core/frame/SubresourceIntegrity.h" | 47 #include "core/frame/SubresourceIntegrity.h" |
45 #include "core/frame/csp/ContentSecurityPolicy.h" | 48 #include "core/frame/csp/ContentSecurityPolicy.h" |
46 #include "core/html/imports/HTMLImport.h" | 49 #include "core/html/imports/HTMLImport.h" |
47 #include "core/html/parser/HTMLParserIdioms.h" | 50 #include "core/html/parser/HTMLParserIdioms.h" |
| 51 #include "core/inspector/ConsoleMessage.h" |
| 52 #include "core/loader/modulescript/ModuleScriptFetchRequest.h" |
48 #include "core/loader/resource/ScriptResource.h" | 53 #include "core/loader/resource/ScriptResource.h" |
49 #include "platform/WebFrameScheduler.h" | 54 #include "platform/WebFrameScheduler.h" |
50 #include "platform/loader/fetch/AccessControlStatus.h" | 55 #include "platform/loader/fetch/AccessControlStatus.h" |
51 #include "platform/loader/fetch/FetchParameters.h" | 56 #include "platform/loader/fetch/FetchParameters.h" |
52 #include "platform/loader/fetch/ResourceFetcher.h" | 57 #include "platform/loader/fetch/ResourceFetcher.h" |
53 #include "platform/network/mime/MIMETypeRegistry.h" | 58 #include "platform/network/mime/MIMETypeRegistry.h" |
54 #include "platform/weborigin/SecurityOrigin.h" | 59 #include "platform/weborigin/SecurityOrigin.h" |
55 #include "platform/wtf/StdLibExtras.h" | 60 #include "platform/wtf/StdLibExtras.h" |
56 #include "platform/wtf/text/StringBuilder.h" | 61 #include "platform/wtf/text/StringBuilder.h" |
57 #include "platform/wtf/text/StringHash.h" | 62 #include "platform/wtf/text/StringHash.h" |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
100 element_->GetDocument().GetScriptableDocumentParser()->LineNumber(); | 105 element_->GetDocument().GetScriptableDocumentParser()->LineNumber(); |
101 } | 106 } |
102 } | 107 } |
103 | 108 |
104 ScriptLoader::~ScriptLoader() {} | 109 ScriptLoader::~ScriptLoader() {} |
105 | 110 |
106 DEFINE_TRACE(ScriptLoader) { | 111 DEFINE_TRACE(ScriptLoader) { |
107 visitor->Trace(element_); | 112 visitor->Trace(element_); |
108 visitor->Trace(resource_); | 113 visitor->Trace(resource_); |
109 visitor->Trace(pending_script_); | 114 visitor->Trace(pending_script_); |
| 115 visitor->Trace(module_tree_client_); |
110 PendingScriptClient::Trace(visitor); | 116 PendingScriptClient::Trace(visitor); |
111 } | 117 } |
112 | 118 |
113 void ScriptLoader::SetFetchDocWrittenScriptDeferIdle() { | 119 void ScriptLoader::SetFetchDocWrittenScriptDeferIdle() { |
114 DCHECK(!created_during_document_write_); | 120 DCHECK(!created_during_document_write_); |
115 document_write_intervention_ = | 121 document_write_intervention_ = |
116 DocumentWriteIntervention::kFetchDocWrittenScriptDeferIdle; | 122 DocumentWriteIntervention::kFetchDocWrittenScriptDeferIdle; |
117 } | 123 } |
118 | 124 |
119 void ScriptLoader::DidNotifySubtreeInsertionsToDocument() { | 125 void ScriptLoader::DidNotifySubtreeInsertionsToDocument() { |
(...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
308 if (!IsScriptForEventSupported()) | 314 if (!IsScriptForEventSupported()) |
309 return false; | 315 return false; |
310 | 316 |
311 // 14. is handled below. | 317 // 14. is handled below. |
312 | 318 |
313 // 15. "Let CORS setting be the current state of the element's | 319 // 15. "Let CORS setting be the current state of the element's |
314 // crossorigin content attribute." | 320 // crossorigin content attribute." |
315 CrossOriginAttributeValue cross_origin = | 321 CrossOriginAttributeValue cross_origin = |
316 GetCrossOriginAttributeValue(element_->CrossOriginAttributeValue()); | 322 GetCrossOriginAttributeValue(element_->CrossOriginAttributeValue()); |
317 | 323 |
318 // 16. will be handled below once module script support is implemented. | 324 // 16. is handled below. |
319 | 325 |
320 // 17. "If the script element has a nonce attribute, | 326 // 17. "If the script element has a nonce attribute, |
321 // then let cryptographic nonce be that attribute's value. | 327 // then let cryptographic nonce be that attribute's value. |
322 // Otherwise, let cryptographic nonce be the empty string." | 328 // Otherwise, let cryptographic nonce be the empty string." |
323 String nonce; | 329 String nonce; |
324 if (element_->IsNonceableElement()) | 330 if (element_->IsNonceableElement()) |
325 nonce = element_->nonce(); | 331 nonce = element_->nonce(); |
326 | 332 |
327 // 18. is handled below. | 333 // 18. is handled below. |
328 | 334 |
(...skipping 28 matching lines...) Expand all Loading... |
357 // 21.5. "If the previous step failed, queue a task to | 363 // 21.5. "If the previous step failed, queue a task to |
358 // fire an event named error at the element, and abort these steps." | 364 // fire an event named error at the element, and abort these steps." |
359 if (!url.IsValid()) { | 365 if (!url.IsValid()) { |
360 // TODO(hiroshige): Make this asynchronous. Currently we fire the error | 366 // TODO(hiroshige): Make this asynchronous. Currently we fire the error |
361 // event synchronously to keep the existing behavior. | 367 // event synchronously to keep the existing behavior. |
362 DispatchErrorEvent(); | 368 DispatchErrorEvent(); |
363 return false; | 369 return false; |
364 } | 370 } |
365 | 371 |
366 DCHECK(!resource_); | 372 DCHECK(!resource_); |
| 373 DCHECK(!module_tree_client_); |
367 | 374 |
368 // 21.6. "Switch on the script's type:" | 375 // 21.6. "Switch on the script's type:" |
369 // - "classic": | 376 if (GetScriptType() == ScriptType::kClassic) { |
| 377 // - "classic": |
370 | 378 |
371 // 14. "If the script element has a charset attribute, | 379 // 14. "If the script element has a charset attribute, |
372 // then let encoding be the result of | 380 // then let encoding be the result of |
373 // getting an encoding from the value of the charset attribute." | 381 // getting an encoding from the value of the charset attribute." |
374 // "If the script element does not have a charset attribute, | 382 // "If the script element does not have a charset attribute, |
375 // or if getting an encoding failed, let encoding | 383 // or if getting an encoding failed, let encoding |
376 // be the same as the encoding of the script element's node | 384 // be the same as the encoding of the script element's node |
377 // document." | 385 // document." |
378 // TODO(hiroshige): Should we handle failure in getting an encoding? | 386 // TODO(hiroshige): Should we handle failure in getting an encoding? |
379 String encoding; | 387 String encoding; |
380 if (!element_->CharsetAttributeValue().IsEmpty()) | 388 if (!element_->CharsetAttributeValue().IsEmpty()) |
381 encoding = element_->CharsetAttributeValue(); | 389 encoding = element_->CharsetAttributeValue(); |
382 else | 390 else |
383 encoding = element_document.characterSet(); | 391 encoding = element_document.characterSet(); |
384 | 392 |
385 // Step 16 is skipped because "module script credentials" is not used | 393 // Step 16 is skipped because "module script credentials" is not used |
386 // for classic scripts. | 394 // for classic scripts. |
387 | 395 |
388 // 18. "If the script element has an integrity attribute, | 396 // 18. "If the script element has an integrity attribute, |
389 // then let integrity metadata be that attribute's value. | 397 // then let integrity metadata be that attribute's value. |
390 // Otherwise, let integrity metadata be the empty string." | 398 // Otherwise, let integrity metadata be the empty string." |
391 String integrity_attr = element_->IntegrityAttributeValue(); | 399 String integrity_attr = element_->IntegrityAttributeValue(); |
392 IntegrityMetadataSet integrity_metadata; | 400 IntegrityMetadataSet integrity_metadata; |
393 if (!integrity_attr.IsEmpty()) { | 401 if (!integrity_attr.IsEmpty()) { |
394 SubresourceIntegrity::ParseIntegrityAttribute( | 402 SubresourceIntegrity::ParseIntegrityAttribute( |
395 integrity_attr, integrity_metadata, &element_document); | 403 integrity_attr, integrity_metadata, &element_document); |
| 404 } |
| 405 |
| 406 if (!FetchClassicScript(url, element_document.Fetcher(), nonce, |
| 407 integrity_metadata, parser_state, cross_origin, |
| 408 element_document.GetSecurityOrigin(), encoding)) { |
| 409 // TODO(hiroshige): Make this asynchronous. Currently we fire the error |
| 410 // event synchronously to keep the existing behavior. |
| 411 DispatchErrorEvent(); |
| 412 return false; |
| 413 } |
| 414 |
| 415 DCHECK(resource_); |
| 416 DCHECK(!module_tree_client_); |
| 417 } else { |
| 418 // - "module": |
| 419 |
| 420 // Steps 14 and 18 are skipped because they are not used in module |
| 421 // scripts. |
| 422 |
| 423 // 16. "Let module script credentials mode be determined by switching |
| 424 // on CORS setting:" |
| 425 WebURLRequest::FetchCredentialsMode credentials_mode = |
| 426 WebURLRequest::kFetchCredentialsModeOmit; |
| 427 switch (cross_origin) { |
| 428 case kCrossOriginAttributeNotSet: |
| 429 credentials_mode = WebURLRequest::kFetchCredentialsModeOmit; |
| 430 break; |
| 431 case kCrossOriginAttributeAnonymous: |
| 432 credentials_mode = WebURLRequest::kFetchCredentialsModeSameOrigin; |
| 433 break; |
| 434 case kCrossOriginAttributeUseCredentials: |
| 435 credentials_mode = WebURLRequest::kFetchCredentialsModeInclude; |
| 436 break; |
| 437 } |
| 438 |
| 439 DCHECK(RuntimeEnabledFeatures::moduleScriptsEnabled()); |
| 440 Modulator* modulator = Modulator::From( |
| 441 ToScriptStateForMainWorld(element_document.GetFrame())); |
| 442 FetchModuleScriptTree(url, modulator, nonce, parser_state, |
| 443 credentials_mode); |
| 444 |
| 445 DCHECK(!resource_); |
| 446 DCHECK(module_tree_client_); |
396 } | 447 } |
397 | 448 |
398 if (!FetchClassicScript(url, element_document.Fetcher(), nonce, | |
399 integrity_metadata, parser_state, cross_origin, | |
400 element_document.GetSecurityOrigin(), encoding)) { | |
401 // TODO(hiroshige): Make this asynchronous. Currently we fire the error | |
402 // event synchronously to keep the existing behavior. | |
403 DispatchErrorEvent(); | |
404 return false; | |
405 } | |
406 | |
407 DCHECK(resource_); | |
408 | |
409 // - "module": | |
410 // TODO(hiroshige): Implement this. | |
411 | |
412 // "When the chosen algorithm asynchronously completes, set | 449 // "When the chosen algorithm asynchronously completes, set |
413 // the script's script to the result. At that time, the script is ready." | 450 // the script's script to the result. At that time, the script is ready." |
414 // When the script is ready, PendingScriptClient::pendingScriptFinished() | 451 // When the script is ready, PendingScriptClient::pendingScriptFinished() |
415 // is used as the notification, and the action to take when | 452 // is used as the notification, and the action to take when |
416 // the script is ready is specified later, in | 453 // the script is ready is specified later, in |
417 // - ScriptLoader::PrepareScript(), or | 454 // - ScriptLoader::PrepareScript(), or |
418 // - HTMLParserScriptRunner, | 455 // - HTMLParserScriptRunner, |
419 // depending on the conditions in Step 23 of "prepare a script". | 456 // depending on the conditions in Step 23 of "prepare a script". |
420 } | 457 } |
421 | 458 |
422 // 22. "If the element does not have a src content attribute, | 459 // 22. "If the element does not have a src content attribute, |
423 // run these substeps:" | 460 // run these substeps:" |
| 461 if (!element_->HasSourceAttribute()) { |
| 462 // 22.1. "Let source text be the value of the text IDL attribute." |
| 463 // This step is done later: |
| 464 // - in ScriptLoader::pendingScript() (Step 23, 6th Clause), |
| 465 // as Element::textFromChildren() in ScriptLoader::scriptContent(), |
| 466 // - in HTMLParserScriptRunner::processScriptElementInternal() |
| 467 // (Duplicated code of Step 23, 6th Clause), |
| 468 // as Element::textContent(), |
| 469 // - in XMLDocumentParser::endElementNs() (Step 23, 5th Clause), |
| 470 // as Element::textFromChildren() in ScriptLoader::scriptContent(), |
| 471 // - PendingScript::getSource() (Indirectly used via |
| 472 // HTMLParserScriptRunner::processScriptElementInternal(), |
| 473 // Step 23, 5th Clause), |
| 474 // as Element::textContent(). |
| 475 // TODO(hiroshige): Make them merged or consistent. |
424 | 476 |
425 // 22.1. "Let source text be the value of the text IDL attribute." | 477 // 22.2. "Switch on the script's type:" |
426 // This step is done later: | 478 switch (GetScriptType()) { |
427 // - in ScriptLoader::pendingScript() (Step 23, 6th Clause), | 479 // - "classic": |
428 // as Element::textFromChildren() in ScriptLoader::scriptContent(), | 480 case ScriptType::kClassic: |
429 // - in HTMLParserScriptRunner::processScriptElementInternal() | 481 // TODO(hiroshige): Clarify how Step 22.2 is implemented for "classic". |
430 // (Duplicated code of Step 23, 6th Clause), | 482 break; |
431 // as Element::textContent(), | |
432 // - in XMLDocumentParser::endElementNs() (Step 23, 5th Clause), | |
433 // as Element::textFromChildren() in ScriptLoader::scriptContent(), | |
434 // - PendingScript::getSource() (Indirectly used via | |
435 // HTMLParserScriptRunner::processScriptElementInternal(), | |
436 // Step 23, 5th Clause), | |
437 // as Element::textContent(). | |
438 // TODO(hiroshige): Make them merged or consistent. | |
439 | 483 |
440 // 22.2. "Switch on the script's type:" | 484 // - "module": |
441 // TODO(hiroshige): Clarify how Step 22.2 is implemented for "classic". | 485 case ScriptType::kModule: |
442 // TODO(hiroshige): Implement Step 22.2 for "module". | 486 // TODO(hiroshige): Implement inline module scripts. |
| 487 element_document.AddConsoleMessage(ConsoleMessage::Create( |
| 488 kJSMessageSource, kErrorMessageLevel, |
| 489 "Inline module script is not yet supported", |
| 490 SourceLocation::Create(element_document.Url().GetString(), |
| 491 script_start_position.line_.OneBasedInt(), |
| 492 script_start_position.column_.OneBasedInt(), |
| 493 nullptr))); |
| 494 return false; |
| 495 } |
| 496 } |
443 | 497 |
444 // [Intervention] | 498 // [Intervention] |
445 // Since the asynchronous, low priority fetch for doc.written blocked | 499 // Since the asynchronous, low priority fetch for doc.written blocked |
446 // script is not for execution, return early from here. Watch for its | 500 // script is not for execution, return early from here. Watch for its |
447 // completion to be able to remove it from the memory cache. | 501 // completion to be able to remove it from the memory cache. |
448 if (document_write_intervention_ == | 502 if (GetScriptType() == ScriptType::kClassic && |
449 DocumentWriteIntervention::kFetchDocWrittenScriptDeferIdle) { | 503 document_write_intervention_ == |
| 504 DocumentWriteIntervention::kFetchDocWrittenScriptDeferIdle) { |
450 pending_script_ = CreatePendingScript(); | 505 pending_script_ = CreatePendingScript(); |
451 pending_script_->WatchForLoad(this); | 506 pending_script_->WatchForLoad(this); |
452 return true; | 507 return true; |
453 } | 508 } |
454 | 509 |
455 // 23. "Then, follow the first of the following options that describes the | 510 // 23. "Then, follow the first of the following options that describes the |
456 // situation:" | 511 // situation:" |
457 | 512 |
458 // Three flags are used to instruct the caller of prepareScript() to execute | 513 // Three flags are used to instruct the caller of prepareScript() to execute |
459 // a part of Step 23, when |m_willBeParserExecuted| is true: | 514 // a part of Step 23, when |m_willBeParserExecuted| is true: |
460 // - |m_willBeParserExecuted| | 515 // - |m_willBeParserExecuted| |
461 // - |m_willExecuteWhenDocumentFinishedParsing| | 516 // - |m_willExecuteWhenDocumentFinishedParsing| |
462 // - |m_readyToBeParserExecuted| | 517 // - |m_readyToBeParserExecuted| |
463 // TODO(hiroshige): Clean up the dependency. | 518 // TODO(hiroshige): Clean up the dependency. |
464 | 519 |
465 // 1st Clause: | 520 // 1st Clause: |
466 // - "If the script's type is "classic", and | 521 // - "If the script's type is "classic", and |
467 // the element has a src attribute, and the element has a defer attribute, | 522 // the element has a src attribute, and the element has a defer attribute, |
468 // and the element has been flagged as "parser-inserted", | 523 // and the element has been flagged as "parser-inserted", |
469 // and the element does not have an async attribute" | 524 // and the element does not have an async attribute" |
470 // TODO(hiroshige): Check the script's type and implement "module" case. | 525 // - "If the script's type is "module", |
471 if (element_->HasSourceAttribute() && element_->DeferAttributeValue() && | 526 // and the element has been flagged as "parser-inserted", |
472 parser_inserted_ && !element_->AsyncAttributeValue()) { | 527 // and the element does not have an async attribute" |
| 528 if ((GetScriptType() == ScriptType::kClassic && |
| 529 element_->HasSourceAttribute() && element_->DeferAttributeValue() && |
| 530 parser_inserted_ && !element_->AsyncAttributeValue()) || |
| 531 (GetScriptType() == ScriptType::kModule && parser_inserted_ && |
| 532 !element_->AsyncAttributeValue())) { |
473 // This clause is implemented by the caller-side of prepareScript(): | 533 // This clause is implemented by the caller-side of prepareScript(): |
474 // - HTMLParserScriptRunner::requestDeferredScript(), and | 534 // - HTMLParserScriptRunner::requestDeferredScript(), and |
475 // - TODO(hiroshige): Investigate XMLDocumentParser::endElementNs() | 535 // - TODO(hiroshige): Investigate XMLDocumentParser::endElementNs() |
476 will_execute_when_document_finished_parsing_ = true; | 536 will_execute_when_document_finished_parsing_ = true; |
477 will_be_parser_executed_ = true; | 537 will_be_parser_executed_ = true; |
478 | 538 |
479 return true; | 539 return true; |
480 } | 540 } |
481 | 541 |
482 // 2nd Clause: | 542 // 2nd Clause: |
483 // - "If the script's type is "classic", | 543 // - "If the script's type is "classic", |
484 // and the element has a src attribute, | 544 // and the element has a src attribute, |
485 // and the element has been flagged as "parser-inserted", | 545 // and the element has been flagged as "parser-inserted", |
486 // and the element does not have an async attribute" | 546 // and the element does not have an async attribute" |
487 // TODO(hiroshige): Check the script's type. | 547 // TODO(hiroshige): Check the script's type. |
488 if (element_->HasSourceAttribute() && parser_inserted_ && | 548 if (GetScriptType() == ScriptType::kClassic && |
| 549 element_->HasSourceAttribute() && parser_inserted_ && |
489 !element_->AsyncAttributeValue()) { | 550 !element_->AsyncAttributeValue()) { |
490 // This clause is implemented by the caller-side of prepareScript(): | 551 // This clause is implemented by the caller-side of prepareScript(): |
491 // - HTMLParserScriptRunner::requestParsingBlockingScript() | 552 // - HTMLParserScriptRunner::requestParsingBlockingScript() |
492 // - TODO(hiroshige): Investigate XMLDocumentParser::endElementNs() | 553 // - TODO(hiroshige): Investigate XMLDocumentParser::endElementNs() |
493 will_be_parser_executed_ = true; | 554 will_be_parser_executed_ = true; |
494 | 555 |
495 return true; | 556 return true; |
496 } | 557 } |
497 | 558 |
498 // 5th Clause: | 559 // 5th Clause: |
499 // TODO(hiroshige): Reorder the clauses to match the spec. | 560 // TODO(hiroshige): Reorder the clauses to match the spec. |
500 // - "If the element does not have a src attribute, | 561 // - "If the element does not have a src attribute, |
501 // and the element has been flagged as "parser-inserted", | 562 // and the element has been flagged as "parser-inserted", |
502 // and either the parser that created the script is an XML parser | 563 // and either the parser that created the script is an XML parser |
503 // or it's an HTML parser whose script nesting level is not greater than | 564 // or it's an HTML parser whose script nesting level is not greater than |
504 // one, | 565 // one, |
505 // and the Document of the HTML parser or XML parser that created | 566 // and the Document of the HTML parser or XML parser that created |
506 // the script element has a style sheet that is blocking scripts" | 567 // the script element has a style sheet that is blocking scripts" |
507 // The last part "... has a style sheet that is blocking scripts" | 568 // The last part "... has a style sheet that is blocking scripts" |
508 // is implemented in Document::isScriptExecutionReady(). | 569 // is implemented in Document::isScriptExecutionReady(). |
509 // Part of the condition check is done in | 570 // Part of the condition check is done in |
510 // HTMLParserScriptRunner::processScriptElementInternal(). | 571 // HTMLParserScriptRunner::processScriptElementInternal(). |
511 // TODO(hiroshige): Clean up the split condition check. | 572 // TODO(hiroshige): Clean up the split condition check. |
512 if (!element_->HasSourceAttribute() && parser_inserted_ && | 573 // We check that the type is "classic" here, because according to the spec |
| 574 // a "module" script doesn't reach the 5th Clause because the 4th Clause |
| 575 // catches all "module" scripts. |
| 576 if (GetScriptType() == ScriptType::kClassic && |
| 577 !element_->HasSourceAttribute() && parser_inserted_ && |
513 !element_document.IsScriptExecutionReady()) { | 578 !element_document.IsScriptExecutionReady()) { |
514 // The former part of this clause is | 579 // The former part of this clause is |
515 // implemented by the caller-side of prepareScript(): | 580 // implemented by the caller-side of prepareScript(): |
516 // - HTMLParserScriptRunner::requestParsingBlockingScript() | 581 // - HTMLParserScriptRunner::requestParsingBlockingScript() |
517 // - TODO(hiroshige): Investigate XMLDocumentParser::endElementNs() | 582 // - TODO(hiroshige): Investigate XMLDocumentParser::endElementNs() |
518 will_be_parser_executed_ = true; | 583 will_be_parser_executed_ = true; |
519 // "Set the element's "ready to be parser-executed" flag." | 584 // "Set the element's "ready to be parser-executed" flag." |
520 ready_to_be_parser_executed_ = true; | 585 ready_to_be_parser_executed_ = true; |
521 | 586 |
522 return true; | 587 return true; |
523 } | 588 } |
524 | 589 |
525 // 3rd Clause: | 590 // 3rd Clause: |
526 // - "If the script's type is "classic", | 591 // - "If the script's type is "classic", |
527 // and the element has a src attribute, | 592 // and the element has a src attribute, |
528 // and the element does not have an async attribute, | 593 // and the element does not have an async attribute, |
529 // and the element does not have the "non-blocking" flag set" | 594 // and the element does not have the "non-blocking" flag set" |
| 595 // - "If the script's type is "module", |
| 596 // and the element does not have an async attribute, |
| 597 // and the element does not have the "non-blocking" flag set" |
530 // TODO(hiroshige): Check the script's type and implement "module" case. | 598 // TODO(hiroshige): Check the script's type and implement "module" case. |
531 if (element_->HasSourceAttribute() && !element_->AsyncAttributeValue() && | 599 if ((GetScriptType() == ScriptType::kClassic && |
532 !non_blocking_) { | 600 element_->HasSourceAttribute() && !element_->AsyncAttributeValue() && |
| 601 !non_blocking_) || |
| 602 (GetScriptType() == ScriptType::kModule && |
| 603 !element_->AsyncAttributeValue() && !non_blocking_)) { |
533 // "Add the element to the end of the list of scripts that will execute | 604 // "Add the element to the end of the list of scripts that will execute |
534 // in order as soon as possible associated with the node document of the | 605 // in order as soon as possible associated with the node document of the |
535 // script element at the time the prepare a script algorithm started." | 606 // script element at the time the prepare a script algorithm started." |
536 pending_script_ = CreatePendingScript(); | 607 pending_script_ = CreatePendingScript(); |
537 async_exec_type_ = ScriptRunner::kInOrder; | 608 async_exec_type_ = ScriptRunner::kInOrder; |
538 // TODO(hiroshige): Here |contextDocument| is used as "node document" | 609 // TODO(hiroshige): Here |contextDocument| is used as "node document" |
539 // while Step 14 uses |elementDocument| as "node document". Fix this. | 610 // while Step 14 uses |elementDocument| as "node document". Fix this. |
540 context_document->GetScriptRunner()->QueueScriptForExecution( | 611 context_document->GetScriptRunner()->QueueScriptForExecution( |
541 this, async_exec_type_); | 612 this, async_exec_type_); |
542 // Note that watchForLoad can immediately call pendingScriptFinished. | 613 // Note that watchForLoad can immediately call pendingScriptFinished. |
543 pending_script_->WatchForLoad(this); | 614 pending_script_->WatchForLoad(this); |
544 // The part "When the script is ready..." is implemented in | 615 // The part "When the script is ready..." is implemented in |
545 // ScriptRunner::notifyScriptReady(). | 616 // ScriptRunner::notifyScriptReady(). |
546 // TODO(hiroshige): Annotate it. | 617 // TODO(hiroshige): Annotate it. |
547 | 618 |
548 return true; | 619 return true; |
549 } | 620 } |
550 | 621 |
551 // 4th Clause: | 622 // 4th Clause: |
552 // - "If the script's type is "classic", and the element has a src attribute" | 623 // - "If the script's type is "classic", and the element has a src attribute" |
553 // TODO(hiroshige): Check the script's type and implement "module" case. | 624 // - "If the script's type is "module"" |
554 if (element_->HasSourceAttribute()) { | 625 if ((GetScriptType() == ScriptType::kClassic && |
| 626 element_->HasSourceAttribute()) || |
| 627 GetScriptType() == ScriptType::kModule) { |
555 // "The element must be added to the set of scripts that will execute | 628 // "The element must be added to the set of scripts that will execute |
556 // as soon as possible of the node document of the script element at the | 629 // as soon as possible of the node document of the script element at the |
557 // time the prepare a script algorithm started." | 630 // time the prepare a script algorithm started." |
558 pending_script_ = CreatePendingScript(); | 631 pending_script_ = CreatePendingScript(); |
559 async_exec_type_ = ScriptRunner::kAsync; | 632 async_exec_type_ = ScriptRunner::kAsync; |
560 pending_script_->StartStreamingIfPossible(&element_->GetDocument(), | 633 pending_script_->StartStreamingIfPossible(&element_->GetDocument(), |
561 ScriptStreamer::kAsync); | 634 ScriptStreamer::kAsync); |
562 // TODO(hiroshige): Here |contextDocument| is used as "node document" | 635 // TODO(hiroshige): Here |contextDocument| is used as "node document" |
563 // while Step 14 uses |elementDocument| as "node document". Fix this. | 636 // while Step 14 uses |elementDocument| as "node document". Fix this. |
564 context_document->GetScriptRunner()->QueueScriptForExecution( | 637 context_document->GetScriptRunner()->QueueScriptForExecution( |
(...skipping 10 matching lines...) Expand all Loading... |
575 // 6th Clause: | 648 // 6th Clause: |
576 // - "Otherwise" | 649 // - "Otherwise" |
577 // "Immediately execute the script block, | 650 // "Immediately execute the script block, |
578 // even if other scripts are already executing." | 651 // even if other scripts are already executing." |
579 // Note: this block is also duplicated in | 652 // Note: this block is also duplicated in |
580 // HTMLParserScriptRunner::processScriptElementInternal(). | 653 // HTMLParserScriptRunner::processScriptElementInternal(). |
581 // TODO(hiroshige): Merge the duplicated code. | 654 // TODO(hiroshige): Merge the duplicated code. |
582 | 655 |
583 // This clause is executed only if the script's type is "classic" | 656 // This clause is executed only if the script's type is "classic" |
584 // and the element doesn't have a src attribute. | 657 // and the element doesn't have a src attribute. |
| 658 DCHECK_EQ(GetScriptType(), ScriptType::kClassic); |
| 659 DCHECK(!is_external_script_); |
585 | 660 |
586 // Reset line numbering for nested writes. | 661 // Reset line numbering for nested writes. |
587 TextPosition position = element_document.IsInDocumentWrite() | 662 TextPosition position = element_document.IsInDocumentWrite() |
588 ? TextPosition() | 663 ? TextPosition() |
589 : script_start_position; | 664 : script_start_position; |
590 KURL script_url = (!element_document.IsInDocumentWrite() && parser_inserted_) | 665 KURL script_url = (!element_document.IsInDocumentWrite() && parser_inserted_) |
591 ? element_document.Url() | 666 ? element_document.Url() |
592 : KURL(); | 667 : KURL(); |
593 | 668 |
594 if (!ExecuteScript(ClassicScript::Create( | 669 if (!ExecuteScript(ClassicScript::Create( |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
662 params.SetDefer(defer); | 737 params.SetDefer(defer); |
663 | 738 |
664 resource_ = ScriptResource::Fetch(params, fetcher); | 739 resource_ = ScriptResource::Fetch(params, fetcher); |
665 | 740 |
666 if (!resource_) | 741 if (!resource_) |
667 return false; | 742 return false; |
668 | 743 |
669 return true; | 744 return true; |
670 } | 745 } |
671 | 746 |
| 747 void ScriptLoader::FetchModuleScriptTree( |
| 748 const KURL& url, |
| 749 Modulator* modulator, |
| 750 const String& nonce, |
| 751 ParserDisposition parser_state, |
| 752 WebURLRequest::FetchCredentialsMode credentials_mode) { |
| 753 // https://html.spec.whatwg.org/#prepare-a-script |
| 754 // 21.6, "module": |
| 755 // "Fetch a module script graph given url, settings, "script", |
| 756 // cryptographic nonce, parser state, and |
| 757 // module script credentials mode." |
| 758 ModuleScriptFetchRequest module_request(url, nonce, parser_state, |
| 759 credentials_mode); |
| 760 |
| 761 module_tree_client_ = ModulePendingScriptTreeClient::Create(); |
| 762 |
| 763 modulator->FetchTree(module_request, module_tree_client_); |
| 764 } |
| 765 |
672 PendingScript* ScriptLoader::CreatePendingScript() { | 766 PendingScript* ScriptLoader::CreatePendingScript() { |
673 CHECK(resource_); | 767 switch (GetScriptType()) { |
674 return ClassicPendingScript::Create(element_, resource_); | 768 case ScriptType::kClassic: |
| 769 CHECK(resource_); |
| 770 return ClassicPendingScript::Create(element_, resource_); |
| 771 case ScriptType::kModule: |
| 772 CHECK(module_tree_client_); |
| 773 return ModulePendingScript::Create(element_, module_tree_client_); |
| 774 } |
| 775 NOTREACHED(); |
| 776 return nullptr; |
675 } | 777 } |
676 | 778 |
677 bool ScriptLoader::ExecuteScript(const Script* script) { | 779 bool ScriptLoader::ExecuteScript(const Script* script) { |
678 double script_exec_start_time = MonotonicallyIncreasingTime(); | 780 double script_exec_start_time = MonotonicallyIncreasingTime(); |
679 bool result = DoExecuteScript(script); | 781 bool result = DoExecuteScript(script); |
680 | 782 |
681 // NOTE: we do not check m_willBeParserExecuted here, since | 783 // NOTE: we do not check m_willBeParserExecuted here, since |
682 // m_willBeParserExecuted is false for inline scripts, and we want to | 784 // m_willBeParserExecuted is false for inline scripts, and we want to |
683 // include inline script execution time as part of parser blocked script | 785 // include inline script execution time as part of parser blocked script |
684 // execution time. | 786 // execution time. |
685 if (async_exec_type_ == ScriptRunner::kNone) | 787 if (async_exec_type_ == ScriptRunner::kNone) |
686 DocumentParserTiming::From(element_->GetDocument()) | 788 DocumentParserTiming::From(element_->GetDocument()) |
687 .RecordParserBlockedOnScriptExecutionDuration( | 789 .RecordParserBlockedOnScriptExecutionDuration( |
688 MonotonicallyIncreasingTime() - script_exec_start_time, | 790 MonotonicallyIncreasingTime() - script_exec_start_time, |
689 WasCreatedDuringDocumentWrite()); | 791 WasCreatedDuringDocumentWrite()); |
690 return result; | 792 return result; |
691 } | 793 } |
692 | 794 |
693 // https://html.spec.whatwg.org/#execute-the-script-block | 795 // https://html.spec.whatwg.org/#execute-the-script-block |
694 // with additional support for HTML imports. | 796 // with additional support for HTML imports. |
695 // Note that Steps 2 and 8 must be handled by the caller of doExecuteScript(), | 797 // Note that Steps 2 and 8 must be handled by the caller of doExecuteScript(), |
696 // i.e. load/error events are dispatched by the caller. | 798 // i.e. load/error events are dispatched by the caller. |
697 // Steps 3--7 are implemented here in doExecuteScript(). | 799 // Steps 3--7 are implemented here in doExecuteScript(). |
698 // TODO(hiroshige): Move event dispatching code to doExecuteScript(). | 800 // TODO(hiroshige): Move event dispatching code to doExecuteScript(). |
699 bool ScriptLoader::DoExecuteScript(const Script* script) { | 801 bool ScriptLoader::DoExecuteScript(const Script* script) { |
700 DCHECK(already_started_); | 802 DCHECK(already_started_); |
| 803 CHECK_EQ(script->GetScriptType(), GetScriptType()); |
701 | 804 |
702 if (script->IsEmpty()) | 805 if (script->IsEmpty()) |
703 return true; | 806 return true; |
704 | 807 |
705 Document* element_document = &(element_->GetDocument()); | 808 Document* element_document = &(element_->GetDocument()); |
706 Document* context_document = element_document->ContextDocument(); | 809 Document* context_document = element_document->ContextDocument(); |
707 if (!context_document) | 810 if (!context_document) |
708 return true; | 811 return true; |
709 | 812 |
710 LocalFrame* frame = context_document->GetFrame(); | 813 LocalFrame* frame = context_document->GetFrame(); |
(...skipping 22 matching lines...) Expand all Loading... |
733 context_document, element_->GetDocument().GetSecurityOrigin())) | 836 context_document, element_->GetDocument().GetSecurityOrigin())) |
734 return false; | 837 return false; |
735 } | 838 } |
736 | 839 |
737 const bool is_imported_script = context_document != element_document; | 840 const bool is_imported_script = context_document != element_document; |
738 | 841 |
739 // 3. "If the script is from an external file, | 842 // 3. "If the script is from an external file, |
740 // or the script's type is module", | 843 // or the script's type is module", |
741 // then increment the ignore-destructive-writes counter of the | 844 // then increment the ignore-destructive-writes counter of the |
742 // script element's node document. Let neutralized doc be that Document." | 845 // script element's node document. Let neutralized doc be that Document." |
743 // TODO(hiroshige): Implement "module" case. | |
744 IgnoreDestructiveWriteCountIncrementer | 846 IgnoreDestructiveWriteCountIncrementer |
745 ignore_destructive_write_count_incrementer( | 847 ignore_destructive_write_count_incrementer( |
746 is_external_script_ || is_imported_script ? context_document : 0); | 848 is_external_script_ || |
| 849 script->GetScriptType() == ScriptType::kModule || |
| 850 is_imported_script |
| 851 ? context_document |
| 852 : 0); |
747 | 853 |
748 // 4. "Let old script element be the value to which the script element's | 854 // 4. "Let old script element be the value to which the script element's |
749 // node document's currentScript object was most recently set." | 855 // node document's currentScript object was most recently set." |
750 // This is implemented as push/popCurrentScript(). | 856 // This is implemented as push/popCurrentScript(). |
751 | 857 |
752 // 5. "Switch on the script's type:" | 858 // 5. "Switch on the script's type:" |
753 // - "classic": | 859 // - "classic": |
754 // 1. "If the script element's root is not a shadow root, | 860 // 1. "If the script element's root is not a shadow root, |
755 // then set the script element's node document's currentScript | 861 // then set the script element's node document's currentScript |
756 // attribute to the script element. Otherwise, set it to null." | 862 // attribute to the script element. Otherwise, set it to null." |
757 context_document->PushCurrentScript(element_.Get()); | 863 // - "module": |
| 864 // 1. "Set the script element's node document's currentScript attribute |
| 865 // to null." |
| 866 ScriptElementBase* current_script = nullptr; |
| 867 if (script->GetScriptType() == ScriptType::kClassic) |
| 868 current_script = element_; |
| 869 context_document->PushCurrentScript(current_script); |
758 | 870 |
| 871 // - "classic": |
759 // 2. "Run the classic script given by the script's script." | 872 // 2. "Run the classic script given by the script's script." |
760 // Note: This is where the script is compiled and actually executed. | 873 // Note: This is where the script is compiled and actually executed. |
| 874 // - "module": |
| 875 // 2. "Run the module script given by the script's script." |
761 script->RunScript(frame, element_->GetDocument().GetSecurityOrigin()); | 876 script->RunScript(frame, element_->GetDocument().GetSecurityOrigin()); |
762 | 877 |
763 // - "module": | |
764 // TODO(hiroshige): Implement this. | |
765 | |
766 // 6. "Set the script element's node document's currentScript attribute | 878 // 6. "Set the script element's node document's currentScript attribute |
767 // to old script element." | 879 // to old script element." |
768 context_document->PopCurrentScript(element_.Get()); | 880 context_document->PopCurrentScript(current_script); |
769 | 881 |
770 return true; | 882 return true; |
771 | 883 |
772 // 7. "Decrement the ignore-destructive-writes counter of neutralized doc, | 884 // 7. "Decrement the ignore-destructive-writes counter of neutralized doc, |
773 // if it was incremented in the earlier step." | 885 // if it was incremented in the earlier step." |
774 // Implemented as the scope out of IgnoreDestructiveWriteCountIncrementer. | 886 // Implemented as the scope out of IgnoreDestructiveWriteCountIncrementer. |
775 } | 887 } |
776 | 888 |
777 void ScriptLoader::Execute() { | 889 void ScriptLoader::Execute() { |
778 DCHECK(!will_be_parser_executed_); | 890 DCHECK(!will_be_parser_executed_); |
779 DCHECK(async_exec_type_ != ScriptRunner::kNone); | 891 DCHECK(async_exec_type_ != ScriptRunner::kNone); |
780 DCHECK(pending_script_->IsExternal()); | 892 DCHECK(pending_script_->IsExternal()); |
781 bool error_occurred = false; | 893 bool error_occurred = false; |
782 Script* script = pending_script_->GetSource(KURL(), error_occurred); | 894 Script* script = pending_script_->GetSource(KURL(), error_occurred); |
783 const bool wasCanceled = pending_script_->WasCanceled(); | 895 const bool wasCanceled = pending_script_->WasCanceled(); |
784 DetachPendingScript(); | 896 DetachPendingScript(); |
785 if (error_occurred) { | 897 if (error_occurred) { |
786 DispatchErrorEvent(); | 898 DispatchErrorEvent(); |
787 } else if (!wasCanceled) { | 899 } else if (!wasCanceled) { |
788 if (ExecuteScript(script)) | 900 if (ExecuteScript(script)) |
789 DispatchLoadEvent(); | 901 DispatchLoadEvent(); |
790 else | 902 else |
791 DispatchErrorEvent(); | 903 DispatchErrorEvent(); |
792 } | 904 } |
793 resource_ = nullptr; | 905 resource_ = nullptr; |
| 906 module_tree_client_ = nullptr; |
794 } | 907 } |
795 | 908 |
796 void ScriptLoader::PendingScriptFinished(PendingScript* pending_script) { | 909 void ScriptLoader::PendingScriptFinished(PendingScript* pending_script) { |
797 DCHECK(!will_be_parser_executed_); | 910 DCHECK(!will_be_parser_executed_); |
798 DCHECK_EQ(pending_script_, pending_script); | 911 DCHECK_EQ(pending_script_, pending_script); |
| 912 DCHECK_EQ(pending_script_->GetScriptType(), GetScriptType()); |
799 | 913 |
800 // We do not need this script in the memory cache. The primary goals of | 914 // We do not need this script in the memory cache. The primary goals of |
801 // sending this fetch request are to let the third party server know | 915 // sending this fetch request are to let the third party server know |
802 // about the document.write scripts intervention and populate the http | 916 // about the document.write scripts intervention and populate the http |
803 // cache for subsequent uses. | 917 // cache for subsequent uses. |
804 if (document_write_intervention_ == | 918 if (document_write_intervention_ == |
805 DocumentWriteIntervention::kFetchDocWrittenScriptDeferIdle) { | 919 DocumentWriteIntervention::kFetchDocWrittenScriptDeferIdle) { |
806 DCHECK_EQ(pending_script_->GetScriptType(), ScriptType::kClassic); | 920 DCHECK_EQ(pending_script_->GetScriptType(), ScriptType::kClassic); |
807 pending_script_->RemoveFromMemoryCache(); | 921 pending_script_->RemoveFromMemoryCache(); |
808 pending_script_->StopWatchingForLoad(); | 922 pending_script_->StopWatchingForLoad(); |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
860 // then abort these steps at this point. The script is not executed. | 974 // then abort these steps at this point. The script is not executed. |
861 return DeprecatedEqualIgnoringCase(event_attribute, "onload") || | 975 return DeprecatedEqualIgnoringCase(event_attribute, "onload") || |
862 DeprecatedEqualIgnoringCase(event_attribute, "onload()"); | 976 DeprecatedEqualIgnoringCase(event_attribute, "onload()"); |
863 } | 977 } |
864 | 978 |
865 String ScriptLoader::ScriptContent() const { | 979 String ScriptLoader::ScriptContent() const { |
866 return element_->TextFromChildren(); | 980 return element_->TextFromChildren(); |
867 } | 981 } |
868 | 982 |
869 } // namespace blink | 983 } // namespace blink |
OLD | NEW |