blob: 66bbece1d35e1a4763bf9ebebf0f0c12cdbef1d7 [file] [log] [blame]
zimmermann@webkit.org9ae47e92008-08-14 02:22:35 +00001/*
2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3 * (C) 1999 Antti Koivisto (koivisto@kde.org)
4 * (C) 2001 Dirk Mueller (mueller@kde.org)
5 * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
6 * Copyright (C) 2008 Nikolas Zimmermann <zimmermann@kde.org>
7 *
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Library General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
12 *
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Library General Public License for more details.
17 *
18 * You should have received a copy of the GNU Library General Public License
19 * along with this library; see the file COPYING.LIB. If not, write to
20 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21 * Boston, MA 02110-1301, USA.
22 */
23
24#include "config.h"
25#include "ScriptElement.h"
26
abarth@webkit.org17d66c62010-09-08 10:26:02 +000027#include "CachedResourceLoader.h"
commit-queue@webkit.org5e7ea1b2012-10-22 23:35:28 +000028#include "CachedResourceRequest.h"
joepeck@webkit.org1f45df92014-02-06 23:45:53 +000029#include "CachedScript.h"
abarth@webkit.orgf921dee2011-03-26 11:59:34 +000030#include "ContentSecurityPolicy.h"
commit-queue@webkit.orga42d1f62012-03-20 05:29:11 +000031#include "CrossOriginAccessControl.h"
kangil.han@samsung.com6b8ffd82013-06-25 02:38:54 +000032#include "CurrentScriptIncrementer.h"
abarth@webkit.org401a3792013-03-03 10:12:59 +000033#include "Event.h"
zimmermann@webkit.org9ae47e92008-08-14 02:22:35 +000034#include "Frame.h"
35#include "FrameLoader.h"
zimmermann@webkit.org67ac8f82009-01-21 19:49:37 +000036#include "HTMLNames.h"
japhet@chromium.org59e6e212011-08-31 19:01:08 +000037#include "HTMLParserIdioms.h"
tonyg@chromium.org8500eb82010-10-22 01:27:27 +000038#include "IgnoreDestructiveWriteCountIncrementer.h"
zimmermann@webkit.org9ae47e92008-08-14 02:22:35 +000039#include "MIMETypeRegistry.h"
eric@webkit.orgab9e7382010-05-19 19:02:12 +000040#include "Page.h"
ossy@webkit.org66d8c0a2014-02-05 11:42:35 +000041#include "SVGNames.h"
42#include "SVGScriptElement.h"
weinig@apple.com123e4aa2013-04-14 00:54:27 +000043#include "ScriptController.h"
simonjam@chromium.org5871a052011-03-16 00:00:09 +000044#include "ScriptRunner.h"
darin@chromium.org6b412472008-11-24 23:07:38 +000045#include "ScriptSourceCode.h"
commit-queue@webkit.orgfae2ea22012-05-25 23:29:45 +000046#include "ScriptableDocumentParser.h"
commit-queue@webkit.orga42d1f62012-03-20 05:29:11 +000047#include "SecurityOrigin.h"
eric@webkit.orgab9e7382010-05-19 19:02:12 +000048#include "Settings.h"
antti@apple.comadb7e122013-08-17 21:33:23 +000049#include "TextNodeTraversal.h"
joepeck@webkit.orga3198442013-12-11 22:40:23 +000050#include <bindings/ScriptValue.h>
joepeck@webkit.org1f45df92014-02-06 23:45:53 +000051#include <inspector/ScriptCallStack.h>
bolsinga@apple.com97e42c42008-11-15 04:47:20 +000052#include <wtf/StdLibExtras.h>
zimmermann@webkit.org64ca9f92011-05-16 10:20:34 +000053#include <wtf/text/StringBuilder.h>
barraclough@apple.combbb3cd42010-08-10 17:45:41 +000054#include <wtf/text/StringHash.h>
zimmermann@webkit.org9ae47e92008-08-14 02:22:35 +000055
56namespace WebCore {
57
akling@apple.coma564ed62014-07-04 19:54:43 +000058ScriptElement::ScriptElement(Element& element, bool parserInserted, bool alreadyStarted)
rniwa@webkit.orgf8278482010-11-17 18:56:45 +000059 : m_element(element)
60 , m_cachedScript(0)
commit-queue@webkit.orgfae2ea22012-05-25 23:29:45 +000061 , m_startLineNumber(WTF::OrdinalNumber::beforeFirst())
simonjam@chromium.org4879ffa2011-02-19 09:39:06 +000062 , m_parserInserted(parserInserted)
rniwa@webkit.orgeb0ec5e2010-12-01 02:09:33 +000063 , m_isExternalScript(false)
simonjam@chromium.org4879ffa2011-02-19 09:39:06 +000064 , m_alreadyStarted(alreadyStarted)
rniwa@webkit.orgeb0ec5e2010-12-01 02:09:33 +000065 , m_haveFiredLoad(false)
simonjam@chromium.org4879ffa2011-02-19 09:39:06 +000066 , m_willBeParserExecuted(false)
67 , m_readyToBeParserExecuted(false)
68 , m_willExecuteWhenDocumentFinishedParsing(false)
simonjam@chromium.org5871a052011-03-16 00:00:09 +000069 , m_forceAsync(!parserInserted)
70 , m_willExecuteInOrder(false)
commit-queue@webkit.orga42d1f62012-03-20 05:29:11 +000071 , m_requestUsesAccessControl(false)
zimmermann@webkit.org9ae47e92008-08-14 02:22:35 +000072{
akling@apple.coma564ed62014-07-04 19:54:43 +000073 if (parserInserted && m_element.document().scriptableDocumentParser() && !m_element.document().isInDocumentWrite())
74 m_startLineNumber = m_element.document().scriptableDocumentParser()->textPosition().m_line;
rniwa@webkit.org1329a192010-11-16 05:23:34 +000075}
76
rniwa@webkit.orgf8278482010-11-17 18:56:45 +000077ScriptElement::~ScriptElement()
rniwa@webkit.org1329a192010-11-16 05:23:34 +000078{
rniwa@webkit.orgf8278482010-11-17 18:56:45 +000079 stopLoadRequest();
rniwa@webkit.org1329a192010-11-16 05:23:34 +000080}
81
aestes@apple.com8b7dab72015-06-21 21:14:51 +000082bool ScriptElement::shouldCallFinishedInsertingSubtree(ContainerNode& insertionPoint)
rniwa@webkit.org1329a192010-11-16 05:23:34 +000083{
aestes@apple.com74888f42015-06-19 21:55:55 +000084 return insertionPoint.inDocument() && !m_parserInserted;
85}
86
aestes@apple.com8b7dab72015-06-21 21:14:51 +000087void ScriptElement::finishedInsertingSubtree()
aestes@apple.com74888f42015-06-19 21:55:55 +000088{
89 ASSERT(!m_parserInserted);
90 prepareScript(); // FIXME: Provide a real starting line number here.
zimmermann@webkit.org9ae47e92008-08-14 02:22:35 +000091}
92
rniwa@webkit.org1329a192010-11-16 05:23:34 +000093void ScriptElement::childrenChanged()
zimmermann@webkit.org9ae47e92008-08-14 02:22:35 +000094{
akling@apple.coma564ed62014-07-04 19:54:43 +000095 if (!m_parserInserted && m_element.inDocument())
simonjam@chromium.org4879ffa2011-02-19 09:39:06 +000096 prepareScript(); // FIXME: Provide a real starting line number here.
zimmermann@webkit.org9ae47e92008-08-14 02:22:35 +000097}
98
rniwa@webkit.org1329a192010-11-16 05:23:34 +000099void ScriptElement::handleSourceAttribute(const String& sourceUrl)
zimmermann@webkit.org9ae47e92008-08-14 02:22:35 +0000100{
rniwa@webkit.orgf8278482010-11-17 18:56:45 +0000101 if (ignoresLoadRequest() || sourceUrl.isEmpty())
zimmermann@webkit.org9ae47e92008-08-14 02:22:35 +0000102 return;
103
simonjam@chromium.org4879ffa2011-02-19 09:39:06 +0000104 prepareScript(); // FIXME: Provide a real starting line number here.
zimmermann@webkit.org9ae47e92008-08-14 02:22:35 +0000105}
106
simonjam@chromium.org5871a052011-03-16 00:00:09 +0000107void ScriptElement::handleAsyncAttribute()
108{
109 m_forceAsync = false;
110}
111
zimmermann@webkit.org9ae47e92008-08-14 02:22:35 +0000112// Helper function
simonjam@chromium.org4879ffa2011-02-19 09:39:06 +0000113static bool isLegacySupportedJavaScriptLanguage(const String& language)
zimmermann@webkit.org9ae47e92008-08-14 02:22:35 +0000114{
simonjam@chromium.org4879ffa2011-02-19 09:39:06 +0000115 // Mozilla 1.8 accepts javascript1.0 - javascript1.7, but WinIE 7 accepts only javascript1.1 - javascript1.3.
116 // Mozilla 1.8 and WinIE 7 both accept javascript and livescript.
117 // WinIE 7 accepts ecmascript and jscript, but Mozilla 1.8 doesn't.
118 // Neither Mozilla 1.8 nor WinIE 7 accept leading or trailing whitespace.
119 // We want to accept all the values that either of these browsers accept, but not other values.
120
121 // FIXME: This function is not HTML5 compliant. These belong in the MIME registry as "text/javascript<version>" entries.
bolsinga@apple.com97e42c42008-11-15 04:47:20 +0000122 typedef HashSet<String, CaseFoldingHash> LanguageSet;
svillar@igalia.com5b31eef2014-03-14 08:30:55 +0000123 DEPRECATED_DEFINE_STATIC_LOCAL(LanguageSet, languages, ());
zimmermann@webkit.org9ae47e92008-08-14 02:22:35 +0000124 if (languages.isEmpty()) {
125 languages.add("javascript");
126 languages.add("javascript");
127 languages.add("javascript1.0");
128 languages.add("javascript1.1");
129 languages.add("javascript1.2");
130 languages.add("javascript1.3");
131 languages.add("javascript1.4");
132 languages.add("javascript1.5");
133 languages.add("javascript1.6");
134 languages.add("javascript1.7");
135 languages.add("livescript");
136 languages.add("ecmascript");
simonjam@chromium.org4879ffa2011-02-19 09:39:06 +0000137 languages.add("jscript");
zimmermann@webkit.org9ae47e92008-08-14 02:22:35 +0000138 }
139
140 return languages.contains(language);
141}
142
yurys@chromium.orgfb5a0d82011-04-20 11:52:04 +0000143void ScriptElement::dispatchErrorEvent()
144{
akling@apple.coma564ed62014-07-04 19:54:43 +0000145 m_element.dispatchEvent(Event::create(eventNames().errorEvent, false, false));
yurys@chromium.orgfb5a0d82011-04-20 11:52:04 +0000146}
147
simonjam@chromium.org4879ffa2011-02-19 09:39:06 +0000148bool ScriptElement::isScriptTypeSupported(LegacyTypeSupport supportLegacyTypes) const
zimmermann@webkit.org9ae47e92008-08-14 02:22:35 +0000149{
simonjam@chromium.org4879ffa2011-02-19 09:39:06 +0000150 // FIXME: isLegacySupportedJavaScriptLanguage() is not valid HTML5. It is used here to maintain backwards compatibility with existing layout tests. The specific violations are:
151 // - Allowing type=javascript. type= should only support MIME types, such as text/javascript.
152 // - Allowing a different set of languages for language= and type=. language= supports Javascript 1.1 and 1.4-1.6, but type= does not.
153
154 String type = typeAttributeValue();
155 String language = languageAttributeValue();
156 if (type.isEmpty() && language.isEmpty())
157 return true; // Assume text/javascript.
158 if (type.isEmpty()) {
159 type = "text/" + language.lower();
160 if (MIMETypeRegistry::isSupportedJavaScriptMIMEType(type) || isLegacySupportedJavaScriptLanguage(language))
161 return true;
162 } else if (MIMETypeRegistry::isSupportedJavaScriptMIMEType(type.stripWhiteSpace().lower()) || (supportLegacyTypes == AllowLegacyTypeInTypeAttribute && isLegacySupportedJavaScriptLanguage(type)))
163 return true;
164 return false;
165}
166
167// http://dev.w3.org/html5/spec/Overview.html#prepare-a-script
commit-queue@webkit.org9c6e4a32011-09-19 18:45:47 +0000168bool ScriptElement::prepareScript(const TextPosition& scriptStartPosition, LegacyTypeSupport supportLegacyTypes)
simonjam@chromium.org4879ffa2011-02-19 09:39:06 +0000169{
170 if (m_alreadyStarted)
171 return false;
172
173 bool wasParserInserted;
174 if (m_parserInserted) {
175 wasParserInserted = true;
176 m_parserInserted = false;
177 } else
178 wasParserInserted = false;
179
simonjam@chromium.org5871a052011-03-16 00:00:09 +0000180 if (wasParserInserted && !asyncAttributeValue())
181 m_forceAsync = true;
simonjam@chromium.org4879ffa2011-02-19 09:39:06 +0000182
183 // FIXME: HTML5 spec says we should check that all children are either comments or empty text nodes.
akling@apple.coma564ed62014-07-04 19:54:43 +0000184 if (!hasSourceAttribute() && !m_element.firstChild())
simonjam@chromium.org4879ffa2011-02-19 09:39:06 +0000185 return false;
186
akling@apple.coma564ed62014-07-04 19:54:43 +0000187 if (!m_element.inDocument())
simonjam@chromium.org4879ffa2011-02-19 09:39:06 +0000188 return false;
189
190 if (!isScriptTypeSupported(supportLegacyTypes))
191 return false;
192
simonjam@chromium.org5871a052011-03-16 00:00:09 +0000193 if (wasParserInserted) {
simonjam@chromium.org4879ffa2011-02-19 09:39:06 +0000194 m_parserInserted = true;
simonjam@chromium.org5871a052011-03-16 00:00:09 +0000195 m_forceAsync = false;
196 }
simonjam@chromium.org4879ffa2011-02-19 09:39:06 +0000197
198 m_alreadyStarted = true;
199
200 // FIXME: If script is parser inserted, verify it's still in the original document.
akling@apple.coma564ed62014-07-04 19:54:43 +0000201 Document& document = m_element.document();
simonjam@chromium.org4879ffa2011-02-19 09:39:06 +0000202
203 // FIXME: Eventually we'd like to evaluate scripts which are inserted into a
mrowe@apple.com5d92f2a2008-09-30 21:04:35 +0000204 // viewless document but this'll do for now.
205 // See http://bugs.webkit.org/show_bug.cgi?id=5727
akling@apple.com622b1a42013-08-30 14:30:12 +0000206 if (!document.frame())
simonjam@chromium.org4879ffa2011-02-19 09:39:06 +0000207 return false;
208
akling@apple.com622b1a42013-08-30 14:30:12 +0000209 if (!document.frame()->script().canExecuteScripts(AboutToExecuteScript))
simonjam@chromium.org4879ffa2011-02-19 09:39:06 +0000210 return false;
211
212 if (!isScriptForEventSupported())
213 return false;
214
215 if (!charsetAttributeValue().isEmpty())
216 m_characterEncoding = charsetAttributeValue();
217 else
akling@apple.com622b1a42013-08-30 14:30:12 +0000218 m_characterEncoding = document.charset();
simonjam@chromium.org4879ffa2011-02-19 09:39:06 +0000219
220 if (hasSourceAttribute())
221 if (!requestScript(sourceAttributeValue()))
222 return false;
223
224 if (hasSourceAttribute() && deferAttributeValue() && m_parserInserted && !asyncAttributeValue()) {
225 m_willExecuteWhenDocumentFinishedParsing = true;
226 m_willBeParserExecuted = true;
227 } else if (hasSourceAttribute() && m_parserInserted && !asyncAttributeValue())
228 m_willBeParserExecuted = true;
akling@apple.com622b1a42013-08-30 14:30:12 +0000229 else if (!hasSourceAttribute() && m_parserInserted && !document.haveStylesheetsLoaded()) {
simonjam@chromium.org4879ffa2011-02-19 09:39:06 +0000230 m_willBeParserExecuted = true;
231 m_readyToBeParserExecuted = true;
simonjam@chromium.org5871a052011-03-16 00:00:09 +0000232 } else if (hasSourceAttribute() && !asyncAttributeValue() && !m_forceAsync) {
233 m_willExecuteInOrder = true;
akling@apple.com622b1a42013-08-30 14:30:12 +0000234 document.scriptRunner()->queueScriptForExecution(this, m_cachedScript, ScriptRunner::IN_ORDER_EXECUTION);
simonjam@chromium.org5871a052011-03-16 00:00:09 +0000235 m_cachedScript->addClient(this);
jochen@chromium.org20935732012-01-16 09:37:03 +0000236 } else if (hasSourceAttribute()) {
akling@apple.coma564ed62014-07-04 19:54:43 +0000237 m_element.document().scriptRunner()->queueScriptForExecution(this, m_cachedScript, ScriptRunner::ASYNC_EXECUTION);
simonjam@chromium.org4879ffa2011-02-19 09:39:06 +0000238 m_cachedScript->addClient(this);
jochen@chromium.org20935732012-01-16 09:37:03 +0000239 } else {
pfeldman@chromium.org2679eaf2011-10-28 13:27:32 +0000240 // Reset line numbering for nested writes.
akling@apple.com622b1a42013-08-30 14:30:12 +0000241 TextPosition position = document.isInDocumentWrite() ? TextPosition() : scriptStartPosition;
242 executeScript(ScriptSourceCode(scriptContent(), document.url(), position));
pfeldman@chromium.org2679eaf2011-10-28 13:27:32 +0000243 }
simonjam@chromium.org4879ffa2011-02-19 09:39:06 +0000244
245 return true;
246}
247
248bool ScriptElement::requestScript(const String& sourceUrl)
249{
akling@apple.coma564ed62014-07-04 19:54:43 +0000250 Ref<Document> originalDocument(m_element.document());
251 if (!m_element.dispatchBeforeLoadEvent(sourceUrl))
simonjam@chromium.org4879ffa2011-02-19 09:39:06 +0000252 return false;
cdumez@apple.com78141732014-11-04 23:00:48 +0000253 if (!m_element.inDocument() || &m_element.document() != originalDocument.ptr())
simonjam@chromium.org4879ffa2011-02-19 09:39:06 +0000254 return false;
hyatt@apple.comad45b612009-10-06 17:37:48 +0000255
zimmermann@webkit.org9ae47e92008-08-14 02:22:35 +0000256 ASSERT(!m_cachedScript);
japhet@chromium.org59e6e212011-08-31 19:01:08 +0000257 if (!stripLeadingAndTrailingHTMLSpaces(sourceUrl).isEmpty()) {
dbates@webkit.org264add72015-07-07 00:42:50 +0000258 ResourceLoaderOptions options = CachedResourceLoader::defaultCachedResourceOptions();
259 options.setContentSecurityPolicyImposition(m_element.isInUserAgentShadowTree() ? ContentSecurityPolicyImposition::SkipPolicyCheck : ContentSecurityPolicyImposition::DoPolicyCheck);
260
261 CachedResourceRequest request(ResourceRequest(m_element.document().completeURL(sourceUrl)), options);
commit-queue@webkit.orga42d1f62012-03-20 05:29:11 +0000262
akling@apple.coma564ed62014-07-04 19:54:43 +0000263 String crossOriginMode = m_element.fastGetAttribute(HTMLNames::crossoriginAttr);
commit-queue@webkit.orga42d1f62012-03-20 05:29:11 +0000264 if (!crossOriginMode.isNull()) {
265 m_requestUsesAccessControl = true;
266 StoredCredentials allowCredentials = equalIgnoringCase(crossOriginMode, "use-credentials") ? AllowStoredCredentials : DoNotAllowStoredCredentials;
akling@apple.coma564ed62014-07-04 19:54:43 +0000267 updateRequestForAccessControl(request.mutableResourceRequest(), m_element.document().securityOrigin(), allowCredentials);
commit-queue@webkit.orga42d1f62012-03-20 05:29:11 +0000268 }
commit-queue@webkit.org5e7ea1b2012-10-22 23:35:28 +0000269 request.setCharset(scriptCharset());
akling@apple.coma564ed62014-07-04 19:54:43 +0000270 request.setInitiator(&element());
commit-queue@webkit.orga42d1f62012-03-20 05:29:11 +0000271
cdumez@apple.com0bb03ec2015-01-28 05:53:53 +0000272 m_cachedScript = m_element.document().cachedResourceLoader().requestScript(request);
japhet@chromium.org59e6e212011-08-31 19:01:08 +0000273 m_isExternalScript = true;
274 }
zimmermann@webkit.org9ae47e92008-08-14 02:22:35 +0000275
gavinp@chromium.org22aaf032011-08-26 13:15:00 +0000276 if (m_cachedScript) {
simonjam@chromium.org4879ffa2011-02-19 09:39:06 +0000277 return true;
gavinp@chromium.org22aaf032011-08-26 13:15:00 +0000278 }
zimmermann@webkit.org9ae47e92008-08-14 02:22:35 +0000279
rniwa@webkit.orgf8278482010-11-17 18:56:45 +0000280 dispatchErrorEvent();
simonjam@chromium.org4879ffa2011-02-19 09:39:06 +0000281 return false;
zimmermann@webkit.org9ae47e92008-08-14 02:22:35 +0000282}
283
simonjam@chromium.org4879ffa2011-02-19 09:39:06 +0000284void ScriptElement::executeScript(const ScriptSourceCode& sourceCode)
zimmermann@webkit.org9ae47e92008-08-14 02:22:35 +0000285{
simonjam@chromium.org4879ffa2011-02-19 09:39:06 +0000286 ASSERT(m_alreadyStarted);
287
288 if (sourceCode.isEmpty())
zimmermann@webkit.org9ae47e92008-08-14 02:22:35 +0000289 return;
290
dbates@webkit.org264add72015-07-07 00:42:50 +0000291 if (!m_isExternalScript && !m_element.document().contentSecurityPolicy()->allowInlineScript(m_element.document().url(), m_startLineNumber, m_element.isInUserAgentShadowTree()))
abarth@webkit.org3285b43b2011-04-07 10:04:22 +0000292 return;
293
mkwst@chromium.org43e54ba2013-02-12 23:44:51 +0000294#if ENABLE(NOSNIFF)
295 if (m_isExternalScript && m_cachedScript && !m_cachedScript->mimeTypeAllowedByNosniff()) {
akling@apple.coma564ed62014-07-04 19:54:43 +0000296 m_element.document().addConsoleMessage(MessageSource::Security, MessageLevel::Error, "Refused to execute script from '" + m_cachedScript->url().stringCenterEllipsizedToLength() + "' because its MIME type ('" + m_cachedScript->mimeType() + "') is not executable, and strict MIME type checking is enabled.");
mkwst@chromium.org43e54ba2013-02-12 23:44:51 +0000297 return;
298 }
299#endif
300
akling@apple.coma564ed62014-07-04 19:54:43 +0000301 Ref<Document> document(m_element.document());
tonyg@chromium.org8500eb82010-10-22 01:27:27 +0000302 if (Frame* frame = document->frame()) {
cdumez@apple.com78141732014-11-04 23:00:48 +0000303 IgnoreDestructiveWriteCountIncrementer ignoreDesctructiveWriteCountIncrementer(m_isExternalScript ? document.ptr() : nullptr);
304 CurrentScriptIncrementer currentScriptIncrementer(document, &m_element);
kangil.han@samsung.com6b8ffd82013-06-25 02:38:54 +0000305
akling@apple.com622b1a42013-08-30 14:30:12 +0000306 // Create a script from the script element node, using the script
307 // block's source and the script block's type.
308 // Note: This is where the script is compiled and actually executed.
309 frame->script().evaluate(sourceCode);
zimmermann@webkit.org9ae47e92008-08-14 02:22:35 +0000310 }
zimmermann@webkit.org9ae47e92008-08-14 02:22:35 +0000311}
312
rniwa@webkit.orgf8278482010-11-17 18:56:45 +0000313void ScriptElement::stopLoadRequest()
zimmermann@webkit.org9ae47e92008-08-14 02:22:35 +0000314{
315 if (m_cachedScript) {
simonjam@chromium.org4879ffa2011-02-19 09:39:06 +0000316 if (!m_willBeParserExecuted)
317 m_cachedScript->removeClient(this);
zimmermann@webkit.org9ae47e92008-08-14 02:22:35 +0000318 m_cachedScript = 0;
319 }
320}
321
rniwa@webkit.orgf8278482010-11-17 18:56:45 +0000322void ScriptElement::execute(CachedScript* cachedScript)
zimmermann@webkit.org9ae47e92008-08-14 02:22:35 +0000323{
simonjam@chromium.org4879ffa2011-02-19 09:39:06 +0000324 ASSERT(!m_willBeParserExecuted);
mitz@apple.com73169a12009-04-20 04:20:08 +0000325 ASSERT(cachedScript);
326 if (cachedScript->errorOccurred())
rniwa@webkit.orgf8278482010-11-17 18:56:45 +0000327 dispatchErrorEvent();
ap@apple.comab624d542011-05-29 01:37:59 +0000328 else if (!cachedScript->wasCanceled()) {
simonjam@chromium.org4879ffa2011-02-19 09:39:06 +0000329 executeScript(ScriptSourceCode(cachedScript));
rniwa@webkit.orgf8278482010-11-17 18:56:45 +0000330 dispatchLoadEvent();
zimmermann@webkit.org9ae47e92008-08-14 02:22:35 +0000331 }
mitz@apple.comaf63be92009-06-10 20:37:47 +0000332 cachedScript->removeClient(this);
mitz@apple.com73169a12009-04-20 04:20:08 +0000333}
zimmermann@webkit.org9ae47e92008-08-14 02:22:35 +0000334
commit-queue@webkit.orga42d1f62012-03-20 05:29:11 +0000335void ScriptElement::notifyFinished(CachedResource* resource)
mitz@apple.com73169a12009-04-20 04:20:08 +0000336{
simonjam@chromium.org4879ffa2011-02-19 09:39:06 +0000337 ASSERT(!m_willBeParserExecuted);
morrita@google.combec58192013-01-17 01:38:20 +0000338
339 // CachedResource possibly invokes this notifyFinished() more than
340 // once because ScriptElement doesn't unsubscribe itself from
341 // CachedResource here and does it in execute() instead.
342 // We use m_cachedScript to check if this function is already called.
commit-queue@webkit.orga42d1f62012-03-20 05:29:11 +0000343 ASSERT_UNUSED(resource, resource == m_cachedScript);
morrita@google.combec58192013-01-17 01:38:20 +0000344 if (!m_cachedScript)
345 return;
commit-queue@webkit.orga42d1f62012-03-20 05:29:11 +0000346
antti@apple.com5c3e6642015-05-16 13:53:21 +0000347 if (m_requestUsesAccessControl && !m_cachedScript->passesSameOriginPolicyCheck(*m_element.document().securityOrigin())) {
commit-queue@webkit.orga42d1f62012-03-20 05:29:11 +0000348 dispatchErrorEvent();
svillar@igalia.com5b31eef2014-03-14 08:30:55 +0000349 DEPRECATED_DEFINE_STATIC_LOCAL(String, consoleMessage, (ASCIILiteral("Cross-origin script load denied by Cross-Origin Resource Sharing policy.")));
akling@apple.coma564ed62014-07-04 19:54:43 +0000350 m_element.document().addConsoleMessage(MessageSource::JS, MessageLevel::Error, consoleMessage);
commit-queue@webkit.orga42d1f62012-03-20 05:29:11 +0000351 return;
352 }
353
simonjam@chromium.org5871a052011-03-16 00:00:09 +0000354 if (m_willExecuteInOrder)
akling@apple.coma564ed62014-07-04 19:54:43 +0000355 m_element.document().scriptRunner()->notifyScriptReady(this, ScriptRunner::IN_ORDER_EXECUTION);
simonjam@chromium.org5871a052011-03-16 00:00:09 +0000356 else
akling@apple.coma564ed62014-07-04 19:54:43 +0000357 m_element.document().scriptRunner()->notifyScriptReady(this, ScriptRunner::ASYNC_EXECUTION);
gavinp@chromium.org22aaf032011-08-26 13:15:00 +0000358
mitz@apple.comaf63be92009-06-10 20:37:47 +0000359 m_cachedScript = 0;
zimmermann@webkit.org9ae47e92008-08-14 02:22:35 +0000360}
361
rniwa@webkit.orgf8278482010-11-17 18:56:45 +0000362bool ScriptElement::ignoresLoadRequest() const
zimmermann@webkit.org9ae47e92008-08-14 02:22:35 +0000363{
akling@apple.coma564ed62014-07-04 19:54:43 +0000364 return m_alreadyStarted || m_isExternalScript || m_parserInserted || !m_element.inDocument();
zimmermann@webkit.org9ae47e92008-08-14 02:22:35 +0000365}
366
simonjam@chromium.org4879ffa2011-02-19 09:39:06 +0000367bool ScriptElement::isScriptForEventSupported() const
zimmermann@webkit.org9ae47e92008-08-14 02:22:35 +0000368{
rniwa@webkit.orgf8278482010-11-17 18:56:45 +0000369 String eventAttribute = eventAttributeValue();
simonjam@chromium.org4879ffa2011-02-19 09:39:06 +0000370 String forAttribute = forAttributeValue();
371 if (!eventAttribute.isEmpty() && !forAttribute.isEmpty()) {
tonyg@chromium.orgbd35ae22010-09-10 22:38:40 +0000372 forAttribute = forAttribute.stripWhiteSpace();
373 if (!equalIgnoringCase(forAttribute, "window"))
374 return false;
simonjam@chromium.org4879ffa2011-02-19 09:39:06 +0000375
tonyg@chromium.orgbd35ae22010-09-10 22:38:40 +0000376 eventAttribute = eventAttribute.stripWhiteSpace();
377 if (!equalIgnoringCase(eventAttribute, "onload") && !equalIgnoringCase(eventAttribute, "onload()"))
378 return false;
379 }
tonyg@chromium.orgbd35ae22010-09-10 22:38:40 +0000380 return true;
zimmermann@webkit.org9ae47e92008-08-14 02:22:35 +0000381}
382
rniwa@webkit.orgf8278482010-11-17 18:56:45 +0000383String ScriptElement::scriptContent() const
zimmermann@webkit.org9ae47e92008-08-14 02:22:35 +0000384{
cdumez@apple.comb7f48502015-01-26 22:36:36 +0000385 return TextNodeTraversal::contentsAsString(m_element);
zimmermann@webkit.org9ae47e92008-08-14 02:22:35 +0000386}
387
pdr@google.comb38b6ff2013-03-28 05:04:38 +0000388ScriptElement* toScriptElementIfPossible(Element* element)
zimmermann@webkit.org67ac8f82009-01-21 19:49:37 +0000389{
cdumez@apple.coma9c60c92014-10-02 19:39:41 +0000390 if (is<HTMLScriptElement>(*element))
cdumez@apple.com72754ba2014-09-23 22:03:15 +0000391 return downcast<HTMLScriptElement>(element);
zimmermann@webkit.org67ac8f82009-01-21 19:49:37 +0000392
cdumez@apple.coma9c60c92014-10-02 19:39:41 +0000393 if (is<SVGScriptElement>(*element))
cdumez@apple.com7487b352014-09-23 00:55:05 +0000394 return downcast<SVGScriptElement>(element);
zimmermann@webkit.org67ac8f82009-01-21 19:49:37 +0000395
cdumez@apple.com7487b352014-09-23 00:55:05 +0000396 return nullptr;
zimmermann@webkit.org67ac8f82009-01-21 19:49:37 +0000397}
398
zimmermann@webkit.org9ae47e92008-08-14 02:22:35 +0000399}