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

Clarify "undefined" assignment for a state/property as the value (not the string) #2177

Open
rahimabdi opened this issue May 5, 2024 · 10 comments · May be fixed by #2172
Open

Clarify "undefined" assignment for a state/property as the value (not the string) #2177

rahimabdi opened this issue May 5, 2024 · 10 comments · May be fixed by #2172
Assignees
Labels
editorial a change to an example, note, spelling, grammar, or is related to publishing or the repo

Comments

@rahimabdi
Copy link
Contributor

rahimabdi commented May 5, 2024

Describe the change

In order to address #2156, @spectranaut /@smhigley /@aardrian suggested clarification in the spec of how to assign undefined for states and properties; namely, to clarify that undefined represents a value (e.g., aria-expanded=undefined) rather than a string (e.g., aria-expanded="undefined"). This change may also involve explicitly stating the absence of a value is equivalent to undefined.

It's unclear where this should be documented (perhaps Section 6.2 Characteristics of States and Properties).

Unconventional techniques for assigning an undefined value

There may need to be additional clarification on the following assignment methods:

  • Empty string: stateOrProperty = "" (this one is referenced in the aria-current section as being allowed via the empty string, i.e., "If the attribute is not present or its value is the empty string...")
  • Null: stateOrProperty = null

Potentially erroneous spec examples of "undefined" string value

The following two undefined references use the string value which may be confusing and require updating:

  1. Section 9.2 States and Properties:

When exposing as a platform API Boolean state:
For values of "" (empty string), "undefined" or no attribute present:

  1. aria-hidden state description section:

NOTE
As of ARIA 1.3, aria-hidden="false" is now synonymous with aria-hidden="undefined".

Validator testing of undefined vs. "undefined"

W3C HTML Validator shows the following parsing results when undefined is assigned as a value (stateOrProperty=undefined) vs. a string (stateOrProperty="undefined").

For states/properties that support explicit assignment of undefined:

