[WebCore] Clean up script loading code in XML
authorutatane.tea@gmail.com <utatane.tea@gmail.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 17 Nov 2016 06:47:31 +0000 (06:47 +0000)
committerutatane.tea@gmail.com <utatane.tea@gmail.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 17 Nov 2016 06:47:31 +0000 (06:47 +0000)
https://bugs.webkit.org/show_bug.cgi?id=161651

Reviewed by Ryosuke Niwa.

Source/WebCore:

This patch cleans up XML document script handling by using PendingScript.
Previously, we directly used CachedScript. But it is not good since we
have PendingScript wrapper.

We also disable ES6 modules for non HTML document. While ES6 modules tag
requires "defer" semantics, "defer" semantics is not implemented in non
HTML documents. And ES6 module tag is only specified in whatwg HTML spec.

* dom/LoadableClassicScript.cpp:
(WebCore::LoadableClassicScript::execute):
* dom/ScriptElement.cpp:
(WebCore::ScriptElement::determineScriptType):
(WebCore::ScriptElement::prepareScript):
(WebCore::ScriptElement::executeClassicScript):
(WebCore::ScriptElement::executePendingScript):
(WebCore::ScriptElement::executeScript): Deleted.
(WebCore::ScriptElement::executeScriptForScriptRunner): Deleted.
* dom/ScriptElement.h:
* dom/ScriptRunner.cpp:
(WebCore::ScriptRunner::timerFired):
* html/parser/HTMLDocumentParser.cpp:
* html/parser/HTMLScriptRunner.cpp:
(WebCore::HTMLScriptRunner::executePendingScriptAndDispatchEvent):
(WebCore::HTMLScriptRunner::runScript):
* xml/parser/XMLDocumentParser.cpp:
(WebCore::XMLDocumentParser::notifyFinished):
* xml/parser/XMLDocumentParser.h:
* xml/parser/XMLDocumentParserLibxml2.cpp:
(WebCore::XMLDocumentParser::XMLDocumentParser):
(WebCore::XMLDocumentParser::~XMLDocumentParser):
(WebCore::XMLDocumentParser::endElementNs):

LayoutTests:

Add tests that ensure modules are not executed in XHTML documents.

* js/dom/modules/module-inline-dynamic-in-xhtml-expected.txt: Added.
* js/dom/modules/module-inline-dynamic-in-xhtml.xhtml: Added.
* js/dom/modules/module-inline-simple-in-xhtml-expected.txt: Added.
* js/dom/modules/module-inline-simple-in-xhtml.xhtml: Added.
* js/dom/modules/module-src-dynamic-in-xhtml-expected.txt: Added.
* js/dom/modules/module-src-dynamic-in-xhtml.xhtml: Added.
* js/dom/modules/module-src-simple-in-xhtml-expected.txt: Added.
* js/dom/modules/module-src-simple-in-xhtml.xhtml: Added.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@208840 268f45cc-cd09-0410-ab3c-d52691b4dbfc

19 files changed:
LayoutTests/ChangeLog
LayoutTests/js/dom/modules/module-inline-dynamic-in-xhtml-expected.txt [new file with mode: 0644]
LayoutTests/js/dom/modules/module-inline-dynamic-in-xhtml.xhtml [new file with mode: 0644]
LayoutTests/js/dom/modules/module-inline-simple-in-xhtml-expected.txt [new file with mode: 0644]
LayoutTests/js/dom/modules/module-inline-simple-in-xhtml.xhtml [new file with mode: 0644]
LayoutTests/js/dom/modules/module-src-dynamic-in-xhtml-expected.txt [new file with mode: 0644]
LayoutTests/js/dom/modules/module-src-dynamic-in-xhtml.xhtml [new file with mode: 0644]
LayoutTests/js/dom/modules/module-src-simple-in-xhtml-expected.txt [new file with mode: 0644]
LayoutTests/js/dom/modules/module-src-simple-in-xhtml.xhtml [new file with mode: 0644]
Source/WebCore/ChangeLog
Source/WebCore/dom/LoadableClassicScript.cpp
Source/WebCore/dom/ScriptElement.cpp
Source/WebCore/dom/ScriptElement.h
Source/WebCore/dom/ScriptRunner.cpp
Source/WebCore/html/parser/HTMLDocumentParser.cpp
Source/WebCore/html/parser/HTMLScriptRunner.cpp
Source/WebCore/xml/parser/XMLDocumentParser.cpp
Source/WebCore/xml/parser/XMLDocumentParser.h
Source/WebCore/xml/parser/XMLDocumentParserLibxml2.cpp

