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 reserv
ed. | 5 * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserv
ed. |
6 * Copyright (C) 2008 Nikolas Zimmermann <zimmermann@kde.org> | 6 * Copyright (C) 2008 Nikolas Zimmermann <zimmermann@kde.org> |
7 * | 7 * |
8 * This library is free software; you can redistribute it and/or | 8 * This library is free software; you can redistribute it and/or |
9 * modify it under the terms of the GNU Library General Public | 9 * modify it under the terms of the GNU Library General Public |
10 * License as published by the Free Software Foundation; either | 10 * License as published by the Free Software Foundation; either |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
59 , m_isExternalScript(false) | 59 , m_isExternalScript(false) |
60 , m_alreadyStarted(alreadyStarted) | 60 , m_alreadyStarted(alreadyStarted) |
61 , m_haveFiredLoad(false) | 61 , m_haveFiredLoad(false) |
62 , m_willBeParserExecuted(false) | 62 , m_willBeParserExecuted(false) |
63 , m_readyToBeParserExecuted(false) | 63 , m_readyToBeParserExecuted(false) |
64 , m_willExecuteWhenDocumentFinishedParsing(false) | 64 , m_willExecuteWhenDocumentFinishedParsing(false) |
65 , m_forceAsync(!parserInserted) | 65 , m_forceAsync(!parserInserted) |
66 , m_willExecuteInOrder(false) | 66 , m_willExecuteInOrder(false) |
67 { | 67 { |
68 ASSERT(m_element); | 68 ASSERT(m_element); |
69 if (parserInserted && m_element->document()->scriptableDocumentParser() && !
m_element->document()->isInDocumentWrite()) | 69 if (parserInserted && element->document()->scriptableDocumentParser() && !el
ement->document()->isInDocumentWrite()) |
70 m_startLineNumber = m_element->document()->scriptableDocumentParser()->l
ineNumber(); | 70 m_startLineNumber = element->document()->scriptableDocumentParser()->lin
eNumber(); |
71 } | 71 } |
72 | 72 |
73 ScriptElement::~ScriptElement() | 73 ScriptElement::~ScriptElement() |
74 { | 74 { |
75 stopLoadRequest(); | 75 stopLoadRequest(); |
76 } | 76 } |
77 | 77 |
78 void ScriptElement::insertedInto(ContainerNode* insertionPoint) | 78 void ScriptElement::insertedInto(ContainerNode* insertionPoint) |
79 { | 79 { |
80 if (insertionPoint->inDocument() && !m_parserInserted) | 80 if (insertionPoint->inDocument() && !m_parserInserted) |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
129 } | 129 } |
130 | 130 |
131 return languages.contains(language); | 131 return languages.contains(language); |
132 } | 132 } |
133 | 133 |
134 void ScriptElement::dispatchErrorEvent() | 134 void ScriptElement::dispatchErrorEvent() |
135 { | 135 { |
136 m_element->dispatchEvent(Event::create(eventNames().errorEvent, false, false
)); | 136 m_element->dispatchEvent(Event::create(eventNames().errorEvent, false, false
)); |
137 } | 137 } |
138 | 138 |
| 139 void ScriptElement::dispatchLoadEvent() |
| 140 { |
| 141 ASSERT(!haveFiredLoadEvent()); |
| 142 if (ScriptElementClient* client = this->client()) |
| 143 client->dispatchLoadEvent(); |
| 144 setHaveFiredLoadEvent(true); |
| 145 } |
| 146 |
139 bool ScriptElement::isScriptTypeSupported(LegacyTypeSupport supportLegacyTypes)
const | 147 bool ScriptElement::isScriptTypeSupported(LegacyTypeSupport supportLegacyTypes)
const |
140 { | 148 { |
141 // FIXME: isLegacySupportedJavaScriptLanguage() is not valid HTML5. It is us
ed here to maintain backwards compatibility with existing layout tests. The spec
ific violations are: | 149 // FIXME: isLegacySupportedJavaScriptLanguage() is not valid HTML5. It is us
ed here to maintain backwards compatibility with existing layout tests. The spec
ific violations are: |
142 // - Allowing type=javascript. type= should only support MIME types, such as
text/javascript. | 150 // - Allowing type=javascript. type= should only support MIME types, such as
text/javascript. |
143 // - Allowing a different set of languages for language= and type=. language
= supports Javascript 1.1 and 1.4-1.6, but type= does not. | 151 // - Allowing a different set of languages for language= and type=. language
= supports Javascript 1.1 and 1.4-1.6, but type= does not. |
144 | 152 |
145 String type = typeAttributeValue(); | 153 String type = client()->typeAttributeValue(); |
146 String language = languageAttributeValue(); | 154 String language = client()->languageAttributeValue(); |
147 if (type.isEmpty() && language.isEmpty()) | 155 if (type.isEmpty() && language.isEmpty()) |
148 return true; // Assume text/javascript. | 156 return true; // Assume text/javascript. |
149 if (type.isEmpty()) { | 157 if (type.isEmpty()) { |
150 type = "text/" + language.lower(); | 158 type = "text/" + language.lower(); |
151 if (MIMETypeRegistry::isSupportedJavaScriptMIMEType(type) || isLegacySup
portedJavaScriptLanguage(language)) | 159 if (MIMETypeRegistry::isSupportedJavaScriptMIMEType(type) || isLegacySup
portedJavaScriptLanguage(language)) |
152 return true; | 160 return true; |
153 } else if (MIMETypeRegistry::isSupportedJavaScriptMIMEType(type.stripWhiteSp
ace().lower()) || (supportLegacyTypes == AllowLegacyTypeInTypeAttribute && isLeg
acySupportedJavaScriptLanguage(type))) | 161 } else if (MIMETypeRegistry::isSupportedJavaScriptMIMEType(type.stripWhiteSp
ace().lower()) || (supportLegacyTypes == AllowLegacyTypeInTypeAttribute && isLeg
acySupportedJavaScriptLanguage(type))) |
154 return true; | 162 return true; |
155 return false; | 163 return false; |
156 } | 164 } |
157 | 165 |
158 // http://dev.w3.org/html5/spec/Overview.html#prepare-a-script | 166 // http://dev.w3.org/html5/spec/Overview.html#prepare-a-script |
159 bool ScriptElement::prepareScript(const TextPosition& scriptStartPosition, Legac
yTypeSupport supportLegacyTypes) | 167 bool ScriptElement::prepareScript(const TextPosition& scriptStartPosition, Legac
yTypeSupport supportLegacyTypes) |
160 { | 168 { |
161 if (m_alreadyStarted) | 169 if (m_alreadyStarted) |
162 return false; | 170 return false; |
163 | 171 |
| 172 ScriptElementClient* client = this->client(); |
| 173 |
164 bool wasParserInserted; | 174 bool wasParserInserted; |
165 if (m_parserInserted) { | 175 if (m_parserInserted) { |
166 wasParserInserted = true; | 176 wasParserInserted = true; |
167 m_parserInserted = false; | 177 m_parserInserted = false; |
168 } else | 178 } else |
169 wasParserInserted = false; | 179 wasParserInserted = false; |
170 | 180 |
171 if (wasParserInserted && !asyncAttributeValue()) | 181 if (wasParserInserted && !client->asyncAttributeValue()) |
172 m_forceAsync = true; | 182 m_forceAsync = true; |
173 | 183 |
174 // FIXME: HTML5 spec says we should check that all children are either comme
nts or empty text nodes. | 184 // FIXME: HTML5 spec says we should check that all children are either comme
nts or empty text nodes. |
175 if (!hasSourceAttribute() && !m_element->firstChild()) | 185 if (!client->hasSourceAttribute() && !m_element->firstChild()) |
176 return false; | 186 return false; |
177 | 187 |
178 if (!m_element->inDocument()) | 188 if (!m_element->inDocument()) |
179 return false; | 189 return false; |
180 | 190 |
181 if (!isScriptTypeSupported(supportLegacyTypes)) | 191 if (!isScriptTypeSupported(supportLegacyTypes)) |
182 return false; | 192 return false; |
183 | 193 |
184 if (wasParserInserted) { | 194 if (wasParserInserted) { |
185 m_parserInserted = true; | 195 m_parserInserted = true; |
(...skipping 10 matching lines...) Expand all Loading... |
196 // See http://bugs.webkit.org/show_bug.cgi?id=5727 | 206 // See http://bugs.webkit.org/show_bug.cgi?id=5727 |
197 if (!document->frame()) | 207 if (!document->frame()) |
198 return false; | 208 return false; |
199 | 209 |
200 if (!document->frame()->script()->canExecuteScripts(AboutToExecuteScript)) | 210 if (!document->frame()->script()->canExecuteScripts(AboutToExecuteScript)) |
201 return false; | 211 return false; |
202 | 212 |
203 if (!isScriptForEventSupported()) | 213 if (!isScriptForEventSupported()) |
204 return false; | 214 return false; |
205 | 215 |
206 if (!charsetAttributeValue().isEmpty()) | 216 if (!client->charsetAttributeValue().isEmpty()) |
207 m_characterEncoding = charsetAttributeValue(); | 217 m_characterEncoding = client->charsetAttributeValue(); |
208 else | 218 else |
209 m_characterEncoding = document->charset(); | 219 m_characterEncoding = document->charset(); |
210 | 220 |
211 if (hasSourceAttribute()) | 221 if (client->hasSourceAttribute()) |
212 if (!requestScript(sourceAttributeValue())) | 222 if (!requestScript(client->sourceAttributeValue())) |
213 return false; | 223 return false; |
214 | 224 |
215 if (hasSourceAttribute() && deferAttributeValue() && m_parserInserted && !as
yncAttributeValue()) { | 225 if (client->hasSourceAttribute() && client->deferAttributeValue() && m_parse
rInserted && !client->asyncAttributeValue()) { |
216 m_willExecuteWhenDocumentFinishedParsing = true; | 226 m_willExecuteWhenDocumentFinishedParsing = true; |
217 m_willBeParserExecuted = true; | 227 m_willBeParserExecuted = true; |
218 } else if (hasSourceAttribute() && m_parserInserted && !asyncAttributeValue(
)) | 228 } else if (client->hasSourceAttribute() && m_parserInserted && !client->asyn
cAttributeValue()) |
219 m_willBeParserExecuted = true; | 229 m_willBeParserExecuted = true; |
220 else if (!hasSourceAttribute() && m_parserInserted && !document->haveStylesh
eetsAndImportsLoaded()) { | 230 else if (!client->hasSourceAttribute() && m_parserInserted && !document->hav
eStylesheetsAndImportsLoaded()) { |
221 m_willBeParserExecuted = true; | 231 m_willBeParserExecuted = true; |
222 m_readyToBeParserExecuted = true; | 232 m_readyToBeParserExecuted = true; |
223 } else if (hasSourceAttribute() && !asyncAttributeValue() && !m_forceAsync)
{ | 233 } else if (client->hasSourceAttribute() && !client->asyncAttributeValue() &&
!m_forceAsync) { |
224 m_willExecuteInOrder = true; | 234 m_willExecuteInOrder = true; |
225 document->scriptRunner()->queueScriptForExecution(this, m_cachedScript,
ScriptRunner::IN_ORDER_EXECUTION); | 235 document->scriptRunner()->queueScriptForExecution(this, m_cachedScript,
ScriptRunner::IN_ORDER_EXECUTION); |
226 m_cachedScript->addClient(this); | 236 m_cachedScript->addClient(this); |
227 } else if (hasSourceAttribute()) { | 237 } else if (client->hasSourceAttribute()) { |
228 m_element->document()->scriptRunner()->queueScriptForExecution(this, m_c
achedScript, ScriptRunner::ASYNC_EXECUTION); | 238 document->scriptRunner()->queueScriptForExecution(this, m_cachedScript,
ScriptRunner::ASYNC_EXECUTION); |
229 m_cachedScript->addClient(this); | 239 m_cachedScript->addClient(this); |
230 } else { | 240 } else { |
231 // Reset line numbering for nested writes. | 241 // Reset line numbering for nested writes. |
232 TextPosition position = document->isInDocumentWrite() ? TextPosition() :
scriptStartPosition; | 242 TextPosition position = document->isInDocumentWrite() ? TextPosition() :
scriptStartPosition; |
233 KURL scriptURL = (!document->isInDocumentWrite() && m_parserInserted) ?
document->url() : KURL(); | 243 KURL scriptURL = (!document->isInDocumentWrite() && m_parserInserted) ?
document->url() : KURL(); |
234 executeScript(ScriptSourceCode(scriptContent(), scriptURL, position)); | 244 executeScript(ScriptSourceCode(scriptContent(), scriptURL, position)); |
235 } | 245 } |
236 | 246 |
237 return true; | 247 return true; |
238 } | 248 } |
239 | 249 |
240 bool ScriptElement::requestScript(const String& sourceUrl) | 250 bool ScriptElement::requestScript(const String& sourceUrl) |
241 { | 251 { |
| 252 ASSERT(m_element); |
| 253 |
242 RefPtr<Document> originalDocument = m_element->document(); | 254 RefPtr<Document> originalDocument = m_element->document(); |
243 if (!m_element->dispatchBeforeLoadEvent(sourceUrl)) | 255 if (!m_element->dispatchBeforeLoadEvent(sourceUrl)) |
244 return false; | 256 return false; |
245 if (!m_element->inDocument() || m_element->document() != originalDocument) | 257 if (!m_element->inDocument() || m_element->document() != originalDocument) |
246 return false; | 258 return false; |
247 | 259 |
248 ASSERT(!m_cachedScript); | 260 ASSERT(!m_cachedScript); |
249 if (!stripLeadingAndTrailingHTMLSpaces(sourceUrl).isEmpty()) { | 261 if (!stripLeadingAndTrailingHTMLSpaces(sourceUrl).isEmpty()) { |
250 CachedResourceRequest request(ResourceRequest(m_element->document()->com
pleteURL(sourceUrl)), element()->localName()); | 262 CachedResourceRequest request(ResourceRequest(m_element->document()->com
pleteURL(sourceUrl)), m_element->localName()); |
251 | 263 |
252 String crossOriginMode = m_element->fastGetAttribute(HTMLNames::crossori
ginAttr); | 264 String crossOriginMode = m_element->fastGetAttribute(HTMLNames::crossori
ginAttr); |
253 if (!crossOriginMode.isNull()) { | 265 if (!crossOriginMode.isNull()) { |
254 StoredCredentials allowCredentials = equalIgnoringCase(crossOriginMo
de, "use-credentials") ? AllowStoredCredentials : DoNotAllowStoredCredentials; | 266 StoredCredentials allowCredentials = equalIgnoringCase(crossOriginMo
de, "use-credentials") ? AllowStoredCredentials : DoNotAllowStoredCredentials; |
255 request.setPotentiallyCrossOriginEnabled(m_element->document()->secu
rityOrigin(), allowCredentials); | 267 request.setPotentiallyCrossOriginEnabled(m_element->document()->secu
rityOrigin(), allowCredentials); |
256 } | 268 } |
257 request.setCharset(scriptCharset()); | 269 request.setCharset(scriptCharset()); |
258 | 270 |
259 bool isValidScriptNonce = m_element->document()->contentSecurityPolicy()
->allowScriptNonce(m_element->fastGetAttribute(HTMLNames::nonceAttr)); | 271 bool isValidScriptNonce = m_element->document()->contentSecurityPolicy()
->allowScriptNonce(m_element->fastGetAttribute(HTMLNames::nonceAttr)); |
260 if (isValidScriptNonce) | 272 if (isValidScriptNonce) |
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
363 if (m_willExecuteInOrder) | 375 if (m_willExecuteInOrder) |
364 m_element->document()->scriptRunner()->notifyScriptReady(this, ScriptRun
ner::IN_ORDER_EXECUTION); | 376 m_element->document()->scriptRunner()->notifyScriptReady(this, ScriptRun
ner::IN_ORDER_EXECUTION); |
365 else | 377 else |
366 m_element->document()->scriptRunner()->notifyScriptReady(this, ScriptRun
ner::ASYNC_EXECUTION); | 378 m_element->document()->scriptRunner()->notifyScriptReady(this, ScriptRun
ner::ASYNC_EXECUTION); |
367 | 379 |
368 m_cachedScript = 0; | 380 m_cachedScript = 0; |
369 } | 381 } |
370 | 382 |
371 bool ScriptElement::ignoresLoadRequest() const | 383 bool ScriptElement::ignoresLoadRequest() const |
372 { | 384 { |
373 return m_alreadyStarted || m_isExternalScript || m_parserInserted || !m_elem
ent->inDocument(); | 385 return m_alreadyStarted || m_isExternalScript || m_parserInserted || !elemen
t() || !element()->inDocument(); |
374 } | 386 } |
375 | 387 |
376 bool ScriptElement::isScriptForEventSupported() const | 388 bool ScriptElement::isScriptForEventSupported() const |
377 { | 389 { |
378 String eventAttribute = eventAttributeValue(); | 390 String eventAttribute = client()->eventAttributeValue(); |
379 String forAttribute = forAttributeValue(); | 391 String forAttribute = client()->forAttributeValue(); |
380 if (!eventAttribute.isEmpty() && !forAttribute.isEmpty()) { | 392 if (!eventAttribute.isEmpty() && !forAttribute.isEmpty()) { |
381 forAttribute = forAttribute.stripWhiteSpace(); | 393 forAttribute = forAttribute.stripWhiteSpace(); |
382 if (!equalIgnoringCase(forAttribute, "window")) | 394 if (!equalIgnoringCase(forAttribute, "window")) |
383 return false; | 395 return false; |
384 | 396 |
385 eventAttribute = eventAttribute.stripWhiteSpace(); | 397 eventAttribute = eventAttribute.stripWhiteSpace(); |
386 if (!equalIgnoringCase(eventAttribute, "onload") && !equalIgnoringCase(e
ventAttribute, "onload()")) | 398 if (!equalIgnoringCase(eventAttribute, "onload") && !equalIgnoringCase(e
ventAttribute, "onload()")) |
387 return false; | 399 return false; |
388 } | 400 } |
389 return true; | 401 return true; |
390 } | 402 } |
391 | 403 |
392 String ScriptElement::scriptContent() const | 404 String ScriptElement::scriptContent() const |
393 { | 405 { |
394 return m_element->textFromChildren(); | 406 return m_element->textFromChildren(); |
395 } | 407 } |
396 | 408 |
| 409 ScriptElementClient* ScriptElement::client() const |
| 410 { |
| 411 if (isHTMLScriptElement(m_element)) |
| 412 return toHTMLScriptElement(m_element); |
| 413 |
| 414 if (isSVGScriptElement(m_element)) |
| 415 return toSVGScriptElement(m_element); |
| 416 |
| 417 ASSERT_NOT_REACHED(); |
| 418 return 0; |
| 419 } |
| 420 |
397 ScriptElement* toScriptElementIfPossible(Element* element) | 421 ScriptElement* toScriptElementIfPossible(Element* element) |
398 { | 422 { |
399 if (isHTMLScriptElement(element)) | 423 if (isHTMLScriptElement(element)) |
400 return toHTMLScriptElement(element); | 424 return toHTMLScriptElement(element)->scriptElement(); |
401 | 425 |
402 if (isSVGScriptElement(element)) | 426 if (isSVGScriptElement(element)) |
403 return toSVGScriptElement(element); | 427 return toSVGScriptElement(element)->scriptElement(); |
404 | 428 |
405 return 0; | 429 return 0; |
406 } | 430 } |
407 | 431 |
408 } | 432 } |
OLD | NEW |