Add <script nomodule> to prevent script evaluation #2261

Merged
merged 4 commits into from Jan 31, 2017

Projects

None yet

5 participants

@domenic
Member
domenic commented Jan 11, 2017 edited

This allows selective delivery of classic scripts only to older user
agents. Fixes #1442.

/cc @whatwg/modules

This is meant to give something concrete to discuss. As @jakearchibald pointed out, it's important that if we do this, everyone does it, so let's try to get some sign-off from all vendors.

@domenic domenic Add <script nomodule> to prevent script evaluation
This allows selective delivery of classic scripts only to older user
agents. Fixes #1442.
8d68f97
source
+ <span data-x="module script">module scripts</span>. This allows selective execution of <span
+ data-x="module script">module scripts</span> in modern user agents and <span data-x="classic
+ script">classic scripts</span> in older user agents, <a href="#script-nomodule-example">as shown
+ below</a>.</p>
@domenic
domenic Jan 11, 2017 edited Member

We should probably add document conformance requirements that this not be specified on module scripts.

source
+ content attribute, then abort these steps. The script is not executed.</p>
+
+ <p class="note">This applies even to scripts with their <code
+ data-x="attr-script-type">type</code> attribute set to "<code data-x="">module</code>".</p>
@zcorpan
zcorpan Jan 12, 2017 Member

This was surprising to me. Why make it apply to module scripts also?

@domenic
domenic Jan 12, 2017 Member

I interpret "nomodule" as "do not run this in browsers that support modules", so that's why I went with this behavior. It should be a document conformance error anyway to use both, BTW.

@zcorpan
zcorpan Jan 12, 2017 Member

Hum, ok... I sort of expect a model where attributes are ignored in contexts where they don't make sense -- e.g. <input type="text" src="foo"> ignores the src attribute because type is not image (and it's non-conforming to specify src there). But maybe there are cases that I'm not thinking about that don't follow this model?

@zcorpan
zcorpan Jan 12, 2017 Member

I checked the attribute index and couldn't find another attribute that has an effect when it "shouldn't" apply. So I think we should check if it's a classic script here.

@Constellation
Member
Constellation commented Jan 12, 2017 edited

I think this is the right direction.
When defining <script type="module">, we do not select <module> tag due to the backward compatibility: <module> will be shown as the unknown HTML tag in the browsers not supporting modules.
I think the essence of this issue is the same. We should have the way to use <script type="module"> without ignoring the older browsers.

@rniwa Any thoughts?

@rniwa
Collaborator
rniwa commented Jan 12, 2017

This feature & approach sane to me. Note that type=module is already in Safari Tech Preview 21.