index d3fd62a..9880874 100644 (file)
@@ -1,3 +1,21 @@
+2016-11-16  Yusuke Suzuki  <utatane.tea@gmail.com>
+
+        [WebCore] Clean up script loading code in XML
+        https://bugs.webkit.org/show_bug.cgi?id=161651
+
+        Reviewed by Ryosuke Niwa.
+
+        Add tests that ensure modules are not executed in XHTML documents.
+
+        * js/dom/modules/module-inline-dynamic-in-xhtml-expected.txt: Added.
+        * js/dom/modules/module-inline-dynamic-in-xhtml.xhtml: Added.
+        * js/dom/modules/module-inline-simple-in-xhtml-expected.txt: Added.
+        * js/dom/modules/module-inline-simple-in-xhtml.xhtml: Added.
+        * js/dom/modules/module-src-dynamic-in-xhtml-expected.txt: Added.
+        * js/dom/modules/module-src-dynamic-in-xhtml.xhtml: Added.
+        * js/dom/modules/module-src-simple-in-xhtml-expected.txt: Added.
+        * js/dom/modules/module-src-simple-in-xhtml.xhtml: Added.
+
 2016-11-16  Ryosuke Niwa  <rniwa@webkit.org>
 
         REGRESSION(r208082): 1% Speedometer regression on iOS
