| 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 |