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