webidl icon indicating copy to clipboard operation
webidl copied to clipboard

Normative source of truth for extended attribute applicability and constraints

Open bathos opened this issue 3 years ago • 4 comments

Spun off from prior convo (https://github.com/whatwg/webidl/pull/940#issuecomment-943924610).

Currently, the rules for which constructs extended attributes are applicable to and secondary constraints (e.g. when two EAs are mutually exclusive) end up specified in multiple places without one location clearly acting as normative/authoritative. Sometimes these do not seem to be in agreement.

For example, the section defining [Unscopable] begins "If the [Unscopable] extended attribute appears on a regular attribute or regular operation," but the lists of which EAs are applicable to regular attributes and regular operations (in their respective sections) do not list [Unscopable].

It might be better if the EA definitions alone were to specify applicability. One reason to favor this as source-of-truth is that applicability conditions are often more complex than just the kind of construct (e.g. [PutForwards] is applicable to only readonly attributes which are not namespace members) and the per-construct lists don't capture the full picture (and might be misleading).

In the mutual exclusion cases, usually each EA's section lists all of the other EAs which it may not appear with, but these lists are also not always consistent. For example:

  • the [LegacyWindowAlias] section specifies that it is mutually exclusive with [LegacyNoInterfaceObject] and [LegacyNamespace]
  • the [LegacyNamespace] section specifies that it is mutually exclusive with [LegacyNoInterfaceObject] only
  • the [LegacyNoInterfaceObject] section mentions neither requirement

These cases are less simple to solve because no single EA in question is the naturally authoritative place for the mutual exclusion to be described. One idea might be a single table that specifies which EAs are compatible with each other up front before the specific EA subsections. Flipping to explicitly saying which are compatible instead of incompatible might help avoid accidentally incoherent changes. I suspect that there are some mutual exclusion constraints which should exist that are currently not specified at all and this might help to reveal them. For example, I would guess that [Global] and [LegacyNamespace] should be considered mutually exclusive, but currently they are not specified this way.

One more example of the kind of hard-to-spot stuff that happens with the current model: presently, the operation of a callback interface can take [LegacyUnforgeable], among others, if the spec is read literally, but this pretty clearly doesn't make sense and no behavior is specified that would be compatible with it.

(@annevk)

bathos avatar Oct 15 '21 07:10 bathos

Regarding mutual exclusion/compatibility, here is what I think is currently specified either directly or indirectly (i.e. there are some cases where it’s not explicit but can be deduced based on other requirements being incompatible). There could easily be mistakes here, but it may help illustrate things / be a starting point.

image of table, but the actual table can be found at the link which follows

https://glory-furry-cabin.glitch.me/

One case that's fuzzy is Default vs NewObject. These are currently implicitly incompatible because Default's sole operation and NewObject establish incompatible constraints on the return type - but because it seems like the idea of Default is that more operations may be added in the future, it may make more sense to say they are compatible.

Another interesting case is Replaceable vs Unforgeable. That these are incompatible cannot be inferred from any combo of assertions in the spec text AFAICT, but the behaviors prescribed for each appear to conflict with each other and it seems very likely that they are intended to be mutually exclusive.

bathos avatar Oct 15 '21 08:10 bathos

That's a great table. Thanks for making it!

Another thing that might help clarify matters is an equivalent table that shows the applicability of extended attributes to the various IDL constructs, such as types and interfaces. That would also end up showing which extended attributes are naturally incompatible. Which perhaps would be interesting to show in your table as well. Are they incompatible because of semantics or because they apply to different constructs?

The current Default operation kind of implies NewObject, no? This might not always be the case though.

annevk avatar Oct 18 '21 12:10 annevk

I'll try a first pass applicability table too. I think the key missing thing from the existing per construct list is distinguishing between whether e.g. they really just mean "regular attribute" or "regular attributes of interfaces/interface mixins only" (it's usually the latter).

The current Default operation kind of implies NewObject, no? This might not always be the case though.

The Default toJSON does always "return a new object" (object type), but [NewObject]-annotated operations are currently required to return "an interface type or a promise type".

bathos avatar Oct 18 '21 13:10 bathos

https://glory-furry-cabin.glitch.me/

Note that depending on the resolution of https://github.com/whatwg/webidl/issues/878, [LegacyFactoryFunction] [LegacyFactoryFunction] might change from a ✔️ to a .

ExE-Boss avatar Nov 08 '21 03:11 ExE-Boss