diff --git a/LayoutTests/js/dom/modules/module-inline-dynamic-in-xhtml-expected.txt b/LayoutTests/js/dom/modules/module-inline-dynamic-in-xhtml-expected.txt
new file mode 100644 (file)
index 0000000..37dfb00
--- /dev/null
@@ -0,0 +1,11 @@
+Test dynamically added inlined module does not work in XHTML document.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+Module is not executed yet.
+PASS window.exportedCocoa is undefined
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/js/dom/modules/module-inline-dynamic-in-xhtml.xhtml b/LayoutTests/js/dom/modules/module-inline-dynamic-in-xhtml.xhtml
new file mode 100644 (file)
index 0000000..7b841f8
--- /dev/null
@@ -0,0 +1,39 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<script src="../../../resources/js-test-pre.js"></script>
+</head>
+<body>
+<script>
+description('Test dynamically added inlined module does not work in XHTML document.');
+
+// Module will be executed asynchronously.
+window.jsTestIsAsync = true;
+</script>
+<script src="../../../resources/js-test-post.js"></script>
+<script>
+debug('Module is not executed yet.');
+(function () {
+    var element = document.createElement("script");
+    element.textContent = `
+        import Cocoa from "./script-tests/module-inline-dynamic.js";
+        var cocoa = new Cocoa();
+
+        debug("Module execution is confined in the module environment.");
+        shouldBeEqualToString("typeof cocoa", "undefined");
+
+        window.exportedCocoa = cocoa;
+        shouldBeEqualToString("typeof exportedCocoa", "object");
+        shouldBeEqualToString("exportedCocoa.taste()", "awesome");
+        finishJSTest();
+    `;
+    element.type = "module";
+    document.body.appendChild(element);
+    setTimeout(function () {
+        shouldBe(`window.exportedCocoa`, `undefined`);
+        finishJSTest();
+    }, 100);
+} ());
+</script>
+</body>
+</html>
diff --git a/LayoutTests/js/dom/modules/module-inline-simple-in-xhtml-expected.txt b/LayoutTests/js/dom/modules/module-inline-simple-in-xhtml-expected.txt
new file mode 100644 (file)
index 0000000..fc5c9c6
--- /dev/null
@@ -0,0 +1,11 @@
+Test inlined module does not work in XHTML document.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+Module is not executed yet.
+PASS window.exportedCocoa is undefined
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/js/dom/modules/module-inline-simple-in-xhtml.xhtml b/LayoutTests/js/dom/modules/module-inline-simple-in-xhtml.xhtml
new file mode 100644 (file)
index 0000000..ad6f6c6
--- /dev/null
@@ -0,0 +1,36 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<script src="../../../resources/js-test-pre.js"></script>
+</head>
+<body>
+<script>
+description('Test inlined module does not work in XHTML document.');
+
+// Module will be executed asynchronously.
+window.jsTestIsAsync = true;
+</script>
+<script>
+debug('Module is not executed yet.');
+</script>
+<script src="../../../resources/js-test-post.js"></script>
+<script type="module">
+import Cocoa from "./script-tests/module-inline-simple.js";
+var cocoa = new Cocoa();
+
+debug("Module execution is confined in the module environment.");
+shouldBeEqualToString("typeof cocoa", "undefined");
+
+window.exportedCocoa = cocoa;
+shouldBeEqualToString("typeof exportedCocoa", "object");
+shouldBeEqualToString("exportedCocoa.taste()", "awesome");
+finishJSTest();
+</script>
+<script>
+window.addEventListener('load', function () {
+    shouldBe(`window.exportedCocoa`, `undefined`);
+    finishJSTest();
+});
+</script>
+</body>
+</html>
diff --git a/LayoutTests/js/dom/modules/module-src-dynamic-in-xhtml-expected.txt b/LayoutTests/js/dom/modules/module-src-dynamic-in-xhtml-expected.txt
new file mode 100644 (file)
index 0000000..cbe931f
--- /dev/null
@@ -0,0 +1,11 @@
+Test dynamically added module with "src" attribute does not work in XHTML document.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+Module is not executed yet.
+PASS window.exportedCocoa is undefined
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/js/dom/modules/module-src-dynamic-in-xhtml.xhtml b/LayoutTests/js/dom/modules/module-src-dynamic-in-xhtml.xhtml
new file mode 100644 (file)
index 0000000..c8e9760
--- /dev/null
@@ -0,0 +1,28 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<script src="../../../resources/js-test-pre.js"></script>
+</head>
+<body>
+<script>
+description('Test dynamically added module with "src" attribute does not work in XHTML document.');
+
+// Module will be executed asynchronously.
+window.jsTestIsAsync = true;
+</script>
+<script src="../../../resources/js-test-post.js"></script>
+<script>
+debug('Module is not executed yet.');
+(function () {
+    var element = document.createElement('script');
+    element.type = 'module';
+    element.src = './script-tests/module-src-dynamic.js';
+    document.body.appendChild(element);
+    setTimeout(function () {
+        shouldBe(`window.exportedCocoa`, `undefined`);
+        finishJSTest();
+    }, 100);
+}());
+</script>
+</body>
+</html>
diff --git a/LayoutTests/js/dom/modules/module-src-simple-in-xhtml-expected.txt b/LayoutTests/js/dom/modules/module-src-simple-in-xhtml-expected.txt
new file mode 100644 (file)
index 0000000..55e4d7a
--- /dev/null
@@ -0,0 +1,11 @@
+Test module with "src" attribute does not work in XHTML document.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+Module is not executed yet.
+PASS window.exportedCocoa is undefined
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/js/dom/modules/module-src-simple-in-xhtml.xhtml b/LayoutTests/js/dom/modules/module-src-simple-in-xhtml.xhtml
new file mode 100644 (file)
index 0000000..a671d78
--- /dev/null
@@ -0,0 +1,25 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<script src="../../../resources/js-test-pre.js"></script>
+</head>
+<body>
+<script>
+description('Test module with "src" attribute does not work in XHTML document.');
+
+// Module will be executed asynchronously.
+window.jsTestIsAsync = true;
+</script>
+<script>
+debug('Module is not executed yet.');
+</script>
+<script src="../../../resources/js-test-post.js"></script>
+<script type="module" src="./script-tests/module-src-simple.js"></script>
+<script>
+window.addEventListener('load', function () {
+    shouldBe(`window.exportedCocoa`, `undefined`);
+    finishJSTest();
+});
+</script>
+</body>
+</html>
index b055f2f..23cb73b 100644 (file)
@@ -1,3 +1,42 @@
+2016-11-16  Yusuke Suzuki  <utatane.tea@gmail.com>
+
+        [WebCore] Clean up script loading code in XML
+        https://bugs.webkit.org/show_bug.cgi?id=161651
+
+        Reviewed by Ryosuke Niwa.
+
+        This patch cleans up XML document script handling by using PendingScript.
+        Previously, we directly used CachedScript. But it is not good since we
+        have PendingScript wrapper.
+
+        We also disable ES6 modules for non HTML document. While ES6 modules tag
+        requires "defer" semantics, "defer" semantics is not implemented in non
+        HTML documents. And ES6 module tag is only specified in whatwg HTML spec.
+
+        * dom/LoadableClassicScript.cpp:
+        (WebCore::LoadableClassicScript::execute):
+        * dom/ScriptElement.cpp:
+        (WebCore::ScriptElement::determineScriptType):
+        (WebCore::ScriptElement::prepareScript):
+        (WebCore::ScriptElement::executeClassicScript):
+        (WebCore::ScriptElement::executePendingScript):
+        (WebCore::ScriptElement::executeScript): Deleted.
+        (WebCore::ScriptElement::executeScriptForScriptRunner): Deleted.
+        * dom/ScriptElement.h:
+        * dom/ScriptRunner.cpp:
+        (WebCore::ScriptRunner::timerFired):
+        * html/parser/HTMLDocumentParser.cpp:
+        * html/parser/HTMLScriptRunner.cpp:
+        (WebCore::HTMLScriptRunner::executePendingScriptAndDispatchEvent):
+        (WebCore::HTMLScriptRunner::runScript):
+        * xml/parser/XMLDocumentParser.cpp:
+        (WebCore::XMLDocumentParser::notifyFinished):
+        * xml/parser/XMLDocumentParser.h:
+        * xml/parser/XMLDocumentParserLibxml2.cpp:
+        (WebCore::XMLDocumentParser::XMLDocumentParser):
+        (WebCore::XMLDocumentParser::~XMLDocumentParser):
+        (WebCore::XMLDocumentParser::endElementNs):
+
 2016-11-16  Chris Dumez  <cdumez@apple.com>
 
         Add Node::isDescendantOf() overload that takes in a reference