@@ -57059,6 +57060,7 @@ interface <dfn>HTMLDialogElement</dfn> : <span>HTMLElement</span> {
interface <dfn>HTMLScriptElement</dfn> : <span>HTMLElement</span> {
[<span>CEReactions</span>] attribute USVString <span data-x="dom-script-src">src</span>;
[<span>CEReactions</span>] attribute DOMString <span data-x="dom-script-type">type</span>;
+ [<span>CEReactions</span>] attribute boolean <span data-x="dom-script-noModule">noModule</span>;
@annevk
annevk Jan 12, 2017 Member

Is this forward-compatible enough with a potential wasm dependency?

@rniwa
rniwa Jan 12, 2017 Collaborator

I guess we’d end up adding noWASM as well? Maybe we want something more generic like nosupport="module wasm"?

@annevk
annevk Jan 12, 2017 Member

@domenic had nomodule=wasm in the original issue, but perhaps we shouldn't worry about it. Initial wasm usage needs to be deployed through JavaScript anyway and there's also the possibility of reviving content negotiation for it.

@rniwa
rniwa Jan 12, 2017 edited Collaborator

That might be a little shortsighted though. I’m sure the next step for WASM is to load it directly in browser, and presumably, we’d be using type=wasm or something.

@annevk
annevk Jan 12, 2017 Member

Well, if they use content negotiation as the opt-in the markup wouldn't have to change necessarily. But if we do add type=wasm or some such, we could add nowasm as @domenic suggested.

@rniwa
rniwa Jan 12, 2017 edited Collaborator

I'd say it does come off a little strange to add a new attribute for each script type that's not supported. I think something like nosupport=wasm / nosupport=module would mirror type attribute better (we can bikeshed the name).

@Constellation
Constellation Jan 12, 2017 Member

What happens if we load the WASM code with type="module"? IIUC, ES6 modules will handle WASM as well (maybe, based on content type): For example, import A from "./A.wasm" will work well.
http://webassembly.org/docs/modules/

@annevk
annevk Jan 12, 2017 Member

Right, what @Constellation alludes to is what I meant by content negotiation above. And that's the route Mozilla's wasm folks want to take.

@domenic
domenic Jan 12, 2017 Member

One reason I didn't go with a more generic syntax is it opens up a bunch of new cases that need to be nailed down and tested. E.g.

<script nosupport=module type=module src="foo.js"></script>
<script nosupport=text/javascript type=module src="foo.js"></script>
<script nosupport=text/livescript type=module src="foo.js"></script>
<script nosupport=text/javascript src="foo.js"></script>
<script nosupport=text/x-handlebars src="foo.js"></script>
<script nosupport=wasm type="module" src="foo.wasm"></script>

You can think up reasonable answers for all of these, but it's extra work for everyone involved. And especially since wasm will likely use type=module anyway, the idea that nosupport should take a type is probably not going to work.

Even if we say that the "support" values are different from the "type" values, there's also the case that we probably would want to allow loading a script only if both wasm and modules are not supported, so now we need to parse space-delimited tokens or similar:

<script nosupport="module wasm" src="es5fallback.js"></script>
<script nosupport="wasm" type="module" src="es6fallback.js"></script>
<script type="module" src="whatireallywanttoload.wasm"></script> <!-- fails to load in non-wasm browsers due to unrecognized MIME type -->

Again, more complexity.

@zcorpan
zcorpan Jan 12, 2017 Member

New boolean attributes for each new thing seems simplest and best to me. I would expect the need for such new things to be pretty rare.

domenic added some commits Jan 12, 2017
@domenic domenic Tweak wording 0906c54
@domenic domenic Some authoring and related changes 71583ef
@domenic domenic Ignore nomodule for module scripts per zcorpan
e2662c9
@domenic
Member
domenic commented Jan 12, 2017 edited

Updated with authoring requirements and to ignore the attribute if type="module", per @zcorpan's advice at #2261 (comment) .

@rniwa @Constellation I am going to tentatively proceed with nomodule instead of a more general syntax, as discussed in #2261 (comment) , and check the WebKit supports box. But let me know if you are not yet convinced and we can continue to discuss.

I will work on web platform tests next.

@rniwa
Collaborator
rniwa commented Jan 12, 2017
@annevk
Member
annevk commented Jan 13, 2017

I filed a Gecko bug indicating that the time to object is now: https://bugzilla.mozilla.org/show_bug.cgi?id=1330900.

@Constellation
Member

Note that the patch is ready in WebKit now. https://bugs.webkit.org/show_bug.cgi?id=166987 Once we all get agreement, I'll land it.

@probins probins referenced this pull request in ModuleLoader/system-register-loader Jan 14, 2017
Closed

Add docs and example for `nomodule` #6

@zcorpan
Member
zcorpan commented Jan 19, 2017

@Constellation it looks like the WebKit patch includes some tests; do you think you could convert them to testharness.js tests and submit to https://github.com/w3c/web-platform-tests ? This pull request is waiting on tests. 🙂

@Constellation
Member

@zcorpan sounds fine!

@domenic
Member
domenic commented Jan 24, 2017

@Constellation have you started work on porting the nomodule tests to web-platform-tests already? If not, I can do it tomorrow :). But I don't want to duplicate work if you have started already.

@Constellation
Member

@domenic oh, sorry, I do not start working on that yet.
I appreciate it if you can work on that :D

@rniwa
Collaborator
rniwa commented Jan 24, 2017

I'll do the conversion.

@hubot hubot pushed a commit to WebKit/webkit that referenced this pull request Jan 24, 2017
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.

Source/WebCore:

As discussed on whatwg/html#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
05ab710
@rniwa rniwa added a commit to rniwa/web-platform-tests that referenced this pull request Jan 24, 2017
@rniwa rniwa Add tests for nomodule content attribute on script elements
This feature is being added in whatwg/html#2261

Converted the tests in https://trac.webkit.org/r211078 to use testharness.js,
refined the test for IDL attribute reflecting content attribute, and re-organized tests.
d38e369
@rniwa rniwa referenced this pull request in w3c/web-platform-tests Jan 24, 2017
Merged

Add tests for nomodule content attribute on script elements #4611

@rniwa rniwa added a commit to rniwa/web-platform-tests that referenced this pull request Jan 24, 2017
@rniwa rniwa Add tests for nomodule content attribute on script elements
This feature is being added in whatwg/html#2261

Converted the tests in https://trac.webkit.org/r211078 to use testharness.js,
refined the test for IDL attribute reflecting content attribute, and re-organized tests.
f1e53e2
@rniwa rniwa added a commit to rniwa/web-platform-tests that referenced this pull request Jan 30, 2017
@rniwa rniwa Add tests for nomodule content attribute on script elements
This feature is being added in whatwg/html#2261

Converted the tests in https://trac.webkit.org/r211078 to use testharness.js,
refined the test for IDL attribute reflecting content attribute, and re-organized tests.
c240d2e
@rniwa rniwa added a commit to rniwa/web-platform-tests that referenced this pull request Jan 31, 2017
@rniwa rniwa Add tests for nomodule content attribute on script elements
This feature is being added in whatwg/html#2261

Converted the tests in https://trac.webkit.org/r211078 to use testharness.js,
refined the test for IDL attribute reflecting content attribute, and re-organized tests.
aedf8ac
@zcorpan
Member
zcorpan commented Jan 31, 2017

Tests are reviewed, I think we're all set.

@domenic domenic added a commit to w3c/web-platform-tests that referenced this pull request Jan 31, 2017
@rniwa @domenic rniwa + domenic Add tests for nomodule content attribute on script elements
This feature is being added in whatwg/html#2261

Converted the tests in https://trac.webkit.org/r211078 to use testharness.js,
refined the test for IDL attribute reflecting content attribute, and re-organized tests.
c4725e5
@domenic domenic merged commit a828019 into master Jan 31, 2017

2 checks passed

continuous-integration/travis-ci/pr The Travis CI build passed
Details
continuous-integration/travis-ci/push The Travis CI build passed
Details
@domenic domenic deleted the nomodule branch Jan 31, 2017
@Constellation
Member

Great!

@zcorpan zcorpan added a commit to w3c/web-platform-tests that referenced this pull request Feb 1, 2017
@zcorpan zcorpan Update idl for HTMLScriptElement
whatwg/html#49 script nonce
whatwg/html#1984 script integrity
whatwg/html#2261 script noModule
937cb75
@zcorpan zcorpan added a commit to w3c/web-platform-tests that referenced this pull request Feb 1, 2017
@zcorpan zcorpan Update reflection tests for <script> 39dd5ea
@zcorpan zcorpan referenced this pull request in w3c/web-platform-tests Feb 1, 2017
Merged

Update idl and reflection tests for <script> #4692

@zcorpan zcorpan added a commit to w3c/web-platform-tests that referenced this pull request Feb 2, 2017
@zcorpan zcorpan Update idl for HTMLScriptElement
whatwg/html#49 script nonce
whatwg/html#1984 script integrity
whatwg/html#2261 script noModule
67edbf9
@zcorpan zcorpan added a commit to w3c/web-platform-tests that referenced this pull request Feb 2, 2017
@zcorpan zcorpan Update reflection tests for <script> 6f711c5
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment