Add the support for nomodule attribute on script element
authorutatane.tea@gmail.com <utatane.tea@gmail.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 24 Jan 2017 06:52:49 +0000 (06:52 +0000)
committerutatane.tea@gmail.com <utatane.tea@gmail.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 24 Jan 2017 06:52:49 +0000 (06:52 +0000)
https://bugs.webkit.org/show_bug.cgi?id=166987

Reviewed by Sam Weinig.

Source/WebCore:

As discussed on https://github.com/whatwg/html/pull/2261, we should have
the way to suppress classic script execution when our user agent have
modules support. With such a feature, developers can write the code like,

    <script type="module" src="./app.js"></script>
    <script nomodule src="./bundled-app.js"></script>

In the above code, if the user agent does not support modules, the bundled-app.js
will be executed. On the other hand, if the user agent supports modules, we should
ignore the script tag which has the `nomodule` attribute.
This way allows us to support the legacy browsers while using modules.

In WebKit, we already support modules. Thus, we should ignore the classic script
attributed `nomodule`.

We also rename asyncAttributeValue and deferAttributeValue to hasAsyncAttribute and
hasDeferAttribute.

Tests: js/dom/modules/nomodule-has-no-effect-on-module-inline.html
       js/dom/modules/nomodule-has-no-effect-on-module-src.html
       js/dom/modules/nomodule-prevents-execution-classic-script-inline.html
       js/dom/modules/nomodule-prevents-execution-classic-script-src.html

* dom/ScriptElement.cpp:
(WebCore::ScriptElement::prepareScript):
* dom/ScriptElement.h:
* html/HTMLAttributeNames.in:
* html/HTMLScriptElement.cpp:
(WebCore::HTMLScriptElement::hasAsyncAttribute):
(WebCore::HTMLScriptElement::hasDeferAttribute):
(WebCore::HTMLScriptElement::hasNoModuleAttribute):
(WebCore::HTMLScriptElement::asyncAttributeValue): Deleted.
(WebCore::HTMLScriptElement::deferAttributeValue): Deleted.
* html/HTMLScriptElement.h:
* html/HTMLScriptElement.idl:
* svg/SVGScriptElement.cpp:
(WebCore::SVGScriptElement::hasAsyncAttribute):
(WebCore::SVGScriptElement::hasDeferAttribute):
(WebCore::SVGScriptElement::hasNoModuleAttribute):
(WebCore::SVGScriptElement::asyncAttributeValue): Deleted.
(WebCore::SVGScriptElement::deferAttributeValue): Deleted.
* svg/SVGScriptElement.h:

LayoutTests:

* js/dom/modules/nomodule-dynamic-classic-inline-expected.txt: Added.
* js/dom/modules/nomodule-dynamic-classic-inline.html: Added.
* js/dom/modules/nomodule-dynamic-classic-src-expected.txt: Added.
* js/dom/modules/nomodule-dynamic-classic-src.html: Added.
* js/dom/modules/nomodule-has-no-effect-on-module-inline-expected.txt: Added.
* js/dom/modules/nomodule-has-no-effect-on-module-inline.html: Added.
* js/dom/modules/nomodule-has-no-effect-on-module-src-expected.txt: Added.
* js/dom/modules/nomodule-has-no-effect-on-module-src.html: Added.
* js/dom/modules/nomodule-prevents-execution-classic-script-inline-expected.txt: Added.
* js/dom/modules/nomodule-prevents-execution-classic-script-inline.html: Added.
* js/dom/modules/nomodule-prevents-execution-classic-script-src-expected.txt: Added.
* js/dom/modules/nomodule-prevents-execution-classic-script-src.html: Added.
* js/dom/modules/nomodule-reflect-expected.txt: Added.
* js/dom/modules/nomodule-reflect.html: Added.
* js/dom/modules/script-tests/error-classic-script.js: Added.

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