index 94c1660..655cd1f 100644 (file)
@@ -102,7 +102,7 @@ void LoadableClassicScript::notifyFinished(CachedResource& resource)
 void LoadableClassicScript::execute(ScriptElement& scriptElement)
 {
     ASSERT(!error());
-    scriptElement.executeScript(ScriptSourceCode(m_cachedScript.get(), JSC::SourceProviderSourceType::Program));
+    scriptElement.executeClassicScript(ScriptSourceCode(m_cachedScript.get(), JSC::SourceProviderSourceType::Program));
 }
 
 }
index 3c2460d..6be0fa7 100644 (file)
@@ -163,6 +163,13 @@ Optional<ScriptElement::ScriptType> ScriptElement::determineScriptType(LegacyTyp
     if (supportLegacyTypes == AllowLegacyTypeInTypeAttribute && isLegacySupportedJavaScriptLanguage(type))
         return ScriptType::Classic;
 
+    // FIXME: XHTML spec defines "defer" attribute. But WebKit does not implement it for a long time.
+    // And module tag also uses defer attribute semantics. We disable script type="module" for non HTML document.
+    // Once "defer" is implemented, we can reconsider enabling modules in XHTML.
+    // https://bugs.webkit.org/show_bug.cgi?id=123387
+    if (!m_element.document().isHTMLDocument())
+        return Nullopt;
+
     auto* settings = m_element.document().settings();
     if (!settings || !settings->es6ModulesEnabled())
         return Nullopt;
@@ -271,7 +278,7 @@ bool ScriptElement::prepareScript(const TextPosition& scriptStartPosition, Legac
     } else {
         ASSERT(scriptType == ScriptType::Classic);
         TextPosition position = document.isInDocumentWrite() ? TextPosition() : scriptStartPosition;
-        executeScript(ScriptSourceCode(scriptContent(), document.url(), position, JSC::SourceProviderSourceType::Program));
+        executeClassicScript(ScriptSourceCode(scriptContent(), document.url(), position, JSC::SourceProviderSourceType::Program));
     }
 
     return true;
@@ -386,7 +393,7 @@ CachedResourceHandle<CachedScript> ScriptElement::requestScriptWithCache(const U
     return document.cachedResourceLoader().requestScript(WTFMove(request));
 }
 
-void ScriptElement::executeScript(const ScriptSourceCode& sourceCode)
+void ScriptElement::executeClassicScript(const ScriptSourceCode& sourceCode)
 {
     ASSERT(m_alreadyStarted);
 
@@ -442,14 +449,14 @@ void ScriptElement::executeScriptAndDispatchEvent(LoadableScript& loadableScript
     }
 }
 
-void ScriptElement::executeScriptForScriptRunner(PendingScript& pendingScript)
+void ScriptElement::executePendingScript(PendingScript& pendingScript)
 {
     if (auto* loadableScript = pendingScript.loadableScript())
         executeScriptAndDispatchEvent(*loadableScript);
     else {
         ASSERT(!pendingScript.error());
-        JSC::SourceProviderSourceType sourceType = scriptType() == ScriptType::Module ? JSC::SourceProviderSourceType::Module : JSC::SourceProviderSourceType::Program;
-        executeScript(ScriptSourceCode(scriptContent(), m_element.document().url(), pendingScript.startingPosition(), sourceType));
+        ASSERT_WITH_MESSAGE(scriptType() == ScriptType::Classic, "Module script always have a loadableScript pointer.");
+        executeClassicScript(ScriptSourceCode(scriptContent(), m_element.document().url(), pendingScript.startingPosition(), JSC::SourceProviderSourceType::Program));
         dispatchLoadEvent();
     }
 }
index 23a7e59..f414b4b 100644 (file)
@@ -51,10 +51,10 @@ public:
 
     String scriptCharset() const { return m_characterEncoding; }
     WEBCORE_EXPORT String scriptContent() const;
-    void executeScript(const ScriptSourceCode&);
+    void executeClassicScript(const ScriptSourceCode&);
     void executeModuleScript(CachedModuleScript&);
 
-    void executeScriptForScriptRunner(PendingScript&);
+    void executePendingScript(PendingScript&);
 
     // XML parser calls these
     virtual void dispatchLoadEvent() = 0;
index 653e40f..70989eb 100644 (file)
@@ -125,7 +125,7 @@ void ScriptRunner::timerFired()
         auto* scriptElement = toScriptElementIfPossible(&script->element());
         ASSERT(scriptElement);
         ASSERT(script->needsLoading());
-        scriptElement->executeScriptForScriptRunner(*script);
+        scriptElement->executePendingScript(*script);
         m_document.decrementLoadEventDelayCount();
     }
 }
