aom
aom copied to clipboard
Need to figure out what the iterable<Foo> attributes should actually be
Specifically, the question is what the backend storage is and what the actual return value should look like. Want to avoid two things:
- Having the browser's accessibility backend need to examine JS objects all the time. In other words, the setter should snapshot the incoming value somehow and that internal snapshot should be what the backend actually looks at.
- Having an attribute getter that returns a new object every time. This is generally considered a bad practice.
One option is to replace attributes with explicit get/set methods, where both would accept sequences. But maybe something involving FrozenArray is doable too. Really, need to figure out the right behavior and then we can figure out how to express that in IDL (possibly including changes to IDL).
//cc @cookiecrook
I'm not following what iterable<Foo>
is referring to here - could you clarify?
This bit in http://a11y-api.github.io/a11y-api/spec/:
attribute iterable<AccessibleNode> controls;
and similar.
Got it, thanks - so, the relationship attributes, more or less?
I had a discussion with James about this yesterday - I believe for phase 1 these should actually be Element
or Node
references.
@minorninth, @cookiecrook what do you think?
If we want to eventually support a list of nodes, need to think a bit about how that evolution will happen...
Agreed, clearly this will become more complicated in V3 when it's possible to create non-Node
-backed accessibility node objects.
Hm - perhaps we're talking at slightly cross purposes, actually.
Is your issue the choice of Array<...>
rather than, e.g., NodeList
?
My issue, and to be clear it's a minor one if we're still deciding on the overall API shape, is that the IDL construct being used doesn't actually exist. I don't have any strong feelings about whether this thing should be a NodeList
or an Array
or something else; those are tradeoffs that depend on how this API will be used in practice and I don't have a good enough understanding of that yet to comment on it intelligently. :)
Right, with you now, thanks! Checking into it.
I think what we want to support here is assignment of (NodeList or Array), and make the return value FrozenArray, so these constructs could work:
n.controls = e.querySelectorAll("...")
n.controls = [a, b, c];
if (n.controls.include(a))
return ...;
I'm not sure how we express that in webidl today, per discussion of a new syntax yesterday I think maybe:
class AccessibleNode {
get FrozenArray<Element> controls();
set controls((NodeList or Array) elements);
}
And then we define the snapshot behavior in the algorithm. Should there be a webidl attribute like [Snapshot]
to express this?
@domenic
@esprehn my understanding is that FrozenArray
is special so that the existing syntax will already give you that behavior, i.e.
interface AccessibleNode {
attribute FrozenArray<Element> controls;
}
The JS-value-to-WebIDL-FrozenArray will convert any iterable (including arrays and NodeLists) to a WebIDL FrozenArray. And of course converting a WebIDL FrozenArray to a JS value will give you a frozen JS array.
In this setup, it's up to the spec author to be explicit about when the FrozenArray gets reset. (That is, when accessibleNode.controls
starts returning a new value.) In this case it would be any time the tree mutates---which is a bit strange, but if tree mutations are rare, I guess it's OK. The alternative is getControls/setControls methods, or maybe just getControls + other tree mutation methods (like clear, append, etc.).
FrozenArray
is special so that the existing syntax will already give you that behavior
Yep.
In this case it would be any time the tree mutates
My understanding is that it would only change when explicitly set; these are not the computed values but the caller-set values being exposed here.
The main issue with FrozenArray
is that the thing it exposes to the browser implementation is the JS frozen Array
object, per spec. But I think that gets of .length
and indices from 0 to length on a frozen array with no holes are not observable in ES (@domenic is that true?). So if the specification said that UAs get the data out of the FrozenArray
via getting .length
and then indexing then the UA impl could in fact stash the thing it cares about into a separate list at set time and not have to worry about touching JS objects from the accessibility code and this would be black-box identical to reading from the frozen Array
. This seems like a viable approach at first glance.
One thing to note is that originally the spec/explainer made it seem like this would be a list of DOM nodes or elements, but it really should be a list of other AccessibleNodes, that makes it possible to use virtual AccessibleNodes too.
So NodeList isn't needed.
FrozenArray<AccessibleNode> sounds right if that exists.