OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) | 2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) |
3 * (C) 1999 Antti Koivisto (koivisto@kde.org) | 3 * (C) 1999 Antti Koivisto (koivisto@kde.org) |
4 * (C) 2001 Dirk Mueller (mueller@kde.org) | 4 * (C) 2001 Dirk Mueller (mueller@kde.org) |
5 * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights | 5 * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights |
6 * reserved. | 6 * reserved. |
7 * Copyright (C) 2008 Nikolas Zimmermann <zimmermann@kde.org> | 7 * Copyright (C) 2008 Nikolas Zimmermann <zimmermann@kde.org> |
8 * | 8 * |
9 * This library is free software; you can redistribute it and/or | 9 * This library is free software; you can redistribute it and/or |
10 * modify it under the terms of the GNU Library General Public | 10 * modify it under the terms of the GNU Library General Public |
(...skipping 13 matching lines...) Expand all Loading... |
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 "core/HTMLNames.h" | 29 #include "core/HTMLNames.h" |
30 #include "core/SVGNames.h" | 30 #include "core/SVGNames.h" |
31 #include "core/dom/Document.h" | 31 #include "core/dom/Document.h" |
32 #include "core/dom/DocumentParserTiming.h" | 32 #include "core/dom/DocumentParserTiming.h" |
33 #include "core/dom/IgnoreDestructiveWriteCountIncrementer.h" | 33 #include "core/dom/IgnoreDestructiveWriteCountIncrementer.h" |
34 #include "core/dom/ScriptLoaderClient.h" | 34 #include "core/dom/ScriptElementBase.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(ScriptElementBase* element, |
64 bool parserInserted, | 62 bool parserInserted, |
65 bool alreadyStarted, | 63 bool alreadyStarted, |
66 bool createdDuringDocumentWrite) | 64 bool createdDuringDocumentWrite) |
67 : m_element(element), | 65 : m_element(element), |
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); | |
77 | |
78 // https://html.spec.whatwg.org/#already-started | 74 // https://html.spec.whatwg.org/#already-started |
79 // "The cloning steps for script elements must set the "already started" | 75 // "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." | 76 // flag on the copy if it is set on the element being cloned." |
81 // TODO(hiroshige): Cloning is implemented together with | 77 // TODO(hiroshige): Cloning is implemented together with |
82 // {HTML,SVG}ScriptElement::cloneElementWithoutAttributesAndChildren(). | 78 // {HTML,SVG}ScriptElement::cloneElementWithoutAttributesAndChildren(). |
83 // Clean up these later. | 79 // Clean up these later. |
84 if (alreadyStarted) | 80 if (alreadyStarted) |
85 m_alreadyStarted = true; | 81 m_alreadyStarted = true; |
86 | 82 |
87 if (parserInserted) { | 83 if (parserInserted) { |
88 // https://html.spec.whatwg.org/#parser-inserted | 84 // https://html.spec.whatwg.org/#parser-inserted |
89 // "It is set by the HTML parser and the XML parser | 85 // "It is set by the HTML parser and the XML parser |
90 // on script elements they insert" | 86 // on script elements they insert" |
91 m_parserInserted = true; | 87 m_parserInserted = true; |
92 | 88 |
93 // https://html.spec.whatwg.org/#non-blocking | 89 // https://html.spec.whatwg.org/#non-blocking |
94 // "It is unset by the HTML parser and the XML parser | 90 // "It is unset by the HTML parser and the XML parser |
95 // on script elements they insert." | 91 // on script elements they insert." |
96 m_nonBlocking = false; | 92 m_nonBlocking = false; |
97 } | 93 } |
98 | 94 |
99 if (parserInserted && element->document().scriptableDocumentParser() && | 95 if (parserInserted && m_element->document().scriptableDocumentParser() && |
100 !element->document().isInDocumentWrite()) | 96 !m_element->document().isInDocumentWrite()) { |
101 m_startLineNumber = | 97 m_startLineNumber = |
102 element->document().scriptableDocumentParser()->lineNumber(); | 98 m_element->document().scriptableDocumentParser()->lineNumber(); |
| 99 } |
103 } | 100 } |
104 | 101 |
105 ScriptLoader::~ScriptLoader() {} | 102 ScriptLoader::~ScriptLoader() {} |
106 | 103 |
107 DEFINE_TRACE(ScriptLoader) { | 104 DEFINE_TRACE(ScriptLoader) { |
108 visitor->trace(m_element); | 105 visitor->trace(m_element); |
109 visitor->trace(m_resource); | 106 visitor->trace(m_resource); |
110 visitor->trace(m_pendingScript); | 107 visitor->trace(m_pendingScript); |
111 PendingScriptClient::trace(visitor); | 108 PendingScriptClient::trace(visitor); |
112 } | 109 } |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
168 equalIgnoringASCIICase(language, "javascript1.4") || | 165 equalIgnoringASCIICase(language, "javascript1.4") || |
169 equalIgnoringASCIICase(language, "javascript1.5") || | 166 equalIgnoringASCIICase(language, "javascript1.5") || |
170 equalIgnoringASCIICase(language, "javascript1.6") || | 167 equalIgnoringASCIICase(language, "javascript1.6") || |
171 equalIgnoringASCIICase(language, "javascript1.7") || | 168 equalIgnoringASCIICase(language, "javascript1.7") || |
172 equalIgnoringASCIICase(language, "livescript") || | 169 equalIgnoringASCIICase(language, "livescript") || |
173 equalIgnoringASCIICase(language, "ecmascript") || | 170 equalIgnoringASCIICase(language, "ecmascript") || |
174 equalIgnoringASCIICase(language, "jscript"); | 171 equalIgnoringASCIICase(language, "jscript"); |
175 } | 172 } |
176 | 173 |
177 void ScriptLoader::dispatchErrorEvent() { | 174 void ScriptLoader::dispatchErrorEvent() { |
178 m_element->dispatchEvent(Event::create(EventTypeNames::error)); | 175 m_element->dispatchErrorEvent(); |
179 } | 176 } |
180 | 177 |
181 void ScriptLoader::dispatchLoadEvent() { | 178 void ScriptLoader::dispatchLoadEvent() { |
182 if (ScriptLoaderClient* client = this->client()) | 179 m_element->dispatchLoadEvent(); |
183 client->dispatchLoadEvent(); | |
184 setHaveFiredLoadEvent(true); | 180 setHaveFiredLoadEvent(true); |
185 } | 181 } |
186 | 182 |
187 bool ScriptLoader::isValidScriptTypeAndLanguage( | 183 bool ScriptLoader::isValidScriptTypeAndLanguage( |
188 const String& type, | 184 const String& type, |
189 const String& language, | 185 const String& language, |
190 LegacyTypeSupport supportLegacyTypes) { | 186 LegacyTypeSupport supportLegacyTypes) { |
191 // FIXME: isLegacySupportedJavaScriptLanguage() is not valid HTML5. It is used | 187 // FIXME: isLegacySupportedJavaScriptLanguage() is not valid HTML5. It is used |
192 // here to maintain backwards compatibility with existing layout tests. The | 188 // here to maintain backwards compatibility with existing layout tests. The |
193 // specific violations are: | 189 // specific violations are: |
(...skipping 14 matching lines...) Expand all Loading... |
208 (supportLegacyTypes == AllowLegacyTypeInTypeAttribute && | 204 (supportLegacyTypes == AllowLegacyTypeInTypeAttribute && |
209 isLegacySupportedJavaScriptLanguage(type))) { | 205 isLegacySupportedJavaScriptLanguage(type))) { |
210 return true; | 206 return true; |
211 } | 207 } |
212 | 208 |
213 return false; | 209 return false; |
214 } | 210 } |
215 | 211 |
216 bool ScriptLoader::isScriptTypeSupported( | 212 bool ScriptLoader::isScriptTypeSupported( |
217 LegacyTypeSupport supportLegacyTypes) const { | 213 LegacyTypeSupport supportLegacyTypes) const { |
218 return isValidScriptTypeAndLanguage(client()->typeAttributeValue(), | 214 return isValidScriptTypeAndLanguage(m_element->typeAttributeValue(), |
219 client()->languageAttributeValue(), | 215 m_element->languageAttributeValue(), |
220 supportLegacyTypes); | 216 supportLegacyTypes); |
221 } | 217 } |
222 | 218 |
223 // https://html.spec.whatwg.org/#prepare-a-script | 219 // https://html.spec.whatwg.org/#prepare-a-script |
224 bool ScriptLoader::prepareScript(const TextPosition& scriptStartPosition, | 220 bool ScriptLoader::prepareScript(const TextPosition& scriptStartPosition, |
225 LegacyTypeSupport supportLegacyTypes) { | 221 LegacyTypeSupport supportLegacyTypes) { |
226 // 1. "If the script element is marked as having "already started", then | 222 // 1. "If the script element is marked as having "already started", then |
227 // abort these steps at this point. The script is not executed." | 223 // abort these steps at this point. The script is not executed." |
228 if (m_alreadyStarted) | 224 if (m_alreadyStarted) |
229 return false; | 225 return false; |
230 | 226 |
231 ScriptLoaderClient* client = this->client(); | |
232 | |
233 // 2. "If the element has its "parser-inserted" flag set, then | 227 // 2. "If the element has its "parser-inserted" flag set, then |
234 // set was-parser-inserted to true and unset the element's | 228 // set was-parser-inserted to true and unset the element's |
235 // "parser-inserted" flag. | 229 // "parser-inserted" flag. |
236 // Otherwise, set was-parser-inserted to false." | 230 // Otherwise, set was-parser-inserted to false." |
237 bool wasParserInserted; | 231 bool wasParserInserted; |
238 if (m_parserInserted) { | 232 if (m_parserInserted) { |
239 wasParserInserted = true; | 233 wasParserInserted = true; |
240 m_parserInserted = false; | 234 m_parserInserted = false; |
241 } else { | 235 } else { |
242 wasParserInserted = false; | 236 wasParserInserted = false; |
243 } | 237 } |
244 | 238 |
245 // 3. "If was-parser-inserted is true and the element does not have an | 239 // 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." | 240 // async attribute, then set the element's "non-blocking" flag to true." |
247 if (wasParserInserted && !client->asyncAttributeValue()) | 241 if (wasParserInserted && !m_element->asyncAttributeValue()) |
248 m_nonBlocking = true; | 242 m_nonBlocking = true; |
249 | 243 |
250 // 4. "If the element has no src attribute, and its child nodes, if any, | 244 // 4. "If the element has no src attribute, and its child nodes, if any, |
251 // consist only of comment nodes and empty Text nodes, | 245 // consist only of comment nodes and empty Text nodes, |
252 // then abort these steps at this point. The script is not executed." | 246 // 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 | 247 // FIXME: HTML5 spec says we should check that all children are either |
254 // comments or empty text nodes. | 248 // comments or empty text nodes. |
255 if (!client->hasSourceAttribute() && !m_element->hasChildren()) | 249 if (!m_element->hasSourceAttribute() && !m_element->hasChildren()) |
256 return false; | 250 return false; |
257 | 251 |
258 // 5. "If the element is not connected, then abort these steps. | 252 // 5. "If the element is not connected, then abort these steps. |
259 // The script is not executed." | 253 // The script is not executed." |
260 if (!m_element->isConnected()) | 254 if (!m_element->isConnected()) |
261 return false; | 255 return false; |
262 | 256 |
263 // 6. | 257 // 6. |
264 // TODO(hiroshige): Annotate and/or cleanup this step. | 258 // TODO(hiroshige): Annotate and/or cleanup this step. |
265 if (!isScriptTypeSupported(supportLegacyTypes)) | 259 if (!isScriptTypeSupported(supportLegacyTypes)) |
(...skipping 10 matching lines...) Expand all Loading... |
276 // 8. "Set the element's "already started" flag." | 270 // 8. "Set the element's "already started" flag." |
277 m_alreadyStarted = true; | 271 m_alreadyStarted = true; |
278 | 272 |
279 // 9. "If the element is flagged as "parser-inserted", but the element's | 273 // 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, | 274 // node document is not the Document of the parser that created the element, |
281 // then abort these steps." | 275 // then abort these steps." |
282 // FIXME: If script is parser inserted, verify it's still in the original | 276 // FIXME: If script is parser inserted, verify it's still in the original |
283 // document. | 277 // document. |
284 Document& elementDocument = m_element->document(); | 278 Document& elementDocument = m_element->document(); |
285 Document* contextDocument = elementDocument.contextDocument(); | 279 Document* contextDocument = elementDocument.contextDocument(); |
286 if (!contextDocument) | 280 if (!elementDocument.executingFrame()) |
| 281 return false; |
| 282 if (!contextDocument || !contextDocument->executingFrame()) |
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->canExecuteScripts(AboutToExecuteScript)) |
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_element->charsetAttributeValue().isEmpty()) |
307 encoding = client->charsetAttributeValue(); | 303 encoding = m_element->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_element->hasSourceAttribute()) { |
315 FetchRequest::DeferOption defer = FetchRequest::NoDefer; | 311 FetchRequest::DeferOption defer = FetchRequest::NoDefer; |
316 if (!m_parserInserted || client->asyncAttributeValue() || | 312 if (!m_parserInserted || m_element->asyncAttributeValue() || |
317 client->deferAttributeValue()) | 313 m_element->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_element->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 Loading... |
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_element.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_element->hasSourceAttribute() && m_element->deferAttributeValue() && |
376 m_parserInserted && !client->asyncAttributeValue()) { | 372 m_parserInserted && !m_element->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_element->hasSourceAttribute() && m_parserInserted && |
393 !client->asyncAttributeValue()) { | 389 !m_element->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_element->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_element->hasSourceAttribute() && !m_element->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_element.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_element->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_element.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_element->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" |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
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); | |
517 | |
518 Document* elementDocument = &(m_element->document()); | 512 Document* elementDocument = &(m_element->document()); |
519 if (!m_element->isConnected() || m_element->document() != elementDocument) | 513 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 ResourceRequest resourceRequest(elementDocument->completeURL(sourceUrl)); | 520 ResourceRequest resourceRequest(elementDocument->completeURL(sourceUrl)); |
527 | 521 |
528 // [Intervention] | 522 // [Intervention] |
529 if (m_documentWriteIntervention == | 523 if (m_documentWriteIntervention == |
530 DocumentWriteIntervention::FetchDocWrittenScriptDeferIdle) { | 524 DocumentWriteIntervention::FetchDocWrittenScriptDeferIdle) { |
531 resourceRequest.setHTTPHeaderField( | 525 resourceRequest.setHTTPHeaderField( |
532 "Intervention", | 526 "Intervention", |
533 "<https://www.chromestatus.com/feature/5718547946799104>"); | 527 "<https://www.chromestatus.com/feature/5718547946799104>"); |
534 } | 528 } |
535 | 529 |
536 FetchRequest request(resourceRequest, m_element->localName()); | 530 FetchRequest request(resourceRequest, m_element->initiatorName()); |
537 | 531 |
538 // 15. "Let CORS setting be the current state of the element's | 532 // 15. "Let CORS setting be the current state of the element's |
539 // crossorigin content attribute." | 533 // crossorigin content attribute." |
540 CrossOriginAttributeValue crossOrigin = crossOriginAttributeValue( | 534 CrossOriginAttributeValue crossOrigin = |
541 m_element->fastGetAttribute(HTMLNames::crossoriginAttr)); | 535 crossOriginAttributeValue(m_element->crossOriginAttributeValue()); |
542 | 536 |
543 // 16. "Let module script credentials mode be determined by switching | 537 // 16. "Let module script credentials mode be determined by switching |
544 // on CORS setting:" | 538 // on CORS setting:" |
545 // TODO(hiroshige): Implement this step for "module". | 539 // TODO(hiroshige): Implement this step for "module". |
546 | 540 |
547 // 21.6, "classic": "Fetch a classic script given ... CORS setting | 541 // 21.6, "classic": "Fetch a classic script given ... CORS setting |
548 // ... and encoding." | 542 // ... and encoding." |
549 if (crossOrigin != CrossOriginAttributeNotSet) | 543 if (crossOrigin != CrossOriginAttributeNotSet) |
550 request.setCrossOriginAccessControl(elementDocument->getSecurityOrigin(), | 544 request.setCrossOriginAccessControl(elementDocument->getSecurityOrigin(), |
551 crossOrigin); | 545 crossOrigin); |
552 | 546 |
553 request.setCharset(encoding); | 547 request.setCharset(encoding); |
554 | 548 |
555 // 17. "If the script element has a nonce attribute, | 549 // 17. "If the script element has a nonce attribute, |
556 // then let cryptographic nonce be that attribute's value. | 550 // then let cryptographic nonce be that attribute's value. |
557 // Otherwise, let cryptographic nonce be the empty string." | 551 // Otherwise, let cryptographic nonce be the empty string." |
558 if (ContentSecurityPolicy::isNonceableElement(m_element.get())) | 552 if (m_element->isNonceableElement()) |
559 request.setContentSecurityPolicyNonce(client()->nonce()); | 553 request.setContentSecurityPolicyNonce(m_element->nonce()); |
560 | 554 |
561 // 19. "Let parser state be "parser-inserted" | 555 // 19. "Let parser state be "parser-inserted" |
562 // if the script element has been flagged as "parser-inserted", | 556 // if the script element has been flagged as "parser-inserted", |
563 // and "not parser-inserted" otherwise." | 557 // and "not parser-inserted" otherwise." |
564 request.setParserDisposition(isParserInserted() ? ParserInserted | 558 request.setParserDisposition(isParserInserted() ? ParserInserted |
565 : NotParserInserted); | 559 : NotParserInserted); |
566 | 560 |
567 request.setDefer(defer); | 561 request.setDefer(defer); |
568 | 562 |
569 // 18. "If the script element has an integrity attribute, | 563 // 18. "If the script element has an integrity attribute, |
570 // then let integrity metadata be that attribute's value. | 564 // then let integrity metadata be that attribute's value. |
571 // Otherwise, let integrity metadata be the empty string." | 565 // Otherwise, let integrity metadata be the empty string." |
572 String integrityAttr = | 566 String integrityAttr = m_element->integrityAttributeValue(); |
573 m_element->fastGetAttribute(HTMLNames::integrityAttr); | |
574 if (!integrityAttr.isEmpty()) { | 567 if (!integrityAttr.isEmpty()) { |
575 IntegrityMetadataSet metadataSet; | 568 IntegrityMetadataSet metadataSet; |
576 SubresourceIntegrity::parseIntegrityAttribute(integrityAttr, metadataSet, | 569 SubresourceIntegrity::parseIntegrityAttribute(integrityAttr, metadataSet, |
577 elementDocument); | 570 elementDocument); |
578 request.setIntegrityMetadata(metadataSet); | 571 request.setIntegrityMetadata(metadataSet); |
579 } | 572 } |
580 | 573 |
581 // 21.6. "Switch on the script's type:" | 574 // 21.6. "Switch on the script's type:" |
582 | 575 |
583 // - "classic": | 576 // - "classic": |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
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_element->document().getSecurityOrigin()->canRequest(resource->url()); |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
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_element->isNonceableElement() ? m_element->nonce() : nullAtom; |
708 ? client()->nonce() | 691 if (!m_isExternalScript && !shouldBypassMainWorldCSP && |
709 : nullAtom; | 692 !m_element->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 = sourceCode.resource(); | 698 ScriptResource* resource = sourceCode.resource(); |
719 CHECK_EQ(resource, m_resource); | 699 CHECK_EQ(resource, m_resource); |
720 CHECK(resource); | 700 CHECK(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 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
779 | 759 |
780 // 4. "Let old script element be the value to which the script element's | 760 // 4. "Let old script element be the value to which the script element's |
781 // node document's currentScript object was most recently set." | 761 // node document's currentScript object was most recently set." |
782 // This is implemented as push/popCurrentScript(). | 762 // This is implemented as push/popCurrentScript(). |
783 | 763 |
784 // 5. "Switch on the script's type:" | 764 // 5. "Switch on the script's type:" |
785 // - "classic": | 765 // - "classic": |
786 // 1. "If the script element's root is not a shadow root, | 766 // 1. "If the script element's root is not a shadow root, |
787 // then set the script element's node document's currentScript | 767 // then set the script element's node document's currentScript |
788 // attribute to the script element. Otherwise, set it to null." | 768 // attribute to the script element. Otherwise, set it to null." |
789 if (isHTMLScriptLoader(m_element) || isSVGScriptLoader(m_element)) | 769 contextDocument->pushCurrentScript(m_element.get()); |
790 contextDocument->pushCurrentScript(m_element); | |
791 | 770 |
792 // 2. "Run the classic script given by the script's script." | 771 // 2. "Run the classic script given by the script's script." |
793 // Note: This is where the script is compiled and actually executed. | 772 // Note: This is where the script is compiled and actually executed. |
794 frame->script().executeScriptInMainWorld(sourceCode, accessControlStatus); | 773 frame->script().executeScriptInMainWorld(sourceCode, accessControlStatus); |
795 | 774 |
796 // - "module": | 775 // - "module": |
797 // TODO(hiroshige): Implement this. | 776 // TODO(hiroshige): Implement this. |
798 | 777 |
799 // 6. "Set the script element's node document's currentScript attribute | 778 // 6. "Set the script element's node document's currentScript attribute |
800 // to old script element." | 779 // to old script element." |
801 if (isHTMLScriptLoader(m_element) || isSVGScriptLoader(m_element)) { | 780 contextDocument->popCurrentScript(m_element.get()); |
802 DCHECK(contextDocument->currentScript() == m_element); | |
803 contextDocument->popCurrentScript(); | |
804 } | |
805 | 781 |
806 return true; | 782 return true; |
807 | 783 |
808 // 7. "Decrement the ignore-destructive-writes counter of neutralized doc, | 784 // 7. "Decrement the ignore-destructive-writes counter of neutralized doc, |
809 // if it was incremented in the earlier step." | 785 // if it was incremented in the earlier step." |
810 // Implemented as the scope out of IgnoreDestructiveWriteCountIncrementer. | 786 // Implemented as the scope out of IgnoreDestructiveWriteCountIncrementer. |
811 } | 787 } |
812 | 788 |
813 void ScriptLoader::execute() { | 789 void ScriptLoader::execute() { |
814 DCHECK(!m_willBeParserExecuted); | 790 DCHECK(!m_willBeParserExecuted); |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
858 detachPendingScript(); | 834 detachPendingScript(); |
859 dispatchErrorEvent(); | 835 dispatchErrorEvent(); |
860 return; | 836 return; |
861 } | 837 } |
862 contextDocument->scriptRunner()->notifyScriptReady(this, m_asyncExecType); | 838 contextDocument->scriptRunner()->notifyScriptReady(this, m_asyncExecType); |
863 m_pendingScript->stopWatchingForLoad(); | 839 m_pendingScript->stopWatchingForLoad(); |
864 } | 840 } |
865 | 841 |
866 bool ScriptLoader::ignoresLoadRequest() const { | 842 bool ScriptLoader::ignoresLoadRequest() const { |
867 return m_alreadyStarted || m_isExternalScript || m_parserInserted || | 843 return m_alreadyStarted || m_isExternalScript || m_parserInserted || |
868 !element() || !element()->isConnected(); | 844 !m_element->isConnected(); |
869 } | 845 } |
870 | 846 |
871 // Step 13 of https://html.spec.whatwg.org/#prepare-a-script | 847 // Step 13 of https://html.spec.whatwg.org/#prepare-a-script |
872 bool ScriptLoader::isScriptForEventSupported() const { | 848 bool ScriptLoader::isScriptForEventSupported() const { |
873 // 1. "Let for be the value of the for attribute." | 849 // 1. "Let for be the value of the for attribute." |
874 String eventAttribute = client()->eventAttributeValue(); | 850 String eventAttribute = m_element->eventAttributeValue(); |
875 // 2. "Let event be the value of the event attribute." | 851 // 2. "Let event be the value of the event attribute." |
876 String forAttribute = client()->forAttributeValue(); | 852 String forAttribute = m_element->forAttributeValue(); |
877 | 853 |
878 // "If the script element has an event attribute and a for attribute, and | 854 // "If the script element has an event attribute and a for attribute, and |
879 // the script's type is "classic", then run these substeps:" | 855 // the script's type is "classic", then run these substeps:" |
880 // TODO(hiroshige): Check the script's type. | 856 // TODO(hiroshige): Check the script's type. |
881 if (eventAttribute.isNull() || forAttribute.isNull()) | 857 if (eventAttribute.isNull() || forAttribute.isNull()) |
882 return true; | 858 return true; |
883 | 859 |
884 // 3. "Strip leading and trailing ASCII whitespace from event and for." | 860 // 3. "Strip leading and trailing ASCII whitespace from event and for." |
885 forAttribute = forAttribute.stripWhiteSpace(); | 861 forAttribute = forAttribute.stripWhiteSpace(); |
886 // 4. "If for is not an ASCII case-insensitive match for the string | 862 // 4. "If for is not an ASCII case-insensitive match for the string |
887 // "window", | 863 // "window", |
888 // then abort these steps at this point. The script is not executed." | 864 // then abort these steps at this point. The script is not executed." |
889 if (!equalIgnoringCase(forAttribute, "window")) | 865 if (!equalIgnoringCase(forAttribute, "window")) |
890 return false; | 866 return false; |
891 eventAttribute = eventAttribute.stripWhiteSpace(); | 867 eventAttribute = eventAttribute.stripWhiteSpace(); |
892 // 5. "If event is not an ASCII case-insensitive match for either the | 868 // 5. "If event is not an ASCII case-insensitive match for either the |
893 // string "onload" or the string "onload()", | 869 // string "onload" or the string "onload()", |
894 // then abort these steps at this point. The script is not executed. | 870 // then abort these steps at this point. The script is not executed. |
895 return equalIgnoringCase(eventAttribute, "onload") || | 871 return equalIgnoringCase(eventAttribute, "onload") || |
896 equalIgnoringCase(eventAttribute, "onload()"); | 872 equalIgnoringCase(eventAttribute, "onload()"); |
897 } | 873 } |
898 | 874 |
899 String ScriptLoader::scriptContent() const { | 875 String ScriptLoader::scriptContent() const { |
900 return m_element->textFromChildren(); | 876 return m_element->textFromChildren(); |
901 } | 877 } |
902 | 878 |
903 ScriptLoaderClient* ScriptLoader::client() const { | |
904 if (isHTMLScriptLoader(m_element)) | |
905 return toHTMLScriptElement(m_element); | |
906 | |
907 if (isSVGScriptLoader(m_element)) | |
908 return toSVGScriptElement(m_element); | |
909 | |
910 NOTREACHED(); | |
911 return 0; | |
912 } | |
913 | |
914 ScriptLoader* toScriptLoaderIfPossible(Element* element) { | |
915 if (isHTMLScriptLoader(element)) | |
916 return toHTMLScriptElement(element)->loader(); | |
917 | |
918 if (isSVGScriptLoader(element)) | |
919 return toSVGScriptElement(element)->loader(); | |
920 | |
921 return 0; | |
922 } | |
923 | |
924 } // namespace blink | 879 } // namespace blink |
OLD | NEW |