index c07cd34..27111fb 100644 (file)
@@ -27,7 +27,6 @@
 #include "config.h"
 #include "HTMLDocumentParser.h"
 
-#include "CachedScript.h"
 #include "DocumentFragment.h"
 #include "Frame.h"
 #include "HTMLDocument.h"
index 6b176f1..c256b42 100644 (file)
@@ -121,7 +121,7 @@ void HTMLScriptRunner::executePendingScriptAndDispatchEvent(RefPtr<PendingScript
 
     if (auto* scriptElement = toScriptElementIfPossible(&pendingScript->element())) {
         NestingLevelIncrementer nestingLevelIncrementer(m_scriptNestingLevel);
-        scriptElement->executeScriptForScriptRunner(*pendingScript);
+        scriptElement->executePendingScript(*pendingScript);
     }
     ASSERT(!isExecutingScript());
 }
@@ -275,7 +275,7 @@ void HTMLScriptRunner::runScript(Element* script, const TextPosition& scriptStar
             if (m_scriptNestingLevel == 1)
                 m_parserBlockingScript = PendingScript::create(*script, scriptStartPosition);
             else
-                scriptElement->executeScript(ScriptSourceCode(script->textContent(), documentURLForScriptExecution(m_document), scriptStartPosition));
+                scriptElement->executeClassicScript(ScriptSourceCode(script->textContent(), documentURLForScriptExecution(m_document), scriptStartPosition));
         } else
             requestParsingBlockingScript(script);
     }
