Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Normative source of truth for extended attribute applicability and constraints #1045

Open
bathos opened this issue Oct 15, 2021 · 4 comments
Labels
clarification Standard could be clearer

Comments

@bathos
Copy link
Contributor

bathos commented Oct 15, 2021

Spun off from prior convo (#940 (comment)).

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)

@annevk annevk added the clarification Standard could be clearer label Oct 15, 2021
@bathos
Copy link
Contributor Author

bathos commented Oct 15, 2021

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.

@annevk
Copy link
Member

annevk commented Oct 18, 2021

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.

@bathos
Copy link
Contributor Author

bathos commented Oct 18, 2021

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".

@ExE-Boss
Copy link
Contributor

ExE-Boss commented Nov 8, 2021

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

Note that depending on the resolution of #878, [LegacyFactoryFunction] ∧ [LegacyFactoryFunction] might change from a ✔️ to a .

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
clarification Standard could be clearer
Development

No branches or pull requests

3 participants