25 files changed:
LayoutTests/ChangeLog
LayoutTests/js/dom/modules/nomodule-dynamic-classic-inline-expected.txt [new file with mode: 0644]
LayoutTests/js/dom/modules/nomodule-dynamic-classic-inline.html [new file with mode: 0644]
LayoutTests/js/dom/modules/nomodule-dynamic-classic-src-expected.txt [new file with mode: 0644]
LayoutTests/js/dom/modules/nomodule-dynamic-classic-src.html [new file with mode: 0644]
LayoutTests/js/dom/modules/nomodule-has-no-effect-on-module-inline-expected.txt [new file with mode: 0644]
LayoutTests/js/dom/modules/nomodule-has-no-effect-on-module-inline.html [new file with mode: 0644]
LayoutTests/js/dom/modules/nomodule-has-no-effect-on-module-src-expected.txt [new file with mode: 0644]
LayoutTests/js/dom/modules/nomodule-has-no-effect-on-module-src.html [new file with mode: 0644]
LayoutTests/js/dom/modules/nomodule-prevents-execution-classic-script-inline-expected.txt [new file with mode: 0644]
LayoutTests/js/dom/modules/nomodule-prevents-execution-classic-script-inline.html [new file with mode: 0644]
LayoutTests/js/dom/modules/nomodule-prevents-execution-classic-script-src-expected.txt [new file with mode: 0644]
LayoutTests/js/dom/modules/nomodule-prevents-execution-classic-script-src.html [new file with mode: 0644]
LayoutTests/js/dom/modules/nomodule-reflect-expected.txt [new file with mode: 0644]
LayoutTests/js/dom/modules/nomodule-reflect.html [new file with mode: 0644]
LayoutTests/js/dom/modules/script-tests/error-classic-script.js [new file with mode: 0644]
Source/WebCore/ChangeLog
Source/WebCore/dom/ScriptElement.cpp
Source/WebCore/dom/ScriptElement.h
Source/WebCore/html/HTMLAttributeNames.in
Source/WebCore/html/HTMLScriptElement.cpp
Source/WebCore/html/HTMLScriptElement.h
Source/WebCore/html/HTMLScriptElement.idl
Source/WebCore/svg/SVGScriptElement.cpp
Source/WebCore/svg/SVGScriptElement.h

index 6008000..0be96e4 100644 (file)
@@ -1,3 +1,26 @@
+2017-01-15  Yusuke Suzuki  <utatane.tea@gmail.com>
+
+        Add the support for nomodule attribute on script element
+        https://bugs.webkit.org/show_bug.cgi?id=166987
+
+        Reviewed by Sam Weinig.
+
+        * js/dom/modules/nomodule-dynamic-classic-inline-expected.txt: Added.
+        * js/dom/modules/nomodule-dynamic-classic-inline.html: Added.
+        * js/dom/modules/nomodule-dynamic-classic-src-expected.txt: Added.
+        * js/dom/modules/nomodule-dynamic-classic-src.html: Added.
+        * js/dom/modules/nomodule-has-no-effect-on-module-inline-expected.txt: Added.
+        * js/dom/modules/nomodule-has-no-effect-on-module-inline.html: Added.
+        * js/dom/modules/nomodule-has-no-effect-on-module-src-expected.txt: Added.
+        * js/dom/modules/nomodule-has-no-effect-on-module-src.html: Added.
+        * js/dom/modules/nomodule-prevents-execution-classic-script-inline-expected.txt: Added.
+        * js/dom/modules/nomodule-prevents-execution-classic-script-inline.html: Added.
+        * js/dom/modules/nomodule-prevents-execution-classic-script-src-expected.txt: Added.
+        * js/dom/modules/nomodule-prevents-execution-classic-script-src.html: Added.
+        * js/dom/modules/nomodule-reflect-expected.txt: Added.
+        * js/dom/modules/nomodule-reflect.html: Added.
+        * js/dom/modules/script-tests/error-classic-script.js: Added.
+
 2017-01-23  Gyuyoung Kim  <gyuyoung.kim@webkit.org>
 
         [EFL] Update timeout tests in media/modern-media-controls