index f1ff7b9..ce20104 100644 (file)
@@ -27,7 +27,6 @@
 #include "XMLDocumentParser.h"
 
 #include "CDATASection.h"
-#include "CachedScript.h"
 #include "Comment.h"
 #include "Document.h"
 #include "DocumentFragment.h"
@@ -39,6 +38,7 @@
 #include "HTMLNames.h"
 #include "HTMLStyleElement.h"
 #include "ImageLoader.h"
+#include "PendingScript.h"
 #include "ProcessingInstruction.h"
 #include "ResourceError.h"
 #include "ResourceRequest.h"
@@ -227,37 +227,18 @@ void XMLDocumentParser::insertErrorMessageBlock()
     m_xmlErrors->insertErrorMessageBlock();
 }
 
-void XMLDocumentParser::notifyFinished(CachedResource& unusedResource)
+void XMLDocumentParser::notifyFinished(PendingScript& pendingScript)
 {
-    ASSERT_UNUSED(unusedResource, &unusedResource == m_pendingScript);
-    ASSERT(m_pendingScript->accessCount() > 0);
-
-    // FIXME: Support ES6 modules in XML document.
-    // https://bugs.webkit.org/show_bug.cgi?id=161651
-    ScriptSourceCode sourceCode(m_pendingScript.get(), JSC::SourceProviderSourceType::Program);
-    bool errorOccurred = m_pendingScript->errorOccurred();
-    bool wasCanceled = m_pendingScript->wasCanceled();
-
-    m_pendingScript->removeClient(*this);
-    m_pendingScript = nullptr;
-
-    RefPtr<Element> e = m_scriptElement;
-    m_scriptElement = nullptr;
-
-    ScriptElement* scriptElement = toScriptElementIfPossible(e.get());
-    ASSERT(scriptElement);
+    ASSERT(&pendingScript == m_pendingScript.get());
 
     // JavaScript can detach this parser, make sure it's kept alive even if detached.
     Ref<XMLDocumentParser> protectedThis(*this);
-    
-    if (errorOccurred)
-        scriptElement->dispatchErrorEvent();
-    else if (!wasCanceled) {
-        scriptElement->executeScript(sourceCode);
-        scriptElement->dispatchLoadEvent();
-    }
 
-    m_scriptElement = nullptr;
+    m_pendingScript = nullptr;
+    pendingScript.clearClient();
+
+    auto& scriptElement = *toScriptElementIfPossible(&pendingScript.element());
+    scriptElement.executePendingScript(pendingScript);
 
     if (!isDetached() && !m_requestingScript)
         resumeParsing();
index 9ae4c65..c691768 100644 (file)
@@ -24,9 +24,8 @@
 
 #pragma once
 
-#include "CachedResourceClient.h"
-#include "CachedResourceHandle.h"
 #include "FragmentScriptingPermission.h"
+#include "PendingScriptClient.h"
 #include "ScriptableDocumentParser.h"
 #include "SegmentedString.h"
 #include "XMLErrors.h"
 namespace WebCore {
 
 class ContainerNode;
-class CachedScript;
 class CachedResourceLoader;
 class DocumentFragment;
 class Document;
 class Element;
 class FrameView;
 class PendingCallbacks;
+class PendingScript;
 class Text;
 
     class XMLParserContext : public RefCounted<XMLParserContext> {
@@ -64,7 +63,7 @@ class Text;
         xmlParserCtxtPtr m_context;
     };
 
-    class XMLDocumentParser final : public ScriptableDocumentParser, public CachedResourceClient {
+    class XMLDocumentParser final : public ScriptableDocumentParser, public PendingScriptClient {
         WTF_MAKE_FAST_ALLOCATED;
     public:
         static Ref<XMLDocumentParser> create(Document& document, FrameView* view)
@@ -106,8 +105,7 @@ class Text;
         TextPosition textPosition() const override;
         bool shouldAssociateConsoleMessagesWithTextPosition() const override;
 
-        // from CachedResourceClient
-        void notifyFinished(CachedResource&) final;
+        void notifyFinished(PendingScript&) final;
 
         void end();
 
@@ -178,8 +176,7 @@ class Text;
 
         std::unique_ptr<XMLErrors> m_xmlErrors;
 
-        CachedResourceHandle<CachedScript> m_pendingScript;
-        RefPtr<Element> m_scriptElement;
+        RefPtr<PendingScript> m_pendingScript;
         TextPosition m_scriptStartPosition;
 
         bool m_parsingFragment;
index 8603775..9f4af7a 100644 (file)
@@ -29,7 +29,6 @@
 #include "XMLDocumentParser.h"
 
 #include "CDATASection.h"
-#include "CachedScript.h"
 #include "Comment.h"
 #include "CachedResourceLoader.h"
 #include "Document.h"
@@ -46,6 +45,7 @@
 #include "HTMLTemplateElement.h"
 #include "LoadableClassicScript.h"
 #include "Page.h"
+#include "PendingScript.h"
 #include "ProcessingInstruction.h"
 #include "ResourceError.h"
 #include "ResourceRequest.h"
@@ -588,7 +588,6 @@ XMLDocumentParser::XMLDocumentParser(Document& document, FrameView* frameView)
     , m_parserPaused(false)
     , m_requestingScript(false)
     , m_finishCalled(false)
-    , m_pendingScript(nullptr)
     , m_scriptStartPosition(TextPosition::belowRangePosition())
     , m_parsingFragment(false)
 {
@@ -610,7 +609,6 @@ XMLDocumentParser::XMLDocumentParser(DocumentFragment& fragment, Element* parent
     , m_parserPaused(false)
     , m_requestingScript(false)
     , m_finishCalled(false)
-    , m_pendingScript(0)
     , m_scriptStartPosition(TextPosition::belowRangePosition())
     , m_parsingFragment(true)
 {
@@ -662,7 +660,7 @@ XMLDocumentParser::~XMLDocumentParser()
 
     // FIXME: m_pendingScript handling should be moved into XMLDocumentParser.cpp!
     if (m_pendingScript)
-        m_pendingScript->removeClient(*this);
+        m_pendingScript->clearClient();
 }
 
 void XMLDocumentParser::doWrite(const String& parseString)
@@ -915,19 +913,15 @@ void XMLDocumentParser::endElementNs()
         // the libxml2 and Qt XMLDocumentParser implementations.
 
         if (scriptElement->readyToBeParserExecuted())
-            scriptElement->executeScript(ScriptSourceCode(scriptElement->scriptContent(), document()->url(), m_scriptStartPosition));
-        else if (scriptElement->willBeParserExecuted() && scriptElement->loadableScript() && is<LoadableClassicScript>(*scriptElement->loadableScript())) {
-            // FIXME: Allow "module" scripts for XML documents.
-            // https://bugs.webkit.org/show_bug.cgi?id=161651
-            m_pendingScript = &downcast<LoadableClassicScript>(*scriptElement->loadableScript()).cachedScript();
-            m_scriptElement = &element;
-            m_pendingScript->addClient(*this);
-
-            // m_pendingScript will be 0 if script was already loaded and addClient() executed it.
+            scriptElement->executeClassicScript(ScriptSourceCode(scriptElement->scriptContent(), document()->url(), m_scriptStartPosition));
+        else if (scriptElement->willBeParserExecuted() && scriptElement->loadableScript()) {
+            m_pendingScript = PendingScript::create(element, *scriptElement->loadableScript());
+            m_pendingScript->setClient(this);
+
+            // m_pendingScript will be nullptr if script was already loaded and setClient() executed it.
             if (m_pendingScript)
                 pauseParsing();
-        } else
-            m_scriptElement = nullptr;
+        }
 
         // JavaScript may have detached the parser
         if (isDetached())