w3ctag / design-reviews

W3C specs and API reviews
Creative Commons Zero v1.0 Universal
332 stars 56 forks source link

HTMLScriptElement.supports(type) method #674

Closed horo-t closed 3 years ago

horo-t commented 3 years ago

Ya ya yawm TAG!

I'm requesting a TAG review of HTMLScriptElement.supports(type) method.

HTMLScriptElement.supports(type) method provides a unified way to detect new features that use script elements.

Further details:

We'd prefer the TAG provide feedback as (please delete all but the desired option):

💬 leave review feedback as a comment in this issue and @-notify @horo-t

LeaVerou commented 3 years ago

Quick question: How is this detected today? Is this API proposing a nicer way to feature detect what values the type attribute supports, or is there no way to do feature detection for this today?

horo-t commented 3 years ago

This API is proposing a nicer and synchronous way to feature detect.

For module, we can use the nomodule attribute to detect the module type support as this example shows.

https://html.spec.whatwg.org/multipage/scripting.html#script-nomodule-example

<script type="module" src="app.mjs"></script>
<script nomodule defer src="classic-app-bundle.js"></script>

(Note: Safari 10 did support module, but didn't support nomodule. So we need some hack like this solution not to load <script nomodule>.)

For importmap, there is no synchronous way to detect the importmap type support. As described in the issue comment, we need to fetch an useless HTTP request.

https://github.com/WICG/import-maps/issues/171#issuecomment-521299519


<script type="importmap">
{
  "imports": {
    "vue": "/vendor/vue.js"
  }
}
</script>
// ...
<script>
import ("vue").catch(() => {
  // We'll get here if we're in a browser that doesn't support import maps,
  // because import "vue" will fail (with no evaluation performed). In that case
  // the <script type=module> was also a no-op (mostly).

  const s = document.createElement('script');
  s.src = "./bundle.js";
  document.body.append(s);
});
</script>
atanassov commented 3 years ago

@plinss and I looked at the proposal during our Gethen vf2f. The overall author simplification and improvement of the API over what they need to do today is certainly great.

One concern we have is they way the capability is to be exposed, the supports method. If this API was designed to check for any kind of support on the HTMLScriptElement then that would be fine, but you are restricting it to the type only. Perhaps you should consider exposing it as HTMLScriptElement.type.supports() (not sure if possible) or HTMLScriptElement.supportsType().

horo-t commented 3 years ago

I understand the concern. Changing the name to HTMLScriptElement.supportsType() sounds reasonable and feasible to me.

@domenic What do you think about it?

domenic commented 3 years ago

I kind of prefer the brevity and clarity of the existing method, and how it matches existing platform conventions (e.g. supports() on DOMTokenList or supports() on CSS). I don't know what other feature you would be detecting support for on HTMLScriptElement.

LeaVerou commented 3 years ago

I definitely see @domenic's point. I suppose if in the future we need to detect something else, there can be an optional second argument to supports() about what is being detected?

plinss commented 3 years ago

Our concern is due to the fact that the behavior is scoped to detecting supported values of type. Ideally, this would be expressed as script.type.supports('...'), but we accept the impracticality of getting that since type is a string.

Two alternate uses of HTMLScriptElement.supports() we came up with are: detecting JS features, e.g. script.supports('es2021'), or script.supports('await'), or a more generic script.supports('some random js code') (the latter would detect if everything is parseable without any execution); or collisions with a HTMLElement.supports() method that could be used to detect otherwise undetectable feature support on an element.

We did consider adding an argument to supports, e.g. script.supports('type', 'module'), but felt that was too early to define how alternative values would work.

domenic commented 3 years ago

Two alternate uses

These don't seems specific to HTMLScriptElement, but instead about JavaScript support in general. They would be best placed in another namespace, e.g. JavaScript.supports() like CSS.supports().

plinss commented 3 years ago

or collisions with a HTMLElement.supports() method that could be used to detect otherwise undetectable feature support on an element.

domenic commented 3 years ago

I don't understand why we would add anything to the HTMLElement base class, given that there are subclasses for all elements that have functionality.

plinss commented 3 years ago

For the reason I stated, as a general purpose supports mechanism, similar to CSS.supports() where results would be dependent on the element class, so a HTML.supports() wouldn't be appropriate.

Note that I'm not trying to design new features here, @atanassov and I are just asking the question "are there potential uses of a generic supports() method that have a different scope and may collide with this one", and I think the answer is, yes.

The bottom line is that while we can spend all day imagining (or denying) future uses, we just can't know what the future will bring. In general, using narrowly scoped features allows more flexibility down the road. If the goal here is brevity, I don't think saving 4 characters is worth the risk of future naming collisions which could lead to author confusion.

If your concern is more about being consistent with DOMTokenList.supports(), then that argues more for HTMLScriptElement.type.supports() than it does for HTMLScriptElement.supports().

domenic commented 3 years ago

OK. I guess we just have to agree to disagree.

atanassov commented 3 years ago

@domenic besides the brevity of the current name I don't see how the current proposal helps.

I kind of prefer the brevity and clarity of the existing method, and how it matches existing platform conventions (e.g. supports() on DOMTokenList or supports() on CSS).

As @plinss pointed out, this is precisely the confusing part with the current proposal because HTMLScriptElement.supports() is not intended to provide the generic capability CSS.supports() does. The fact that people recognize the API name will only add to the confusion as they realize that the only thing they can check for is type.

domenic commented 3 years ago

It provides the appropriately-scoped capability for the name. HTMLScriptElement.supports() is about what the HTML <script> element supports. If you want to check for JS feature support you should use a hypothetical JavaScript.supports().

plinss commented 3 years ago

But that’s just it, it doesn’t test what the script element supports, it tests what values of the type property the script element supports. What about when we want to add a test for values of another property?

domenic commented 3 years ago

It is my judgment as HTML editor that the most fundamental property of the script element is what types it supports. If, in some hypothetical (but in my judgment extremely unlikely) future there were some other property we'd want to test support for, we would add a new method named supportsX() for that, or an overload like supports("prop", "value"), and leave supports("value") for the most fundamental (and very likely only) thing that would be support-tested.

annevk commented 3 years ago

Also, most newer IDL attributes are limited to "known values", which means you can do feature testing without a dedicated method. That's generally the HTML way and what I would expect us to continue to use.

atanassov commented 3 years ago

@annevk and @domenic, thank you both for the engagement and feedback. It seems like we've exhausted the feedback on this particular issue on both sides. You have TAG's naming opinion and it is up to you what the final shape of it is. After all, our position is to provide advice and not force an opinion.

With that being said, the merit of the overall proposal is something we do like and want to see move forward, thus, closing the review. Thank you for working with us. Looking forward to your further progress.