diff --git a/LayoutTests/js/dom/modules/nomodule-dynamic-classic-inline-expected.txt b/LayoutTests/js/dom/modules/nomodule-dynamic-classic-inline-expected.txt
new file mode 100644 (file)
index 0000000..8f74702
--- /dev/null
@@ -0,0 +1,10 @@
+Test dynamic inlined classic script with nomodule.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS executed is false
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/js/dom/modules/nomodule-dynamic-classic-inline.html b/LayoutTests/js/dom/modules/nomodule-dynamic-classic-inline.html
new file mode 100644 (file)
index 0000000..a3544bb
--- /dev/null
@@ -0,0 +1,31 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<script src="../../../resources/js-test-pre.js"></script>
+</head>
+<body>
+<script>
+description('Test dynamic inlined classic script with nomodule.');
+window.executed = false;
+
+// Module will be executed asynchronously.
+window.jsTestIsAsync = true;
+</script>
+<script src="../../../resources/js-test-post.js"></script>
+<script>
+(function () {
+    var element = document.createElement("script");
+    element.noModule = true;
+    element.textContent = `
+        testFailed('error');
+        window.executed = true;
+    `;
+    document.body.appendChild(element);
+    setTimeout(function () {
+        shouldBeFalse(`executed`);
+        finishJSTest();
+    }, 100);
+} ());
+</script>
+</body>
+</html>
diff --git a/LayoutTests/js/dom/modules/nomodule-dynamic-classic-src-expected.txt b/LayoutTests/js/dom/modules/nomodule-dynamic-classic-src-expected.txt
new file mode 100644 (file)
index 0000000..01782e7
--- /dev/null
@@ -0,0 +1,10 @@
+Test dynamic "src" classic script with nomodule.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS executed is false
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/js/dom/modules/nomodule-dynamic-classic-src.html b/LayoutTests/js/dom/modules/nomodule-dynamic-classic-src.html
new file mode 100644 (file)
index 0000000..5c73b38
--- /dev/null
@@ -0,0 +1,28 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<script src="../../../resources/js-test-pre.js"></script>
+</head>
+<body>
+<script>
+description('Test dynamic "src" classic script with nomodule.');
+window.executed = false;
+
+// Module will be executed asynchronously.
+window.jsTestIsAsync = true;
+</script>
+<script src="../../../resources/js-test-post.js"></script>
+<script>
+(function () {
+    var element = document.createElement('script');
+    element.noModule = true;
+    element.src = './script-tests/error-classic-script.js';
+    document.body.appendChild(element);
+    setTimeout(function () {
+        shouldBeFalse(`executed`);
+        finishJSTest();
+    }, 100);
+}());
+</script>
+</body>
+</html>
diff --git a/LayoutTests/js/dom/modules/nomodule-has-no-effect-on-module-inline-expected.txt b/LayoutTests/js/dom/modules/nomodule-has-no-effect-on-module-inline-expected.txt
new file mode 100644 (file)
index 0000000..d1b22d3
--- /dev/null
@@ -0,0 +1,14 @@
+Test nomodule does not have any effect on module script.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+Module is not executed yet.
+Module execution is confined in the module environment.
+PASS typeof cocoa is "undefined"
+PASS typeof exportedCocoa is "object"
+PASS exportedCocoa.taste() is "awesome"
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/js/dom/modules/nomodule-has-no-effect-on-module-inline.html b/LayoutTests/js/dom/modules/nomodule-has-no-effect-on-module-inline.html
new file mode 100644 (file)
index 0000000..0f3c671
--- /dev/null
@@ -0,0 +1,30 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<script src="../../../resources/js-test-pre.js"></script>
+</head>
+<body>
+<script>
+description('Test nomodule does not have any effect on module script.');
+
+// 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 nomodule 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>
+</body>
+</html>
diff --git a/LayoutTests/js/dom/modules/nomodule-has-no-effect-on-module-src-expected.txt b/LayoutTests/js/dom/modules/nomodule-has-no-effect-on-module-src-expected.txt
new file mode 100644 (file)
index 0000000..70ec0b5
--- /dev/null
@@ -0,0 +1,14 @@
+Test nomodule does not have any effect on module script.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+Module is not executed yet.
+Module execution is confined in the module environment.
+PASS typeof cocoa is "undefined"
+PASS typeof exportedCocoa is "object"
+PASS exportedCocoa.taste() is "nice"
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/js/dom/modules/nomodule-has-no-effect-on-module-src.html b/LayoutTests/js/dom/modules/nomodule-has-no-effect-on-module-src.html
new file mode 100644 (file)
index 0000000..26ba2b3
--- /dev/null
@@ -0,0 +1,19 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<script src="../../../resources/js-test-pre.js"></script>
+</head>
+<body>
+<script>
+description('Test nomodule does not have any effect on module script.');
+
+// 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 nomodule type="module" src="./script-tests/module-src-simple.js"></script>
+</body>
+</html>
diff --git a/LayoutTests/js/dom/modules/nomodule-prevents-execution-classic-script-inline-expected.txt b/LayoutTests/js/dom/modules/nomodule-prevents-execution-classic-script-inline-expected.txt
new file mode 100644 (file)
index 0000000..259bcee
--- /dev/null
@@ -0,0 +1,10 @@
+Test nomodule prevents execution of classic script.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS executed is false
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/js/dom/modules/nomodule-prevents-execution-classic-script-inline.html b/LayoutTests/js/dom/modules/nomodule-prevents-execution-classic-script-inline.html
new file mode 100644 (file)
index 0000000..035a067
--- /dev/null
@@ -0,0 +1,20 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<script src="../../../resources/js-test-pre.js"></script>
+</head>
+<body>
+<script>
+description('Test nomodule prevents execution of classic script.');
+window.executed = false;
+</script>
+<script nomodule>
+window.executed = true;
+testFailed("error");
+</script>
+<script>
+shouldBeFalse(`executed`);
+</script>
+<script src="../../../resources/js-test-post.js"></script>
+</body>
+</html>
diff --git a/LayoutTests/js/dom/modules/nomodule-prevents-execution-classic-script-src-expected.txt b/LayoutTests/js/dom/modules/nomodule-prevents-execution-classic-script-src-expected.txt
new file mode 100644 (file)
index 0000000..259bcee
--- /dev/null
@@ -0,0 +1,10 @@
+Test nomodule prevents execution of classic script.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS executed is false
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/js/dom/modules/nomodule-prevents-execution-classic-script-src.html b/LayoutTests/js/dom/modules/nomodule-prevents-execution-classic-script-src.html
new file mode 100644 (file)
index 0000000..cae3349
--- /dev/null
@@ -0,0 +1,17 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<script src="../../../resources/js-test-pre.js"></script>
+</head>
+<body>
+<script>
+description('Test nomodule prevents execution of classic script.');
+window.executed = false;
+</script>
+<script nomodule src="./script-tests/module-src-simple.js"></script>
+<script>
+shouldBeFalse(`executed`);
+</script>
+<script src="../../../resources/js-test-post.js"></script>
+</body>
+</html>
diff --git a/LayoutTests/js/dom/modules/nomodule-reflect-expected.txt b/LayoutTests/js/dom/modules/nomodule-reflect-expected.txt
new file mode 100644 (file)
index 0000000..07dd6cf
--- /dev/null
@@ -0,0 +1,13 @@
+Test dynamic "src" classic script with nomodule.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS element.noModule is true
+PASS executed is false
+PASS element.noModule is false
+PASS executed2 is true
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/js/dom/modules/nomodule-reflect.html b/LayoutTests/js/dom/modules/nomodule-reflect.html
new file mode 100644 (file)
index 0000000..868ac9e
--- /dev/null
@@ -0,0 +1,37 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<script src="../../../resources/js-test-pre.js"></script>
+</head>
+<body>
+<script>
+description('Test dynamic "src" classic script with nomodule.');
+window.executed = false;
+window.executed2 = false;
+
+// Module will be executed asynchronously.
+window.jsTestIsAsync = true;
+</script>
+<script src="../../../resources/js-test-post.js"></script>
+<script id="target" src="./script-tests/error-classic-script.js" nomodule></script>
+<script id="target2">
+window.executed2 = true;
+</script>
+<script>
+window.element = null;
+(function () {
+    {
+        element = document.getElementById('target');
+        shouldBeTrue(`element.noModule`);
+        shouldBeFalse(`executed`);
+    }
+    {
+        element = document.getElementById('target2');
+        shouldBeFalse(`element.noModule`);
+        shouldBeTrue(`executed2`);
+    }
+    finishJSTest();
+}());
+</script>
+</body>
+</html>
diff --git a/LayoutTests/js/dom/modules/script-tests/error-classic-script.js b/LayoutTests/js/dom/modules/script-tests/error-classic-script.js
new file mode 100644 (file)
index 0000000..3d70688
--- /dev/null
@@ -0,0 +1,3 @@
+window.executed = true;
+testFailed("error");
+
index d8a2a9e..7562bd3 100644 (file)
@@ -1,3 +1,53 @@
+2017-01-15  Yusuke Suzuki  <utatane.tea@gmail.com>
+
+        Add the support for nomodule attribute on script element
+        https://bugs.webkit.org/show_bug.cgi?id=166987
+
+        Reviewed by Sam Weinig.
+
+        As discussed on https://github.com/whatwg/html/pull/2261, we should have
+        the way to suppress classic script execution when our user agent have
+        modules support. With such a feature, developers can write the code like,
+
+            <script type="module" src="./app.js"></script>
+            <script nomodule src="./bundled-app.js"></script>
+
+        In the above code, if the user agent does not support modules, the bundled-app.js
+        will be executed. On the other hand, if the user agent supports modules, we should
+        ignore the script tag which has the `nomodule` attribute.
+        This way allows us to support the legacy browsers while using modules.
+
+        In WebKit, we already support modules. Thus, we should ignore the classic script
+        attributed `nomodule`.
+
+        We also rename asyncAttributeValue and deferAttributeValue to hasAsyncAttribute and
+        hasDeferAttribute.
+
+        Tests: js/dom/modules/nomodule-has-no-effect-on-module-inline.html
+               js/dom/modules/nomodule-has-no-effect-on-module-src.html
+               js/dom/modules/nomodule-prevents-execution-classic-script-inline.html
+               js/dom/modules/nomodule-prevents-execution-classic-script-src.html
+
+        * dom/ScriptElement.cpp:
+        (WebCore::ScriptElement::prepareScript):
+        * dom/ScriptElement.h:
+        * html/HTMLAttributeNames.in:
+        * html/HTMLScriptElement.cpp:
+        (WebCore::HTMLScriptElement::hasAsyncAttribute):
+        (WebCore::HTMLScriptElement::hasDeferAttribute):
+        (WebCore::HTMLScriptElement::hasNoModuleAttribute):
+        (WebCore::HTMLScriptElement::asyncAttributeValue): Deleted.
+        (WebCore::HTMLScriptElement::deferAttributeValue): Deleted.
+        * html/HTMLScriptElement.h:
+        * html/HTMLScriptElement.idl:
+        * svg/SVGScriptElement.cpp:
+        (WebCore::SVGScriptElement::hasAsyncAttribute):
+        (WebCore::SVGScriptElement::hasDeferAttribute):
+        (WebCore::SVGScriptElement::hasNoModuleAttribute):
+        (WebCore::SVGScriptElement::asyncAttributeValue): Deleted.
+        (WebCore::SVGScriptElement::deferAttributeValue): Deleted.
+        * svg/SVGScriptElement.h:
+
 2017-01-23  Joseph Pecoraro  <pecoraro@apple.com>
 
         Web Inspector: Provide a way to trigger a Garbage Collection
index f30ad08..fd8bee0 100644 (file)
@@ -187,7 +187,7 @@ bool ScriptElement::prepareScript(const TextPosition& scriptStartPosition, Legac
     } else
         wasParserInserted = false;
 
-    if (wasParserInserted && !asyncAttributeValue())
+    if (wasParserInserted && !hasAsyncAttribute())
         m_forceAsync = true;
 
     // FIXME: HTML5 spec says we should check that all children are either comments or empty text nodes.
@@ -220,6 +220,9 @@ bool ScriptElement::prepareScript(const TextPosition& scriptStartPosition, Legac
     if (!document.frame())
         return false;
 
+    if (scriptType == ScriptType::Classic && hasNoModuleAttribute())
+        return false;
+
     if (!document.frame()->script().canExecuteScripts(AboutToExecuteScript))
         return false;
 
@@ -249,21 +252,21 @@ bool ScriptElement::prepareScript(const TextPosition& scriptStartPosition, Legac
     // is handled as the same to the external module script.
 
     bool isClassicExternalScript = scriptType == ScriptType::Classic && hasSourceAttribute();
-    bool isParserInsertedDeferredScript = ((isClassicExternalScript && deferAttributeValue()) || scriptType == ScriptType::Module)
-        && m_parserInserted && !asyncAttributeValue();
+    bool isParserInsertedDeferredScript = ((isClassicExternalScript && hasDeferAttribute()) || scriptType == ScriptType::Module)
+        && m_parserInserted && !hasAsyncAttribute();
     if (isParserInsertedDeferredScript) {
         m_willExecuteWhenDocumentFinishedParsing = true;
         m_willBeParserExecuted = true;
-    } else if (isClassicExternalScript && m_parserInserted && !asyncAttributeValue()) {
+    } else if (isClassicExternalScript && m_parserInserted && !hasAsyncAttribute()) {
         ASSERT(scriptType == ScriptType::Classic);
         m_willBeParserExecuted = true;
-    } else if ((isClassicExternalScript || scriptType == ScriptType::Module) && !asyncAttributeValue() && !m_forceAsync) {
+    } else if ((isClassicExternalScript || scriptType == ScriptType::Module) && !hasAsyncAttribute() && !m_forceAsync) {
         m_willExecuteInOrder = true;
         ASSERT(m_loadableScript);
         document.scriptRunner()->queueScriptForExecution(*this, *m_loadableScript, ScriptRunner::IN_ORDER_EXECUTION);
     } else if (hasSourceAttribute() || scriptType == ScriptType::Module) {
         ASSERT(m_loadableScript);
-        ASSERT(asyncAttributeValue() || m_forceAsync);
+        ASSERT(hasAsyncAttribute() || m_forceAsync);
         document.scriptRunner()->queueScriptForExecution(*this, *m_loadableScript, ScriptRunner::ASYNC_EXECUTION);
     } else if (!hasSourceAttribute() && m_parserInserted && !document.haveStylesheetsLoaded()) {
         ASSERT(scriptType == ScriptType::Classic);
index 03025f8..0034667 100644 (file)
@@ -106,9 +106,10 @@ private:
     virtual String languageAttributeValue() const = 0;
     virtual String forAttributeValue() const = 0;
     virtual String eventAttributeValue() const = 0;
-    virtual bool asyncAttributeValue() const = 0;
-    virtual bool deferAttributeValue() const = 0;
+    virtual bool hasAsyncAttribute() const = 0;
+    virtual bool hasDeferAttribute() const = 0;
     virtual bool hasSourceAttribute() const = 0;
+    virtual bool hasNoModuleAttribute() const = 0;
 
     Element& m_element;
     WTF::OrdinalNumber m_startLineNumber;
index 5a73426..88f1a43 100644 (file)
@@ -174,6 +174,7 @@ multiple
 muted
 name
 nohref
+nomodule
 nonce
 noresize
 noshade
index 7a2b82d..65808a0 100644 (file)
@@ -148,16 +148,21 @@ String HTMLScriptElement::eventAttributeValue() const
     return attributeWithoutSynchronization(eventAttr).string();
 }
 
-bool HTMLScriptElement::asyncAttributeValue() const
+bool HTMLScriptElement::hasAsyncAttribute() const
 {
     return hasAttributeWithoutSynchronization(asyncAttr);
 }
 
-bool HTMLScriptElement::deferAttributeValue() const
+bool HTMLScriptElement::hasDeferAttribute() const
 {
     return hasAttributeWithoutSynchronization(deferAttr);
 }
 
+bool HTMLScriptElement::hasNoModuleAttribute() const
+{
+    return hasAttributeWithoutSynchronization(nomoduleAttr);
+}
+
 bool HTMLScriptElement::hasSourceAttribute() const
 {
     return hasAttributeWithoutSynchronization(srcAttr);
index 32d8ee0..7abbd35 100644 (file)
@@ -64,8 +64,9 @@ private:
     String languageAttributeValue() const final;
     String forAttributeValue() const final;
     String eventAttributeValue() const final;
-    bool asyncAttributeValue() const final;
-    bool deferAttributeValue() const final;
+    bool hasAsyncAttribute() const final;
+    bool hasDeferAttribute() const final;
+    bool hasNoModuleAttribute() const final;
     bool hasSourceAttribute() const final;
 
     void dispatchLoadEvent() final;
index f3f574f..019f4d5 100644 (file)
@@ -29,4 +29,5 @@ interface HTMLScriptElement : HTMLElement {
     [Reflect] attribute DOMString type;
     attribute DOMString? crossOrigin;
     [Reflect] attribute DOMString nonce;
+    [Reflect] attribute boolean noModule;
 };
index d6380b8..669adae 100644 (file)
@@ -138,12 +138,17 @@ String SVGScriptElement::eventAttributeValue() const
     return String();
 }
 
-bool SVGScriptElement::asyncAttributeValue() const
+bool SVGScriptElement::hasAsyncAttribute() const
 {
     return false;
 }
 
-bool SVGScriptElement::deferAttributeValue() const
+bool SVGScriptElement::hasDeferAttribute() const
+{
+    return false;
+}
+
+bool SVGScriptElement::hasNoModuleAttribute() const
 {
     return false;
 }
index e267869..23277f7 100644 (file)
@@ -59,8 +59,9 @@ private:
     String languageAttributeValue() const final;
     String forAttributeValue() const final;
     String eventAttributeValue() const final;
-    bool asyncAttributeValue() const final;
-    bool deferAttributeValue() const final;
+    bool hasAsyncAttribute() const final;
+    bool hasDeferAttribute() const final;
+    bool hasNoModuleAttribute() const final;
     bool hasSourceAttribute() const final;
 
     void dispatchLoadEvent() final { SVGExternalResourcesRequired::dispatchLoadEvent(this); }