State/property "undefined" string undefined value Tested elements
aria-checked passes passes role="checkbox", role="radio"
aria-current (may be missing undefined in its Values table, see #2176) fails fails <button>, <a>, role="button", role="link"
aria-expanded passes passes <button>, <a>, role="button", role="link"
aria-grabbed Not tested Not tested None (deprecated element)
aria-hidden (very recently added as part of #2090) fails fails <button>, <a>, role="button", role="link"
aria-orientation passes passes role="scrollbar", "role="slider", role="tablist"
aria-pressed passes passes <button>, role="button"
aria-selected passes passes role="tab"
aria-multiselectable (may be missing undefined in its Values table, see #2176) fails fails role="tablist", role="listbox"

Link to the version of the specification or documentation you were looking at

Link to documentation: https://w3c.github.io/aria

Does the issue exists in the editors draft (the editors draft is the most recent draft of the specification)?

Yes.

@rahimabdi rahimabdi added the editorial a change to an example, note, spelling, grammar, or is related to publishing or the repo label May 5, 2024
@rahimabdi rahimabdi self-assigned this May 5, 2024
@jnurthen jnurthen added the Agenda label May 9, 2024
@smhigley
Copy link
Contributor

@rahimabdi could you clarify how you're testing the not-string undefined value with the W3C HTML validator? I'm definitely not getting failures for HTML like <button>some text</button> (i.e. with no attribute defined), and I don't believe the validator is looking at scripting or setting of IDL attributes. Some of the things you have marked as failures under the "undefined value" column are kinda throwing me a bit 😅

@smhigley
Copy link
Contributor

smhigley commented May 15, 2024

Also dropping this here as well (I posted it in a reply comment in a PR, but thought it'd be easier to find here too):

I made a test page to output the browser-mapped values when ARIA attributes are set to the string "undefined", not set at all, or set programmatically to undefined: https://jsfiddle.net/pobwvgs9/

I checked it in Chrome, Edge, Safari, and Firefox on macOS and Windows (Safari only on mac), and all of them had the same not-undefined results for the string "undefined". The results for not-defined and programmatic = undefined values are what I'd expect & what matches the spec, while the string "undefined" are not.

@spectranaut
Copy link
Contributor

Discussed briefly during the ARIA working group meeting: https://www.w3.org/2024/05/16-aria-minutes#t09

Consensus that the string "undefined" should not be considered undefined.

@jnurthen jnurthen removed the Agenda label May 21, 2024
@rahimabdi
Copy link
Contributor Author

rahimabdi commented May 21, 2024

@rahimabdi could you clarify how you're testing the not-string undefined value with the W3C HTML validator? I'm definitely not getting failures for HTML like <button>some text</button> (i.e. with no attribute defined), and I don't believe the validator is looking at scripting or setting of IDL attributes. Some of the things you have marked as failures under the "undefined value" column are kinda throwing me a bit 😅

@smhigley For the undefined assignment (not the string), I took each of the state/properties and set it as follows: stateOrProperty=undefined, e.g., aria-expanded=undefined. I've never implemented these in this manner, or seen them implemented this way, but the spec language (and HTML Validator) seem to be OK with it.

I think the spec may benefit from greater clarity on what it means for a state/property to be undefined, and to delaminate all the ways something can be undefined. I counted the following techniques:

  • stateOrProperty="undefined" (the ARIA WG agrees this is invalid)
  • stateOrProperty=undefined
  • stateOrProperty=null
  • stateOrProperty="" (empty string)
  • stateOrProperty (without an assignment, e.g., aria-current). Does this one need a default value?

@aardrian
Copy link
Contributor

I am on board with consistency within the spec itself. Are you proposing a PR to do so?

Otherwise I cannot tell from your comment what you feel the next step should be.

@MarioBatusic
Copy link
Contributor

Do I understand it correctly: PROPERTY=undefined and PROPERTY is not set results in the value undefined; and PROPERTY="undefined" or PROPERTY="" is not undefined.

If so we should correct it in the specs.

@rahimabdi
Copy link
Contributor Author

rahimabdi commented Jul 13, 2024

ARIA WG "undefined" deep dive meeting notes from Thursday June 27 2024:

  • Rahim: this issue around “undefined”, and how it is specified, came about as part of WPT aria-hidden test (Create wai-aria/hidden/aria-hidden-tested-via-label.html web-platform-tests/wpt#45694)
    • Question: what kind of attributes are ARIA attributes?
    • HTML spec describes lots of attributes, e.g., content, boolean, enumerated, etc.
  • Valerie: appreciate you doing this work because there are problems with aligning ARIA and HTML because of the IDL part of ARIA. Anne VK. is also working on this
    • There may be some information on this in previous IDL discussion
    • Mapping is not straight and as clear as it needs to be
  • James N.: it depends on the attribute. We have a mapping of the ARIA value types to languages in Appendix A of the ARIA spec. That’s where we have attempted to map this
  • James C.: it’s a fairly straightforward answer. Most of them are reflected DOMStrings
    • ARIAMixin interface: https://w3c.github.io/aria/#idl-interface
    • Most of these have attribute DOMString as the prefix; a few of them are FrozenArray (anything where we have an object reference to a DOM node or nodes)
    • For example, and you can see this by the plurality of the reflected interface, e.g., FrozenArray? ariaDescribedByElements
    • But most are DOMString, so there’s no value type enforced other than string at the IDL layer
    • We do have additional prose in spec as to what those values are; part of the reason is because there’s no standard way in IDL to list reflection (implementations differ)
  • Rahim: is that why ARIA IDL doesn’t align 1:1 with HTML IDL? ARIA WG seems to approach it differently than how HTML IDL works
  • James C.: what we’ve currently always referred to as the ARIA attributes, these are known as content attributes. E.g., <someElement attribute=“”> versus DOM properties accessed via JavaScript: element.ariaLabel
    • HTML is aligning all of their content attributes (which are always string) with the reflected DOM properties which can be of any value type
    • There are also rules that determine what happens if the content attribute’s string value doesn’t match one of these data types
    • HTML is a little bit more strict and holds off on defining reflections until value type is worked out
    • ARIA IDL held off on defining FrozenArray references; part of the reason is that we’ve had ARIA content attributes for a decade or more so there wasn’t a clean transition that wouldn’t negatively affect some web compatibility circumstance (trying to avoid breaking websites by leaving these as DOMString)
    • Conversation is not completely closed
  • Valerie: linking this issue which has more context: ARIAMixin has many integer attributes with string types and uses DOMString? incorrectly #1110
  • James C: to summarize, most of these are DOMStrings and the various stakeholder concluded they will likely stay as such unless there is a very compelling reason to change them now. But there may be other non-string accessors added later, for example CSS added tokenlist classlist to avoid breaking the string classname property. ARIA could do something similar
  • Rahim: a couple follow-up questions
  • James C.: ARIA shipped IDL interface in 1.2; at that point, ARIA WG was having open discussions about changing them but it became a self-referential problem
    • ARIA WG shipped them as nullable DOMStrings, and not non-nullable DOMString
    • The 6.3.4 note may be outdated
  • James N.: ARIA spec mentions in 6.3.2 that “missing value default” and “invalid value default” should not reflect to IDL; should use a “null” instead
  • Valerie: to Rahim’s question. what becomes null in the IDL interface?
  • Rahim: right; what becomes null; for the stuff that gets serialized (i.e., content attributes). Also, does null = undefined?
  • James C.: to follow up on James N.’s comment on 6.3.2: part of the reason for that is the problem of unshipping for webcompat reason
    • IDL handles some of the base for us, and then provide follow on rules (in spec prose) because we couldn’t write them in IDL and keep backwards-compatible nullable DOMString IDL
    • Complicates implementation but priority of constituencies is respected (authors over implementors and spec editors)
  • Rahim: if I’m understanding correctly, part of this is also not treating ARIA content attributes as true boolean types (but boolean-like tokens)
    • This allows for ability to add new ARIA values to existing attributes
  • James C.: when ARIA was first conceived, there weren’t boolean attributes in HTML
    • ARIA needed values that could be referenced and later HTML spec solidified these rules formally
  • Rahim: what about setting an ARIA attribute to the string value “undefined” vs. non-string value undefined?
  • James C.: to some degree, it behaves the same way although not in the IDL
    • What we have as aria-hidden is effectively an enumerated attribute
    • Look in example 20 in 6.3.4.1 (https://w3c.github.io/aria/#enumeration-example); boolean “false” is effectively missing value default
    • However, not reflected this was in IDL because it could break older websites
  • Sarah H.: might be my fault for the confusion around quotations or not for “undefined”; my comment differentiated between 1) setting undefined as string in HTML vs 2) IDL attribute and 3) setAttribute() method
    • When I put undefined without quotations, was indicating setting it via element.ariaChecked=undefined, or element.setAttribute(“aria-checked”, undefined)
    • In HTML you can omit quotes and functionally the same thing as putting quotes around it
  • James C.: but the implementation of that is that it becomes an invalid value default, which is null?
  • Sarah H.: I don’t think so; I made a test case (Clarify "undefined" assignment for a state/property as the value (not the string) #2177)
    • You can pass in undefined without strings and IDL reflection is the string “undefined” instead of null
  • James C.: is that the case for all browsers? This is complicated because there is no way (in WPT) to check in-browser representation of the value before it reaches platform API
  • Sarah H.: I checked several browsers including Chrome, Edge and Safari
  • James C.: although the value itself may be reflected as the DOMString (IDL reflects DOMString “undefined”), implementations may not be up-to-date with ARIA spec
    • Also may not be a way to test WPT reflected value
  • Sarah H.: to make sure we’re on the same page, this is the difference between <button aria-expanded=undefined> vs. <button aria-expanded=“undefined”> as there should be no difference in those values
  • James C.: agreed. What I was trying to understand was effectively, for an enumerated attribute for example, setting undefined (or an incorrect spelling of undefined) reflects the same thing as an invalid value
  • Valerie: for the purpose of this discussion and ARIA specification going forward, it might be clear to use these concepts of missing/invalid value default as it’s helpful for more alignment between ARIA/HTML
  • Rahim: one thing I would mention is that in HTML, there’s not always going to be a missing/invalid value default so some attributes would return no state (returns nothing as the value)
  • Valerie: ARIA WG needs to be clear in spec if an invalid value is treated the same as an undefined value
  • Rahim: that’s one of my questions today
  • James C.: that’s what is handled by the IDL in HTML for enumerated attributes
  • Valerie: because the invalid value is turned into the undefined value
  • James C.: correct; ARIA also has a couple of attributes where the invalid value is (if unrecognized) counted as true but there wasn’t a reflection problem in the DOM because it needed to be passed downstream through an accessibility API
  • Scott: I wanted to chime in on expectation for undefined value, and we brought this up at a previous ARIA meeting
    • In past testing, undefined wasn’t an empty string or invalid value. It seemed to be a way to prime browsers to expect a state change
    • For example, <button aria-expanded=“undefined”> because the button needed a start state but upon pressing, it became a true or false expanded button. However, if I started with <button aria-expanded=“foo”>, then the aria-expanded state would not be consistently or properly announced
    • From what I understand, there was a difference between undefined representing an invalid value vs. undefined being a “special”, new value
  • James C.: does this count as spec working around a browser bug?
  • Scott: is it a browser bug, or is it the fact that there are 3 values defined for aria-expanded (true, false, undefined) and the expectation is that these are probably just strings
    • I’m not saying we have to maintain this but we need to make incredibly clear in spec that undefined is not meant to be another token value
    • Not sure how many people are relying on this as it’s just one example
  • Rahim: should “undefined” the string value be a separate value for some ARIA attributes?
  • James C.: I recall early discussions (pre-2010), ARIA allows empty strings or the string as a token “undefined” to be the same value for readability, understandability, and some of it for the implementation problem that Scott pointed out
  • Sarah: H. is that happening now for any attributes?
  • James C.: not until we can test these downstream, such as ARIA-AT
  • Sarah H.: not a fan of having undefined the string map to undefined the value
  • James C.: in most cases, it doesn’t matter because the undefined will be the missing/invalid value default
    • If you write it in the string “undefined”, it would be an invalid token (like a typo for the word undefined, would trigger the functionality of the missing value default which is undefined)
    • “Undefined” would not need to be a special case
  • Scott: we need to be explicit in spec because while undefined is default for many attributes, some attributes have “none” as default value and undefined isn’t mentioned at all
  • James C.: I agree it should be explicit; perhaps there could be a row added to the characteristics table
    • Spec currently has values where you bold the default value
    • Could have missing default and invalid default defined explicitly as a token or string value (or null or undefined)
  • Scott: I’m fine with that; aria-autocomplete is an example where undefined isn’t specified
  • Rahim: I like that approach because it gets closer to HTML concept of enumerated attributes. However, what should be done about section 9.2 and the “Fallback values for missing required attributes” table (https://w3c.github.io/aria/#document-handling_author-errors_states-properties)?
  • James C.: for this table, it sounds like the 9.2 table could be removed and the table entries would be integrated in each attribute’s characteristics table
    • Called out as two separate values: for missing value default, but spec would also need invalid value default
  • Scott: aria-checked is an interesting one; the author error table says fallback value is “false” but undefined is default value
    • If the attribute isn’t defined at all, then the fallback value is actually false per author error table
  • James N.: ARIA WG needs to be careful about moving stuff from author error table to somewhere else
    • Whole point is that validators can flag these as errors if author has not defined something
    • It should be flagged because it was probably a mistake
  • James C.: there wasn’t a way in IDL to have a role-specific value default that was different from the attribute’s value default
    • For example, aria-orientation defaults to vertical for scrollbar but default be different for another role
  • Rahim: what are all the ways to define undefined for HTML (content attributes)? is “undefined” the string OK as an assignment method?
  • Valerie: are you referring to everything that is treated as the undefined state?
  • James C.: yes, changing it could be complicated
    • One place it could be a problem is, for an attribute that had an undefined value, where missing value default and undefined value default should be different
    • This would be problematic for this example because if undefined was treated as an invalid value, and resolved different for an undefined value, those two rules would conflict
  • Sarah H.: are you saying undefined the string is OK, in a way that is different than keyboard mashing?
  • James C.: I don’t know if it’s different in implementations today but ideally, spec would define missing/invalid value default are equivalent to undefined state, they would behave the same way (i.e., undefined string and button masher string would be equivalent and would resolve to undefined state)
  • Next steps for ARIA WG

@cookiecrook
Copy link
Contributor

cookiecrook commented Jul 30, 2024

Capturing my notes from an IDL meeting with @rahimabdi and @annevk a few weeks ago.

  1. reflected nullable DOMString? is unlikely to change, especially now that Gecko shipped it too.
  2. however, it’s possible ARIA WG could update some of the attributes to be defined as proper Enumerated Attributes with enforced values. This would have some validation benefits, would be backwards compatible in all non-author-error scenarios, and would be testable with existing WPT DOM tests.
  3. Some complications might include the boolean-like ENUM value types defined in the spec: true/false, and true/false/undefined. These are achievable, but authors might be confused. aria-pressed is a good example where there an enumerated true/false/undefined is critical to distinguish toggle buttons from push buttons.
  4. Another oddity is aria-invalid, where the MISSING VALUE DEFAULT would be undefined, but the INVALID VALUE DEFAULT would be true. Other enumerated values include grammar, spelling, etc… So a misspelled grammer [sic] would still equate to true.

The ARIA spec is not in line with the algorithm defined below this portion of the HTML spec: search for “If a reflected IDL attribute has the type DOMString?:” (in particular, ARIA has nullable (?) strings that are not enumerated.)

For web compatibility reasons, implementations would never be able to retrofit the numeric strings to number types, but if needed in the future, we could add another accessor, as was done with CSS element.classList vs element.classname

ARIA WG could consider not adding new DOMString? reflection for non-string types (like numbers) when new corresponding content attributes are added in the future, though this may be confusing to authors unless some convention makes it clear which are strings vs other types. (e.g. as we did with element.ariaLabelledByElements)

Another complication that I forgot to discuss during that meeting is that, without the nullable ? char, all numeric values would have to have defaults… Some would be doable, like aria-min and aria-max could be 0 and 1 like html min and max on <input type=range>, but that would not work for an indeterminate progressbar for example. So there were a number of reasons why these stayed as nullable DOMStrings… It wasn’t just an editorial screw up.

ARIA WG should consider adding notes in the spec (or in a wiki) documenting why these decisions were made.

@cookiecrook
Copy link
Contributor

Adding Agenda+ to discuss potential actions at an upcoming WG meeting. In particular, do we want to track issues for:

  • Should we test the DOM to enforce values on the ENUM types defined as nullable DOMStrings? (Plenty of upsides. Are there any downsides besides the inevitable risk of implementation churn?)
  • Should the spec document why some of these IDL decisions were made in the past?
  • What about the suggestion to not add any new DOMString accessors for non-string types?
  • Is there a need for DOMTokenList-like accessors like the CSS WG added for element.classList? For exampleelement.ariaInvalidList?

@spectranaut
Copy link
Contributor

Discussed briefly in Aug 9th ARIA WG meeting: https://www.w3.org/2024/08/08-aria-minutes#t08

@jnurthen jnurthen removed the Agenda label Aug 27, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
editorial a change to an example, note, spelling, grammar, or is related to publishing or the repo
Projects
None yet
7 participants