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

Unified Diff: third_party/WebKit/Source/core/dom/ScriptLoader.cpp

Issue 2723793002: De-Element ScriptLoader (Closed)
Patch Set: De-Element ScriptLoader Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: third_party/WebKit/Source/core/dom/ScriptLoader.cpp
diff --git a/third_party/WebKit/Source/core/dom/ScriptLoader.cpp b/third_party/WebKit/Source/core/dom/ScriptLoader.cpp
index 556fd9b9bc08b85524bea725d0620f317f46dbbf..c7efab3ec63333965efd28f00a469fa483a4b8b3 100644
--- a/third_party/WebKit/Source/core/dom/ScriptLoader.cpp
+++ b/third_party/WebKit/Source/core/dom/ScriptLoader.cpp
@@ -41,11 +41,9 @@
#include "core/frame/UseCounter.h"
#include "core/frame/csp/ContentSecurityPolicy.h"
#include "core/html/CrossOriginAttribute.h"
-#include "core/html/HTMLScriptElement.h"
#include "core/html/imports/HTMLImport.h"
#include "core/html/parser/HTMLParserIdioms.h"
#include "core/inspector/ConsoleMessage.h"
-#include "core/svg/SVGScriptElement.h"
#include "platform/WebFrameScheduler.h"
#include "platform/loader/fetch/AccessControlStatus.h"
#include "platform/loader/fetch/FetchRequest.h"
@@ -60,11 +58,11 @@
namespace blink {
-ScriptLoader::ScriptLoader(Element* element,
+ScriptLoader::ScriptLoader(ScriptLoaderClient* client,
bool parserInserted,
bool alreadyStarted,
bool createdDuringDocumentWrite)
- : m_element(element),
+ : m_client(client),
m_startLineNumber(WTF::OrdinalNumber::beforeFirst()),
m_haveFiredLoad(false),
m_willBeParserExecuted(false),
@@ -73,7 +71,7 @@ ScriptLoader::ScriptLoader(Element* element,
m_asyncExecType(ScriptRunner::None),
m_documentWriteIntervention(
DocumentWriteIntervention::DocumentWriteInterventionNone) {
- DCHECK(m_element);
+ DCHECK(m_client);
// https://html.spec.whatwg.org/#already-started
// "The cloning steps for script elements must set the "already started"
@@ -96,16 +94,17 @@ ScriptLoader::ScriptLoader(Element* element,
m_nonBlocking = false;
}
- if (parserInserted && element->document().scriptableDocumentParser() &&
- !element->document().isInDocumentWrite())
+ if (parserInserted && m_client->document().scriptableDocumentParser() &&
+ !m_client->document().isInDocumentWrite()) {
m_startLineNumber =
- element->document().scriptableDocumentParser()->lineNumber();
+ m_client->document().scriptableDocumentParser()->lineNumber();
+ }
}
ScriptLoader::~ScriptLoader() {}
DEFINE_TRACE(ScriptLoader) {
- visitor->trace(m_element);
+ visitor->trace(m_client);
visitor->trace(m_resource);
visitor->trace(m_pendingScript);
PendingScriptClient::trace(visitor);
@@ -123,7 +122,7 @@ void ScriptLoader::didNotifySubtreeInsertionsToDocument() {
}
void ScriptLoader::childrenChanged() {
- if (!m_parserInserted && m_element->isConnected())
+ if (!m_parserInserted && m_client->isConnected())
prepareScript(); // FIXME: Provide a real starting line number here.
}
@@ -175,12 +174,11 @@ static bool isLegacySupportedJavaScriptLanguage(const String& language) {
}
void ScriptLoader::dispatchErrorEvent() {
- m_element->dispatchEvent(Event::create(EventTypeNames::error));
+ m_client->dispatchErrorEvent();
}
void ScriptLoader::dispatchLoadEvent() {
- if (ScriptLoaderClient* client = this->client())
hiroshige 2017/03/01 00:58:14 So client() was always non-null and this if condit
Nate Chapin 2017/03/01 21:34:59 I believe so. I guess if buggy code had constructo
- client->dispatchLoadEvent();
+ m_client->dispatchLoadEvent();
setHaveFiredLoadEvent(true);
}
@@ -215,8 +213,8 @@ bool ScriptLoader::isValidScriptTypeAndLanguage(
bool ScriptLoader::isScriptTypeSupported(
LegacyTypeSupport supportLegacyTypes) const {
- return isValidScriptTypeAndLanguage(client()->typeAttributeValue(),
- client()->languageAttributeValue(),
+ return isValidScriptTypeAndLanguage(m_client->typeAttributeValue(),
+ m_client->languageAttributeValue(),
supportLegacyTypes);
}
@@ -228,8 +226,6 @@ bool ScriptLoader::prepareScript(const TextPosition& scriptStartPosition,
if (m_alreadyStarted)
return false;
- ScriptLoaderClient* client = this->client();
-
// 2. "If the element has its "parser-inserted" flag set, then
// set was-parser-inserted to true and unset the element's
// "parser-inserted" flag.
@@ -244,7 +240,7 @@ bool ScriptLoader::prepareScript(const TextPosition& scriptStartPosition,
// 3. "If was-parser-inserted is true and the element does not have an
// async attribute, then set the element's "non-blocking" flag to true."
- if (wasParserInserted && !client->asyncAttributeValue())
+ if (wasParserInserted && !m_client->asyncAttributeValue())
m_nonBlocking = true;
// 4. "If the element has no src attribute, and its child nodes, if any,
@@ -252,12 +248,12 @@ bool ScriptLoader::prepareScript(const TextPosition& scriptStartPosition,
// then abort these steps at this point. The script is not executed."
// FIXME: HTML5 spec says we should check that all children are either
// comments or empty text nodes.
- if (!client->hasSourceAttribute() && !m_element->hasChildren())
+ if (!m_client->hasSourceAttribute() && !m_client->hasChildren())
return false;
// 5. "If the element is not connected, then abort these steps.
// The script is not executed."
- if (!m_element->isConnected())
+ if (!m_client->isConnected())
return false;
// 6.
@@ -281,14 +277,14 @@ bool ScriptLoader::prepareScript(const TextPosition& scriptStartPosition,
// then abort these steps."
// FIXME: If script is parser inserted, verify it's still in the original
// document.
- Document& elementDocument = m_element->document();
+ Document& elementDocument = m_client->document();
Document* contextDocument = elementDocument.contextDocument();
if (!contextDocument)
return false;
// 10. "If scripting is disabled for the script element, then abort these
// steps at this point. The script is not executed."
- if (!contextDocument->allowExecutingScripts(m_element))
+ if (!contextDocument->allowExecutingScripts(&elementDocument))
return false;
// 13.
@@ -303,23 +299,23 @@ bool ScriptLoader::prepareScript(const TextPosition& scriptStartPosition,
// be the same as the encoding of the script element's node document."
// TODO(hiroshige): Should we handle failure in getting an encoding?
String encoding;
- if (!client->charsetAttributeValue().isEmpty())
- encoding = client->charsetAttributeValue();
+ if (!m_client->charsetAttributeValue().isEmpty())
+ encoding = m_client->charsetAttributeValue();
else
encoding = elementDocument.characterSet();
// Steps 15--20 are handled in fetchScript().
// 21. "If the element has a src content attribute, run these substeps:"
- if (client->hasSourceAttribute()) {
+ if (m_client->hasSourceAttribute()) {
FetchRequest::DeferOption defer = FetchRequest::NoDefer;
- if (!m_parserInserted || client->asyncAttributeValue() ||
- client->deferAttributeValue())
+ if (!m_parserInserted || m_client->asyncAttributeValue() ||
+ m_client->deferAttributeValue())
defer = FetchRequest::LazyLoad;
if (m_documentWriteIntervention ==
DocumentWriteIntervention::FetchDocWrittenScriptDeferIdle)
defer = FetchRequest::IdleLoad;
- if (!fetchScript(client->sourceAttributeValue(), encoding, defer))
+ if (!fetchScript(m_client->sourceAttributeValue(), encoding, defer))
return false;
}
@@ -351,7 +347,7 @@ bool ScriptLoader::prepareScript(const TextPosition& scriptStartPosition,
// completion to be able to remove it from the memory cache.
if (m_documentWriteIntervention ==
DocumentWriteIntervention::FetchDocWrittenScriptDeferIdle) {
- m_pendingScript = PendingScript::create(m_element, m_resource.get());
+ m_pendingScript = PendingScript::create(m_client.get(), m_resource.get());
m_pendingScript->watchForLoad(this);
return true;
}
@@ -372,8 +368,8 @@ bool ScriptLoader::prepareScript(const TextPosition& scriptStartPosition,
// and the element has been flagged as "parser-inserted",
// and the element does not have an async attribute"
// TODO(hiroshige): Check the script's type and implement "module" case.
- if (client->hasSourceAttribute() && client->deferAttributeValue() &&
- m_parserInserted && !client->asyncAttributeValue()) {
+ if (m_client->hasSourceAttribute() && m_client->deferAttributeValue() &&
+ m_parserInserted && !m_client->asyncAttributeValue()) {
// This clause is implemented by the caller-side of prepareScript():
// - HTMLParserScriptRunner::requestDeferredScript(), and
// - TODO(hiroshige): Investigate XMLDocumentParser::endElementNs()
@@ -389,8 +385,8 @@ bool ScriptLoader::prepareScript(const TextPosition& scriptStartPosition,
// and the element has been flagged as "parser-inserted",
// and the element does not have an async attribute"
// TODO(hiroshige): Check the script's type.
- if (client->hasSourceAttribute() && m_parserInserted &&
- !client->asyncAttributeValue()) {
+ if (m_client->hasSourceAttribute() && m_parserInserted &&
+ !m_client->asyncAttributeValue()) {
// This clause is implemented by the caller-side of prepareScript():
// - HTMLParserScriptRunner::requestParsingBlockingScript()
// - TODO(hiroshige): Investigate XMLDocumentParser::endElementNs()
@@ -413,7 +409,7 @@ bool ScriptLoader::prepareScript(const TextPosition& scriptStartPosition,
// Part of the condition check is done in
// HTMLParserScriptRunner::processScriptElementInternal().
// TODO(hiroshige): Clean up the split condition check.
- if (!client->hasSourceAttribute() && m_parserInserted &&
+ if (!m_client->hasSourceAttribute() && m_parserInserted &&
!elementDocument.isScriptExecutionReady()) {
// The former part of this clause is
// implemented by the caller-side of prepareScript():
@@ -432,12 +428,12 @@ bool ScriptLoader::prepareScript(const TextPosition& scriptStartPosition,
// and the element does not have an async attribute,
// and the element does not have the "non-blocking" flag set"
// TODO(hiroshige): Check the script's type and implement "module" case.
- if (client->hasSourceAttribute() && !client->asyncAttributeValue() &&
+ if (m_client->hasSourceAttribute() && !m_client->asyncAttributeValue() &&
!m_nonBlocking) {
// "Add the element to the end of the list of scripts that will execute
// in order as soon as possible associated with the node document of the
// script element at the time the prepare a script algorithm started."
- m_pendingScript = PendingScript::create(m_element, m_resource.get());
+ m_pendingScript = PendingScript::create(m_client.get(), m_resource.get());
m_asyncExecType = ScriptRunner::InOrder;
// TODO(hiroshige): Here |contextDocument| is used as "node document"
// while Step 14 uses |elementDocument| as "node document". Fix this.
@@ -455,13 +451,13 @@ bool ScriptLoader::prepareScript(const TextPosition& scriptStartPosition,
// 4th Clause:
// - "If the script's type is "classic", and the element has a src attribute"
// TODO(hiroshige): Check the script's type and implement "module" case.
- if (client->hasSourceAttribute()) {
+ if (m_client->hasSourceAttribute()) {
// "The element must be added to the set of scripts that will execute
// as soon as possible of the node document of the script element at the
// time the prepare a script algorithm started."
- m_pendingScript = PendingScript::create(m_element, m_resource.get());
+ m_pendingScript = PendingScript::create(m_client.get(), m_resource.get());
m_asyncExecType = ScriptRunner::Async;
- LocalFrame* frame = m_element->document().frame();
+ LocalFrame* frame = m_client->document().frame();
if (frame) {
ScriptState* scriptState = ScriptState::forMainWorld(frame);
if (scriptState)
@@ -513,10 +509,8 @@ bool ScriptLoader::prepareScript(const TextPosition& scriptStartPosition,
bool ScriptLoader::fetchScript(const String& sourceUrl,
const String& encoding,
FetchRequest::DeferOption defer) {
- DCHECK(m_element);
-
- Document* elementDocument = &(m_element->document());
- if (!m_element->isConnected() || m_element->document() != elementDocument)
+ Document* elementDocument = &(m_client->document());
+ if (!m_client->isConnected() || m_client->document() != elementDocument)
return false;
DCHECK(!m_resource);
@@ -525,12 +519,12 @@ bool ScriptLoader::fetchScript(const String& sourceUrl,
// 21.4. "Parse src relative to the element's node document."
FetchRequest request(
ResourceRequest(elementDocument->completeURL(sourceUrl)),
- m_element->localName());
+ m_client->initiatorName());
// 15. "Let CORS setting be the current state of the element's
// crossorigin content attribute."
- CrossOriginAttributeValue crossOrigin = crossOriginAttributeValue(
- m_element->fastGetAttribute(HTMLNames::crossoriginAttr));
+ CrossOriginAttributeValue crossOrigin =
+ crossOriginAttributeValue(m_client->crossOriginAttributeValue());
// 16. "Let module script credentials mode be determined by switching
// on CORS setting:"
@@ -547,8 +541,8 @@ bool ScriptLoader::fetchScript(const String& sourceUrl,
// 17. "If the script element has a nonce attribute,
// then let cryptographic nonce be that attribute's value.
// Otherwise, let cryptographic nonce be the empty string."
- if (ContentSecurityPolicy::isNonceableElement(m_element.get()))
- request.setContentSecurityPolicyNonce(client()->nonce());
+ if (m_client->isNonceableElement())
+ request.setContentSecurityPolicyNonce(m_client->nonce());
// 19. "Let parser state be "parser-inserted"
// if the script element has been flagged as "parser-inserted",
@@ -561,8 +555,7 @@ bool ScriptLoader::fetchScript(const String& sourceUrl,
// 18. "If the script element has an integrity attribute,
// then let integrity metadata be that attribute's value.
// Otherwise, let integrity metadata be the empty string."
- String integrityAttr =
- m_element->fastGetAttribute(HTMLNames::integrityAttr);
+ String integrityAttr = m_client->integrityAttributeValue();
if (!integrityAttr.isEmpty()) {
IntegrityMetadataSet metadataSet;
SubresourceIntegrity::parseIntegrityAttribute(integrityAttr, metadataSet,
@@ -625,16 +618,6 @@ bool ScriptLoader::fetchScript(const String& sourceUrl,
return true;
}
-bool isHTMLScriptLoader(Element* element) {
- DCHECK(element);
- return isHTMLScriptElement(*element);
-}
-
-bool isSVGScriptLoader(Element* element) {
- DCHECK(element);
- return isSVGScriptElement(*element);
-}
-
void ScriptLoader::logScriptMIMEType(LocalFrame* frame,
ScriptResource* resource,
const String& mimeType) {
@@ -644,7 +627,7 @@ void ScriptLoader::logScriptMIMEType(LocalFrame* frame,
if (isText && isLegacySupportedJavaScriptLanguage(mimeType.substring(5)))
return;
bool isSameOrigin =
- m_element->document().getSecurityOrigin()->canRequest(resource->url());
+ m_client->document().getSecurityOrigin()->canRequest(resource->url());
bool isApplication =
!isText && mimeType.startsWith("application/", TextCaseASCIIInsensitive);
@@ -669,7 +652,7 @@ bool ScriptLoader::executeScript(const ScriptSourceCode& sourceCode) {
// include inline script execution time as part of parser blocked script
// execution time.
if (m_asyncExecType == ScriptRunner::None)
- DocumentParserTiming::from(m_element->document())
+ DocumentParserTiming::from(m_client->document())
.recordParserBlockedOnScriptExecutionDuration(
monotonicallyIncreasingTime() - scriptExecStartTime,
wasCreatedDuringDocumentWrite());
@@ -688,7 +671,7 @@ bool ScriptLoader::doExecuteScript(const ScriptSourceCode& sourceCode) {
if (sourceCode.isEmpty())
return true;
- Document* elementDocument = &(m_element->document());
+ Document* elementDocument = &(m_client->document());
Document* contextDocument = elementDocument->contextDocument();
if (!contextDocument)
return true;
@@ -704,13 +687,10 @@ bool ScriptLoader::doExecuteScript(const ScriptSourceCode& sourceCode) {
ContentSecurityPolicy::InlineType::Block);
AtomicString nonce =
- ContentSecurityPolicy::isNonceableElement(m_element.get())
- ? client()->nonce()
- : nullAtom;
- if (!m_isExternalScript &&
- (!shouldBypassMainWorldCSP &&
- !csp->allowInlineScript(m_element, elementDocument->url(), nonce,
- m_startLineNumber, sourceCode.source()))) {
+ m_client->isNonceableElement() ? m_client->nonce() : nullAtom;
+ if (!m_isExternalScript && !shouldBypassMainWorldCSP &&
+ !m_client->allowInlineScriptForCSP(nonce, m_startLineNumber,
+ sourceCode.source())) {
return false;
}
@@ -763,7 +743,7 @@ bool ScriptLoader::doExecuteScript(const ScriptSourceCode& sourceCode) {
else
accessControlStatus = SharableCrossOrigin;
} else if (sourceCode.resource()->passesAccessControlCheck(
- m_element->document().getSecurityOrigin())) {
+ m_client->document().getSecurityOrigin())) {
accessControlStatus = SharableCrossOrigin;
}
}
@@ -787,8 +767,7 @@ bool ScriptLoader::doExecuteScript(const ScriptSourceCode& sourceCode) {
// 1. "If the script element's root is not a shadow root,
// then set the script element's node document's currentScript
// attribute to the script element. Otherwise, set it to null."
- if (isHTMLScriptLoader(m_element) || isSVGScriptLoader(m_element))
- contextDocument->pushCurrentScript(m_element);
+ contextDocument->pushCurrentScript(m_client.get());
// 2. "Run the classic script given by the script's script."
// Note: This is where the script is compiled and actually executed.
@@ -799,10 +778,7 @@ bool ScriptLoader::doExecuteScript(const ScriptSourceCode& sourceCode) {
// 6. "Set the script element's node document's currentScript attribute
// to old script element."
- if (isHTMLScriptLoader(m_element) || isSVGScriptLoader(m_element)) {
- DCHECK(contextDocument->currentScript() == m_element);
- contextDocument->popCurrentScript();
- }
+ contextDocument->popCurrentScript(m_client.get());
return true;
@@ -847,7 +823,7 @@ void ScriptLoader::pendingScriptFinished(PendingScript* pendingScript) {
DCHECK(m_asyncExecType != ScriptRunner::None);
- Document* contextDocument = m_element->document().contextDocument();
+ Document* contextDocument = m_client->document().contextDocument();
if (!contextDocument) {
detachPendingScript();
return;
@@ -866,15 +842,15 @@ void ScriptLoader::pendingScriptFinished(PendingScript* pendingScript) {
bool ScriptLoader::ignoresLoadRequest() const {
return m_alreadyStarted || m_isExternalScript || m_parserInserted ||
- !element() || !element()->isConnected();
+ !m_client->isConnected();
}
// Step 13 of https://html.spec.whatwg.org/#prepare-a-script
bool ScriptLoader::isScriptForEventSupported() const {
// 1. "Let for be the value of the for attribute."
- String eventAttribute = client()->eventAttributeValue();
+ String eventAttribute = m_client->eventAttributeValue();
// 2. "Let event be the value of the event attribute."
- String forAttribute = client()->forAttributeValue();
+ String forAttribute = m_client->forAttributeValue();
// "If the script element has an event attribute and a for attribute, and
// the script's type is "classic", then run these substeps:"
@@ -898,28 +874,7 @@ bool ScriptLoader::isScriptForEventSupported() const {
}
String ScriptLoader::scriptContent() const {
- return m_element->textFromChildren();
-}
-
-ScriptLoaderClient* ScriptLoader::client() const {
- if (isHTMLScriptLoader(m_element))
- return toHTMLScriptElement(m_element);
-
- if (isSVGScriptLoader(m_element))
- return toSVGScriptElement(m_element);
-
- NOTREACHED();
- return 0;
-}
-
-ScriptLoader* toScriptLoaderIfPossible(Element* element) {
- if (isHTMLScriptLoader(element))
- return toHTMLScriptElement(element)->loader();
-
- if (isSVGScriptLoader(element))
- return toSVGScriptElement(element)->loader();
-
- return 0;
+ return m_client->textFromChildren();
}
} // namespace blink

Powered by Google App Engine
This is Rietveld 408576698