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

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: ModuleTreeLinkerTest.fetchTreeInstantiationFailure 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/CrossOriginAttribute.h"
46 #include "core/html/imports/HTMLImport.h" 48 #include "core/html/imports/HTMLImport.h"
47 #include "core/html/parser/HTMLParserIdioms.h" 49 #include "core/html/parser/HTMLParserIdioms.h"
50 #include "core/loader/modulescript/ModuleScriptFetchRequest.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 30 matching lines...) Expand all
150 154
151 void ScriptLoader::DispatchErrorEvent() { 155 void ScriptLoader::DispatchErrorEvent() {
152 element_->DispatchErrorEvent(); 156 element_->DispatchErrorEvent();
153 } 157 }
154 158
155 void ScriptLoader::DispatchLoadEvent() { 159 void ScriptLoader::DispatchLoadEvent() {
156 element_->DispatchLoadEvent(); 160 element_->DispatchLoadEvent();
157 SetHaveFiredLoadEvent(true); 161 SetHaveFiredLoadEvent(true);
158 } 162 }
159 163
160 bool ScriptLoader::IsValidScriptTypeAndLanguage( 164 namespace {
165
166 bool IsValidClassicScriptTypeAndLanguage(
161 const String& type, 167 const String& type,
162 const String& language, 168 const String& language,
163 LegacyTypeSupport support_legacy_types) { 169 ScriptLoader::LegacyTypeSupport support_legacy_types) {
164 // FIXME: isLegacySupportedJavaScriptLanguage() is not valid HTML5. It is used 170 // FIXME: isLegacySupportedJavaScriptLanguage() is not valid HTML5. It is used
165 // here to maintain backwards compatibility with existing layout tests. The 171 // here to maintain backwards compatibility with existing layout tests. The
166 // specific violations are: 172 // specific violations are:
167 // - Allowing type=javascript. type= should only support MIME types, such as 173 // - Allowing type=javascript. type= should only support MIME types, such as
168 // text/javascript. 174 // text/javascript.
169 // - Allowing a different set of languages for language= and type=. language= 175 // - Allowing a different set of languages for language= and type=. language=
170 // supports Javascript 1.1 and 1.4-1.6, but type= does not. 176 // supports Javascript 1.1 and 1.4-1.6, but type= does not.
171 if (type.IsEmpty()) { 177 if (type.IsEmpty()) {
172 return language.IsEmpty() || // assume text/javascript. 178 return language.IsEmpty() || // assume text/javascript.
173 MIMETypeRegistry::IsSupportedJavaScriptMIMEType("text/" + 179 MIMETypeRegistry::IsSupportedJavaScriptMIMEType("text/" +
174 language) || 180 language) ||
175 MIMETypeRegistry::IsLegacySupportedJavaScriptLanguage(language); 181 MIMETypeRegistry::IsLegacySupportedJavaScriptLanguage(language);
176 } else if (RuntimeEnabledFeatures::moduleScriptsEnabled() &&
177 type == "module") {
178 return true;
179 } else if (MIMETypeRegistry::IsSupportedJavaScriptMIMEType( 182 } else if (MIMETypeRegistry::IsSupportedJavaScriptMIMEType(
180 type.StripWhiteSpace()) || 183 type.StripWhiteSpace()) ||
181 (support_legacy_types == kAllowLegacyTypeInTypeAttribute && 184 (support_legacy_types ==
185 ScriptLoader::kAllowLegacyTypeInTypeAttribute &&
182 MIMETypeRegistry::IsLegacySupportedJavaScriptLanguage(type))) { 186 MIMETypeRegistry::IsLegacySupportedJavaScriptLanguage(type))) {
183 return true; 187 return true;
184 } 188 }
185 189
186 return false; 190 return false;
187 } 191 }
188 192
189 bool ScriptLoader::IsScriptTypeSupported( 193 } // namespace
190 LegacyTypeSupport support_legacy_types) const { 194
195 // Step 6 of https://html.spec.whatwg.org/#prepare-a-script
196 bool ScriptLoader::IsValidScriptTypeAndLanguage(
197 const String& type,
198 const String& language,
199 LegacyTypeSupport support_legacy_types,
200 ScriptType& out_script_type) {
201 if (IsValidClassicScriptTypeAndLanguage(type, language,
202 support_legacy_types)) {
203 // - "If the script block's type string is an ASCII case-insensitive match
204 // for any JavaScript MIME type, the script's type is "classic"."
205 // TODO(hiroshige): Annotate and/or cleanup this step.
206 out_script_type = ScriptType::kClassic;
207 return true;
208 }
209
210 if (RuntimeEnabledFeatures::moduleScriptsEnabled() && type == "module") {
211 // - "If the script block's type string is an ASCII case-insensitive match
212 // for the string "module", the script's type is "module"."
213 out_script_type = ScriptType::kModule;
214 return true;
215 }
216
217 // - "If neither of the above conditions are true, then abort these steps
218 // at this point. No script is executed."
219 return false;
220 }
221
222 bool ScriptLoader::IsScriptTypeSupported(LegacyTypeSupport support_legacy_types,
223 ScriptType& out_script_type) const {
191 return IsValidScriptTypeAndLanguage(element_->TypeAttributeValue(), 224 return IsValidScriptTypeAndLanguage(element_->TypeAttributeValue(),
192 element_->LanguageAttributeValue(), 225 element_->LanguageAttributeValue(),
193 support_legacy_types); 226 support_legacy_types, out_script_type);
194 } 227 }
195 228
196 // https://html.spec.whatwg.org/#prepare-a-script 229 // https://html.spec.whatwg.org/#prepare-a-script
197 bool ScriptLoader::PrepareScript(const TextPosition& script_start_position, 230 bool ScriptLoader::PrepareScript(const TextPosition& script_start_position,
198 LegacyTypeSupport support_legacy_types) { 231 LegacyTypeSupport support_legacy_types) {
199 // 1. "If the script element is marked as having "already started", then 232 // 1. "If the script element is marked as having "already started", then
200 // abort these steps at this point. The script is not executed." 233 // abort these steps at this point. The script is not executed."
201 if (already_started_) 234 if (already_started_)
202 return false; 235 return false;
203 236
(...skipping 20 matching lines...) Expand all
224 // FIXME: HTML5 spec says we should check that all children are either 257 // FIXME: HTML5 spec says we should check that all children are either
225 // comments or empty text nodes. 258 // comments or empty text nodes.
226 if (!element_->HasSourceAttribute() && !element_->HasChildren()) 259 if (!element_->HasSourceAttribute() && !element_->HasChildren())
227 return false; 260 return false;
228 261
229 // 5. "If the element is not connected, then abort these steps. 262 // 5. "If the element is not connected, then abort these steps.
230 // The script is not executed." 263 // The script is not executed."
231 if (!element_->IsConnected()) 264 if (!element_->IsConnected())
232 return false; 265 return false;
233 266
234 // 6. 267 // 6. "Determine the script's type as follows:"
235 // TODO(hiroshige): Annotate and/or cleanup this step. 268 // |script_type_| is set here.
236 if (!IsScriptTypeSupported(support_legacy_types)) 269 if (!IsScriptTypeSupported(support_legacy_types, script_type_))
237 return false; 270 return false;
238 271
239 // 7. "If was-parser-inserted is true, 272 // 7. "If was-parser-inserted is true,
240 // then flag the element as "parser-inserted" again, 273 // then flag the element as "parser-inserted" again,
241 // and set the element's "non-blocking" flag to false." 274 // and set the element's "non-blocking" flag to false."
242 if (was_parser_inserted) { 275 if (was_parser_inserted) {
243 parser_inserted_ = true; 276 parser_inserted_ = true;
244 non_blocking_ = false; 277 non_blocking_ = false;
245 } 278 }
246 279
(...skipping 10 matching lines...) Expand all
257 if (!element_document.ExecutingFrame()) 290 if (!element_document.ExecutingFrame())
258 return false; 291 return false;
259 if (!context_document || !context_document->ExecutingFrame()) 292 if (!context_document || !context_document->ExecutingFrame())
260 return false; 293 return false;
261 294
262 // 10. "If scripting is disabled for the script element, then abort these 295 // 10. "If scripting is disabled for the script element, then abort these
263 // steps at this point. The script is not executed." 296 // steps at this point. The script is not executed."
264 if (!context_document->CanExecuteScripts(kAboutToExecuteScript)) 297 if (!context_document->CanExecuteScripts(kAboutToExecuteScript))
265 return false; 298 return false;
266 299
300 // 11. "If the script element has a nomodule content attribute
301 // and the script's type is "classic", then abort these steps.
302 // The script is not executed."
303 // TODO(japhet): Implement this step.
304
267 // 13. 305 // 13.
268 if (!IsScriptForEventSupported()) 306 if (!IsScriptForEventSupported())
269 return false; 307 return false;
270 308
271 // 14. "If the script element has a charset attribute, 309 // 14. is handled below.
272 // then let encoding be the result of 310
273 // getting an encoding from the value of the charset attribute." 311 // 15. "Let CORS setting be the current state of the element's
274 // "If the script element does not have a charset attribute, 312 // crossorigin content attribute."
275 // or if getting an encoding failed, let encoding 313 CrossOriginAttributeValue cross_origin =
276 // be the same as the encoding of the script element's node document." 314 GetCrossOriginAttributeValue(element_->CrossOriginAttributeValue());
277 // TODO(hiroshige): Should we handle failure in getting an encoding? 315
278 String encoding; 316 // 16. is handled below.
279 if (!element_->CharsetAttributeValue().IsEmpty()) 317
280 encoding = element_->CharsetAttributeValue(); 318 // 17. "If the script element has a nonce attribute,
281 else 319 // then let cryptographic nonce be that attribute's value.
282 encoding = element_document.characterSet(); 320 // Otherwise, let cryptographic nonce be the empty string."
283 321 String nonce;
284 // Steps 15--20 are handled in fetchScript(). 322 if (element_->IsNonceableElement())
323 nonce = element_->nonce();
324
325 // 18. is handled below.
326
327 // 19. "Let parser state be "parser-inserted"
328 // if the script element has been flagged as "parser-inserted",
329 // and "not parser-inserted" otherwise."
330 ParserDisposition parser_state =
331 IsParserInserted() ? kParserInserted : kNotParserInserted;
285 332
286 // 21. "If the element has a src content attribute, run these substeps:" 333 // 21. "If the element has a src content attribute, run these substeps:"
287 if (element_->HasSourceAttribute()) { 334 if (element_->HasSourceAttribute()) {
288 FetchParameters::DeferOption defer = FetchParameters::kNoDefer; 335 // 21.1. Let src be the value of the element's src attribute.
289 if (!parser_inserted_ || element_->AsyncAttributeValue() || 336 String src =
290 element_->DeferAttributeValue()) 337 StripLeadingAndTrailingHTMLSpaces(element_->SourceAttributeValue());
291 defer = FetchParameters::kLazyLoad; 338
292 if (document_write_intervention_ == 339 // 21.2. "If src is the empty string, queue a task to
293 DocumentWriteIntervention::kFetchDocWrittenScriptDeferIdle) 340 // fire an event named error at the element, and abort these steps."
294 defer = FetchParameters::kIdleLoad; 341 if (src.IsEmpty()) {
295 if (!FetchScript(element_->SourceAttributeValue(), encoding, defer)) 342 // TODO(hiroshige): Make this asynchronous. Currently we fire the error
343 // event synchronously to keep the existing behavior.
344 DispatchErrorEvent();
296 return false; 345 return false;
346 }
347
348 // 21.3. "Set the element's from an external file flag."
349 is_external_script_ = true;
350
351 // 21.4. "Parse src relative to the element's node document."
352 KURL url = element_document.CompleteURL(src);
353
354 // 21.5. "If the previous step failed, queue a task to
355 // fire an event named error at the element, and abort these steps."
356 if (!url.IsValid()) {
357 // TODO(hiroshige): Make this asynchronous. Currently we fire the error
358 // event synchronously to keep the existing behavior.
359 DispatchErrorEvent();
360 return false;
361 }
362
363 DCHECK(!resource_);
364 DCHECK(!module_tree_client_);
365
366 // 21.6. "Switch on the script's type:"
367 if (GetScriptType() == ScriptType::kClassic) {
368 // - "classic":
369
370 // 14. "If the script element has a charset attribute,
371 // then let encoding be the result of
372 // getting an encoding from the value of the charset attribute."
373 // "If the script element does not have a charset attribute,
374 // or if getting an encoding failed, let encoding
375 // be the same as the encoding of the script element's node
376 // document."
377 // TODO(hiroshige): Should we handle failure in getting an encoding?
378 String encoding;
379 if (!element_->CharsetAttributeValue().IsEmpty())
380 encoding = element_->CharsetAttributeValue();
381 else
382 encoding = element_document.characterSet();
383
384 // Step 16 is skipped because "module script credentials" is not used
385 // for classic scripts.
386
387 // 18. "If the script element has an integrity attribute,
388 // then let integrity metadata be that attribute's value.
389 // Otherwise, let integrity metadata be the empty string."
390 String integrity_attr = element_->IntegrityAttributeValue();
391 IntegrityMetadataSet integrity_metadata;
392 if (!integrity_attr.IsEmpty()) {
393 SubresourceIntegrity::ParseIntegrityAttribute(
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_);
438 }
439
440 // "When the chosen algorithm asynchronously completes, set
441 // the script's script to the result. At that time, the script is ready."
442 // When the script is ready, PendingScriptClient::pendingScriptFinished()
443 // is used as the notification, and the action to take when
444 // the script is ready is specified later, in
445 // - ScriptLoader::PrepareScript(), or
446 // - HTMLParserScriptRunner,
447 // depending on the conditions in Step 23 of "prepare a script".
297 } 448 }
298 449
299 // 22. "If the element does not have a src content attribute, 450 // 22. "If the element does not have a src content attribute,
300 // run these substeps:" 451 // run these substeps:"
301 452 if (!element_->HasSourceAttribute()) {
302 // 22.1. "Let source text be the value of the text IDL attribute." 453 // 22.1. "Let source text be the value of the text IDL attribute."
303 // This step is done later: 454 // This step is done later:
304 // - in ScriptLoader::pendingScript() (Step 23, 6th Clause), 455 // - in ScriptLoader::pendingScript() (Step 23, 6th Clause),
305 // as Element::textFromChildren() in ScriptLoader::scriptContent(), 456 // as Element::textFromChildren() in ScriptLoader::scriptContent(),
306 // - in HTMLParserScriptRunner::processScriptElementInternal() 457 // - in HTMLParserScriptRunner::processScriptElementInternal()
307 // (Duplicated code of Step 23, 6th Clause), 458 // (Duplicated code of Step 23, 6th Clause),
308 // as Element::textContent(), 459 // as Element::textContent(),
309 // - in XMLDocumentParser::endElementNs() (Step 23, 5th Clause), 460 // - in XMLDocumentParser::endElementNs() (Step 23, 5th Clause),
310 // as Element::textFromChildren() in ScriptLoader::scriptContent(), 461 // as Element::textFromChildren() in ScriptLoader::scriptContent(),
311 // - PendingScript::getSource() (Indirectly used via 462 // - PendingScript::getSource() (Indirectly used via
312 // HTMLParserScriptRunner::processScriptElementInternal(), 463 // HTMLParserScriptRunner::processScriptElementInternal(),
313 // Step 23, 5th Clause), 464 // Step 23, 5th Clause),
314 // as Element::textContent(). 465 // as Element::textContent().
315 // TODO(hiroshige): Make them merged or consistent. 466 // TODO(hiroshige): Make them merged or consistent.
316 467
317 // 22.2. "Switch on the script's type:" 468 // 22.2. "Switch on the script's type:"
318 // TODO(hiroshige): Clarify how Step 22.2 is implemented for "classic". 469 switch (GetScriptType()) {
319 // TODO(hiroshige): Implement Step 22.2 for "module". 470 // - "classic":
471 case ScriptType::kClassic:
472 // TODO(hiroshige): Clarify how Step 22.2 is implemented for "classic".
473 break;
474
475 // - "module":
476 case ScriptType::kModule:
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 }
320 487
321 // [Intervention] 488 // [Intervention]
322 // Since the asynchronous, low priority fetch for doc.written blocked 489 // Since the asynchronous, low priority fetch for doc.written blocked
323 // 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
324 // completion to be able to remove it from the memory cache. 491 // completion to be able to remove it from the memory cache.
325 if (document_write_intervention_ == 492 if (GetScriptType() == ScriptType::kClassic &&
326 DocumentWriteIntervention::kFetchDocWrittenScriptDeferIdle) { 493 document_write_intervention_ ==
494 DocumentWriteIntervention::kFetchDocWrittenScriptDeferIdle) {
327 pending_script_ = CreatePendingScript(); 495 pending_script_ = CreatePendingScript();
328 pending_script_->WatchForLoad(this); 496 pending_script_->WatchForLoad(this);
329 return true; 497 return true;
330 } 498 }
331 499
332 // 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
333 // situation:" 501 // situation:"
334 502
335 // 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
336 // a part of Step 23, when |m_willBeParserExecuted| is true: 504 // a part of Step 23, when |m_willBeParserExecuted| is true:
337 // - |m_willBeParserExecuted| 505 // - |m_willBeParserExecuted|
338 // - |m_willExecuteWhenDocumentFinishedParsing| 506 // - |m_willExecuteWhenDocumentFinishedParsing|
339 // - |m_readyToBeParserExecuted| 507 // - |m_readyToBeParserExecuted|
340 // TODO(hiroshige): Clean up the dependency. 508 // TODO(hiroshige): Clean up the dependency.
341 509
342 // 1st Clause: 510 // 1st Clause:
343 // - "If the script's type is "classic", and 511 // - "If the script's type is "classic", and
344 // 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,
345 // and the element has been flagged as "parser-inserted", 513 // and the element has been flagged as "parser-inserted",
346 // and the element does not have an async attribute" 514 // and the element does not have an async attribute"
347 // TODO(hiroshige): Check the script's type and implement "module" case. 515 // - "If the script's type is "module",
348 if (element_->HasSourceAttribute() && element_->DeferAttributeValue() && 516 // and the element has been flagged as "parser-inserted",
349 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())) {
350 // This clause is implemented by the caller-side of prepareScript(): 523 // This clause is implemented by the caller-side of prepareScript():
351 // - HTMLParserScriptRunner::requestDeferredScript(), and 524 // - HTMLParserScriptRunner::requestDeferredScript(), and
352 // - TODO(hiroshige): Investigate XMLDocumentParser::endElementNs() 525 // - TODO(hiroshige): Investigate XMLDocumentParser::endElementNs()
353 will_execute_when_document_finished_parsing_ = true; 526 will_execute_when_document_finished_parsing_ = true;
354 will_be_parser_executed_ = true; 527 will_be_parser_executed_ = true;
355 528
356 return true; 529 return true;
357 } 530 }
358 531
359 // 2nd Clause: 532 // 2nd Clause:
360 // - "If the script's type is "classic", 533 // - "If the script's type is "classic",
361 // and the element has a src attribute, 534 // and the element has a src attribute,
362 // and the element has been flagged as "parser-inserted", 535 // and the element has been flagged as "parser-inserted",
363 // and the element does not have an async attribute" 536 // and the element does not have an async attribute"
364 // TODO(hiroshige): Check the script's type. 537 // TODO(hiroshige): Check the script's type.
365 if (element_->HasSourceAttribute() && parser_inserted_ && 538 if (GetScriptType() == ScriptType::kClassic &&
539 element_->HasSourceAttribute() && parser_inserted_ &&
366 !element_->AsyncAttributeValue()) { 540 !element_->AsyncAttributeValue()) {
367 // This clause is implemented by the caller-side of prepareScript(): 541 // This clause is implemented by the caller-side of prepareScript():
368 // - HTMLParserScriptRunner::requestParsingBlockingScript() 542 // - HTMLParserScriptRunner::requestParsingBlockingScript()
369 // - TODO(hiroshige): Investigate XMLDocumentParser::endElementNs() 543 // - TODO(hiroshige): Investigate XMLDocumentParser::endElementNs()
370 will_be_parser_executed_ = true; 544 will_be_parser_executed_ = true;
371 545
372 return true; 546 return true;
373 } 547 }
374 548
375 // 5th Clause: 549 // 5th Clause:
376 // TODO(hiroshige): Reorder the clauses to match the spec. 550 // TODO(hiroshige): Reorder the clauses to match the spec.
377 // - "If the element does not have a src attribute, 551 // - "If the element does not have a src attribute,
378 // and the element has been flagged as "parser-inserted", 552 // and the element has been flagged as "parser-inserted",
379 // 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
380 // 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
381 // one, 555 // one,
382 // 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
383 // the script element has a style sheet that is blocking scripts" 557 // the script element has a style sheet that is blocking scripts"
384 // The last part "... has a style sheet that is blocking scripts" 558 // The last part "... has a style sheet that is blocking scripts"
385 // is implemented in Document::isScriptExecutionReady(). 559 // is implemented in Document::isScriptExecutionReady().
386 // Part of the condition check is done in 560 // Part of the condition check is done in
387 // HTMLParserScriptRunner::processScriptElementInternal(). 561 // HTMLParserScriptRunner::processScriptElementInternal().
388 // TODO(hiroshige): Clean up the split condition check. 562 // TODO(hiroshige): Clean up the split condition check.
389 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_ &&
390 !element_document.IsScriptExecutionReady()) { 568 !element_document.IsScriptExecutionReady()) {
391 // The former part of this clause is 569 // The former part of this clause is
392 // implemented by the caller-side of prepareScript(): 570 // implemented by the caller-side of prepareScript():
393 // - HTMLParserScriptRunner::requestParsingBlockingScript() 571 // - HTMLParserScriptRunner::requestParsingBlockingScript()
394 // - TODO(hiroshige): Investigate XMLDocumentParser::endElementNs() 572 // - TODO(hiroshige): Investigate XMLDocumentParser::endElementNs()
395 will_be_parser_executed_ = true; 573 will_be_parser_executed_ = true;
396 // "Set the element's "ready to be parser-executed" flag." 574 // "Set the element's "ready to be parser-executed" flag."
397 ready_to_be_parser_executed_ = true; 575 ready_to_be_parser_executed_ = true;
398 576
399 return true; 577 return true;
400 } 578 }
401 579
402 // 3rd Clause: 580 // 3rd Clause:
403 // - "If the script's type is "classic", 581 // - "If the script's type is "classic",
404 // and the element has a src attribute, 582 // and the element has a src attribute,
405 // and the element does not have an async attribute, 583 // and the element does not have an async attribute,
406 // 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"
407 // TODO(hiroshige): Check the script's type and implement "module" case. 588 // TODO(hiroshige): Check the script's type and implement "module" case.
408 if (element_->HasSourceAttribute() && !element_->AsyncAttributeValue() && 589 if ((GetScriptType() == ScriptType::kClassic &&
409 !non_blocking_) { 590 element_->HasSourceAttribute() && !element_->AsyncAttributeValue() &&
591 !non_blocking_) ||
592 (GetScriptType() == ScriptType::kModule &&
593 !element_->AsyncAttributeValue() && !non_blocking_)) {
410 // "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
411 // 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
412 // script element at the time the prepare a script algorithm started." 596 // script element at the time the prepare a script algorithm started."
413 pending_script_ = CreatePendingScript(); 597 pending_script_ = CreatePendingScript();
414 async_exec_type_ = ScriptRunner::kInOrder; 598 async_exec_type_ = ScriptRunner::kInOrder;
415 // TODO(hiroshige): Here |contextDocument| is used as "node document" 599 // TODO(hiroshige): Here |contextDocument| is used as "node document"
416 // while Step 14 uses |elementDocument| as "node document". Fix this. 600 // while Step 14 uses |elementDocument| as "node document". Fix this.
417 context_document->GetScriptRunner()->QueueScriptForExecution( 601 context_document->GetScriptRunner()->QueueScriptForExecution(
418 this, async_exec_type_); 602 this, async_exec_type_);
419 // Note that watchForLoad can immediately call pendingScriptFinished. 603 // Note that watchForLoad can immediately call pendingScriptFinished.
420 pending_script_->WatchForLoad(this); 604 pending_script_->WatchForLoad(this);
421 // The part "When the script is ready..." is implemented in 605 // The part "When the script is ready..." is implemented in
422 // ScriptRunner::notifyScriptReady(). 606 // ScriptRunner::notifyScriptReady().
423 // TODO(hiroshige): Annotate it. 607 // TODO(hiroshige): Annotate it.
424 608
425 return true; 609 return true;
426 } 610 }
427 611
428 // 4th Clause: 612 // 4th Clause:
429 // - "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"
430 // TODO(hiroshige): Check the script's type and implement "module" case. 614 // - "If the script's type is "module""
431 if (element_->HasSourceAttribute()) { 615 if ((GetScriptType() == ScriptType::kClassic &&
616 element_->HasSourceAttribute()) ||
617 GetScriptType() == ScriptType::kModule) {
432 // "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
433 // 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
434 // time the prepare a script algorithm started." 620 // time the prepare a script algorithm started."
435 pending_script_ = CreatePendingScript(); 621 pending_script_ = CreatePendingScript();
436 async_exec_type_ = ScriptRunner::kAsync; 622 async_exec_type_ = ScriptRunner::kAsync;
437 pending_script_->StartStreamingIfPossible(&element_->GetDocument(), 623 pending_script_->StartStreamingIfPossible(&element_->GetDocument(),
438 ScriptStreamer::kAsync); 624 ScriptStreamer::kAsync);
439 // TODO(hiroshige): Here |contextDocument| is used as "node document" 625 // TODO(hiroshige): Here |contextDocument| is used as "node document"
440 // while Step 14 uses |elementDocument| as "node document". Fix this. 626 // while Step 14 uses |elementDocument| as "node document". Fix this.
441 context_document->GetScriptRunner()->QueueScriptForExecution( 627 context_document->GetScriptRunner()->QueueScriptForExecution(
(...skipping 10 matching lines...) Expand all
452 // 6th Clause: 638 // 6th Clause:
453 // - "Otherwise" 639 // - "Otherwise"
454 // "Immediately execute the script block, 640 // "Immediately execute the script block,
455 // even if other scripts are already executing." 641 // even if other scripts are already executing."
456 // Note: this block is also duplicated in 642 // Note: this block is also duplicated in
457 // HTMLParserScriptRunner::processScriptElementInternal(). 643 // HTMLParserScriptRunner::processScriptElementInternal().
458 // TODO(hiroshige): Merge the duplicated code. 644 // TODO(hiroshige): Merge the duplicated code.
459 645
460 // 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"
461 // 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_);
462 650
463 // Reset line numbering for nested writes. 651 // Reset line numbering for nested writes.
464 TextPosition position = element_document.IsInDocumentWrite() 652 TextPosition position = element_document.IsInDocumentWrite()
465 ? TextPosition() 653 ? TextPosition()
466 : script_start_position; 654 : script_start_position;
467 KURL script_url = (!element_document.IsInDocumentWrite() && parser_inserted_) 655 KURL script_url = (!element_document.IsInDocumentWrite() && parser_inserted_)
468 ? element_document.Url() 656 ? element_document.Url()
469 : KURL(); 657 : KURL();
470 658
471 if (!ExecuteScript(ClassicScript::Create( 659 if (!ExecuteScript(ClassicScript::Create(
472 ScriptSourceCode(ScriptContent(), script_url, position)))) { 660 ScriptSourceCode(ScriptContent(), script_url, position)))) {
473 DispatchErrorEvent(); 661 DispatchErrorEvent();
474 return false; 662 return false;
475 } 663 }
476 664
477 return true; 665 return true;
478 } 666 }
479 667
480 // Steps 15--21 of https://html.spec.whatwg.org/#prepare-a-script 668 bool ScriptLoader::FetchClassicScript(
481 bool ScriptLoader::FetchScript(const String& source_url, 669 const KURL& url,
482 const String& encoding, 670 ResourceFetcher* fetcher,
483 FetchParameters::DeferOption defer) { 671 const String& nonce,
484 Document* element_document = &(element_->GetDocument()); 672 const IntegrityMetadataSet& integrity_metadata,
485 if (!element_->IsConnected() || element_->GetDocument() != element_document) 673 ParserDisposition parser_state,
486 return false; 674 CrossOriginAttributeValue cross_origin,
675 SecurityOrigin* security_origin,
676 const String& encoding) {
677 // https://html.spec.whatwg.org/#prepare-a-script
678 // 21.6, "classic":
679 // "Fetch a classic script given url, settings, ..."
680 ResourceRequest resource_request(url);
487 681
488 DCHECK(!resource_); 682 // [Intervention]
489 // 21. "If the element has a src content attribute, run these substeps:" 683 if (document_write_intervention_ ==
490 if (!StripLeadingAndTrailingHTMLSpaces(source_url).IsEmpty()) { 684 DocumentWriteIntervention::kFetchDocWrittenScriptDeferIdle) {
491 // 21.4. "Parse src relative to the element's node document." 685 resource_request.SetHTTPHeaderField(
492 ResourceRequest resource_request(element_document->CompleteURL(source_url)); 686 "Intervention",
493 687 "<https://www.chromestatus.com/feature/5718547946799104>");
494 // [Intervention]
495 if (document_write_intervention_ ==
496 DocumentWriteIntervention::kFetchDocWrittenScriptDeferIdle) {
497 resource_request.SetHTTPHeaderField(
498 "Intervention",
499 "<https://www.chromestatus.com/feature/5718547946799104>");
500 }
501
502 FetchParameters params(resource_request, element_->InitiatorName());
503
504 // 15. "Let CORS setting be the current state of the element's
505 // crossorigin content attribute."
506 CrossOriginAttributeValue cross_origin =
507 GetCrossOriginAttributeValue(element_->CrossOriginAttributeValue());
508
509 // 16. "Let module script credentials mode be determined by switching
510 // on CORS setting:"
511 // TODO(hiroshige): Implement this step for "module".
512
513 // 21.6, "classic": "Fetch a classic script given ... CORS setting
514 // ... and encoding."
515 if (cross_origin != kCrossOriginAttributeNotSet) {
516 params.SetCrossOriginAccessControl(element_document->GetSecurityOrigin(),
517 cross_origin);
518 }
519
520 params.SetCharset(encoding);
521
522 // 17. "If the script element has a nonce attribute,
523 // then let cryptographic nonce be that attribute's value.
524 // Otherwise, let cryptographic nonce be the empty string."
525 if (element_->IsNonceableElement())
526 params.SetContentSecurityPolicyNonce(element_->nonce());
527
528 // 19. "Let parser state be "parser-inserted"
529 // if the script element has been flagged as "parser-inserted",
530 // and "not parser-inserted" otherwise."
531 params.SetParserDisposition(IsParserInserted() ? kParserInserted
532 : kNotParserInserted);
533
534 params.SetDefer(defer);
535
536 // 18. "If the script element has an integrity attribute,
537 // then let integrity metadata be that attribute's value.
538 // Otherwise, let integrity metadata be the empty string."
539 String integrity_attr = element_->IntegrityAttributeValue();
540 if (!integrity_attr.IsEmpty()) {
541 IntegrityMetadataSet metadata_set;
542 SubresourceIntegrity::ParseIntegrityAttribute(
543 integrity_attr, metadata_set, element_document);
544 params.SetIntegrityMetadata(metadata_set);
545 }
546
547 // 21.6. "Switch on the script's type:"
548
549 // - "classic":
550 // "Fetch a classic script given url, settings, cryptographic nonce,
551 // integrity metadata, parser state, CORS setting, and encoding."
552 resource_ = ScriptResource::Fetch(params, element_document->Fetcher());
553
554 // - "module":
555 // "Fetch a module script graph given url, settings, "script",
556 // cryptographic nonce, parser state, and
557 // module script credentials mode."
558 // TODO(kouhei, hiroshige): Implement this.
559
560 // "When the chosen algorithm asynchronously completes, set
561 // the script's script to the result. At that time, the script is ready."
562 // When the script is ready, PendingScriptClient::pendingScriptFinished()
563 // is used as the notification, and the action to take when
564 // the script is ready is specified later, in
565 // - ScriptLoader::prepareScript(), or
566 // - HTMLParserScriptRunner,
567 // depending on the conditions in Step 23 of "prepare a script".
568
569 // 21.3. "Set the element's from an external file flag."
570 is_external_script_ = true;
571 } 688 }
572 689
573 if (!resource_) { 690 FetchParameters params(resource_request, element_->InitiatorName());
574 // 21.2. "If src is the empty string, queue a task to 691
575 // fire an event named error at the element, and abort these steps." 692 // "... cryptographic nonce, ..."
576 // 21.5. "If the previous step failed, queue a task to 693 params.SetContentSecurityPolicyNonce(nonce);
577 // fire an event named error at the element, and abort these steps." 694
578 // TODO(hiroshige): Make this asynchronous. 695 // "... integrity metadata, ..."
579 DispatchErrorEvent(); 696 params.SetIntegrityMetadata(integrity_metadata);
697
698 // "... parser state, ..."
699 params.SetParserDisposition(parser_state);
700
701 // "... CORS setting, ..."
702 if (cross_origin != kCrossOriginAttributeNotSet) {
703 params.SetCrossOriginAccessControl(security_origin, cross_origin);
704 }
705
706 // "... and encoding."
707 params.SetCharset(encoding);
708
709 // This DeferOption logic is only for classic scripts, as we always set
710 // |kLazyLoad| for module scripts in ModuleScriptLoader.
711 FetchParameters::DeferOption defer = FetchParameters::kNoDefer;
712 if (!parser_inserted_ || element_->AsyncAttributeValue() ||
713 element_->DeferAttributeValue())
714 defer = FetchParameters::kLazyLoad;
715 if (document_write_intervention_ ==
716 DocumentWriteIntervention::kFetchDocWrittenScriptDeferIdle)
717 defer = FetchParameters::kIdleLoad;
718 params.SetDefer(defer);
719
720 resource_ = ScriptResource::Fetch(params, fetcher);
721
722 if (!resource_)
580 return false; 723 return false;
581 }
582 724
583 // [Intervention] 725 // [Intervention]
584 if (created_during_document_write_ && 726 if (created_during_document_write_ &&
585 resource_->GetResourceRequest().GetCachePolicy() == 727 resource_->GetResourceRequest().GetCachePolicy() ==
586 WebCachePolicy::kReturnCacheDataDontLoad) { 728 WebCachePolicy::kReturnCacheDataDontLoad) {
587 document_write_intervention_ = 729 document_write_intervention_ =
588 DocumentWriteIntervention::kDoNotFetchDocWrittenScript; 730 DocumentWriteIntervention::kDoNotFetchDocWrittenScript;
589 } 731 }
590 732
591 return true; 733 return true;
592 } 734 }
593 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
594 PendingScript* ScriptLoader::CreatePendingScript() { 755 PendingScript* ScriptLoader::CreatePendingScript() {
595 CHECK(resource_); 756 switch (GetScriptType()) {
596 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;
597 } 766 }
598 767
599 bool ScriptLoader::ExecuteScript(const Script* script) { 768 bool ScriptLoader::ExecuteScript(const Script* script) {
600 double script_exec_start_time = MonotonicallyIncreasingTime(); 769 double script_exec_start_time = MonotonicallyIncreasingTime();
601 bool result = DoExecuteScript(script); 770 bool result = DoExecuteScript(script);
602 771
603 // NOTE: we do not check m_willBeParserExecuted here, since 772 // NOTE: we do not check m_willBeParserExecuted here, since
604 // m_willBeParserExecuted is false for inline scripts, and we want to 773 // m_willBeParserExecuted is false for inline scripts, and we want to
605 // include inline script execution time as part of parser blocked script 774 // include inline script execution time as part of parser blocked script
606 // execution time. 775 // execution time.
607 if (async_exec_type_ == ScriptRunner::kNone) 776 if (async_exec_type_ == ScriptRunner::kNone)
608 DocumentParserTiming::From(element_->GetDocument()) 777 DocumentParserTiming::From(element_->GetDocument())
609 .RecordParserBlockedOnScriptExecutionDuration( 778 .RecordParserBlockedOnScriptExecutionDuration(
610 MonotonicallyIncreasingTime() - script_exec_start_time, 779 MonotonicallyIncreasingTime() - script_exec_start_time,
611 WasCreatedDuringDocumentWrite()); 780 WasCreatedDuringDocumentWrite());
612 return result; 781 return result;
613 } 782 }
614 783
615 // https://html.spec.whatwg.org/#execute-the-script-block 784 // https://html.spec.whatwg.org/#execute-the-script-block
616 // with additional support for HTML imports. 785 // with additional support for HTML imports.
617 // 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(),
618 // i.e. load/error events are dispatched by the caller. 787 // i.e. load/error events are dispatched by the caller.
619 // Steps 3--7 are implemented here in doExecuteScript(). 788 // Steps 3--7 are implemented here in doExecuteScript().
620 // TODO(hiroshige): Move event dispatching code to doExecuteScript(). 789 // TODO(hiroshige): Move event dispatching code to doExecuteScript().
621 bool ScriptLoader::DoExecuteScript(const Script* script) { 790 bool ScriptLoader::DoExecuteScript(const Script* script) {
622 DCHECK(already_started_); 791 DCHECK(already_started_);
792 CHECK_EQ(script->GetScriptType(), GetScriptType());
623 793
624 if (script->IsEmpty()) 794 if (script->IsEmpty())
625 return true; 795 return true;
626 796
627 Document* element_document = &(element_->GetDocument()); 797 Document* element_document = &(element_->GetDocument());
628 Document* context_document = element_document->ContextDocument(); 798 Document* context_document = element_document->ContextDocument();
629 if (!context_document) 799 if (!context_document)
630 return true; 800 return true;
631 801
632 LocalFrame* frame = context_document->GetFrame(); 802 LocalFrame* frame = context_document->GetFrame();
(...skipping 22 matching lines...) Expand all
655 context_document, element_->GetDocument().GetSecurityOrigin())) 825 context_document, element_->GetDocument().GetSecurityOrigin()))
656 return false; 826 return false;
657 } 827 }
658 828
659 const bool is_imported_script = context_document != element_document; 829 const bool is_imported_script = context_document != element_document;
660 830
661 // 3. "If the script is from an external file, 831 // 3. "If the script is from an external file,
662 // or the script's type is module", 832 // or the script's type is module",
663 // then increment the ignore-destructive-writes counter of the 833 // then increment the ignore-destructive-writes counter of the
664 // script element's node document. Let neutralized doc be that Document." 834 // script element's node document. Let neutralized doc be that Document."
665 // TODO(hiroshige): Implement "module" case.
666 IgnoreDestructiveWriteCountIncrementer 835 IgnoreDestructiveWriteCountIncrementer
667 ignore_destructive_write_count_incrementer( 836 ignore_destructive_write_count_incrementer(
668 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);
669 842
670 // 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
671 // node document's currentScript object was most recently set." 844 // node document's currentScript object was most recently set."
672 // This is implemented as push/popCurrentScript(). 845 // This is implemented as push/popCurrentScript().
673 846
674 // 5. "Switch on the script's type:" 847 // 5. "Switch on the script's type:"
675 // - "classic": 848 // - "classic":
676 // 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,
677 // then set the script element's node document's currentScript 850 // then set the script element's node document's currentScript
678 // attribute to the script element. Otherwise, set it to null." 851 // attribute to the script element. Otherwise, set it to null."
679 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);
680 859
860 // - "classic":
681 // 2. "Run the classic script given by the script's script." 861 // 2. "Run the classic script given by the script's script."
682 // 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."
683 script->RunScript(frame, element_->GetDocument().GetSecurityOrigin()); 865 script->RunScript(frame, element_->GetDocument().GetSecurityOrigin());
684 866
685 // - "module":
686 // TODO(hiroshige): Implement this.
687
688 // 6. "Set the script element's node document's currentScript attribute 867 // 6. "Set the script element's node document's currentScript attribute
689 // to old script element." 868 // to old script element."
690 context_document->PopCurrentScript(element_.Get()); 869 context_document->PopCurrentScript(current_script);
691 870
692 return true; 871 return true;
693 872
694 // 7. "Decrement the ignore-destructive-writes counter of neutralized doc, 873 // 7. "Decrement the ignore-destructive-writes counter of neutralized doc,
695 // if it was incremented in the earlier step." 874 // if it was incremented in the earlier step."
696 // Implemented as the scope out of IgnoreDestructiveWriteCountIncrementer. 875 // Implemented as the scope out of IgnoreDestructiveWriteCountIncrementer.
697 } 876 }
698 877
699 void ScriptLoader::Execute() { 878 void ScriptLoader::Execute() {
700 DCHECK(!will_be_parser_executed_); 879 DCHECK(!will_be_parser_executed_);
701 DCHECK(async_exec_type_ != ScriptRunner::kNone); 880 DCHECK(async_exec_type_ != ScriptRunner::kNone);
702 DCHECK(pending_script_->GetResource()); 881 DCHECK(pending_script_->IsExternal());
703 bool error_occurred = false; 882 bool error_occurred = false;
704 Script* script = pending_script_->GetSource(KURL(), error_occurred); 883 Script* script = pending_script_->GetSource(KURL(), error_occurred);
884 const bool wasCanceled = pending_script_->WasCanceled();
705 DetachPendingScript(); 885 DetachPendingScript();
706 if (error_occurred) { 886 if (error_occurred) {
707 DispatchErrorEvent(); 887 DispatchErrorEvent();
708 } else if (!resource_->WasCanceled()) { 888 } else if (!wasCanceled) {
709 if (ExecuteScript(script)) 889 if (ExecuteScript(script))
710 DispatchLoadEvent(); 890 DispatchLoadEvent();
711 else 891 else
712 DispatchErrorEvent(); 892 DispatchErrorEvent();
713 } 893 }
714 resource_ = nullptr; 894 resource_ = nullptr;
895 module_tree_client_ = nullptr;
715 } 896 }
716 897
717 void ScriptLoader::PendingScriptFinished(PendingScript* pending_script) { 898 void ScriptLoader::PendingScriptFinished(PendingScript* pending_script) {
718 DCHECK(!will_be_parser_executed_); 899 DCHECK(!will_be_parser_executed_);
719 DCHECK_EQ(pending_script_, pending_script); 900 DCHECK_EQ(pending_script_, pending_script);
720 DCHECK_EQ(pending_script->GetResource(), resource_); 901 DCHECK_EQ(pending_script_->GetScriptType(), GetScriptType());
721 902
722 // 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
723 // 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
724 // about the document.write scripts intervention and populate the http 905 // about the document.write scripts intervention and populate the http
725 // cache for subsequent uses. 906 // cache for subsequent uses.
726 if (document_write_intervention_ == 907 if (document_write_intervention_ ==
727 DocumentWriteIntervention::kFetchDocWrittenScriptDeferIdle) { 908 DocumentWriteIntervention::kFetchDocWrittenScriptDeferIdle) {
728 GetMemoryCache()->Remove(pending_script_->GetResource()); 909 DCHECK_EQ(pending_script_->GetScriptType(), ScriptType::kClassic);
910 pending_script_->RemoveFromMemoryCache();
729 pending_script_->StopWatchingForLoad(); 911 pending_script_->StopWatchingForLoad();
730 return; 912 return;
731 } 913 }
732 914
733 DCHECK(async_exec_type_ != ScriptRunner::kNone); 915 DCHECK(async_exec_type_ != ScriptRunner::kNone);
734 916
735 Document* context_document = element_->GetDocument().ContextDocument(); 917 Document* context_document = element_->GetDocument().ContextDocument();
736 if (!context_document) { 918 if (!context_document) {
737 DetachPendingScript(); 919 DetachPendingScript();
738 return; 920 return;
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
781 // 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.
782 return DeprecatedEqualIgnoringCase(event_attribute, "onload") || 964 return DeprecatedEqualIgnoringCase(event_attribute, "onload") ||
783 DeprecatedEqualIgnoringCase(event_attribute, "onload()"); 965 DeprecatedEqualIgnoringCase(event_attribute, "onload()");
784 } 966 }
785 967
786 String ScriptLoader::ScriptContent() const { 968 String ScriptLoader::ScriptContent() const {
787 return element_->TextFromChildren(); 969 return element_->TextFromChildren();
788 } 970 }
789 971
790 } // namespace blink 972 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698