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

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

Issue 2723793002: De-Element ScriptLoader (Closed)
Patch Set: De-Element ScriptLoader Created 3 years, 9 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 23 matching lines...) Expand all
34 #include "core/dom/ScriptLoaderClient.h" 34 #include "core/dom/ScriptLoaderClient.h"
35 #include "core/dom/ScriptRunner.h" 35 #include "core/dom/ScriptRunner.h"
36 #include "core/dom/ScriptableDocumentParser.h" 36 #include "core/dom/ScriptableDocumentParser.h"
37 #include "core/dom/Text.h" 37 #include "core/dom/Text.h"
38 #include "core/events/Event.h" 38 #include "core/events/Event.h"
39 #include "core/frame/LocalFrame.h" 39 #include "core/frame/LocalFrame.h"
40 #include "core/frame/SubresourceIntegrity.h" 40 #include "core/frame/SubresourceIntegrity.h"
41 #include "core/frame/UseCounter.h" 41 #include "core/frame/UseCounter.h"
42 #include "core/frame/csp/ContentSecurityPolicy.h" 42 #include "core/frame/csp/ContentSecurityPolicy.h"
43 #include "core/html/CrossOriginAttribute.h" 43 #include "core/html/CrossOriginAttribute.h"
44 #include "core/html/HTMLScriptElement.h"
45 #include "core/html/imports/HTMLImport.h" 44 #include "core/html/imports/HTMLImport.h"
46 #include "core/html/parser/HTMLParserIdioms.h" 45 #include "core/html/parser/HTMLParserIdioms.h"
47 #include "core/inspector/ConsoleMessage.h" 46 #include "core/inspector/ConsoleMessage.h"
48 #include "core/svg/SVGScriptElement.h"
49 #include "platform/WebFrameScheduler.h" 47 #include "platform/WebFrameScheduler.h"
50 #include "platform/loader/fetch/AccessControlStatus.h" 48 #include "platform/loader/fetch/AccessControlStatus.h"
51 #include "platform/loader/fetch/FetchRequest.h" 49 #include "platform/loader/fetch/FetchRequest.h"
52 #include "platform/loader/fetch/MemoryCache.h" 50 #include "platform/loader/fetch/MemoryCache.h"
53 #include "platform/loader/fetch/ResourceFetcher.h" 51 #include "platform/loader/fetch/ResourceFetcher.h"
54 #include "platform/network/mime/MIMETypeRegistry.h" 52 #include "platform/network/mime/MIMETypeRegistry.h"
55 #include "platform/weborigin/SecurityOrigin.h" 53 #include "platform/weborigin/SecurityOrigin.h"
56 #include "public/platform/WebCachePolicy.h" 54 #include "public/platform/WebCachePolicy.h"
57 #include "wtf/StdLibExtras.h" 55 #include "wtf/StdLibExtras.h"
58 #include "wtf/text/StringBuilder.h" 56 #include "wtf/text/StringBuilder.h"
59 #include "wtf/text/StringHash.h" 57 #include "wtf/text/StringHash.h"
60 58
61 namespace blink { 59 namespace blink {
62 60
63 ScriptLoader::ScriptLoader(Element* element, 61 ScriptLoader::ScriptLoader(ScriptLoaderClient* client,
64 bool parserInserted, 62 bool parserInserted,
65 bool alreadyStarted, 63 bool alreadyStarted,
66 bool createdDuringDocumentWrite) 64 bool createdDuringDocumentWrite)
67 : m_element(element), 65 : m_client(client),
68 m_startLineNumber(WTF::OrdinalNumber::beforeFirst()), 66 m_startLineNumber(WTF::OrdinalNumber::beforeFirst()),
69 m_haveFiredLoad(false), 67 m_haveFiredLoad(false),
70 m_willBeParserExecuted(false), 68 m_willBeParserExecuted(false),
71 m_willExecuteWhenDocumentFinishedParsing(false), 69 m_willExecuteWhenDocumentFinishedParsing(false),
72 m_createdDuringDocumentWrite(createdDuringDocumentWrite), 70 m_createdDuringDocumentWrite(createdDuringDocumentWrite),
73 m_asyncExecType(ScriptRunner::None), 71 m_asyncExecType(ScriptRunner::None),
74 m_documentWriteIntervention( 72 m_documentWriteIntervention(
75 DocumentWriteIntervention::DocumentWriteInterventionNone) { 73 DocumentWriteIntervention::DocumentWriteInterventionNone) {
76 DCHECK(m_element); 74 DCHECK(m_client);
77 75
78 // https://html.spec.whatwg.org/#already-started 76 // https://html.spec.whatwg.org/#already-started
79 // "The cloning steps for script elements must set the "already started" 77 // "The cloning steps for script elements must set the "already started"
80 // flag on the copy if it is set on the element being cloned." 78 // flag on the copy if it is set on the element being cloned."
81 // TODO(hiroshige): Cloning is implemented together with 79 // TODO(hiroshige): Cloning is implemented together with
82 // {HTML,SVG}ScriptElement::cloneElementWithoutAttributesAndChildren(). 80 // {HTML,SVG}ScriptElement::cloneElementWithoutAttributesAndChildren().
83 // Clean up these later. 81 // Clean up these later.
84 if (alreadyStarted) 82 if (alreadyStarted)
85 m_alreadyStarted = true; 83 m_alreadyStarted = true;
86 84
87 if (parserInserted) { 85 if (parserInserted) {
88 // https://html.spec.whatwg.org/#parser-inserted 86 // https://html.spec.whatwg.org/#parser-inserted
89 // "It is set by the HTML parser and the XML parser 87 // "It is set by the HTML parser and the XML parser
90 // on script elements they insert" 88 // on script elements they insert"
91 m_parserInserted = true; 89 m_parserInserted = true;
92 90
93 // https://html.spec.whatwg.org/#non-blocking 91 // https://html.spec.whatwg.org/#non-blocking
94 // "It is unset by the HTML parser and the XML parser 92 // "It is unset by the HTML parser and the XML parser
95 // on script elements they insert." 93 // on script elements they insert."
96 m_nonBlocking = false; 94 m_nonBlocking = false;
97 } 95 }
98 96
99 if (parserInserted && element->document().scriptableDocumentParser() && 97 if (parserInserted && m_client->document().scriptableDocumentParser() &&
100 !element->document().isInDocumentWrite()) 98 !m_client->document().isInDocumentWrite()) {
101 m_startLineNumber = 99 m_startLineNumber =
102 element->document().scriptableDocumentParser()->lineNumber(); 100 m_client->document().scriptableDocumentParser()->lineNumber();
101 }
103 } 102 }
104 103
105 ScriptLoader::~ScriptLoader() {} 104 ScriptLoader::~ScriptLoader() {}
106 105
107 DEFINE_TRACE(ScriptLoader) { 106 DEFINE_TRACE(ScriptLoader) {
108 visitor->trace(m_element); 107 visitor->trace(m_client);
109 visitor->trace(m_resource); 108 visitor->trace(m_resource);
110 visitor->trace(m_pendingScript); 109 visitor->trace(m_pendingScript);
111 PendingScriptClient::trace(visitor); 110 PendingScriptClient::trace(visitor);
112 } 111 }
113 112
114 void ScriptLoader::setFetchDocWrittenScriptDeferIdle() { 113 void ScriptLoader::setFetchDocWrittenScriptDeferIdle() {
115 DCHECK(!m_createdDuringDocumentWrite); 114 DCHECK(!m_createdDuringDocumentWrite);
116 m_documentWriteIntervention = 115 m_documentWriteIntervention =
117 DocumentWriteIntervention::FetchDocWrittenScriptDeferIdle; 116 DocumentWriteIntervention::FetchDocWrittenScriptDeferIdle;
118 } 117 }
119 118
120 void ScriptLoader::didNotifySubtreeInsertionsToDocument() { 119 void ScriptLoader::didNotifySubtreeInsertionsToDocument() {
121 if (!m_parserInserted) 120 if (!m_parserInserted)
122 prepareScript(); // FIXME: Provide a real starting line number here. 121 prepareScript(); // FIXME: Provide a real starting line number here.
123 } 122 }
124 123
125 void ScriptLoader::childrenChanged() { 124 void ScriptLoader::childrenChanged() {
126 if (!m_parserInserted && m_element->isConnected()) 125 if (!m_parserInserted && m_client->isConnected())
127 prepareScript(); // FIXME: Provide a real starting line number here. 126 prepareScript(); // FIXME: Provide a real starting line number here.
128 } 127 }
129 128
130 void ScriptLoader::handleSourceAttribute(const String& sourceUrl) { 129 void ScriptLoader::handleSourceAttribute(const String& sourceUrl) {
131 if (ignoresLoadRequest() || sourceUrl.isEmpty()) 130 if (ignoresLoadRequest() || sourceUrl.isEmpty())
132 return; 131 return;
133 132
134 prepareScript(); // FIXME: Provide a real starting line number here. 133 prepareScript(); // FIXME: Provide a real starting line number here.
135 } 134 }
136 135
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
168 equalIgnoringASCIICase(language, "javascript1.4") || 167 equalIgnoringASCIICase(language, "javascript1.4") ||
169 equalIgnoringASCIICase(language, "javascript1.5") || 168 equalIgnoringASCIICase(language, "javascript1.5") ||
170 equalIgnoringASCIICase(language, "javascript1.6") || 169 equalIgnoringASCIICase(language, "javascript1.6") ||
171 equalIgnoringASCIICase(language, "javascript1.7") || 170 equalIgnoringASCIICase(language, "javascript1.7") ||
172 equalIgnoringASCIICase(language, "livescript") || 171 equalIgnoringASCIICase(language, "livescript") ||
173 equalIgnoringASCIICase(language, "ecmascript") || 172 equalIgnoringASCIICase(language, "ecmascript") ||
174 equalIgnoringASCIICase(language, "jscript"); 173 equalIgnoringASCIICase(language, "jscript");
175 } 174 }
176 175
177 void ScriptLoader::dispatchErrorEvent() { 176 void ScriptLoader::dispatchErrorEvent() {
178 m_element->dispatchEvent(Event::create(EventTypeNames::error)); 177 m_client->dispatchErrorEvent();
179 } 178 }
180 179
181 void ScriptLoader::dispatchLoadEvent() { 180 void ScriptLoader::dispatchLoadEvent() {
182 if (ScriptLoaderClient* client = this->client()) 181 m_client->dispatchLoadEvent();
hiroshige 2017/03/01 00:58:14 So client() was always non-null and this if condit
Nate Chapin 2017/03/01 21:34:59 I believe so. I guess if buggy code had constructo
183 client->dispatchLoadEvent();
184 setHaveFiredLoadEvent(true); 182 setHaveFiredLoadEvent(true);
185 } 183 }
186 184
187 bool ScriptLoader::isValidScriptTypeAndLanguage( 185 bool ScriptLoader::isValidScriptTypeAndLanguage(
188 const String& type, 186 const String& type,
189 const String& language, 187 const String& language,
190 LegacyTypeSupport supportLegacyTypes) { 188 LegacyTypeSupport supportLegacyTypes) {
191 // FIXME: isLegacySupportedJavaScriptLanguage() is not valid HTML5. It is used 189 // FIXME: isLegacySupportedJavaScriptLanguage() is not valid HTML5. It is used
192 // here to maintain backwards compatibility with existing layout tests. The 190 // here to maintain backwards compatibility with existing layout tests. The
193 // specific violations are: 191 // specific violations are:
(...skipping 14 matching lines...) Expand all
208 (supportLegacyTypes == AllowLegacyTypeInTypeAttribute && 206 (supportLegacyTypes == AllowLegacyTypeInTypeAttribute &&
209 isLegacySupportedJavaScriptLanguage(type))) { 207 isLegacySupportedJavaScriptLanguage(type))) {
210 return true; 208 return true;
211 } 209 }
212 210
213 return false; 211 return false;
214 } 212 }
215 213
216 bool ScriptLoader::isScriptTypeSupported( 214 bool ScriptLoader::isScriptTypeSupported(
217 LegacyTypeSupport supportLegacyTypes) const { 215 LegacyTypeSupport supportLegacyTypes) const {
218 return isValidScriptTypeAndLanguage(client()->typeAttributeValue(), 216 return isValidScriptTypeAndLanguage(m_client->typeAttributeValue(),
219 client()->languageAttributeValue(), 217 m_client->languageAttributeValue(),
220 supportLegacyTypes); 218 supportLegacyTypes);
221 } 219 }
222 220
223 // https://html.spec.whatwg.org/#prepare-a-script 221 // https://html.spec.whatwg.org/#prepare-a-script
224 bool ScriptLoader::prepareScript(const TextPosition& scriptStartPosition, 222 bool ScriptLoader::prepareScript(const TextPosition& scriptStartPosition,
225 LegacyTypeSupport supportLegacyTypes) { 223 LegacyTypeSupport supportLegacyTypes) {
226 // 1. "If the script element is marked as having "already started", then 224 // 1. "If the script element is marked as having "already started", then
227 // abort these steps at this point. The script is not executed." 225 // abort these steps at this point. The script is not executed."
228 if (m_alreadyStarted) 226 if (m_alreadyStarted)
229 return false; 227 return false;
230 228
231 ScriptLoaderClient* client = this->client();
232
233 // 2. "If the element has its "parser-inserted" flag set, then 229 // 2. "If the element has its "parser-inserted" flag set, then
234 // set was-parser-inserted to true and unset the element's 230 // set was-parser-inserted to true and unset the element's
235 // "parser-inserted" flag. 231 // "parser-inserted" flag.
236 // Otherwise, set was-parser-inserted to false." 232 // Otherwise, set was-parser-inserted to false."
237 bool wasParserInserted; 233 bool wasParserInserted;
238 if (m_parserInserted) { 234 if (m_parserInserted) {
239 wasParserInserted = true; 235 wasParserInserted = true;
240 m_parserInserted = false; 236 m_parserInserted = false;
241 } else { 237 } else {
242 wasParserInserted = false; 238 wasParserInserted = false;
243 } 239 }
244 240
245 // 3. "If was-parser-inserted is true and the element does not have an 241 // 3. "If was-parser-inserted is true and the element does not have an
246 // async attribute, then set the element's "non-blocking" flag to true." 242 // async attribute, then set the element's "non-blocking" flag to true."
247 if (wasParserInserted && !client->asyncAttributeValue()) 243 if (wasParserInserted && !m_client->asyncAttributeValue())
248 m_nonBlocking = true; 244 m_nonBlocking = true;
249 245
250 // 4. "If the element has no src attribute, and its child nodes, if any, 246 // 4. "If the element has no src attribute, and its child nodes, if any,
251 // consist only of comment nodes and empty Text nodes, 247 // consist only of comment nodes and empty Text nodes,
252 // then abort these steps at this point. The script is not executed." 248 // then abort these steps at this point. The script is not executed."
253 // FIXME: HTML5 spec says we should check that all children are either 249 // FIXME: HTML5 spec says we should check that all children are either
254 // comments or empty text nodes. 250 // comments or empty text nodes.
255 if (!client->hasSourceAttribute() && !m_element->hasChildren()) 251 if (!m_client->hasSourceAttribute() && !m_client->hasChildren())
256 return false; 252 return false;
257 253
258 // 5. "If the element is not connected, then abort these steps. 254 // 5. "If the element is not connected, then abort these steps.
259 // The script is not executed." 255 // The script is not executed."
260 if (!m_element->isConnected()) 256 if (!m_client->isConnected())
261 return false; 257 return false;
262 258
263 // 6. 259 // 6.
264 // TODO(hiroshige): Annotate and/or cleanup this step. 260 // TODO(hiroshige): Annotate and/or cleanup this step.
265 if (!isScriptTypeSupported(supportLegacyTypes)) 261 if (!isScriptTypeSupported(supportLegacyTypes))
266 return false; 262 return false;
267 263
268 // 7. "If was-parser-inserted is true, 264 // 7. "If was-parser-inserted is true,
269 // then flag the element as "parser-inserted" again, 265 // then flag the element as "parser-inserted" again,
270 // and set the element's "non-blocking" flag to false." 266 // and set the element's "non-blocking" flag to false."
271 if (wasParserInserted) { 267 if (wasParserInserted) {
272 m_parserInserted = true; 268 m_parserInserted = true;
273 m_nonBlocking = false; 269 m_nonBlocking = false;
274 } 270 }
275 271
276 // 8. "Set the element's "already started" flag." 272 // 8. "Set the element's "already started" flag."
277 m_alreadyStarted = true; 273 m_alreadyStarted = true;
278 274
279 // 9. "If the element is flagged as "parser-inserted", but the element's 275 // 9. "If the element is flagged as "parser-inserted", but the element's
280 // node document is not the Document of the parser that created the element, 276 // node document is not the Document of the parser that created the element,
281 // then abort these steps." 277 // then abort these steps."
282 // FIXME: If script is parser inserted, verify it's still in the original 278 // FIXME: If script is parser inserted, verify it's still in the original
283 // document. 279 // document.
284 Document& elementDocument = m_element->document(); 280 Document& elementDocument = m_client->document();
285 Document* contextDocument = elementDocument.contextDocument(); 281 Document* contextDocument = elementDocument.contextDocument();
286 if (!contextDocument) 282 if (!contextDocument)
287 return false; 283 return false;
288 284
289 // 10. "If scripting is disabled for the script element, then abort these 285 // 10. "If scripting is disabled for the script element, then abort these
290 // steps at this point. The script is not executed." 286 // steps at this point. The script is not executed."
291 if (!contextDocument->allowExecutingScripts(m_element)) 287 if (!contextDocument->allowExecutingScripts(&elementDocument))
292 return false; 288 return false;
293 289
294 // 13. 290 // 13.
295 if (!isScriptForEventSupported()) 291 if (!isScriptForEventSupported())
296 return false; 292 return false;
297 293
298 // 14. "If the script element has a charset attribute, 294 // 14. "If the script element has a charset attribute,
299 // then let encoding be the result of 295 // then let encoding be the result of
300 // getting an encoding from the value of the charset attribute." 296 // getting an encoding from the value of the charset attribute."
301 // "If the script element does not have a charset attribute, 297 // "If the script element does not have a charset attribute,
302 // or if getting an encoding failed, let encoding 298 // or if getting an encoding failed, let encoding
303 // be the same as the encoding of the script element's node document." 299 // be the same as the encoding of the script element's node document."
304 // TODO(hiroshige): Should we handle failure in getting an encoding? 300 // TODO(hiroshige): Should we handle failure in getting an encoding?
305 String encoding; 301 String encoding;
306 if (!client->charsetAttributeValue().isEmpty()) 302 if (!m_client->charsetAttributeValue().isEmpty())
307 encoding = client->charsetAttributeValue(); 303 encoding = m_client->charsetAttributeValue();
308 else 304 else
309 encoding = elementDocument.characterSet(); 305 encoding = elementDocument.characterSet();
310 306
311 // Steps 15--20 are handled in fetchScript(). 307 // Steps 15--20 are handled in fetchScript().
312 308
313 // 21. "If the element has a src content attribute, run these substeps:" 309 // 21. "If the element has a src content attribute, run these substeps:"
314 if (client->hasSourceAttribute()) { 310 if (m_client->hasSourceAttribute()) {
315 FetchRequest::DeferOption defer = FetchRequest::NoDefer; 311 FetchRequest::DeferOption defer = FetchRequest::NoDefer;
316 if (!m_parserInserted || client->asyncAttributeValue() || 312 if (!m_parserInserted || m_client->asyncAttributeValue() ||
317 client->deferAttributeValue()) 313 m_client->deferAttributeValue())
318 defer = FetchRequest::LazyLoad; 314 defer = FetchRequest::LazyLoad;
319 if (m_documentWriteIntervention == 315 if (m_documentWriteIntervention ==
320 DocumentWriteIntervention::FetchDocWrittenScriptDeferIdle) 316 DocumentWriteIntervention::FetchDocWrittenScriptDeferIdle)
321 defer = FetchRequest::IdleLoad; 317 defer = FetchRequest::IdleLoad;
322 if (!fetchScript(client->sourceAttributeValue(), encoding, defer)) 318 if (!fetchScript(m_client->sourceAttributeValue(), encoding, defer))
323 return false; 319 return false;
324 } 320 }
325 321
326 // 22. "If the element does not have a src content attribute, 322 // 22. "If the element does not have a src content attribute,
327 // run these substeps:" 323 // run these substeps:"
328 324
329 // 22.1. "Let source text be the value of the text IDL attribute." 325 // 22.1. "Let source text be the value of the text IDL attribute."
330 // This step is done later: 326 // This step is done later:
331 // - in ScriptLoader::pendingScript() (Step 23, 6th Clause), 327 // - in ScriptLoader::pendingScript() (Step 23, 6th Clause),
332 // as Element::textFromChildren() in ScriptLoader::scriptContent(), 328 // as Element::textFromChildren() in ScriptLoader::scriptContent(),
(...skipping 11 matching lines...) Expand all
344 // 22.2. "Switch on the script's type:" 340 // 22.2. "Switch on the script's type:"
345 // TODO(hiroshige): Clarify how Step 22.2 is implemented for "classic". 341 // TODO(hiroshige): Clarify how Step 22.2 is implemented for "classic".
346 // TODO(hiroshige): Implement Step 22.2 for "module". 342 // TODO(hiroshige): Implement Step 22.2 for "module".
347 343
348 // [Intervention] 344 // [Intervention]
349 // Since the asynchronous, low priority fetch for doc.written blocked 345 // Since the asynchronous, low priority fetch for doc.written blocked
350 // script is not for execution, return early from here. Watch for its 346 // script is not for execution, return early from here. Watch for its
351 // completion to be able to remove it from the memory cache. 347 // completion to be able to remove it from the memory cache.
352 if (m_documentWriteIntervention == 348 if (m_documentWriteIntervention ==
353 DocumentWriteIntervention::FetchDocWrittenScriptDeferIdle) { 349 DocumentWriteIntervention::FetchDocWrittenScriptDeferIdle) {
354 m_pendingScript = PendingScript::create(m_element, m_resource.get()); 350 m_pendingScript = PendingScript::create(m_client.get(), m_resource.get());
355 m_pendingScript->watchForLoad(this); 351 m_pendingScript->watchForLoad(this);
356 return true; 352 return true;
357 } 353 }
358 354
359 // 23. "Then, follow the first of the following options that describes the 355 // 23. "Then, follow the first of the following options that describes the
360 // situation:" 356 // situation:"
361 357
362 // Three flags are used to instruct the caller of prepareScript() to execute 358 // Three flags are used to instruct the caller of prepareScript() to execute
363 // a part of Step 23, when |m_willBeParserExecuted| is true: 359 // a part of Step 23, when |m_willBeParserExecuted| is true:
364 // - |m_willBeParserExecuted| 360 // - |m_willBeParserExecuted|
365 // - |m_willExecuteWhenDocumentFinishedParsing| 361 // - |m_willExecuteWhenDocumentFinishedParsing|
366 // - |m_readyToBeParserExecuted| 362 // - |m_readyToBeParserExecuted|
367 // TODO(hiroshige): Clean up the dependency. 363 // TODO(hiroshige): Clean up the dependency.
368 364
369 // 1st Clause: 365 // 1st Clause:
370 // - "If the script's type is "classic", and 366 // - "If the script's type is "classic", and
371 // the element has a src attribute, and the element has a defer attribute, 367 // the element has a src attribute, and the element has a defer attribute,
372 // and the element has been flagged as "parser-inserted", 368 // and the element has been flagged as "parser-inserted",
373 // and the element does not have an async attribute" 369 // and the element does not have an async attribute"
374 // TODO(hiroshige): Check the script's type and implement "module" case. 370 // TODO(hiroshige): Check the script's type and implement "module" case.
375 if (client->hasSourceAttribute() && client->deferAttributeValue() && 371 if (m_client->hasSourceAttribute() && m_client->deferAttributeValue() &&
376 m_parserInserted && !client->asyncAttributeValue()) { 372 m_parserInserted && !m_client->asyncAttributeValue()) {
377 // This clause is implemented by the caller-side of prepareScript(): 373 // This clause is implemented by the caller-side of prepareScript():
378 // - HTMLParserScriptRunner::requestDeferredScript(), and 374 // - HTMLParserScriptRunner::requestDeferredScript(), and
379 // - TODO(hiroshige): Investigate XMLDocumentParser::endElementNs() 375 // - TODO(hiroshige): Investigate XMLDocumentParser::endElementNs()
380 m_willExecuteWhenDocumentFinishedParsing = true; 376 m_willExecuteWhenDocumentFinishedParsing = true;
381 m_willBeParserExecuted = true; 377 m_willBeParserExecuted = true;
382 378
383 return true; 379 return true;
384 } 380 }
385 381
386 // 2nd Clause: 382 // 2nd Clause:
387 // - "If the script's type is "classic", 383 // - "If the script's type is "classic",
388 // and the element has a src attribute, 384 // and the element has a src attribute,
389 // and the element has been flagged as "parser-inserted", 385 // and the element has been flagged as "parser-inserted",
390 // and the element does not have an async attribute" 386 // and the element does not have an async attribute"
391 // TODO(hiroshige): Check the script's type. 387 // TODO(hiroshige): Check the script's type.
392 if (client->hasSourceAttribute() && m_parserInserted && 388 if (m_client->hasSourceAttribute() && m_parserInserted &&
393 !client->asyncAttributeValue()) { 389 !m_client->asyncAttributeValue()) {
394 // This clause is implemented by the caller-side of prepareScript(): 390 // This clause is implemented by the caller-side of prepareScript():
395 // - HTMLParserScriptRunner::requestParsingBlockingScript() 391 // - HTMLParserScriptRunner::requestParsingBlockingScript()
396 // - TODO(hiroshige): Investigate XMLDocumentParser::endElementNs() 392 // - TODO(hiroshige): Investigate XMLDocumentParser::endElementNs()
397 m_willBeParserExecuted = true; 393 m_willBeParserExecuted = true;
398 394
399 return true; 395 return true;
400 } 396 }
401 397
402 // 5th Clause: 398 // 5th Clause:
403 // TODO(hiroshige): Reorder the clauses to match the spec. 399 // TODO(hiroshige): Reorder the clauses to match the spec.
404 // - "If the element does not have a src attribute, 400 // - "If the element does not have a src attribute,
405 // and the element has been flagged as "parser-inserted", 401 // and the element has been flagged as "parser-inserted",
406 // and either the parser that created the script is an XML parser 402 // and either the parser that created the script is an XML parser
407 // or it's an HTML parser whose script nesting level is not greater than 403 // or it's an HTML parser whose script nesting level is not greater than
408 // one, 404 // one,
409 // and the Document of the HTML parser or XML parser that created 405 // and the Document of the HTML parser or XML parser that created
410 // the script element has a style sheet that is blocking scripts" 406 // the script element has a style sheet that is blocking scripts"
411 // The last part "... has a style sheet that is blocking scripts" 407 // The last part "... has a style sheet that is blocking scripts"
412 // is implemented in Document::isScriptExecutionReady(). 408 // is implemented in Document::isScriptExecutionReady().
413 // Part of the condition check is done in 409 // Part of the condition check is done in
414 // HTMLParserScriptRunner::processScriptElementInternal(). 410 // HTMLParserScriptRunner::processScriptElementInternal().
415 // TODO(hiroshige): Clean up the split condition check. 411 // TODO(hiroshige): Clean up the split condition check.
416 if (!client->hasSourceAttribute() && m_parserInserted && 412 if (!m_client->hasSourceAttribute() && m_parserInserted &&
417 !elementDocument.isScriptExecutionReady()) { 413 !elementDocument.isScriptExecutionReady()) {
418 // The former part of this clause is 414 // The former part of this clause is
419 // implemented by the caller-side of prepareScript(): 415 // implemented by the caller-side of prepareScript():
420 // - HTMLParserScriptRunner::requestParsingBlockingScript() 416 // - HTMLParserScriptRunner::requestParsingBlockingScript()
421 // - TODO(hiroshige): Investigate XMLDocumentParser::endElementNs() 417 // - TODO(hiroshige): Investigate XMLDocumentParser::endElementNs()
422 m_willBeParserExecuted = true; 418 m_willBeParserExecuted = true;
423 // "Set the element's "ready to be parser-executed" flag." 419 // "Set the element's "ready to be parser-executed" flag."
424 m_readyToBeParserExecuted = true; 420 m_readyToBeParserExecuted = true;
425 421
426 return true; 422 return true;
427 } 423 }
428 424
429 // 3rd Clause: 425 // 3rd Clause:
430 // - "If the script's type is "classic", 426 // - "If the script's type is "classic",
431 // and the element has a src attribute, 427 // and the element has a src attribute,
432 // and the element does not have an async attribute, 428 // and the element does not have an async attribute,
433 // and the element does not have the "non-blocking" flag set" 429 // and the element does not have the "non-blocking" flag set"
434 // TODO(hiroshige): Check the script's type and implement "module" case. 430 // TODO(hiroshige): Check the script's type and implement "module" case.
435 if (client->hasSourceAttribute() && !client->asyncAttributeValue() && 431 if (m_client->hasSourceAttribute() && !m_client->asyncAttributeValue() &&
436 !m_nonBlocking) { 432 !m_nonBlocking) {
437 // "Add the element to the end of the list of scripts that will execute 433 // "Add the element to the end of the list of scripts that will execute
438 // in order as soon as possible associated with the node document of the 434 // in order as soon as possible associated with the node document of the
439 // script element at the time the prepare a script algorithm started." 435 // script element at the time the prepare a script algorithm started."
440 m_pendingScript = PendingScript::create(m_element, m_resource.get()); 436 m_pendingScript = PendingScript::create(m_client.get(), m_resource.get());
441 m_asyncExecType = ScriptRunner::InOrder; 437 m_asyncExecType = ScriptRunner::InOrder;
442 // TODO(hiroshige): Here |contextDocument| is used as "node document" 438 // TODO(hiroshige): Here |contextDocument| is used as "node document"
443 // while Step 14 uses |elementDocument| as "node document". Fix this. 439 // while Step 14 uses |elementDocument| as "node document". Fix this.
444 contextDocument->scriptRunner()->queueScriptForExecution(this, 440 contextDocument->scriptRunner()->queueScriptForExecution(this,
445 m_asyncExecType); 441 m_asyncExecType);
446 // Note that watchForLoad can immediately call pendingScriptFinished. 442 // Note that watchForLoad can immediately call pendingScriptFinished.
447 m_pendingScript->watchForLoad(this); 443 m_pendingScript->watchForLoad(this);
448 // The part "When the script is ready..." is implemented in 444 // The part "When the script is ready..." is implemented in
449 // ScriptRunner::notifyScriptReady(). 445 // ScriptRunner::notifyScriptReady().
450 // TODO(hiroshige): Annotate it. 446 // TODO(hiroshige): Annotate it.
451 447
452 return true; 448 return true;
453 } 449 }
454 450
455 // 4th Clause: 451 // 4th Clause:
456 // - "If the script's type is "classic", and the element has a src attribute" 452 // - "If the script's type is "classic", and the element has a src attribute"
457 // TODO(hiroshige): Check the script's type and implement "module" case. 453 // TODO(hiroshige): Check the script's type and implement "module" case.
458 if (client->hasSourceAttribute()) { 454 if (m_client->hasSourceAttribute()) {
459 // "The element must be added to the set of scripts that will execute 455 // "The element must be added to the set of scripts that will execute
460 // as soon as possible of the node document of the script element at the 456 // as soon as possible of the node document of the script element at the
461 // time the prepare a script algorithm started." 457 // time the prepare a script algorithm started."
462 m_pendingScript = PendingScript::create(m_element, m_resource.get()); 458 m_pendingScript = PendingScript::create(m_client.get(), m_resource.get());
463 m_asyncExecType = ScriptRunner::Async; 459 m_asyncExecType = ScriptRunner::Async;
464 LocalFrame* frame = m_element->document().frame(); 460 LocalFrame* frame = m_client->document().frame();
465 if (frame) { 461 if (frame) {
466 ScriptState* scriptState = ScriptState::forMainWorld(frame); 462 ScriptState* scriptState = ScriptState::forMainWorld(frame);
467 if (scriptState) 463 if (scriptState)
468 ScriptStreamer::startStreaming( 464 ScriptStreamer::startStreaming(
469 m_pendingScript.get(), ScriptStreamer::Async, frame->settings(), 465 m_pendingScript.get(), ScriptStreamer::Async, frame->settings(),
470 scriptState, frame->frameScheduler()->loadingTaskRunner()); 466 scriptState, frame->frameScheduler()->loadingTaskRunner());
471 } 467 }
472 // TODO(hiroshige): Here |contextDocument| is used as "node document" 468 // TODO(hiroshige): Here |contextDocument| is used as "node document"
473 // while Step 14 uses |elementDocument| as "node document". Fix this. 469 // while Step 14 uses |elementDocument| as "node document". Fix this.
474 contextDocument->scriptRunner()->queueScriptForExecution(this, 470 contextDocument->scriptRunner()->queueScriptForExecution(this,
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
506 return false; 502 return false;
507 } 503 }
508 504
509 return true; 505 return true;
510 } 506 }
511 507
512 // Steps 15--21 of https://html.spec.whatwg.org/#prepare-a-script 508 // Steps 15--21 of https://html.spec.whatwg.org/#prepare-a-script
513 bool ScriptLoader::fetchScript(const String& sourceUrl, 509 bool ScriptLoader::fetchScript(const String& sourceUrl,
514 const String& encoding, 510 const String& encoding,
515 FetchRequest::DeferOption defer) { 511 FetchRequest::DeferOption defer) {
516 DCHECK(m_element); 512 Document* elementDocument = &(m_client->document());
517 513 if (!m_client->isConnected() || m_client->document() != elementDocument)
518 Document* elementDocument = &(m_element->document());
519 if (!m_element->isConnected() || m_element->document() != elementDocument)
520 return false; 514 return false;
521 515
522 DCHECK(!m_resource); 516 DCHECK(!m_resource);
523 // 21. "If the element has a src content attribute, run these substeps:" 517 // 21. "If the element has a src content attribute, run these substeps:"
524 if (!stripLeadingAndTrailingHTMLSpaces(sourceUrl).isEmpty()) { 518 if (!stripLeadingAndTrailingHTMLSpaces(sourceUrl).isEmpty()) {
525 // 21.4. "Parse src relative to the element's node document." 519 // 21.4. "Parse src relative to the element's node document."
526 FetchRequest request( 520 FetchRequest request(
527 ResourceRequest(elementDocument->completeURL(sourceUrl)), 521 ResourceRequest(elementDocument->completeURL(sourceUrl)),
528 m_element->localName()); 522 m_client->initiatorName());
529 523
530 // 15. "Let CORS setting be the current state of the element's 524 // 15. "Let CORS setting be the current state of the element's
531 // crossorigin content attribute." 525 // crossorigin content attribute."
532 CrossOriginAttributeValue crossOrigin = crossOriginAttributeValue( 526 CrossOriginAttributeValue crossOrigin =
533 m_element->fastGetAttribute(HTMLNames::crossoriginAttr)); 527 crossOriginAttributeValue(m_client->crossOriginAttributeValue());
534 528
535 // 16. "Let module script credentials mode be determined by switching 529 // 16. "Let module script credentials mode be determined by switching
536 // on CORS setting:" 530 // on CORS setting:"
537 // TODO(hiroshige): Implement this step for "module". 531 // TODO(hiroshige): Implement this step for "module".
538 532
539 // 21.6, "classic": "Fetch a classic script given ... CORS setting 533 // 21.6, "classic": "Fetch a classic script given ... CORS setting
540 // ... and encoding." 534 // ... and encoding."
541 if (crossOrigin != CrossOriginAttributeNotSet) 535 if (crossOrigin != CrossOriginAttributeNotSet)
542 request.setCrossOriginAccessControl(elementDocument->getSecurityOrigin(), 536 request.setCrossOriginAccessControl(elementDocument->getSecurityOrigin(),
543 crossOrigin); 537 crossOrigin);
544 538
545 request.setCharset(encoding); 539 request.setCharset(encoding);
546 540
547 // 17. "If the script element has a nonce attribute, 541 // 17. "If the script element has a nonce attribute,
548 // then let cryptographic nonce be that attribute's value. 542 // then let cryptographic nonce be that attribute's value.
549 // Otherwise, let cryptographic nonce be the empty string." 543 // Otherwise, let cryptographic nonce be the empty string."
550 if (ContentSecurityPolicy::isNonceableElement(m_element.get())) 544 if (m_client->isNonceableElement())
551 request.setContentSecurityPolicyNonce(client()->nonce()); 545 request.setContentSecurityPolicyNonce(m_client->nonce());
552 546
553 // 19. "Let parser state be "parser-inserted" 547 // 19. "Let parser state be "parser-inserted"
554 // if the script element has been flagged as "parser-inserted", 548 // if the script element has been flagged as "parser-inserted",
555 // and "not parser-inserted" otherwise." 549 // and "not parser-inserted" otherwise."
556 request.setParserDisposition(isParserInserted() ? ParserInserted 550 request.setParserDisposition(isParserInserted() ? ParserInserted
557 : NotParserInserted); 551 : NotParserInserted);
558 552
559 request.setDefer(defer); 553 request.setDefer(defer);
560 554
561 // 18. "If the script element has an integrity attribute, 555 // 18. "If the script element has an integrity attribute,
562 // then let integrity metadata be that attribute's value. 556 // then let integrity metadata be that attribute's value.
563 // Otherwise, let integrity metadata be the empty string." 557 // Otherwise, let integrity metadata be the empty string."
564 String integrityAttr = 558 String integrityAttr = m_client->integrityAttributeValue();
565 m_element->fastGetAttribute(HTMLNames::integrityAttr);
566 if (!integrityAttr.isEmpty()) { 559 if (!integrityAttr.isEmpty()) {
567 IntegrityMetadataSet metadataSet; 560 IntegrityMetadataSet metadataSet;
568 SubresourceIntegrity::parseIntegrityAttribute(integrityAttr, metadataSet, 561 SubresourceIntegrity::parseIntegrityAttribute(integrityAttr, metadataSet,
569 elementDocument); 562 elementDocument);
570 request.setIntegrityMetadata(metadataSet); 563 request.setIntegrityMetadata(metadataSet);
571 } 564 }
572 565
573 // [Intervention] 566 // [Intervention]
574 if (m_documentWriteIntervention == 567 if (m_documentWriteIntervention ==
575 DocumentWriteIntervention::FetchDocWrittenScriptDeferIdle) { 568 DocumentWriteIntervention::FetchDocWrittenScriptDeferIdle) {
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
618 if (m_createdDuringDocumentWrite && 611 if (m_createdDuringDocumentWrite &&
619 m_resource->resourceRequest().getCachePolicy() == 612 m_resource->resourceRequest().getCachePolicy() ==
620 WebCachePolicy::ReturnCacheDataDontLoad) { 613 WebCachePolicy::ReturnCacheDataDontLoad) {
621 m_documentWriteIntervention = 614 m_documentWriteIntervention =
622 DocumentWriteIntervention::DoNotFetchDocWrittenScript; 615 DocumentWriteIntervention::DoNotFetchDocWrittenScript;
623 } 616 }
624 617
625 return true; 618 return true;
626 } 619 }
627 620
628 bool isHTMLScriptLoader(Element* element) {
629 DCHECK(element);
630 return isHTMLScriptElement(*element);
631 }
632
633 bool isSVGScriptLoader(Element* element) {
634 DCHECK(element);
635 return isSVGScriptElement(*element);
636 }
637
638 void ScriptLoader::logScriptMIMEType(LocalFrame* frame, 621 void ScriptLoader::logScriptMIMEType(LocalFrame* frame,
639 ScriptResource* resource, 622 ScriptResource* resource,
640 const String& mimeType) { 623 const String& mimeType) {
641 if (MIMETypeRegistry::isSupportedJavaScriptMIMEType(mimeType)) 624 if (MIMETypeRegistry::isSupportedJavaScriptMIMEType(mimeType))
642 return; 625 return;
643 bool isText = mimeType.startsWith("text/", TextCaseASCIIInsensitive); 626 bool isText = mimeType.startsWith("text/", TextCaseASCIIInsensitive);
644 if (isText && isLegacySupportedJavaScriptLanguage(mimeType.substring(5))) 627 if (isText && isLegacySupportedJavaScriptLanguage(mimeType.substring(5)))
645 return; 628 return;
646 bool isSameOrigin = 629 bool isSameOrigin =
647 m_element->document().getSecurityOrigin()->canRequest(resource->url()); 630 m_client->document().getSecurityOrigin()->canRequest(resource->url());
648 bool isApplication = 631 bool isApplication =
649 !isText && mimeType.startsWith("application/", TextCaseASCIIInsensitive); 632 !isText && mimeType.startsWith("application/", TextCaseASCIIInsensitive);
650 633
651 UseCounter::Feature feature = 634 UseCounter::Feature feature =
652 isSameOrigin 635 isSameOrigin
653 ? (isText ? UseCounter::SameOriginTextScript 636 ? (isText ? UseCounter::SameOriginTextScript
654 : isApplication ? UseCounter::SameOriginApplicationScript 637 : isApplication ? UseCounter::SameOriginApplicationScript
655 : UseCounter::SameOriginOtherScript) 638 : UseCounter::SameOriginOtherScript)
656 : (isText ? UseCounter::CrossOriginTextScript 639 : (isText ? UseCounter::CrossOriginTextScript
657 : isApplication ? UseCounter::CrossOriginApplicationScript 640 : isApplication ? UseCounter::CrossOriginApplicationScript
658 : UseCounter::CrossOriginOtherScript); 641 : UseCounter::CrossOriginOtherScript);
659 642
660 UseCounter::count(frame, feature); 643 UseCounter::count(frame, feature);
661 } 644 }
662 645
663 bool ScriptLoader::executeScript(const ScriptSourceCode& sourceCode) { 646 bool ScriptLoader::executeScript(const ScriptSourceCode& sourceCode) {
664 double scriptExecStartTime = monotonicallyIncreasingTime(); 647 double scriptExecStartTime = monotonicallyIncreasingTime();
665 bool result = doExecuteScript(sourceCode); 648 bool result = doExecuteScript(sourceCode);
666 649
667 // NOTE: we do not check m_willBeParserExecuted here, since 650 // NOTE: we do not check m_willBeParserExecuted here, since
668 // m_willBeParserExecuted is false for inline scripts, and we want to 651 // m_willBeParserExecuted is false for inline scripts, and we want to
669 // include inline script execution time as part of parser blocked script 652 // include inline script execution time as part of parser blocked script
670 // execution time. 653 // execution time.
671 if (m_asyncExecType == ScriptRunner::None) 654 if (m_asyncExecType == ScriptRunner::None)
672 DocumentParserTiming::from(m_element->document()) 655 DocumentParserTiming::from(m_client->document())
673 .recordParserBlockedOnScriptExecutionDuration( 656 .recordParserBlockedOnScriptExecutionDuration(
674 monotonicallyIncreasingTime() - scriptExecStartTime, 657 monotonicallyIncreasingTime() - scriptExecStartTime,
675 wasCreatedDuringDocumentWrite()); 658 wasCreatedDuringDocumentWrite());
676 return result; 659 return result;
677 } 660 }
678 661
679 // https://html.spec.whatwg.org/#execute-the-script-block 662 // https://html.spec.whatwg.org/#execute-the-script-block
680 // with additional support for HTML imports. 663 // with additional support for HTML imports.
681 // Note that Steps 2 and 8 must be handled by the caller of doExecuteScript(), 664 // Note that Steps 2 and 8 must be handled by the caller of doExecuteScript(),
682 // i.e. load/error events are dispatched by the caller. 665 // i.e. load/error events are dispatched by the caller.
683 // Steps 3--7 are implemented here in doExecuteScript(). 666 // Steps 3--7 are implemented here in doExecuteScript().
684 // TODO(hiroshige): Move event dispatching code to doExecuteScript(). 667 // TODO(hiroshige): Move event dispatching code to doExecuteScript().
685 bool ScriptLoader::doExecuteScript(const ScriptSourceCode& sourceCode) { 668 bool ScriptLoader::doExecuteScript(const ScriptSourceCode& sourceCode) {
686 DCHECK(m_alreadyStarted); 669 DCHECK(m_alreadyStarted);
687 670
688 if (sourceCode.isEmpty()) 671 if (sourceCode.isEmpty())
689 return true; 672 return true;
690 673
691 Document* elementDocument = &(m_element->document()); 674 Document* elementDocument = &(m_client->document());
692 Document* contextDocument = elementDocument->contextDocument(); 675 Document* contextDocument = elementDocument->contextDocument();
693 if (!contextDocument) 676 if (!contextDocument)
694 return true; 677 return true;
695 678
696 LocalFrame* frame = contextDocument->frame(); 679 LocalFrame* frame = contextDocument->frame();
697 if (!frame) 680 if (!frame)
698 return true; 681 return true;
699 682
700 const ContentSecurityPolicy* csp = elementDocument->contentSecurityPolicy(); 683 const ContentSecurityPolicy* csp = elementDocument->contentSecurityPolicy();
701 bool shouldBypassMainWorldCSP = 684 bool shouldBypassMainWorldCSP =
702 (frame->script().shouldBypassMainWorldCSP()) || 685 (frame->script().shouldBypassMainWorldCSP()) ||
703 csp->allowScriptWithHash(sourceCode.source(), 686 csp->allowScriptWithHash(sourceCode.source(),
704 ContentSecurityPolicy::InlineType::Block); 687 ContentSecurityPolicy::InlineType::Block);
705 688
706 AtomicString nonce = 689 AtomicString nonce =
707 ContentSecurityPolicy::isNonceableElement(m_element.get()) 690 m_client->isNonceableElement() ? m_client->nonce() : nullAtom;
708 ? client()->nonce() 691 if (!m_isExternalScript && !shouldBypassMainWorldCSP &&
709 : nullAtom; 692 !m_client->allowInlineScriptForCSP(nonce, m_startLineNumber,
710 if (!m_isExternalScript && 693 sourceCode.source())) {
711 (!shouldBypassMainWorldCSP &&
712 !csp->allowInlineScript(m_element, elementDocument->url(), nonce,
713 m_startLineNumber, sourceCode.source()))) {
714 return false; 694 return false;
715 } 695 }
716 696
717 if (m_isExternalScript) { 697 if (m_isExternalScript) {
718 ScriptResource* resource = 698 ScriptResource* resource =
719 m_resource ? m_resource.get() : sourceCode.resource(); 699 m_resource ? m_resource.get() : sourceCode.resource();
720 if (resource) { 700 if (resource) {
721 if (!ScriptResource::mimeTypeAllowedByNosniff(resource->response())) { 701 if (!ScriptResource::mimeTypeAllowedByNosniff(resource->response())) {
722 contextDocument->addConsoleMessage(ConsoleMessage::create( 702 contextDocument->addConsoleMessage(ConsoleMessage::create(
723 SecurityMessageSource, ErrorMessageLevel, 703 SecurityMessageSource, ErrorMessageLevel,
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
756 if (!m_isExternalScript) { 736 if (!m_isExternalScript) {
757 accessControlStatus = SharableCrossOrigin; 737 accessControlStatus = SharableCrossOrigin;
758 } else if (sourceCode.resource()) { 738 } else if (sourceCode.resource()) {
759 if (sourceCode.resource()->response().wasFetchedViaServiceWorker()) { 739 if (sourceCode.resource()->response().wasFetchedViaServiceWorker()) {
760 if (sourceCode.resource()->response().serviceWorkerResponseType() == 740 if (sourceCode.resource()->response().serviceWorkerResponseType() ==
761 WebServiceWorkerResponseTypeOpaque) 741 WebServiceWorkerResponseTypeOpaque)
762 accessControlStatus = OpaqueResource; 742 accessControlStatus = OpaqueResource;
763 else 743 else
764 accessControlStatus = SharableCrossOrigin; 744 accessControlStatus = SharableCrossOrigin;
765 } else if (sourceCode.resource()->passesAccessControlCheck( 745 } else if (sourceCode.resource()->passesAccessControlCheck(
766 m_element->document().getSecurityOrigin())) { 746 m_client->document().getSecurityOrigin())) {
767 accessControlStatus = SharableCrossOrigin; 747 accessControlStatus = SharableCrossOrigin;
768 } 748 }
769 } 749 }
770 750
771 const bool isImportedScript = contextDocument != elementDocument; 751 const bool isImportedScript = contextDocument != elementDocument;
772 752
773 // 3. "If the script is from an external file, 753 // 3. "If the script is from an external file,
774 // or the script's type is module", 754 // or the script's type is module",
775 // then increment the ignore-destructive-writes counter of the 755 // then increment the ignore-destructive-writes counter of the
776 // script element's node document. Let neutralized doc be that Document." 756 // script element's node document. Let neutralized doc be that Document."
777 // TODO(hiroshige): Implement "module" case. 757 // TODO(hiroshige): Implement "module" case.
778 IgnoreDestructiveWriteCountIncrementer ignoreDestructiveWriteCountIncrementer( 758 IgnoreDestructiveWriteCountIncrementer ignoreDestructiveWriteCountIncrementer(
779 m_isExternalScript || isImportedScript ? contextDocument : 0); 759 m_isExternalScript || isImportedScript ? contextDocument : 0);
780 760
781 // 4. "Let old script element be the value to which the script element's 761 // 4. "Let old script element be the value to which the script element's
782 // node document's currentScript object was most recently set." 762 // node document's currentScript object was most recently set."
783 // This is implemented as push/popCurrentScript(). 763 // This is implemented as push/popCurrentScript().
784 764
785 // 5. "Switch on the script's type:" 765 // 5. "Switch on the script's type:"
786 // - "classic": 766 // - "classic":
787 // 1. "If the script element's root is not a shadow root, 767 // 1. "If the script element's root is not a shadow root,
788 // then set the script element's node document's currentScript 768 // then set the script element's node document's currentScript
789 // attribute to the script element. Otherwise, set it to null." 769 // attribute to the script element. Otherwise, set it to null."
790 if (isHTMLScriptLoader(m_element) || isSVGScriptLoader(m_element)) 770 contextDocument->pushCurrentScript(m_client.get());
791 contextDocument->pushCurrentScript(m_element);
792 771
793 // 2. "Run the classic script given by the script's script." 772 // 2. "Run the classic script given by the script's script."
794 // Note: This is where the script is compiled and actually executed. 773 // Note: This is where the script is compiled and actually executed.
795 frame->script().executeScriptInMainWorld(sourceCode, accessControlStatus); 774 frame->script().executeScriptInMainWorld(sourceCode, accessControlStatus);
796 775
797 // - "module": 776 // - "module":
798 // TODO(hiroshige): Implement this. 777 // TODO(hiroshige): Implement this.
799 778
800 // 6. "Set the script element's node document's currentScript attribute 779 // 6. "Set the script element's node document's currentScript attribute
801 // to old script element." 780 // to old script element."
802 if (isHTMLScriptLoader(m_element) || isSVGScriptLoader(m_element)) { 781 contextDocument->popCurrentScript(m_client.get());
803 DCHECK(contextDocument->currentScript() == m_element);
804 contextDocument->popCurrentScript();
805 }
806 782
807 return true; 783 return true;
808 784
809 // 7. "Decrement the ignore-destructive-writes counter of neutralized doc, 785 // 7. "Decrement the ignore-destructive-writes counter of neutralized doc,
810 // if it was incremented in the earlier step." 786 // if it was incremented in the earlier step."
811 // Implemented as the scope out of IgnoreDestructiveWriteCountIncrementer. 787 // Implemented as the scope out of IgnoreDestructiveWriteCountIncrementer.
812 } 788 }
813 789
814 void ScriptLoader::execute() { 790 void ScriptLoader::execute() {
815 DCHECK(!m_willBeParserExecuted); 791 DCHECK(!m_willBeParserExecuted);
(...skipping 24 matching lines...) Expand all
840 // cache for subsequent uses. 816 // cache for subsequent uses.
841 if (m_documentWriteIntervention == 817 if (m_documentWriteIntervention ==
842 DocumentWriteIntervention::FetchDocWrittenScriptDeferIdle) { 818 DocumentWriteIntervention::FetchDocWrittenScriptDeferIdle) {
843 memoryCache()->remove(m_pendingScript->resource()); 819 memoryCache()->remove(m_pendingScript->resource());
844 m_pendingScript->stopWatchingForLoad(); 820 m_pendingScript->stopWatchingForLoad();
845 return; 821 return;
846 } 822 }
847 823
848 DCHECK(m_asyncExecType != ScriptRunner::None); 824 DCHECK(m_asyncExecType != ScriptRunner::None);
849 825
850 Document* contextDocument = m_element->document().contextDocument(); 826 Document* contextDocument = m_client->document().contextDocument();
851 if (!contextDocument) { 827 if (!contextDocument) {
852 detachPendingScript(); 828 detachPendingScript();
853 return; 829 return;
854 } 830 }
855 831
856 if (errorOccurred()) { 832 if (errorOccurred()) {
857 contextDocument->scriptRunner()->notifyScriptLoadError(this, 833 contextDocument->scriptRunner()->notifyScriptLoadError(this,
858 m_asyncExecType); 834 m_asyncExecType);
859 detachPendingScript(); 835 detachPendingScript();
860 dispatchErrorEvent(); 836 dispatchErrorEvent();
861 return; 837 return;
862 } 838 }
863 contextDocument->scriptRunner()->notifyScriptReady(this, m_asyncExecType); 839 contextDocument->scriptRunner()->notifyScriptReady(this, m_asyncExecType);
864 m_pendingScript->stopWatchingForLoad(); 840 m_pendingScript->stopWatchingForLoad();
865 } 841 }
866 842
867 bool ScriptLoader::ignoresLoadRequest() const { 843 bool ScriptLoader::ignoresLoadRequest() const {
868 return m_alreadyStarted || m_isExternalScript || m_parserInserted || 844 return m_alreadyStarted || m_isExternalScript || m_parserInserted ||
869 !element() || !element()->isConnected(); 845 !m_client->isConnected();
870 } 846 }
871 847
872 // Step 13 of https://html.spec.whatwg.org/#prepare-a-script 848 // Step 13 of https://html.spec.whatwg.org/#prepare-a-script
873 bool ScriptLoader::isScriptForEventSupported() const { 849 bool ScriptLoader::isScriptForEventSupported() const {
874 // 1. "Let for be the value of the for attribute." 850 // 1. "Let for be the value of the for attribute."
875 String eventAttribute = client()->eventAttributeValue(); 851 String eventAttribute = m_client->eventAttributeValue();
876 // 2. "Let event be the value of the event attribute." 852 // 2. "Let event be the value of the event attribute."
877 String forAttribute = client()->forAttributeValue(); 853 String forAttribute = m_client->forAttributeValue();
878 854
879 // "If the script element has an event attribute and a for attribute, and 855 // "If the script element has an event attribute and a for attribute, and
880 // the script's type is "classic", then run these substeps:" 856 // the script's type is "classic", then run these substeps:"
881 // TODO(hiroshige): Check the script's type. 857 // TODO(hiroshige): Check the script's type.
882 if (eventAttribute.isNull() || forAttribute.isNull()) 858 if (eventAttribute.isNull() || forAttribute.isNull())
883 return true; 859 return true;
884 860
885 // 3. "Strip leading and trailing ASCII whitespace from event and for." 861 // 3. "Strip leading and trailing ASCII whitespace from event and for."
886 forAttribute = forAttribute.stripWhiteSpace(); 862 forAttribute = forAttribute.stripWhiteSpace();
887 // 4. "If for is not an ASCII case-insensitive match for the string 863 // 4. "If for is not an ASCII case-insensitive match for the string
888 // "window", 864 // "window",
889 // then abort these steps at this point. The script is not executed." 865 // then abort these steps at this point. The script is not executed."
890 if (!equalIgnoringCase(forAttribute, "window")) 866 if (!equalIgnoringCase(forAttribute, "window"))
891 return false; 867 return false;
892 eventAttribute = eventAttribute.stripWhiteSpace(); 868 eventAttribute = eventAttribute.stripWhiteSpace();
893 // 5. "If event is not an ASCII case-insensitive match for either the 869 // 5. "If event is not an ASCII case-insensitive match for either the
894 // string "onload" or the string "onload()", 870 // string "onload" or the string "onload()",
895 // then abort these steps at this point. The script is not executed. 871 // then abort these steps at this point. The script is not executed.
896 return equalIgnoringCase(eventAttribute, "onload") || 872 return equalIgnoringCase(eventAttribute, "onload") ||
897 equalIgnoringCase(eventAttribute, "onload()"); 873 equalIgnoringCase(eventAttribute, "onload()");
898 } 874 }
899 875
900 String ScriptLoader::scriptContent() const { 876 String ScriptLoader::scriptContent() const {
901 return m_element->textFromChildren(); 877 return m_client->textFromChildren();
902 }
903
904 ScriptLoaderClient* ScriptLoader::client() const {
905 if (isHTMLScriptLoader(m_element))
906 return toHTMLScriptElement(m_element);
907
908 if (isSVGScriptLoader(m_element))
909 return toSVGScriptElement(m_element);
910
911 NOTREACHED();
912 return 0;
913 }
914
915 ScriptLoader* toScriptLoaderIfPossible(Element* element) {
916 if (isHTMLScriptLoader(element))
917 return toHTMLScriptElement(element)->loader();
918
919 if (isSVGScriptLoader(element))
920 return toSVGScriptElement(element)->loader();
921
922 return 0;
923 } 878 }
924 879
925 } // namespace blink 880 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698